@bernierllc/zod-openapi-converter
v1.2.2
Published
Zod schema to OpenAPI conversion with runtime validation support
Readme
@bernierllc/zod-openapi-converter
Zod schema to OpenAPI conversion with runtime validation support
Installation
npm install @bernierllc/zod-openapi-converterPeer Dependencies
This package requires zod as a peer dependency:
npm install zodUsage
Basic Conversion
import { z } from 'zod';
import { ZodOpenAPIConverter } from '@bernierllc/zod-openapi-converter';
const converter = new ZodOpenAPIConverter();
// Define your Zod schema
const UserSchema = z.object({
id: z.number().int().positive(),
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(0).max(150).optional()
});
// Convert to OpenAPI schema
const openApiSchema = converter.convertToSchema(UserSchema);
console.log(openApiSchema);
/*
{
type: 'object',
properties: {
id: { type: 'integer', minimum: 0, exclusiveMinimum: 0 },
name: { type: 'string', minLength: 1, maxLength: 100 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0, maximum: 150 }
},
required: ['id', 'name', 'email']
}
*/Full Conversion with Components and Examples
import { ZodOpenAPIConverter } from '@bernierllc/zod-openapi-converter';
const converter = new ZodOpenAPIConverter({
includeExamples: true,
preserveZodMeta: true
});
const UserSchema = z.object({
id: z.number().int().positive().describe('Unique user identifier'),
name: z.string().min(1).max(100).describe('User full name'),
email: z.string().email().describe('User email address'),
role: z.enum(['admin', 'user', 'guest']).default('user')
}).describe('User profile information');
// Get complete conversion with metadata
const result = converter.convert(UserSchema);
console.log(result.schema); // OpenAPI schema object
console.log(result.components); // Reusable component definitions
console.log(result.examples); // Generated examples
console.log(result.zodMeta); // Original Zod metadataComplex Schema Types
Discriminated Unions
const ApiResponse = z.discriminatedUnion('status', [
z.object({
status: z.literal('success'),
data: z.object({
id: z.number(),
message: z.string()
})
}),
z.object({
status: z.literal('error'),
error: z.string(),
code: z.number().int()
})
]);
const schema = converter.convertToSchema(ApiResponse);
/*
{
oneOf: [
{
type: 'object',
properties: {
status: { type: 'string', const: 'success' },
data: { type: 'object', properties: {...} }
},
required: ['status', 'data']
},
{
type: 'object',
properties: {
status: { type: 'string', const: 'error' },
error: { type: 'string' },
code: { type: 'integer' }
},
required: ['status', 'error', 'code']
}
],
discriminator: { propertyName: 'status' }
}
*/Arrays and Tuples
// Array with constraints
const TagsSchema = z.array(z.string()).min(1).max(10);
const tagsOpenAPI = converter.convertToSchema(TagsSchema);
// { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 10 }
// Tuple with specific types
const CoordinatesSchema = z.tuple([z.number(), z.number()]);
const coordsOpenAPI = converter.convertToSchema(CoordinatesSchema);
// { type: 'array', prefixItems: [{ type: 'number' }, { type: 'number' }], minItems: 2, maxItems: 2 }Records and Maps
// Record with dynamic keys
const MetadataSchema = z.record(z.string(), z.number());
const metadataOpenAPI = converter.convertToSchema(MetadataSchema);
// { type: 'object', additionalProperties: { type: 'number' } }Runtime Validation
import { ZodValidationIntegrator } from '@bernierllc/zod-openapi-converter';
const integrator = new ZodValidationIntegrator();
// Create a validator
const validator = integrator.createValidator(UserSchema);
const validationResult = validator({
id: 1,
name: 'John Doe',
email: '[email protected]'
});
if (validationResult.success) {
console.log('Valid data:', validationResult.data);
} else {
console.log('Validation errors:', validationResult.errors);
}
// Generate example data
const example = integrator.generateValidationExample(UserSchema);
console.log('Example:', example);
// { id: 42, name: 'example string', email: '[email protected]' }Schema Optimization
import { SchemaOptimizer } from '@bernierllc/zod-openapi-converter';
const optimizer = new SchemaOptimizer();
// Optimize a schema
const schema = {
type: 'object',
properties: { name: { type: 'string' } },
required: [] // Empty required array
};
const optimized = optimizer.optimizeSchema(schema);
// required field is removed
// Simplify unions
const unionSchema = {
anyOf: [{ type: 'string' }, { type: 'number' }, { type: 'string' }]
};
const simplified = optimizer.simplifyUnions(unionSchema);
// Duplicates removed: { anyOf: [{ type: 'string' }, { type: 'number' }] }API Reference
ZodOpenAPIConverter
Main converter class for transforming Zod schemas to OpenAPI format.
Constructor Options
interface ZodOpenAPIConverterOptions {
strictMode?: boolean; // Strict OpenAPI compliance (default: true)
includeExamples?: boolean; // Generate examples from defaults (default: true)
preserveZodMeta?: boolean; // Keep Zod metadata in extensions (default: false)
customTransforms?: ZodTransformMap; // Custom schema transformations
componentPrefix?: string; // Prefix for component names (default: '')
deduplicateComponents?: boolean; // Deduplicate identical components (default: true)
}Methods
convert(zodSchema)- Complete conversion with components and metadataconvertToSchema(zodSchema)- Convert to OpenAPI schema onlyconvertWithComponents(zodSchema)- Convert with component extractionconvertObject(schema)- Convert ZodObjectconvertArray(schema)- Convert ZodArrayconvertUnion(schema)- Convert ZodUnionconvertEnum(schema)- Convert ZodEnumextractValidationRules(schema)- Extract validation constraints
ZodValidationIntegrator
Runtime validation integration with Zod schemas.
Methods
validateRequest(schema, data)- Validate data against schemacreateValidator(schema)- Create reusable validator functioncreateValidationMiddleware(schema)- Create middleware functiongenerateValidationExample(schema)- Generate example datacreateAsyncValidator(schema)- Create async validator
SchemaOptimizer
Schema optimization utilities for cleaner OpenAPI output.
Methods
optimizeSchema(schema)- Remove redundant propertiesdeduplicateSchemas(schemas)- Remove duplicate schemasextractCommonPatterns(schemas)- Find reusable patternssimplifyUnions(schema)- Simplify union typesmergeAllOf(schema)- Merge compatible allOf schemas
Supported Zod Types
- ✅ Primitives: string, number, boolean, date, bigint
- ✅ Special: null, undefined, any, unknown, never, void
- ✅ Objects: object, record, map
- ✅ Arrays: array, tuple, set
- ✅ Unions: union, discriminated union, intersection
- ✅ Enums: enum, native enum, literal
- ✅ Modifiers: optional, nullable, default
- ✅ Effects: refinements, transforms (with metadata preservation)
- ✅ Advanced: lazy, promise, branded, pipeline
String Validation Support
All Zod string validations are converted to appropriate OpenAPI constraints:
min/max→minLength/maxLengthlength→minLengthandmaxLengthemail→format: 'email'url→format: 'uri'uuid→format: 'uuid'regex→patternstartsWith/endsWith/includes→pattern
Number Validation Support
min/max→minimum/maximumorexclusiveMinimum/exclusiveMaximumint→type: 'integer'positive/negative→ appropriate min/max constraintsmultipleOf→multipleOf
Integration Status
- Logger integration: not-applicable - Pure schema conversion utility with no runtime logging requirements. Operations are synchronous transformations without side effects requiring observation. No @bernierllc/logger dependency needed.
- Docs-Suite: ready - Complete API documentation with TypeDoc comments and comprehensive usage examples in markdown format.
- NeverHub integration: not-applicable - Core utility package focused on schema transformation. No service discovery, event bus, or dynamic configuration needs. Designed as a pure functional library for build-time and runtime schema conversion. No @bernierllc/neverhub-adapter dependency needed.
See Also
- @bernierllc/openapi-schema-builder - OpenAPI schema construction utilities
- Zod Documentation - Zod schema validation library
License
Copyright (c) 2025 Bernier LLC. All rights reserved.
This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
