UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

96 lines 2.97 kB
/** * Error catalog and AppError definitions for Beignet */ const APP_ERROR_BRAND = Symbol.for("beignet.AppError"); /** * Define an application error catalog without losing literal key and code types. */ export function defineErrors(defs) { return defs; } /** * Application error thrown from use cases, policies, and route handlers. * * The server maps `AppError` instances to Beignet's standard error envelope and * marks them as route-owned errors when the contract declares the catalog entry. */ export class AppError extends Error { [APP_ERROR_BRAND] = true; /** Error definition from the catalog. */ def; /** * Optional structured details for clients or UI. * * Beignet does not automatically redact route-owned error details. Keep * provider errors, stack traces, secrets, and private content in `cause`, * logs, or error reporting instead. */ details; /** * Optional HTTP response headers set when this error crosses the HTTP * boundary, such as `Retry-After` on a 429. Headers are public response * data; only include values that are safe to expose. */ headers; constructor(def, details, overrideMessage, options) { super(overrideMessage ?? def.message, { cause: options?.cause }); this.name = "AppError"; this.def = def; this.details = details; this.headers = options?.headers; } /** * Stable public error code. */ get code() { return this.def.code; } /** * HTTP status code associated with this error. */ get status() { return this.def.status; } } /** * Create a callable `AppError` helper bound to a specific catalog. * * The returned function validates the catalog key and preserves each entry's * details type for `options.details`. */ export function createAppError(catalog) { const appError = ((key, options) => { const def = catalog[key]; if (!def) { throw new Error(`Unknown error catalog key: ${String(key)}`); } return new AppError(def, options?.details, options?.message, { cause: options?.cause, headers: options?.headers, }); }); appError.catalog = catalog; return appError; } /** * Check whether an unknown value is a Beignet `AppError`. */ export function isAppError(err) { if (err instanceof AppError) return true; if (typeof err !== "object" || err === null) return false; const value = err; if (value[APP_ERROR_BRAND] === true) return true; if (value.name !== "AppError") return false; const def = value.def; if (typeof def !== "object" || def === null) return false; const errorDef = def; return (typeof errorDef.code === "string" && typeof errorDef.status === "number" && typeof errorDef.message === "string"); } //# sourceMappingURL=catalog.js.map