@beignet/core
Version:
Core framework primitives for Beignet
76 lines (67 loc) • 2.27 kB
text/typescript
/**
* Internal schema shape helpers shared by server route registration and
* OpenAPI generation.
*
* These helpers are intentionally zod-free: zod is an optional peer
* dependency, so shape extraction duck-types Zod's `_def.shape` internals and
* returns undefined for schemas it cannot introspect. This module is not
* exported from the package index.
*/
/**
* Extract the field shape (field name → field schema) from an object schema.
*
* Returns undefined when the schema is not an introspectable object schema,
* for example a non-Zod Standard Schema.
*/
export function getObjectSchemaShape(
schema: unknown,
): Record<string, unknown> | undefined {
if (!schema || typeof schema !== "object") return undefined;
const schemaDef = (schema as Record<string, unknown>)?._def;
if (!schemaDef || typeof schemaDef !== "object") return undefined;
if (!("shape" in schemaDef)) return undefined;
let shape: unknown;
if (typeof schemaDef.shape === "function") {
shape = schemaDef.shape();
} else if (typeof schemaDef.shape === "object") {
shape = schemaDef.shape;
}
if (!shape || typeof shape !== "object") return undefined;
return shape as Record<string, unknown>;
}
/**
* Compare a path template's dynamic keys against a pathParams schema shape.
*/
export function comparePathParamsToTemplate(args: {
pathKeys: readonly string[];
shapeKeys: readonly string[];
}): { missingKeys: string[]; extraKeys: string[] } {
const missingKeys = args.pathKeys.filter(
(key) => !args.shapeKeys.includes(key),
);
const extraKeys = args.shapeKeys.filter(
(key) => !args.pathKeys.includes(key),
);
return { missingKeys, extraKeys };
}
/**
* Format a pathParams/template mismatch for error messages.
*
* Shared so server registration and OpenAPI generation report the same
* diagnostic details.
*/
export function formatPathParamsMismatch(args: {
missingKeys: readonly string[];
extraKeys: readonly string[];
}): string {
return [
args.missingKeys.length > 0
? `missing pathParams keys: ${args.missingKeys.join(", ")}`
: undefined,
args.extraKeys.length > 0
? `extra pathParams keys: ${args.extraKeys.join(", ")}`
: undefined,
]
.filter(Boolean)
.join("; ");
}