@beignet/core
Version:
Core framework primitives for Beignet
69 lines • 2.97 kB
JavaScript
import { STANDARD_ERROR_RESPONSE_SCHEMA } from "./types.js";
function isContractErrorDefinition(value) {
return (typeof value === "object" &&
value !== null &&
typeof value.code === "string" &&
typeof value.status === "number" &&
typeof value.message === "string");
}
/**
* Extract catalog error definitions declared in contract metadata.
*/
export function catalogErrorsFromMeta(metadata) {
const errors = metadata.errors;
if (typeof errors !== "object" || errors === null)
return {};
const catalog = {};
for (const [key, definition] of Object.entries(errors)) {
if (isContractErrorDefinition(definition)) {
catalog[key] = definition;
}
}
return catalog;
}
/**
* Convert catalog error definitions into standard envelope response schemas.
*/
export function responsesFromErrors(errors) {
const responses = {};
for (const error of Object.values(errors)) {
responses[error.status] = STANDARD_ERROR_RESPONSE_SCHEMA;
}
return responses;
}
/**
* Merge catalog errors already declared in metadata with new declarations.
*
* Later declarations win when the same catalog key is declared twice.
*/
export function mergeCatalogErrors(metadata, errorDefs) {
return { ...catalogErrorsFromMeta(metadata), ...errorDefs };
}
function catalogErrorStatuses(metadata) {
return new Set(Object.values(catalogErrorsFromMeta(metadata)).map((error) => String(error.status)));
}
/**
* Reject `.errors()` statuses that collide with custom response schemas.
*
* Statuses declared by earlier `.errors()` calls are allowed: catalog errors
* share the standard error envelope, so multiple codes can map to one status.
*/
export function assertErrorsAvoidCustomResponseStatuses(metadata, responses, nextErrorResponses) {
const existingErrorStatuses = catalogErrorStatuses(metadata);
const customStatuses = new Set(Object.keys(responses).filter((status) => !existingErrorStatuses.has(status)));
const conflicts = Object.keys(nextErrorResponses).filter((status) => customStatuses.has(status));
if (conflicts.length) {
throw new Error(`.errors() cannot declare status ${conflicts.join(", ")} because a response schema for that status already exists. Use .responses() without .errors() when you need a custom error response body.`);
}
}
/**
* Reject `.responses()` statuses already declared by catalog errors.
*/
export function assertResponsesAvoidCatalogErrorStatuses(metadata, next) {
const errorStatuses = catalogErrorStatuses(metadata);
const conflicts = Object.keys(next).filter((status) => errorStatuses.has(status));
if (conflicts.length) {
throw new Error(`.responses() cannot declare status ${conflicts.join(", ")} because that status is already declared by .errors(). Use .responses() without .errors() when you need a custom error response body.`);
}
}
//# sourceMappingURL=catalog-errors.js.map