@beignet/core
Version:
Core framework primitives for Beignet
96 lines • 2.97 kB
JavaScript
/**
* 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