diff --git a/src/lib/request.ts b/src/lib/request.ts index 690f6c7..32efbf0 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -26,16 +26,6 @@ function authenticationHeader(auth?: Authentication): string { throw new Error("auth must contain apiKey, jwt, or username/password"); } -function handleError(error: string) { - if (this.debug) { - console.error(error); - console.groupEnd(); - } - - // TODO: make this error more informative - throw new Error("CiviCRM request failed"); -} - export function bindRequest( requestFn: BaseRequestFn, config: ClientConfig, @@ -102,3 +92,47 @@ export async function request( return json.values; } + +function handleError(errorResponse: string | object) { + const error = new CiviCRMRequestError(errorResponse); + + if (this.debug) { + console.error(error); + console.groupEnd(); + } + + throw error; +} + +class CiviCRMRequestError extends Error { + name = "CiviCRMRequestError"; + message: string; + detail: any; + + parseError(error: string | { error_message: string }) { + if (typeof error === "object") { + return error; + } + + try { + const object = JSON.parse(error); + + if (object && typeof object === "object") { + return object; + } + } catch (e) {} + + return { + error_message: error || "CiviCRM request failed", + }; + } + + constructor(error: any) { + super(); + + const { error_message, ...detail } = this.parseError(error); + + this.message = error_message; + this.detail = detail; + } +} diff --git a/test/api3.test.ts b/test/api3.test.ts index b25417d..6de6e45 100644 --- a/test/api3.test.ts +++ b/test/api3.test.ts @@ -176,7 +176,12 @@ describe("debug", () => { } catch {} expect(consoleSpy.group).toHaveBeenCalled(); - expect(consoleSpy.error).toHaveBeenCalledWith("Internal Server Error"); + expect(consoleSpy.error).toHaveBeenCalledWith( + expect.objectContaining({ + name: "CiviCRMRequestError", + message: "Internal Server Error", + }), + ); expect(consoleSpy.groupEnd).toHaveBeenCalled(); }); }); diff --git a/test/api4.test.ts b/test/api4.test.ts index 0f3151f..4efcc48 100644 --- a/test/api4.test.ts +++ b/test/api4.test.ts @@ -239,7 +239,12 @@ describe("debug", () => { } catch {} expect(consoleSpy.group).toHaveBeenCalled(); - expect(consoleSpy.error).toHaveBeenCalledWith("Internal Server Error"); + expect(consoleSpy.error).toHaveBeenCalledWith( + expect.objectContaining({ + name: "CiviCRMRequestError", + message: "Internal Server Error", + }), + ); expect(consoleSpy.groupEnd).toHaveBeenCalled(); }); });