diff --git a/packages/common/src/error.ts b/packages/common/src/error.ts index f26ad8dc6..a638443fc 100644 --- a/packages/common/src/error.ts +++ b/packages/common/src/error.ts @@ -13,7 +13,9 @@ // limitations under the License. import { type TranslationKey, i18n as i18next } from "@prosopo/locale"; +import { ZodError } from "zod"; import { type LogLevel, type Logger, getLoggerDefault } from "./index.js"; +import type { ApiJsonError } from "./types.js"; type BaseErrorOptions = { name?: string; @@ -176,3 +178,36 @@ export class ProsopoApiError extends ProsopoBaseError { this.code = code; } } + +export const unwrapError = (err: ProsopoApiError | SyntaxError | ZodError) => { + const code = "code" in err ? err.code : 400; + let message = err.message; + let jsonError: ApiJsonError = { code, message }; + let statusMessage = err.message; + jsonError.message = message; + // unwrap the errors to get the actual error message + while (err instanceof ProsopoBaseError && err.context) { + // base error will not have a translation key + jsonError.code = + err.context.translationKey || err.translationKey || jsonError.code; + jsonError.message = err.message; + if (err.context.error) { + err = err.context.error; + } else { + break; + } + } + + if (err instanceof ZodError) { + message = i18next.t("CAPTCHA.PARSE_ERROR"); + statusMessage = message; + if (typeof err.message === "object") { + jsonError = err.message; + } else { + jsonError.message = JSON.parse(err.message); + } + } + + jsonError.code = jsonError.code || code; + return { code, statusMessage, jsonError }; +}; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 3211006c8..81107a130 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -17,3 +17,4 @@ export * from "./logger.js"; export * from "./array.js"; export * from "./hash.js"; export * from "./string.js"; +export * from "./types.js"; diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts new file mode 100644 index 000000000..2a3b33a4c --- /dev/null +++ b/packages/common/src/types.ts @@ -0,0 +1,4 @@ +export type ApiJsonError = { + message: string; + code: number; +}; diff --git a/packages/provider/src/api/errorHandler.ts b/packages/provider/src/api/errorHandler.ts index b192942a9..f87ba4d97 100644 --- a/packages/provider/src/api/errorHandler.ts +++ b/packages/provider/src/api/errorHandler.ts @@ -12,11 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. // We need the unused params to make express recognise this function as an error handler -import { type ProsopoApiError, ProsopoBaseError } from "@prosopo/common"; -import { i18n as i18next } from "@prosopo/locale"; -import type { ApiJsonError } from "@prosopo/types"; +import { type ProsopoApiError, unwrapError } from "@prosopo/common"; import type { NextFunction, Request, Response } from "express"; -import { ZodError } from "zod"; +import type { ZodError } from "zod"; export const handleErrors = ( err: ProsopoApiError | SyntaxError | ZodError, @@ -31,36 +29,3 @@ export const handleErrors = ( response.send({ error: jsonError }); response.end(); }; - -export const unwrapError = (err: ProsopoApiError | SyntaxError | ZodError) => { - const code = "code" in err ? err.code : 400; - let message = err.message; - let jsonError: ApiJsonError = { code, message }; - let statusMessage = err.message; - jsonError.message = message; - // unwrap the errors to get the actual error message - while (err instanceof ProsopoBaseError && err.context) { - // base error will not have a translation key - jsonError.code = - err.context.translationKey || err.translationKey || jsonError.code; - jsonError.message = err.message; - if (err.context.error) { - err = err.context.error; - } else { - break; - } - } - - if (err instanceof ZodError) { - message = i18next.t("CAPTCHA.PARSE_ERROR"); - statusMessage = message; - if (typeof err.message === "object") { - jsonError = err.message; - } else { - jsonError.message = JSON.parse(err.message); - } - } - - jsonError.code = jsonError.code || code; - return { code, statusMessage, jsonError }; -}; diff --git a/packages/types/src/provider/api.ts b/packages/types/src/provider/api.ts index f909c6050..d72330fac 100644 --- a/packages/types/src/provider/api.ts +++ b/packages/types/src/provider/api.ts @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +import type { ApiJsonError } from "@prosopo/common"; import type { Address4, Address6 } from "ip-address"; import { type ZodDefault, @@ -230,11 +231,6 @@ export interface ProviderRegistered { status: "Registered" | "Unregistered"; } -export type ApiJsonError = { - message: string; - code: number; -}; - export interface ApiResponse { [ApiParams.status]: string; [ApiParams.error]?: ApiJsonError;