Schema Utility
Helper functions and predefined schemas for working with zod and @hono/zod-openapi - building JSON request/response schemas, path-param schemas, and case-converting schemas for API routes.
In one example
import { jsonResponse, requiredString, idParamsSchema } from '@venizia/ignis';
import { z } from '@hono/zod-openapi';
const UserSchema = z.object({ id: z.number(), name: requiredString({ min: 1, max: 50 }) });
this.defineRoute({
configs: {
path: '/{id}',
method: 'get',
request: { params: idParamsSchema({ idType: 'number' }) },
responses: jsonResponse({ schema: UserSchema, description: 'A single user object' }),
},
handler: (context) => {
const { id } = context.req.valid('param');
// ...
},
});Functions
| Function | Signature | What it does |
|---|---|---|
jsonContent | jsonContent(opts: { schema: ZodType; description: string; required?: boolean }): { description; content; required } | Builds a standard OpenAPI content object for an application/json payload. |
jsonResponse | jsonResponse(opts: { schema: ZodType; description?: string; required?: boolean; headers?: Record<string, THeaderObject> }): Record<number | string, ...> | Builds a full response map: 200 success (via jsonContent, description defaults to 'Success Response') plus the 4XX and 5XX entries of errorResponses(). |
errorResponses | errorResponses(): { '4XX': ...; '5XX': ... } | The JSON error body under 4XX and 5XX, both jsonContent({ description: 'Error Response', schema: ErrorSchema }). Spread it into a route whose success body is not JSON. |
requiredString | requiredString(opts?: { min?: number; max?: number; fixed?: number }): ZodString | A non-empty (.nonempty()) Zod string, optionally constrained by min, max, or an exact fixed length. |
idParamsSchema | idParamsSchema(opts?: { idType: TIdSchemaType }): ZodObject | Builds a path-param schema for { id }, typed and OpenAPI-documented as number or string. TIdSchemaType is 'number' | 'string'. Throws on any other value. The whole opts object is optional and defaults to number, but once you pass it, idType is required. |
snakeToCamel | snakeToCamel<T extends ZodRawShape>(shape: T): ZodPipe | Wraps a Zod object shape so it accepts snake_case input keys and produces a camelCase-keyed output: z.object(shape).transform(keysToCamel).pipe(z.object(camelShape)). |
Predefined schemas and types
| Export | What it is |
|---|---|
AnyObjectSchema | z.object().catchall(z.any()), OpenAPI-described as 'Unknown schema' - a permissive object schema. |
TAnyObjectSchema | Type alias for z.ZodObject<z.ZodRawShape>. |
TInferSchema<T> | Type alias for z.infer<T> - the TypeScript type inferred from a Zod schema T. |
Notes
Three source files, one page.
requiredString,AnyObjectSchema,TAnyObjectSchema, andTInferSchemalive inbase/controllers/common/schema-builders.ts(they callz.object()at module load, so they sit with the REST surface rather than in the zod-freeutilities/barrel);jsonContent,jsonResponse, andidParamsSchemalive inbase/models/common/schemas.ts;snakeToCamellives inbase/models/common/utilities.ts. All three are re-exported from the@venizia/ignisroot barrel, so the import path is the same either way.jsonResponse's error branch is fixed - it always usesErrorSchemaunder the4XXand5XXkeys (the only range keys OpenAPI accepts, so client generators type the error body); only the success schema, description, and headers are customizable per call.ErrorSchemais the named componentErrorResponse. Every route's4XXand5XXreference#/components/schemas/ErrorResponse, so a generated client types the error ascomponents['schemas']['ErrorResponse']. A schema that extendsErrorSchemais documented asallOfthat reference plus its own fields. Only one schema can own the name, so rename a component of your own calledErrorResponse.A route with a non-JSON success body (a file stream, an image) spreads
errorResponses()beside its own200:typescriptresponses: { [HTTP.ResultCodes.RS_2.Ok]: { description: 'PNG frame', content: { 'image/png': { schema: { type: 'string', format: 'binary' } } }, }, ...errorResponses(), },The workspace is on Zod v4.
snakeToCamelreturns aZodPipe; there is noZodEffectsto hold, that class belonged to v3.TInferSchema<T>constrainsTtoz.ZodType. The full declaration isTInferSchema<T extends z.ZodType> = z.infer<T>.HTML responses are a separate utility. For
text/htmlroutes, usehtmlContent/htmlResponsefrom the JSX Utility instead ofjsonContent/jsonResponse.
See also
- Utilities Overview - all utility functions
- JSX Utility -
htmlContent()/htmlResponse()for HTML routes - Parse Utility -
toCamel()/keysToCamel(), the transformssnakeToCamelbuilds on - REST Controllers Guide - defining routes with
request/responses
Files: