- Improved error handling with more specific errors

- Error 404 (when a record is not found) is now translated into `RecordNotFoundException`
- Added documentation
- Added unittest updates to test the usage of `RecordNotFoundException` in `deleteRecord()`, `viewRecord()` and `updateRecord()`
This commit is contained in:
Tristan B. Velloza Kildaire 2022-12-30 14:01:04 +02:00
parent 0b0a8d2b31
commit 1027e5580f
1 changed files with 177 additions and 28 deletions

View File

@ -5,32 +5,61 @@ import std.stdio;
import std.net.curl; import std.net.curl;
import std.conv : to; import std.conv : to;
public final class PBException : Exception public class PBException : Exception
{ {
public enum ErrorType this()
{ {
CURL_NETWORK_ERROR, super("bruh todo");
JSON_PARSE_ERROR
} }
}
private ErrorType errType; public final class RecordNotFoundException : PBException
{
this(ErrorType errType, string msg) public const string offendingTable;
public const string offendingId;
this(string table, string id)
{ {
this.errType = errType; this.offendingTable = table;
super("PBException("~to!(string)(errType)~"): "~msg); this.offendingId = id;
} }
} }
public final class NetworkException : PBException
{
this()
{
}
}
public final class PocketBaseParsingException : PBException
{
}
public class PocketBase public class PocketBase
{ {
private string pocketBaseURL; private string pocketBaseURL;
/**
* Constructs a new PocketBase instance with
* the default settings
*/
this(string pocketBaseURL = "http://127.0.0.1:8090/api/") this(string pocketBaseURL = "http://127.0.0.1:8090/api/")
{ {
this.pocketBaseURL = pocketBaseURL; this.pocketBaseURL = pocketBaseURL;
} }
/**
* List all of the records in the given table
*
* Params:
* table = the table to list from
* page = the page to look at (default is 1)
* perPage = the number of items to return per page (default is 30)
*
* Returns: A list of type <code>RecordType</code>
*/
public RecordType[] listRecords(RecordType)(string table, ulong page = 1, ulong perPage = 30) public RecordType[] listRecords(RecordType)(string table, ulong page = 1, ulong perPage = 30)
{ {
RecordType[] recordsOut; RecordType[] recordsOut;
@ -52,14 +81,23 @@ public class PocketBase
} }
catch(CurlException e) catch(CurlException e)
{ {
throw new PBException(PBException.ErrorType.CURL_NETWORK_ERROR, e.msg); throw new NetworkException();
} }
catch(JSONException e) catch(JSONException e)
{ {
throw new PBException(PBException.ErrorType.JSON_PARSE_ERROR, e.msg); throw new PocketBaseParsingException();
} }
} }
/**
* Creates a record in the given table
*
* Params:
* table = the table to create the record in
* item = The Record to create
*
* Returns: An instance of the created <code>RecordType</code>
*/
public RecordType createRecord(string, RecordType)(string table, RecordType item) public RecordType createRecord(string, RecordType)(string table, RecordType item)
{ {
idAbleCheck(item); idAbleCheck(item);
@ -83,14 +121,23 @@ public class PocketBase
} }
catch(CurlException e) catch(CurlException e)
{ {
throw new PBException(PBException.ErrorType.CURL_NETWORK_ERROR, e.msg); throw new NetworkException();
} }
catch(JSONException e) catch(JSONException e)
{ {
throw new PBException(PBException.ErrorType.JSON_PARSE_ERROR, e.msg); throw new PocketBaseParsingException();
} }
} }
/**
* View the given record by id
*
* Params:
* table = the table to lookup the record in
* id = the id to lookup the record by
*
* Returns: The found record of type <code>RecordType</code>
*/
public RecordType viewRecord(RecordType)(string table, string id) public RecordType viewRecord(RecordType)(string table, string id)
{ {
RecordType recordOut; RecordType recordOut;
@ -104,16 +151,38 @@ public class PocketBase
return recordOut; return recordOut;
} }
catch(HTTPStatusException e)
{
if(e.status == 404)
{
throw new RecordNotFoundException(table, id);
}
else
{
// TODO: Fix this
throw new NetworkException();
}
}
catch(CurlException e) catch(CurlException e)
{ {
throw new PBException(PBException.ErrorType.CURL_NETWORK_ERROR, e.msg); throw new NetworkException();
} }
catch(JSONException e) catch(JSONException e)
{ {
throw new PBException(PBException.ErrorType.JSON_PARSE_ERROR, e.msg); throw new PocketBaseParsingException();
} }
} }
/**
* Updates the given record in the given table, returning the
* updated record
*
* Params:
* table = tabe table to update the record in
* item = the record of type <code>RecordType</code> to update
*
* Returns: The updated <code>RecordType</code>
*/
public RecordType updateRecord(string, RecordType)(string table, RecordType item) public RecordType updateRecord(string, RecordType)(string table, RecordType item)
{ {
idAbleCheck(item); idAbleCheck(item);
@ -135,26 +204,70 @@ public class PocketBase
return recordOut; return recordOut;
} }
catch(HTTPStatusException e)
{
if(e.status == 404)
{
throw new RecordNotFoundException(table, item.id);
}
else
{
// TODO: Fix this
throw new NetworkException();
}
}
catch(CurlException e) catch(CurlException e)
{ {
throw new PBException(PBException.ErrorType.CURL_NETWORK_ERROR, e.msg); throw new NetworkException();
} }
catch(JSONException e) catch(JSONException e)
{ {
throw new PBException(PBException.ErrorType.JSON_PARSE_ERROR, e.msg); throw new PocketBaseParsingException();
} }
} }
/**
* Deletes the provided record by id from the given table
*
* Params:
* table = the table to delete the record from
* id = the id of the record to delete
*/
public void deleteRecord(string table, string id) public void deleteRecord(string table, string id)
{ {
try try
{ {
del(pocketBaseURL~"collections/"~table~"/records/"~id); del(pocketBaseURL~"collections/"~table~"/records/"~id);
} }
catch(HTTPStatusException e)
{
if(e.status == 404)
{
throw new RecordNotFoundException(table, id);
}
else
{
// TODO: Fix this
throw new NetworkException();
}
}
catch(CurlException e) catch(CurlException e)
{ {
throw new PBException(PBException.ErrorType.CURL_NETWORK_ERROR, e.msg); throw new NetworkException();
} }
}
/**
* Deletes the provided record from the given table
*
* Params:
* table = the table to delete from
* record = the record of type <code>RecordType</code> to delete
*/
public void deleteRecord(string, RecordType)(string table, RecordType record)
{
idAbleCheck(record);
deleteRecord(table, record.id);
} }
public static void idAbleCheck(RecordType)(RecordType record) public static void idAbleCheck(RecordType)(RecordType record)
@ -180,14 +293,8 @@ public class PocketBase
} }
} }
//TODO: Here and upate record we must enforce the `.id` // TODO: Implement the streaming functionality
public void deleteRecord(string, RecordType)(string table, RecordType record) private void stream(string table)
{
idAbleCheck(record);
deleteRecord(table, record.id);
}
public void stream(string table)
{ {
} }
@ -484,4 +591,46 @@ unittest
} }
pb.deleteRecord("dummy", returnedPerson); pb.deleteRecord("dummy", returnedPerson);
} }
try
{
recordFetched = pb.viewRecord!(Person)("dummy", people[0].id);
assert(false);
}
catch(RecordNotFoundException e)
{
assert(cmp(e.offendingTable, "dummy") == 0 && e.offendingId == people[0].id);
}
catch(Exception e)
{
assert(false);
}
try
{
recordFetched = pb.updateRecord("dummy", people[0]);
assert(false);
}
catch(RecordNotFoundException e)
{
assert(cmp(e.offendingTable, "dummy") == 0 && e.offendingId == people[0].id);
}
catch(Exception e)
{
assert(false);
}
try
{
pb.deleteRecord("dummy", people[0]);
assert(false);
}
catch(RecordNotFoundException e)
{
assert(cmp(e.offendingTable, "dummy") == 0 && e.offendingId == people[0].id);
}
catch(Exception e)
{
assert(false);
}
} }