@alt-stack/zod-openapi 1.0.3 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/dependencies.ts","../src/types/boolean.ts","../src/types/number.ts","../src/registry.ts","../src/types/string.ts","../src/types/array.ts","../src/types/object.ts","../src/types/union.ts","../src/types/intersection.ts","../src/to-zod.ts","../src/routes.ts","../src/to-typescript.ts"],"sourcesContent":["export { openApiToZodTsCode } from \"./to-typescript.js\";\nexport {\n registerZodSchemaToOpenApiSchema,\n clearZodSchemaToOpenApiSchemaRegistry,\n getSchemaExportedVariableNameForStringFormat,\n SUPPORTED_STRING_FORMATS,\n schemaRegistry,\n} from \"./registry.js\";\nexport type {\n ZodOpenApiRegistrationString,\n ZodOpenApiRegistrationStrings,\n ZodOpenApiRegistrationPrimitive,\n ZodOpenApiRegistration,\n} from \"./registry.js\";\nexport { convertSchemaToZodString } from \"./to-zod.js\";\nexport {\n parseOpenApiPaths,\n generateRouteSchemaNames,\n} from \"./routes.js\";\nexport type {\n HttpMethod,\n RouteParameter,\n RouteInfo,\n RouteSchemaNames,\n} from \"./routes.js\";\nexport type { AnySchema, OpenAPIObjectSchema } from \"./types/types.js\";\n\n","import type { AnySchema } from \"./types/types\";\n\n/**\n * Extracts all schema references ($ref) from an OpenAPI schema by recursively\n * traversing its structure.\n *\n * This function is used during the OpenAPI-to-Zod conversion process to identify\n * which schemas a given schema depends on. It traverses all OpenAPI schema\n * structures including objects, arrays, unions (oneOf), intersections (allOf),\n * conditionals (if/then/else), and discriminator mappings to find all $ref\n * references that point to other schemas in the components/schemas section.\n *\n * The extracted dependency names are used by `topologicalSortSchemas` to build\n * a dependency graph and determine the correct order for generating Zod schemas,\n * ensuring that referenced schemas are defined before they are used in the\n * generated TypeScript code.\n *\n * @param schema - The OpenAPI schema to extract dependencies from\n * @returns An array of schema names that this schema references (via $ref)\n */\nexport function extractSchemaDependencies(schema: AnySchema): string[] {\n const dependencies: Set<string> = new Set();\n const visited = new WeakSet();\n\n function traverse(obj: any): void {\n if (!obj || typeof obj !== \"object\") return;\n\n if (visited.has(obj)) return;\n visited.add(obj);\n\n if (obj[\"$ref\"] && typeof obj[\"$ref\"] === \"string\") {\n const match = (obj[\"$ref\"] as string).match(\n /#\\/components\\/schemas\\/(.+)/,\n );\n if (match && match[1]) {\n dependencies.add(decodeURIComponent(match[1]));\n }\n return;\n }\n\n if (Array.isArray(obj)) {\n obj.forEach(traverse);\n return;\n }\n\n if (obj.properties && typeof obj.properties === \"object\") {\n for (const propValue of Object.values(obj.properties)) {\n traverse(propValue);\n }\n }\n\n const schemaKeys = [\n \"items\",\n \"oneOf\",\n \"allOf\",\n \"anyOf\",\n \"not\",\n \"if\",\n \"then\",\n \"else\",\n \"prefixItems\",\n \"contains\",\n \"propertyNames\",\n \"dependentSchemas\",\n ];\n\n for (const key of schemaKeys) {\n if (obj[key]) {\n traverse(obj[key]);\n }\n }\n\n if (\n obj.additionalProperties &&\n typeof obj.additionalProperties === \"object\"\n ) {\n traverse(obj.additionalProperties);\n }\n\n if (obj.discriminator?.mapping) {\n Object.values(obj.discriminator.mapping).forEach(traverse);\n }\n }\n\n traverse(schema);\n return Array.from(dependencies);\n}\n\n/**\n * Sorts OpenAPI schemas topologically based on their dependencies to ensure\n * correct generation order.\n *\n * When converting OpenAPI schemas to Zod schemas and generating TypeScript code,\n * schemas must be defined before they are referenced. For example, if `UserSchema`\n * references `ProfileSchema` (via $ref), then `ProfileSchema` must be generated\n * before `UserSchema` to avoid \"undefined variable\" errors in the generated code.\n *\n * This function uses Kahn's algorithm for topological sorting to order schemas\n * such that all dependencies come before their dependents. It:\n * 1. Extracts dependencies for each schema using `extractSchemaDependencies`\n * 2. Builds a dependency graph and computes in-degrees\n * 3. Sorts schemas starting with those that have no dependencies (in-degree 0)\n * 4. Handles circular dependencies gracefully by appending any remaining schemas\n * that couldn't be sorted (though this indicates a problematic schema structure)\n *\n * This function is called by `openApiToZodTsCode` to determine the order in which\n * schemas should be converted and emitted in the generated TypeScript file.\n *\n * @param schemas - A record mapping schema names to their OpenAPI schema definitions\n * @returns An array of schema names sorted in topological order (dependencies before dependents)\n */\nexport function topologicalSortSchemas(\n schemas: Record<string, AnySchema>,\n): string[] {\n const schemaNames = Object.keys(schemas);\n const dependencies: Map<string, string[]> = new Map();\n const inDegree: Map<string, number> = new Map();\n const sorted: string[] = [];\n const queue: string[] = [];\n const dependents: Map<string, string[]> = new Map();\n\n for (const name of schemaNames) {\n dependencies.set(name, []);\n dependents.set(name, []);\n inDegree.set(name, 0);\n }\n\n for (const name of schemaNames) {\n const schemaValue = schemas[name];\n if (schemaValue) {\n const deps = extractSchemaDependencies(schemaValue);\n const validDeps = deps.filter((dep) => schemaNames.includes(dep));\n dependencies.set(name, validDeps);\n\n for (const dep of validDeps) {\n const currentDependents = dependents.get(dep) || [];\n currentDependents.push(name);\n dependents.set(dep, currentDependents);\n }\n }\n }\n\n for (const [name, deps] of dependencies.entries()) {\n inDegree.set(name, deps.length);\n }\n\n for (const [name, degree] of inDegree.entries()) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n sorted.push(current);\n\n const currentDependents = dependents.get(current) || [];\n for (const dependent of currentDependents) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n if (sorted.length !== schemaNames.length) {\n for (const name of schemaNames) {\n if (!sorted.includes(name)) {\n sorted.push(name);\n }\n }\n }\n\n return sorted;\n}\n","/**\n * Convert an OpenAPI v3 boolean schema to a Zod schema string\n */\nexport function convertOpenAPIBooleanToZod(_: { type: \"boolean\" }): string {\n return \"z.boolean()\";\n}\n","/**\n * Convert an OpenAPI v3 number/integer schema to a Zod schema string\n */\nexport function convertOpenAPINumberToZod(schema: {\n type: \"number\" | \"integer\";\n minimum?: number;\n maximum?: number;\n}): string {\n let result = \"z.number()\";\n if (schema.type === \"integer\") {\n result += \".int()\";\n }\n if (typeof schema.minimum === \"number\") {\n result += `.min(${schema.minimum})`;\n }\n if (typeof schema.maximum === \"number\") {\n result += `.max(${schema.maximum})`;\n }\n return result;\n}\n","import { z } from \"zod\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst SUPPORTED_STRING_FORMATS_MAP = {\n \"color-hex\": 1,\n date: 1,\n \"date-time\": 1,\n email: 1,\n \"iso-date\": 1,\n \"iso-date-time\": 1,\n objectid: 1,\n uri: 1,\n url: 1,\n uuid: 1,\n} as const;\n\nexport const SUPPORTED_STRING_FORMATS = Object.keys(\n SUPPORTED_STRING_FORMATS_MAP,\n) as unknown as keyof typeof SUPPORTED_STRING_FORMATS_MAP;\n\ntype SupportedStringFormat = typeof SUPPORTED_STRING_FORMATS;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ZodOpenApiRegistrationString<\n F extends SupportedStringFormat = SupportedStringFormat,\n> = {\n /** The name of the schema variable, IMPORTANT: must be named the same as the variable name */\n schemaExportedVariableName: string;\n type: \"string\";\n description?: string;\n format: F;\n};\n\nexport type ZodOpenApiRegistrationStrings<\n Fs extends\n readonly SupportedStringFormat[] = readonly SupportedStringFormat[],\n> = {\n /** The name of the schema variable, IMPORTANT: must be named the same as the variable name */\n schemaExportedVariableName: string;\n type: \"string\";\n description?: string;\n formats: Fs;\n};\n\nexport type ZodOpenApiRegistrationPrimitive = {\n /** The name of the schema variable, IMPORTANT: must be named the same as the variable name */\n schemaExportedVariableName: string;\n description?: string;\n type: \"number\" | \"integer\" | \"boolean\";\n};\n\nexport type ZodOpenApiRegistration =\n | ZodOpenApiRegistrationString\n | ZodOpenApiRegistrationStrings\n | ZodOpenApiRegistrationPrimitive;\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\nfunction isStringRegistration(\n reg: ZodOpenApiRegistration,\n): reg is ZodOpenApiRegistrationString {\n return reg.type === \"string\" && \"format\" in reg;\n}\n\nfunction isStringsRegistration(\n reg: ZodOpenApiRegistration,\n): reg is ZodOpenApiRegistrationStrings {\n return reg.type === \"string\" && \"formats\" in reg;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\ntype TypeFormatPair = { type: string; format: string | undefined };\n\nfunction getTypeFormatPairs(reg: ZodOpenApiRegistration): TypeFormatPair[] {\n if (isStringRegistration(reg)) {\n return [{ type: \"string\", format: reg.format }];\n }\n\n if (isStringsRegistration(reg)) {\n return reg.formats.map((f) => ({ type: \"string\", format: f }));\n }\n\n return [];\n}\n\n// ============================================================================\n// Registry Class\n// ============================================================================\n\n/**\n * Global registry for mapping Zod schemas to OpenAPI schema representations\n */\nclass ZodSchemaRegistry {\n private readonly map = new Map<z.ZodTypeAny, ZodOpenApiRegistration>();\n\n /**\n * Register a Zod schema with its OpenAPI representation\n */\n register<F extends SupportedStringFormat>(\n schema: z.ZodTypeAny,\n registration: ZodOpenApiRegistrationString<F>,\n ): void;\n register<Fs extends readonly SupportedStringFormat[]>(\n schema: z.ZodTypeAny,\n registration: ZodOpenApiRegistrationStrings<Fs>,\n ): void;\n register(\n schema: z.ZodTypeAny,\n registration: ZodOpenApiRegistrationPrimitive,\n ): void;\n register(schema: z.ZodTypeAny, registration: ZodOpenApiRegistration): void {\n const newPairs = getTypeFormatPairs(registration);\n\n if (newPairs.length > 0) {\n for (const [existingSchema, existingRegistration] of this.map.entries()) {\n if (existingSchema === schema) continue;\n\n const existingPairs = getTypeFormatPairs(existingRegistration);\n for (const { type, format } of newPairs) {\n if (\n existingPairs.some((p) => p.type === type && p.format === format)\n ) {\n throw new Error(\n `duplicate Zod OpenAPI registration for (type, format)=('${type}', '${format as string}')`,\n );\n }\n }\n }\n }\n\n this.map.set(schema, registration);\n }\n\n /**\n * Get the OpenAPI schema for a given Zod schema\n */\n getOpenApiSchema(schema: z.ZodTypeAny): ZodOpenApiRegistration | undefined {\n return this.map.get(schema);\n }\n\n /**\n * Check if a Zod schema is registered\n */\n isRegistered(schema: z.ZodTypeAny): boolean {\n return this.map.has(schema);\n }\n\n /**\n * Clear all registered schemas\n */\n clear(): void {\n this.map.clear();\n }\n\n /**\n * Reverse-lookup helper: given a string format, return the registered schema's exported variable name\n */\n getSchemaExportedVariableNameForStringFormat(\n format: SupportedStringFormat,\n ): string | undefined {\n for (const registration of this.map.values()) {\n if (registration.type !== \"string\") continue;\n\n if (\n isStringRegistration(registration) &&\n registration.format === format\n ) {\n return registration.schemaExportedVariableName;\n }\n\n if (\n isStringsRegistration(registration) &&\n registration.formats.includes(format)\n ) {\n return registration.schemaExportedVariableName;\n }\n }\n return undefined;\n }\n}\n\n// ============================================================================\n// Global Registry Instance\n// ============================================================================\n\nexport const schemaRegistry = new ZodSchemaRegistry();\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Helper function to register a Zod schema with its OpenAPI representation\n */\nexport function registerZodSchemaToOpenApiSchema(\n schema: z.ZodTypeAny,\n openApiSchema: ZodOpenApiRegistration,\n): void {\n schemaRegistry.register(schema, openApiSchema as any);\n}\n\n/**\n * Convenience helper to get an exported schema variable name for a given string format\n */\nexport function getSchemaExportedVariableNameForStringFormat(\n format: SupportedStringFormat,\n): string | undefined {\n return schemaRegistry.getSchemaExportedVariableNameForStringFormat(format);\n}\n\n/**\n * Clear all registered schemas in the global registry\n */\nexport function clearZodSchemaToOpenApiSchemaRegistry(): void {\n schemaRegistry.clear();\n}\n","import {\n getSchemaExportedVariableNameForStringFormat,\n SUPPORTED_STRING_FORMATS,\n} from \"../registry\";\n\n/**\n * Convert an OpenAPI v3 string schema to a Zod schema string\n */\nexport function convertOpenAPIStringToZod(schema: {\n type: \"string\";\n format?: typeof SUPPORTED_STRING_FORMATS;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n enum?: string[];\n}): string {\n // Handle enum values\n if (schema.enum) {\n return `z.enum([${schema.enum.map((value) => `'${value}'`).join(\", \")}])`;\n }\n\n // Check for custom registered format schemas\n if (schema.format && SUPPORTED_STRING_FORMATS.includes(schema.format)) {\n const customSchemaName = getSchemaExportedVariableNameForStringFormat(\n schema.format,\n );\n\n // Use custom schema if registered (ignores other constraints)\n if (customSchemaName) {\n return customSchemaName;\n }\n }\n\n // Build string schema with format modifiers\n let zodSchema = \"z.string()\";\n\n if (schema.format) {\n zodSchema += getFormatModifier(schema.format);\n }\n\n // Apply length constraints\n if (typeof schema.minLength === \"number\") {\n zodSchema += `.min(${schema.minLength})`;\n }\n\n if (typeof schema.maxLength === \"number\") {\n zodSchema += `.max(${schema.maxLength})`;\n }\n\n // Apply pattern constraint\n if (typeof schema.pattern === \"string\") {\n zodSchema += `.regex(/${schema.pattern}/)`;\n }\n\n return zodSchema;\n}\n\n/**\n * Get the Zod modifier for built-in string formats\n */\nfunction getFormatModifier(format: string): string {\n switch (format) {\n case \"email\":\n return \".email()\";\n case \"url\":\n case \"uri\":\n return \".url()\";\n case \"uuid\":\n return \".uuid()\";\n case \"color-hex\":\n return \".regex(/^[a-fA-F0-9]{6}$/)\";\n default:\n return \"\";\n }\n}\n","import type { AnySchema } from \"./types\";\n\nexport function convertOpenAPIArrayToZod(\n schema: {\n type: \"array\";\n items?: any;\n minItems?: number;\n maxItems?: number;\n },\n convertSchema: (schema: AnySchema) => string,\n): string {\n const item = schema.items;\n\n let itemZodString = \"z.unknown()\";\n if (item && typeof item === \"object\") {\n itemZodString = convertSchema(item);\n }\n\n let result = `z.array(${itemZodString})`;\n\n if (typeof schema.minItems === \"number\") {\n result += `.min(${schema.minItems})`;\n }\n if (typeof schema.maxItems === \"number\") {\n result += `.max(${schema.maxItems})`;\n }\n\n return result;\n}\n","import { AnySchema, OpenAPIObjectSchema } from \"./types\";\n\nexport function convertOpenAPIObjectToZod(\n schema: OpenAPIObjectSchema,\n convertSchema: (schema: AnySchema) => string,\n): string {\n const properties = schema.properties || {};\n const propertyNames = Object.keys(properties);\n\n if (propertyNames.length === 0) {\n if (schema.additionalProperties === false) {\n return \"z.object({}).strict()\";\n }\n return \"z.record(z.string(), z.unknown())\";\n }\n\n const requiredSet = new Set(schema.required || []);\n\n const entries: string[] = [];\n for (const [propName, propSchema] of Object.entries(properties)) {\n let zodProp = \"z.unknown()\";\n\n if (propSchema && typeof propSchema === \"object\") {\n zodProp = convertSchema(propSchema);\n }\n\n if (!requiredSet.has(propName)) {\n zodProp += \".optional()\";\n }\n\n entries.push(`${propName}: ${zodProp}`);\n }\n\n let result = `z.object({ ${entries.join(\", \")} })`;\n\n if (schema.additionalProperties === false) {\n result += \".strict()\";\n }\n\n return result;\n}\n","import type { AnySchema } from \"./types\";\n\nexport function convertOpenAPIUnionToZod(\n schema: { oneOf: AnySchema[] },\n convertSchema: (schema: AnySchema) => string,\n): string {\n const items = schema.oneOf.map((item) => convertSchema(item));\n return `z.union([${items.join(\", \")}])`;\n}\n\n","import type { AnySchema } from \"./types\";\n\nexport function convertOpenAPIIntersectionToZod(\n schema: { allOf: AnySchema[] },\n convertSchema: (schema: AnySchema) => string,\n): string {\n const items = schema.allOf.map((item) => convertSchema(item));\n\n if (schema.allOf.length === 0) return \"z.unknown()\";\n if (schema.allOf.length === 1) return convertSchema(schema.allOf[0]!);\n\n return `z.intersection(${items.join(\", \")})`;\n}\n\n","import { convertOpenAPIBooleanToZod } from \"./types/boolean\";\nimport { convertOpenAPINumberToZod } from \"./types/number\";\nimport { convertOpenAPIStringToZod } from \"./types/string\";\nimport { convertOpenAPIArrayToZod } from \"./types/array\";\nimport { convertOpenAPIObjectToZod } from \"./types/object\";\nimport { convertOpenAPIUnionToZod } from \"./types/union\";\nimport { convertOpenAPIIntersectionToZod } from \"./types/intersection\";\nimport type { AnySchema } from \"./types/types\";\n\nexport function convertSchemaToZodString(schema: AnySchema): string {\n if (!schema || typeof schema !== \"object\") return \"z.unknown()\";\n\n if (schema[\"$ref\"] && typeof schema[\"$ref\"] === \"string\") {\n const match = (schema[\"$ref\"] as string).match(\n /#\\/components\\/schemas\\/(.+)/,\n );\n let result = \"z.unknown()\";\n if (match && match[1]) {\n result = `${match[1]}Schema`;\n }\n if (schema[\"nullable\"] === true) {\n result = `z.union([${result}, z.null()])`;\n }\n return result;\n }\n let result: string = \"z.unknown()\";\n\n if (\"oneOf\" in schema && Array.isArray(schema[\"oneOf\"])) {\n result = convertOpenAPIUnionToZod(\n schema as { oneOf: AnySchema[] },\n convertSchemaToZodString,\n );\n } else if (\"allOf\" in schema && Array.isArray(schema[\"allOf\"])) {\n result = convertOpenAPIIntersectionToZod(\n schema as { allOf: AnySchema[] },\n convertSchemaToZodString,\n );\n } else {\n switch (schema[\"type\"]) {\n case \"string\":\n result = convertOpenAPIStringToZod({\n enum: schema[\"enum\"],\n format: schema[\"format\"],\n maxLength: schema[\"maxLength\"],\n minLength: schema[\"minLength\"],\n pattern: schema[\"pattern\"],\n type: \"string\",\n });\n break;\n case \"number\":\n result = convertOpenAPINumberToZod({\n maximum: schema[\"maximum\"],\n minimum: schema[\"minimum\"],\n type: \"number\",\n });\n break;\n case \"integer\":\n result = convertOpenAPINumberToZod({\n maximum: schema[\"maximum\"],\n minimum: schema[\"minimum\"],\n type: \"integer\",\n });\n break;\n case \"boolean\":\n result = convertOpenAPIBooleanToZod({ type: \"boolean\" });\n break;\n case \"array\":\n result = convertOpenAPIArrayToZod(\n {\n items: schema[\"items\"],\n maxItems: schema[\"maxItems\"],\n minItems: schema[\"minItems\"],\n type: \"array\",\n },\n convertSchemaToZodString,\n );\n break;\n case \"object\":\n result = convertOpenAPIObjectToZod(\n {\n additionalProperties: schema[\"additionalProperties\"],\n properties: schema[\"properties\"],\n required: schema[\"required\"],\n type: \"object\",\n },\n convertSchemaToZodString,\n );\n break;\n default:\n if (schema[\"properties\"]) {\n result = convertOpenAPIObjectToZod(\n {\n additionalProperties: schema[\"additionalProperties\"],\n properties: schema[\"properties\"],\n required: schema[\"required\"],\n type: \"object\",\n },\n convertSchemaToZodString,\n );\n } else {\n result = \"z.unknown()\";\n }\n break;\n }\n }\n\n if (schema[\"nullable\"] === true) {\n result = `z.union([${result}, z.null()])`;\n }\n\n return result;\n}\n","import type { AnySchema } from \"./types/types\";\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\" | \"HEAD\" | \"OPTIONS\";\n\nexport interface RouteParameter {\n name: string;\n in: \"path\" | \"query\" | \"header\" | \"cookie\";\n required: boolean;\n schema: AnySchema;\n}\n\nexport interface RouteInfo {\n path: string;\n method: HttpMethod;\n parameters: RouteParameter[];\n requestBody?: AnySchema;\n responses: Record<string, AnySchema>;\n}\n\nexport interface RouteSchemaNames {\n paramsSchemaName?: string;\n querySchemaName?: string;\n headersSchemaName?: string;\n bodySchemaName?: string;\n responseSchemaName?: string;\n}\n\nfunction toUpperCaseMethod(method: string): HttpMethod {\n const upper = method.toUpperCase();\n if (\n upper === \"GET\" ||\n upper === \"POST\" ||\n upper === \"PUT\" ||\n upper === \"PATCH\" ||\n upper === \"DELETE\" ||\n upper === \"HEAD\" ||\n upper === \"OPTIONS\"\n ) {\n return upper as HttpMethod;\n }\n return \"GET\";\n}\n\nfunction toPascalCase(str: string): string {\n return str\n .replace(/[^a-zA-Z0-9]/g, \" \")\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\nfunction generateRouteSchemaName(\n path: string,\n method: HttpMethod,\n suffix: string,\n): string {\n const pathParts = path\n .split(\"/\")\n .filter((p) => p)\n .map((p) => {\n if (p.startsWith(\"{\") && p.endsWith(\"}\")) {\n return p.slice(1, -1);\n }\n return p;\n })\n .map(toPascalCase);\n const methodPrefix = method.charAt(0) + method.slice(1).toLowerCase();\n const parts = [methodPrefix, ...pathParts, suffix];\n return parts.join(\"\");\n}\n\nexport function parseOpenApiPaths(\n openapi: Record<string, unknown>,\n): RouteInfo[] {\n const paths = (openapi as AnySchema)[\"paths\"] as\n | Record<string, AnySchema>\n | undefined;\n if (!paths) {\n return [];\n }\n\n const routes: RouteInfo[] = [];\n\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!pathItem || typeof pathItem !== \"object\") continue;\n\n const methods = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"head\",\n \"options\",\n ] as const;\n\n for (const method of methods) {\n const operation = pathItem[method] as AnySchema | undefined;\n if (!operation) continue;\n\n const parameters: RouteParameter[] = [];\n const responses: Record<string, AnySchema> = {};\n\n if (Array.isArray(pathItem[\"parameters\"])) {\n for (const param of pathItem[\"parameters\"]) {\n if (param && typeof param === \"object\") {\n parameters.push({\n name: String(param[\"name\"] || \"\"),\n in: param[\"in\"] || \"query\",\n required: Boolean(param[\"required\"]),\n schema: param[\"schema\"] || {},\n });\n }\n }\n }\n\n if (Array.isArray(operation[\"parameters\"])) {\n for (const param of operation[\"parameters\"]) {\n if (param && typeof param === \"object\") {\n parameters.push({\n name: String(param[\"name\"] || \"\"),\n in: param[\"in\"] || \"query\",\n required: Boolean(param[\"required\"]),\n schema: param[\"schema\"] || {},\n });\n }\n }\n }\n\n let requestBody: AnySchema | undefined;\n if (operation[\"requestBody\"]) {\n const rb = operation[\"requestBody\"];\n if (rb && typeof rb === \"object\") {\n const content = rb[\"content\"];\n if (content && typeof content === \"object\") {\n const jsonContent = content[\"application/json\"];\n if (jsonContent && typeof jsonContent === \"object\") {\n requestBody = jsonContent[\"schema\"] || {};\n }\n }\n }\n }\n\n if (operation[\"responses\"] && typeof operation[\"responses\"] === \"object\") {\n for (const [statusCode, response] of Object.entries(\n operation[\"responses\"],\n )) {\n if (response && typeof response === \"object\") {\n const responseSchema = response as AnySchema;\n const content = responseSchema[\"content\"];\n if (content && typeof content === \"object\") {\n const jsonContent = content[\"application/json\"];\n if (jsonContent && typeof jsonContent === \"object\") {\n const schema = jsonContent[\"schema\"];\n if (schema) {\n responses[statusCode] = schema;\n }\n }\n }\n }\n }\n }\n\n routes.push({\n path,\n method: toUpperCaseMethod(method),\n parameters,\n requestBody,\n responses,\n });\n }\n }\n\n return routes;\n}\n\nexport function generateRouteSchemaNames(\n route: RouteInfo,\n): RouteSchemaNames {\n const pathParams = route.parameters.filter((p) => p.in === \"path\");\n const queryParams = route.parameters.filter((p) => p.in === \"query\");\n const headerParams = route.parameters.filter((p) => p.in === \"header\");\n const successStatuses = Object.keys(route.responses).filter((s) =>\n s.startsWith(\"2\"),\n );\n\n const result: RouteSchemaNames = {\n responseSchemaName: successStatuses.length > 0\n ? generateRouteSchemaName(\n route.path,\n route.method,\n \"Response\",\n )\n : undefined,\n };\n\n if (pathParams.length > 0) {\n result.paramsSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Params\",\n );\n }\n\n if (queryParams.length > 0) {\n result.querySchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Query\",\n );\n }\n\n if (headerParams.length > 0) {\n result.headersSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Headers\",\n );\n }\n\n if (route.requestBody) {\n result.bodySchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Body\",\n );\n }\n\n return result;\n}\n\n","import { topologicalSortSchemas } from \"./dependencies\";\nimport { convertSchemaToZodString } from \"./to-zod\";\nimport type { AnySchema } from \"./types/types\";\nimport {\n parseOpenApiPaths,\n generateRouteSchemaNames,\n type RouteInfo,\n} from \"./routes\";\n\nfunction generateRouteSchemaName(\n path: string,\n method: string,\n suffix: string,\n): string {\n const pathParts = path\n .split(\"/\")\n .filter((p) => p)\n .map((p) => {\n if (p.startsWith(\"{\") && p.endsWith(\"}\")) {\n return p.slice(1, -1);\n }\n return p;\n })\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());\n const methodPrefix = method.charAt(0) + method.slice(1).toLowerCase();\n const parts = [methodPrefix, ...pathParts, suffix];\n return parts.join(\"\");\n}\n\nfunction generateRouteSchemas(\n routes: RouteInfo[],\n convertSchema: (schema: AnySchema) => string,\n): string[] {\n const lines: string[] = [];\n const schemaNames = new Set<string>();\n\n for (const route of routes) {\n const names = generateRouteSchemaNames(route);\n const pathParams = route.parameters.filter((p) => p.in === \"path\");\n const queryParams = route.parameters.filter((p) => p.in === \"query\");\n const headerParams = route.parameters.filter((p) => p.in === \"header\");\n\n if (names.paramsSchemaName && pathParams.length > 0) {\n if (!schemaNames.has(names.paramsSchemaName)) {\n schemaNames.add(names.paramsSchemaName);\n const properties: string[] = [];\n const required: string[] = [];\n for (const param of pathParams) {\n const zodExpr = convertSchema(param.schema);\n properties.push(`${param.name}: ${zodExpr}`);\n if (param.required) {\n required.push(param.name);\n }\n }\n lines.push(\n `export const ${names.paramsSchemaName} = z.object({ ${properties.join(\", \")} });`,\n );\n }\n }\n\n if (names.querySchemaName && queryParams.length > 0) {\n if (!schemaNames.has(names.querySchemaName)) {\n schemaNames.add(names.querySchemaName);\n const properties: string[] = [];\n for (const param of queryParams) {\n let zodExpr = convertSchema(param.schema);\n if (!param.required) {\n zodExpr += \".optional()\";\n }\n properties.push(`${param.name}: ${zodExpr}`);\n }\n lines.push(\n `export const ${names.querySchemaName} = z.object({ ${properties.join(\", \")} });`,\n );\n }\n }\n\n if (names.headersSchemaName && headerParams.length > 0) {\n if (!schemaNames.has(names.headersSchemaName)) {\n schemaNames.add(names.headersSchemaName);\n const properties: string[] = [];\n for (const param of headerParams) {\n let zodExpr = convertSchema(param.schema);\n if (!param.required) {\n zodExpr += \".optional()\";\n }\n properties.push(`${param.name}: ${zodExpr}`);\n }\n lines.push(\n `export const ${names.headersSchemaName} = z.object({ ${properties.join(\", \")} });`,\n );\n }\n }\n\n if (names.bodySchemaName && route.requestBody) {\n if (!schemaNames.has(names.bodySchemaName)) {\n schemaNames.add(names.bodySchemaName);\n const zodExpr = convertSchema(route.requestBody);\n lines.push(`export const ${names.bodySchemaName} = ${zodExpr};`);\n }\n }\n\n // Generate schemas for ALL status codes, not just success\n for (const [statusCode, responseSchema] of Object.entries(\n route.responses,\n )) {\n if (!responseSchema) continue;\n\n const isSuccess = statusCode.startsWith(\"2\");\n const suffix = isSuccess\n ? `${statusCode}Response`\n : `${statusCode}ErrorResponse`;\n const responseSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n suffix,\n );\n\n if (!schemaNames.has(responseSchemaName)) {\n schemaNames.add(responseSchemaName);\n const zodExpr = convertSchema(responseSchema);\n lines.push(`export const ${responseSchemaName} = ${zodExpr};`);\n }\n }\n }\n\n return lines;\n}\n\nfunction generateRequestResponseObjects(routes: RouteInfo[]): string[] {\n const lines: string[] = [];\n const requestPaths: Record<string, Record<string, string[]>> = {};\n const responsePaths: Record<\n string,\n Record<string, Record<string, string>>\n > = {};\n\n for (const route of routes) {\n const names = generateRouteSchemaNames(route);\n const pathParams = route.parameters.filter((p) => p.in === \"path\");\n const queryParams = route.parameters.filter((p) => p.in === \"query\");\n const headerParams = route.parameters.filter((p) => p.in === \"header\");\n\n if (!requestPaths[route.path]) {\n requestPaths[route.path] = {};\n }\n const requestMethodObj = requestPaths[route.path]!;\n if (!requestMethodObj[route.method]) {\n requestMethodObj[route.method] = [];\n }\n\n const requestParts: string[] = [];\n if (names.paramsSchemaName && pathParams.length > 0) {\n requestParts.push(`params: ${names.paramsSchemaName}`);\n }\n if (names.querySchemaName && queryParams.length > 0) {\n requestParts.push(`query: ${names.querySchemaName}`);\n }\n if (names.headersSchemaName && headerParams.length > 0) {\n requestParts.push(`headers: ${names.headersSchemaName}`);\n }\n if (names.bodySchemaName && route.requestBody) {\n requestParts.push(`body: ${names.bodySchemaName}`);\n }\n\n if (requestParts.length > 0) {\n requestMethodObj[route.method] = requestParts;\n }\n\n // Store all status codes in nested structure\n if (!responsePaths[route.path]) {\n responsePaths[route.path] = {};\n }\n const responseMethodObj = responsePaths[route.path]!;\n if (!responseMethodObj[route.method]) {\n responseMethodObj[route.method] = {};\n }\n\n for (const [statusCode, responseSchema] of Object.entries(\n route.responses,\n )) {\n if (!responseSchema) continue;\n\n const isSuccess = statusCode.startsWith(\"2\");\n const suffix = isSuccess\n ? `${statusCode}Response`\n : `${statusCode}ErrorResponse`;\n const responseSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n suffix,\n );\n responseMethodObj[route.method]![statusCode] = responseSchemaName;\n }\n }\n\n lines.push(\"export const Request = {\");\n for (const [path, methods] of Object.entries(requestPaths)) {\n const methodEntries = Object.entries(methods).filter(\n ([, parts]) => parts.length > 0,\n );\n if (methodEntries.length > 0) {\n lines.push(` '${path}': {`);\n for (const [method, parts] of methodEntries) {\n lines.push(` ${method}: {`);\n for (const part of parts) {\n lines.push(` ${part},`);\n }\n lines.push(` },`);\n }\n lines.push(` },`);\n }\n }\n lines.push(\"} as const;\");\n lines.push(\"\");\n\n lines.push(\"export const Response = {\");\n for (const [path, methods] of Object.entries(responsePaths)) {\n const methodEntries = Object.entries(methods);\n if (methodEntries.length > 0) {\n lines.push(` '${path}': {`);\n for (const [method, statusCodes] of methodEntries) {\n lines.push(` ${method}: {`);\n for (const [statusCode, schemaName] of Object.entries(statusCodes)) {\n lines.push(` '${statusCode}': ${schemaName},`);\n }\n lines.push(` },`);\n }\n lines.push(` },`);\n }\n }\n lines.push(\"} as const;\");\n\n return lines;\n}\n\nexport const openApiToZodTsCode = (\n openapi: Record<string, unknown>,\n customImportLines?: string[],\n options?: { includeRoutes?: boolean },\n): string => {\n const components = (openapi as AnySchema)[\"components\"] as\n | AnySchema\n | undefined;\n const schemas: Record<string, AnySchema> =\n (components?.[\"schemas\"] as Record<string, AnySchema>) ?? {};\n\n const lines: string[] = [];\n lines.push(\"/**\");\n lines.push(\" * This file was automatically generated from OpenAPI schema\");\n lines.push(\" * Do not manually edit this file\");\n lines.push(\" */\");\n lines.push(\"\");\n lines.push(\"import { z } from 'zod';\");\n lines.push(...(customImportLines ?? []));\n lines.push(\"\");\n\n const sortedSchemaNames = topologicalSortSchemas(schemas);\n\n for (const name of sortedSchemaNames) {\n const schema = schemas[name];\n if (schema) {\n const zodExpr = convertSchemaToZodString(schema);\n const schemaName = `${name}Schema`;\n const typeName = name;\n lines.push(`export const ${schemaName} = ${zodExpr};`);\n lines.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);\n lines.push(\"\");\n }\n }\n\n if (options?.includeRoutes) {\n const routes = parseOpenApiPaths(openapi);\n if (routes.length > 0) {\n const routeSchemas = generateRouteSchemas(\n routes,\n convertSchemaToZodString,\n );\n if (routeSchemas.length > 0) {\n lines.push(...routeSchemas);\n lines.push(\"\");\n const requestResponseObjs = generateRequestResponseObjects(routes);\n lines.push(...requestResponseObjs);\n }\n }\n }\n\n return lines.join(\"\\n\");\n};\n"],"mappings":"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","names":["result","generateRouteSchemaName"]}
1
+ {"version":3,"sources":["../src/dependencies.ts","../src/types/boolean.ts","../src/types/number.ts","../src/registry.ts","../src/types/string.ts","../src/types/array.ts","../src/types/object.ts","../src/types/union.ts","../src/types/intersection.ts","../src/to-zod.ts","../src/routes.ts","../src/to-typescript.ts"],"sourcesContent":["import type { AnySchema } from \"./types/types\";\n\n/**\n * Extracts all schema references ($ref) from an OpenAPI schema by recursively\n * traversing its structure.\n *\n * This function is used during the OpenAPI-to-Zod conversion process to identify\n * which schemas a given schema depends on. It traverses all OpenAPI schema\n * structures including objects, arrays, unions (oneOf), intersections (allOf),\n * conditionals (if/then/else), and discriminator mappings to find all $ref\n * references that point to other schemas in the components/schemas section.\n *\n * The extracted dependency names are used by `topologicalSortSchemas` to build\n * a dependency graph and determine the correct order for generating Zod schemas,\n * ensuring that referenced schemas are defined before they are used in the\n * generated TypeScript code.\n *\n * @param schema - The OpenAPI schema to extract dependencies from\n * @returns An array of schema names that this schema references (via $ref)\n */\nexport function extractSchemaDependencies(schema: AnySchema): string[] {\n const dependencies: Set<string> = new Set();\n const visited = new WeakSet();\n\n function traverse(obj: any): void {\n if (!obj || typeof obj !== \"object\") return;\n\n if (visited.has(obj)) return;\n visited.add(obj);\n\n if (obj[\"$ref\"] && typeof obj[\"$ref\"] === \"string\") {\n const match = (obj[\"$ref\"] as string).match(\n /#\\/components\\/schemas\\/(.+)/,\n );\n if (match && match[1]) {\n dependencies.add(decodeURIComponent(match[1]));\n }\n return;\n }\n\n if (Array.isArray(obj)) {\n obj.forEach(traverse);\n return;\n }\n\n if (obj.properties && typeof obj.properties === \"object\") {\n for (const propValue of Object.values(obj.properties)) {\n traverse(propValue);\n }\n }\n\n const schemaKeys = [\n \"items\",\n \"oneOf\",\n \"allOf\",\n \"anyOf\",\n \"not\",\n \"if\",\n \"then\",\n \"else\",\n \"prefixItems\",\n \"contains\",\n \"propertyNames\",\n \"dependentSchemas\",\n ];\n\n for (const key of schemaKeys) {\n if (obj[key]) {\n traverse(obj[key]);\n }\n }\n\n if (\n obj.additionalProperties &&\n typeof obj.additionalProperties === \"object\"\n ) {\n traverse(obj.additionalProperties);\n }\n\n if (obj.discriminator?.mapping) {\n Object.values(obj.discriminator.mapping).forEach(traverse);\n }\n }\n\n traverse(schema);\n return Array.from(dependencies);\n}\n\n/**\n * Sorts OpenAPI schemas topologically based on their dependencies to ensure\n * correct generation order.\n *\n * When converting OpenAPI schemas to Zod schemas and generating TypeScript code,\n * schemas must be defined before they are referenced. For example, if `UserSchema`\n * references `ProfileSchema` (via $ref), then `ProfileSchema` must be generated\n * before `UserSchema` to avoid \"undefined variable\" errors in the generated code.\n *\n * This function uses Kahn's algorithm for topological sorting to order schemas\n * such that all dependencies come before their dependents. It:\n * 1. Extracts dependencies for each schema using `extractSchemaDependencies`\n * 2. Builds a dependency graph and computes in-degrees\n * 3. Sorts schemas starting with those that have no dependencies (in-degree 0)\n * 4. Handles circular dependencies gracefully by appending any remaining schemas\n * that couldn't be sorted (though this indicates a problematic schema structure)\n *\n * This function is called by `openApiToZodTsCode` to determine the order in which\n * schemas should be converted and emitted in the generated TypeScript file.\n *\n * @param schemas - A record mapping schema names to their OpenAPI schema definitions\n * @returns An array of schema names sorted in topological order (dependencies before dependents)\n */\nexport function topologicalSortSchemas(\n schemas: Record<string, AnySchema>,\n): string[] {\n const schemaNames = Object.keys(schemas);\n const dependencies: Map<string, string[]> = new Map();\n const inDegree: Map<string, number> = new Map();\n const sorted: string[] = [];\n const queue: string[] = [];\n const dependents: Map<string, string[]> = new Map();\n\n for (const name of schemaNames) {\n dependencies.set(name, []);\n dependents.set(name, []);\n inDegree.set(name, 0);\n }\n\n for (const name of schemaNames) {\n const schemaValue = schemas[name];\n if (schemaValue) {\n const deps = extractSchemaDependencies(schemaValue);\n const validDeps = deps.filter((dep) => schemaNames.includes(dep));\n dependencies.set(name, validDeps);\n\n for (const dep of validDeps) {\n const currentDependents = dependents.get(dep) || [];\n currentDependents.push(name);\n dependents.set(dep, currentDependents);\n }\n }\n }\n\n for (const [name, deps] of dependencies.entries()) {\n inDegree.set(name, deps.length);\n }\n\n for (const [name, degree] of inDegree.entries()) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n sorted.push(current);\n\n const currentDependents = dependents.get(current) || [];\n for (const dependent of currentDependents) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n if (sorted.length !== schemaNames.length) {\n for (const name of schemaNames) {\n if (!sorted.includes(name)) {\n sorted.push(name);\n }\n }\n }\n\n return sorted;\n}\n","/**\n * Convert an OpenAPI v3 boolean schema to a Zod schema string\n */\nexport function convertOpenAPIBooleanToZod(_: { type: \"boolean\" }): string {\n return \"z.boolean()\";\n}\n","/**\n * Convert an OpenAPI v3 number/integer schema to a Zod schema string\n */\nexport function convertOpenAPINumberToZod(schema: {\n type: \"number\" | \"integer\";\n minimum?: number;\n maximum?: number;\n}): string {\n let result = \"z.number()\";\n if (schema.type === \"integer\") {\n result += \".int()\";\n }\n if (typeof schema.minimum === \"number\") {\n result += `.min(${schema.minimum})`;\n }\n if (typeof schema.maximum === \"number\") {\n result += `.max(${schema.maximum})`;\n }\n return result;\n}\n","import { z } from \"zod\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst SUPPORTED_STRING_FORMATS_MAP = {\n \"color-hex\": 1,\n date: 1,\n \"date-time\": 1,\n email: 1,\n \"iso-date\": 1,\n \"iso-date-time\": 1,\n objectid: 1,\n uri: 1,\n url: 1,\n uuid: 1,\n} as const;\n\nexport const SUPPORTED_STRING_FORMATS = Object.keys(\n SUPPORTED_STRING_FORMATS_MAP,\n) as unknown as keyof typeof SUPPORTED_STRING_FORMATS_MAP;\n\ntype SupportedStringFormat = typeof SUPPORTED_STRING_FORMATS;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ZodOpenApiRegistrationString<\n F extends SupportedStringFormat = SupportedStringFormat,\n> = {\n /** The name of the schema variable, IMPORTANT: must be named the same as the variable name */\n schemaExportedVariableName: string;\n type: \"string\";\n description?: string;\n format: F;\n};\n\nexport type ZodOpenApiRegistrationStrings<\n Fs extends\n readonly SupportedStringFormat[] = readonly SupportedStringFormat[],\n> = {\n /** The name of the schema variable, IMPORTANT: must be named the same as the variable name */\n schemaExportedVariableName: string;\n type: \"string\";\n description?: string;\n formats: Fs;\n};\n\nexport type ZodOpenApiRegistrationPrimitive = {\n /** The name of the schema variable, IMPORTANT: must be named the same as the variable name */\n schemaExportedVariableName: string;\n description?: string;\n type: \"number\" | \"integer\" | \"boolean\";\n};\n\nexport type ZodOpenApiRegistration =\n | ZodOpenApiRegistrationString\n | ZodOpenApiRegistrationStrings\n | ZodOpenApiRegistrationPrimitive;\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\nfunction isStringRegistration(\n reg: ZodOpenApiRegistration,\n): reg is ZodOpenApiRegistrationString {\n return reg.type === \"string\" && \"format\" in reg;\n}\n\nfunction isStringsRegistration(\n reg: ZodOpenApiRegistration,\n): reg is ZodOpenApiRegistrationStrings {\n return reg.type === \"string\" && \"formats\" in reg;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\ntype TypeFormatPair = { type: string; format: string | undefined };\n\nfunction getTypeFormatPairs(reg: ZodOpenApiRegistration): TypeFormatPair[] {\n if (isStringRegistration(reg)) {\n return [{ type: \"string\", format: reg.format }];\n }\n\n if (isStringsRegistration(reg)) {\n return reg.formats.map((f) => ({ type: \"string\", format: f }));\n }\n\n return [];\n}\n\n// ============================================================================\n// Registry Class\n// ============================================================================\n\n/**\n * Global registry for mapping Zod schemas to OpenAPI schema representations\n */\nclass ZodSchemaRegistry {\n private readonly map = new Map<z.ZodTypeAny, ZodOpenApiRegistration>();\n\n /**\n * Register a Zod schema with its OpenAPI representation\n */\n register<F extends SupportedStringFormat>(\n schema: z.ZodTypeAny,\n registration: ZodOpenApiRegistrationString<F>,\n ): void;\n register<Fs extends readonly SupportedStringFormat[]>(\n schema: z.ZodTypeAny,\n registration: ZodOpenApiRegistrationStrings<Fs>,\n ): void;\n register(\n schema: z.ZodTypeAny,\n registration: ZodOpenApiRegistrationPrimitive,\n ): void;\n register(schema: z.ZodTypeAny, registration: ZodOpenApiRegistration): void {\n const newPairs = getTypeFormatPairs(registration);\n\n if (newPairs.length > 0) {\n for (const [existingSchema, existingRegistration] of this.map.entries()) {\n if (existingSchema === schema) continue;\n\n const existingPairs = getTypeFormatPairs(existingRegistration);\n for (const { type, format } of newPairs) {\n if (\n existingPairs.some((p) => p.type === type && p.format === format)\n ) {\n throw new Error(\n `duplicate Zod OpenAPI registration for (type, format)=('${type}', '${format as string}')`,\n );\n }\n }\n }\n }\n\n this.map.set(schema, registration);\n }\n\n /**\n * Get the OpenAPI schema for a given Zod schema\n */\n getOpenApiSchema(schema: z.ZodTypeAny): ZodOpenApiRegistration | undefined {\n return this.map.get(schema);\n }\n\n /**\n * Check if a Zod schema is registered\n */\n isRegistered(schema: z.ZodTypeAny): boolean {\n return this.map.has(schema);\n }\n\n /**\n * Clear all registered schemas\n */\n clear(): void {\n this.map.clear();\n }\n\n /**\n * Reverse-lookup helper: given a string format, return the registered schema's exported variable name\n */\n getSchemaExportedVariableNameForStringFormat(\n format: SupportedStringFormat,\n ): string | undefined {\n for (const registration of this.map.values()) {\n if (registration.type !== \"string\") continue;\n\n if (\n isStringRegistration(registration) &&\n registration.format === format\n ) {\n return registration.schemaExportedVariableName;\n }\n\n if (\n isStringsRegistration(registration) &&\n registration.formats.includes(format)\n ) {\n return registration.schemaExportedVariableName;\n }\n }\n return undefined;\n }\n}\n\n// ============================================================================\n// Global Registry Instance\n// ============================================================================\n\nexport const schemaRegistry = new ZodSchemaRegistry();\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Helper function to register a Zod schema with its OpenAPI representation\n */\nexport function registerZodSchemaToOpenApiSchema(\n schema: z.ZodTypeAny,\n openApiSchema: ZodOpenApiRegistration,\n): void {\n schemaRegistry.register(schema, openApiSchema as any);\n}\n\n/**\n * Convenience helper to get an exported schema variable name for a given string format\n */\nexport function getSchemaExportedVariableNameForStringFormat(\n format: SupportedStringFormat,\n): string | undefined {\n return schemaRegistry.getSchemaExportedVariableNameForStringFormat(format);\n}\n\n/**\n * Clear all registered schemas in the global registry\n */\nexport function clearZodSchemaToOpenApiSchemaRegistry(): void {\n schemaRegistry.clear();\n}\n","import {\n getSchemaExportedVariableNameForStringFormat,\n SUPPORTED_STRING_FORMATS,\n} from \"../registry\";\n\n/**\n * Convert an OpenAPI v3 string schema to a Zod schema string\n */\nexport function convertOpenAPIStringToZod(schema: {\n type: \"string\";\n format?: typeof SUPPORTED_STRING_FORMATS;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n enum?: string[];\n}): string {\n // Handle enum values\n if (schema.enum) {\n return `z.enum([${schema.enum.map((value) => `'${value}'`).join(\", \")}])`;\n }\n\n // Check for custom registered format schemas\n if (schema.format && SUPPORTED_STRING_FORMATS.includes(schema.format)) {\n const customSchemaName = getSchemaExportedVariableNameForStringFormat(\n schema.format,\n );\n\n // Use custom schema if registered (ignores other constraints)\n if (customSchemaName) {\n return customSchemaName;\n }\n }\n\n // Build string schema with format modifiers\n let zodSchema = \"z.string()\";\n\n if (schema.format) {\n zodSchema += getFormatModifier(schema.format);\n }\n\n // Apply length constraints\n if (typeof schema.minLength === \"number\") {\n zodSchema += `.min(${schema.minLength})`;\n }\n\n if (typeof schema.maxLength === \"number\") {\n zodSchema += `.max(${schema.maxLength})`;\n }\n\n // Apply pattern constraint\n if (typeof schema.pattern === \"string\") {\n zodSchema += `.regex(/${schema.pattern}/)`;\n }\n\n return zodSchema;\n}\n\n/**\n * Get the Zod modifier for built-in string formats\n */\nfunction getFormatModifier(format: string): string {\n switch (format) {\n case \"email\":\n return \".email()\";\n case \"url\":\n case \"uri\":\n return \".url()\";\n case \"uuid\":\n return \".uuid()\";\n case \"color-hex\":\n return \".regex(/^[a-fA-F0-9]{6}$/)\";\n default:\n return \"\";\n }\n}\n","import type { AnySchema } from \"./types\";\n\nexport function convertOpenAPIArrayToZod(\n schema: {\n type: \"array\";\n items?: any;\n minItems?: number;\n maxItems?: number;\n },\n convertSchema: (schema: AnySchema) => string,\n): string {\n const item = schema.items;\n\n let itemZodString = \"z.unknown()\";\n if (item && typeof item === \"object\") {\n itemZodString = convertSchema(item);\n }\n\n let result = `z.array(${itemZodString})`;\n\n if (typeof schema.minItems === \"number\") {\n result += `.min(${schema.minItems})`;\n }\n if (typeof schema.maxItems === \"number\") {\n result += `.max(${schema.maxItems})`;\n }\n\n return result;\n}\n","import { AnySchema, OpenAPIObjectSchema } from \"./types\";\n\nconst validIdentifierRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;\n\nfunction quotePropertyName(name: string): string {\n return validIdentifierRegex.test(name) ? name : `'${name}'`;\n}\n\nexport function convertOpenAPIObjectToZod(\n schema: OpenAPIObjectSchema,\n convertSchema: (schema: AnySchema) => string,\n): string {\n const properties = schema.properties || {};\n const propertyNames = Object.keys(properties);\n\n if (propertyNames.length === 0) {\n if (schema.additionalProperties === false) {\n return \"z.object({}).strict()\";\n }\n return \"z.record(z.string(), z.unknown())\";\n }\n\n const requiredSet = new Set(schema.required || []);\n\n const entries: string[] = [];\n for (const [propName, propSchema] of Object.entries(properties)) {\n let zodProp = \"z.unknown()\";\n\n if (propSchema && typeof propSchema === \"object\") {\n zodProp = convertSchema(propSchema);\n }\n\n if (!requiredSet.has(propName)) {\n zodProp += \".optional()\";\n }\n\n entries.push(`${quotePropertyName(propName)}: ${zodProp}`);\n }\n\n let result = `z.object({ ${entries.join(\", \")} })`;\n\n if (schema.additionalProperties === false) {\n result += \".strict()\";\n }\n\n return result;\n}\n","import type { AnySchema } from \"./types\";\n\nexport function convertOpenAPIUnionToZod(\n schema: { oneOf: AnySchema[] },\n convertSchema: (schema: AnySchema) => string,\n): string {\n const items = schema.oneOf.map((item) => convertSchema(item));\n return `z.union([${items.join(\", \")}])`;\n}\n\n","import type { AnySchema } from \"./types\";\n\nexport function convertOpenAPIIntersectionToZod(\n schema: { allOf: AnySchema[] },\n convertSchema: (schema: AnySchema) => string,\n): string {\n const items = schema.allOf.map((item) => convertSchema(item));\n\n if (schema.allOf.length === 0) return \"z.unknown()\";\n if (schema.allOf.length === 1) return convertSchema(schema.allOf[0]!);\n\n return `z.intersection(${items.join(\", \")})`;\n}\n\n","import { convertOpenAPIBooleanToZod } from \"./types/boolean\";\nimport { convertOpenAPINumberToZod } from \"./types/number\";\nimport { convertOpenAPIStringToZod } from \"./types/string\";\nimport { convertOpenAPIArrayToZod } from \"./types/array\";\nimport { convertOpenAPIObjectToZod } from \"./types/object\";\nimport { convertOpenAPIUnionToZod } from \"./types/union\";\nimport { convertOpenAPIIntersectionToZod } from \"./types/intersection\";\nimport type { AnySchema } from \"./types/types\";\n\nexport function convertSchemaToZodString(schema: AnySchema): string {\n if (!schema || typeof schema !== \"object\") return \"z.unknown()\";\n\n if (schema[\"$ref\"] && typeof schema[\"$ref\"] === \"string\") {\n const match = (schema[\"$ref\"] as string).match(\n /#\\/components\\/schemas\\/(.+)/,\n );\n let result = \"z.unknown()\";\n if (match && match[1]) {\n result = `${match[1]}Schema`;\n }\n if (schema[\"nullable\"] === true) {\n result = `z.union([${result}, z.null()])`;\n }\n return result;\n }\n let result: string = \"z.unknown()\";\n\n if (\"oneOf\" in schema && Array.isArray(schema[\"oneOf\"])) {\n result = convertOpenAPIUnionToZod(\n schema as { oneOf: AnySchema[] },\n convertSchemaToZodString,\n );\n } else if (\"allOf\" in schema && Array.isArray(schema[\"allOf\"])) {\n result = convertOpenAPIIntersectionToZod(\n schema as { allOf: AnySchema[] },\n convertSchemaToZodString,\n );\n } else {\n switch (schema[\"type\"]) {\n case \"string\":\n result = convertOpenAPIStringToZod({\n enum: schema[\"enum\"],\n format: schema[\"format\"],\n maxLength: schema[\"maxLength\"],\n minLength: schema[\"minLength\"],\n pattern: schema[\"pattern\"],\n type: \"string\",\n });\n break;\n case \"number\":\n result = convertOpenAPINumberToZod({\n maximum: schema[\"maximum\"],\n minimum: schema[\"minimum\"],\n type: \"number\",\n });\n break;\n case \"integer\":\n result = convertOpenAPINumberToZod({\n maximum: schema[\"maximum\"],\n minimum: schema[\"minimum\"],\n type: \"integer\",\n });\n break;\n case \"boolean\":\n result = convertOpenAPIBooleanToZod({ type: \"boolean\" });\n break;\n case \"array\":\n result = convertOpenAPIArrayToZod(\n {\n items: schema[\"items\"],\n maxItems: schema[\"maxItems\"],\n minItems: schema[\"minItems\"],\n type: \"array\",\n },\n convertSchemaToZodString,\n );\n break;\n case \"object\":\n result = convertOpenAPIObjectToZod(\n {\n additionalProperties: schema[\"additionalProperties\"],\n properties: schema[\"properties\"],\n required: schema[\"required\"],\n type: \"object\",\n },\n convertSchemaToZodString,\n );\n break;\n default:\n if (schema[\"properties\"]) {\n result = convertOpenAPIObjectToZod(\n {\n additionalProperties: schema[\"additionalProperties\"],\n properties: schema[\"properties\"],\n required: schema[\"required\"],\n type: \"object\",\n },\n convertSchemaToZodString,\n );\n } else {\n result = \"z.unknown()\";\n }\n break;\n }\n }\n\n if (schema[\"nullable\"] === true) {\n result = `z.union([${result}, z.null()])`;\n }\n\n return result;\n}\n","import type { AnySchema } from \"./types/types\";\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\" | \"HEAD\" | \"OPTIONS\";\n\nexport interface RouteParameter {\n name: string;\n in: \"path\" | \"query\" | \"header\" | \"cookie\";\n required: boolean;\n schema: AnySchema;\n}\n\nexport interface RouteInfo {\n path: string;\n method: HttpMethod;\n parameters: RouteParameter[];\n requestBody?: AnySchema;\n responses: Record<string, AnySchema>;\n}\n\nexport interface RouteSchemaNames {\n paramsSchemaName?: string;\n querySchemaName?: string;\n headersSchemaName?: string;\n bodySchemaName?: string;\n responseSchemaName?: string;\n}\n\nfunction toUpperCaseMethod(method: string): HttpMethod {\n const upper = method.toUpperCase();\n if (\n upper === \"GET\" ||\n upper === \"POST\" ||\n upper === \"PUT\" ||\n upper === \"PATCH\" ||\n upper === \"DELETE\" ||\n upper === \"HEAD\" ||\n upper === \"OPTIONS\"\n ) {\n return upper as HttpMethod;\n }\n return \"GET\";\n}\n\nfunction toPascalCase(str: string): string {\n return str\n .replace(/[^a-zA-Z0-9]/g, \" \")\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\nfunction generateRouteSchemaName(\n path: string,\n method: HttpMethod,\n suffix: string,\n): string {\n const pathParts = path\n .split(\"/\")\n .filter((p) => p)\n .map((p) => {\n if (p.startsWith(\"{\") && p.endsWith(\"}\")) {\n return p.slice(1, -1);\n }\n return p;\n })\n .map(toPascalCase);\n const methodPrefix = method.charAt(0) + method.slice(1).toLowerCase();\n const parts = [methodPrefix, ...pathParts, suffix];\n return parts.join(\"\");\n}\n\nexport function parseOpenApiPaths(\n openapi: Record<string, unknown>,\n): RouteInfo[] {\n const paths = (openapi as AnySchema)[\"paths\"] as\n | Record<string, AnySchema>\n | undefined;\n if (!paths) {\n return [];\n }\n\n const routes: RouteInfo[] = [];\n\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!pathItem || typeof pathItem !== \"object\") continue;\n\n const methods = [\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"head\",\n \"options\",\n ] as const;\n\n for (const method of methods) {\n const operation = pathItem[method] as AnySchema | undefined;\n if (!operation) continue;\n\n const parameters: RouteParameter[] = [];\n const responses: Record<string, AnySchema> = {};\n\n if (Array.isArray(pathItem[\"parameters\"])) {\n for (const param of pathItem[\"parameters\"]) {\n if (param && typeof param === \"object\") {\n parameters.push({\n name: String(param[\"name\"] || \"\"),\n in: param[\"in\"] || \"query\",\n required: Boolean(param[\"required\"]),\n schema: param[\"schema\"] || {},\n });\n }\n }\n }\n\n if (Array.isArray(operation[\"parameters\"])) {\n for (const param of operation[\"parameters\"]) {\n if (param && typeof param === \"object\") {\n parameters.push({\n name: String(param[\"name\"] || \"\"),\n in: param[\"in\"] || \"query\",\n required: Boolean(param[\"required\"]),\n schema: param[\"schema\"] || {},\n });\n }\n }\n }\n\n let requestBody: AnySchema | undefined;\n if (operation[\"requestBody\"]) {\n const rb = operation[\"requestBody\"];\n if (rb && typeof rb === \"object\") {\n const content = rb[\"content\"];\n if (content && typeof content === \"object\") {\n const jsonContent = content[\"application/json\"];\n if (jsonContent && typeof jsonContent === \"object\") {\n requestBody = jsonContent[\"schema\"] || {};\n }\n }\n }\n }\n\n if (operation[\"responses\"] && typeof operation[\"responses\"] === \"object\") {\n for (const [statusCode, response] of Object.entries(\n operation[\"responses\"],\n )) {\n if (response && typeof response === \"object\") {\n const responseSchema = response as AnySchema;\n const content = responseSchema[\"content\"];\n if (content && typeof content === \"object\") {\n const jsonContent = content[\"application/json\"];\n if (jsonContent && typeof jsonContent === \"object\") {\n const schema = jsonContent[\"schema\"];\n if (schema) {\n responses[statusCode] = schema;\n }\n }\n }\n }\n }\n }\n\n routes.push({\n path,\n method: toUpperCaseMethod(method),\n parameters,\n requestBody,\n responses,\n });\n }\n }\n\n return routes;\n}\n\nexport function generateRouteSchemaNames(\n route: RouteInfo,\n): RouteSchemaNames {\n const pathParams = route.parameters.filter((p) => p.in === \"path\");\n const queryParams = route.parameters.filter((p) => p.in === \"query\");\n const headerParams = route.parameters.filter((p) => p.in === \"header\");\n const successStatuses = Object.keys(route.responses).filter((s) =>\n s.startsWith(\"2\"),\n );\n\n const result: RouteSchemaNames = {\n responseSchemaName: successStatuses.length > 0\n ? generateRouteSchemaName(\n route.path,\n route.method,\n \"Response\",\n )\n : undefined,\n };\n\n if (pathParams.length > 0) {\n result.paramsSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Params\",\n );\n }\n\n if (queryParams.length > 0) {\n result.querySchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Query\",\n );\n }\n\n if (headerParams.length > 0) {\n result.headersSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Headers\",\n );\n }\n\n if (route.requestBody) {\n result.bodySchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n \"Body\",\n );\n }\n\n return result;\n}\n\n","import { topologicalSortSchemas } from \"./dependencies\";\nimport { convertSchemaToZodString } from \"./to-zod\";\nimport type { AnySchema } from \"./types/types\";\nimport {\n parseOpenApiPaths,\n generateRouteSchemaNames,\n type RouteInfo,\n} from \"./routes\";\n\nconst validIdentifierRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;\n\nfunction quotePropertyName(name: string): string {\n return validIdentifierRegex.test(name) ? name : `'${name}'`;\n}\n\nfunction generateRouteSchemaName(\n path: string,\n method: string,\n suffix: string,\n): string {\n const pathParts = path\n .split(\"/\")\n .filter((p) => p)\n .map((p) => {\n if (p.startsWith(\"{\") && p.endsWith(\"}\")) {\n return p.slice(1, -1);\n }\n return p;\n })\n .map((word) => {\n // Convert hyphenated words to PascalCase (e.g., \"timer-drafts\" -> \"TimerDrafts\")\n return word\n .split(/[-_]/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase())\n .join(\"\");\n });\n const methodPrefix = method.charAt(0) + method.slice(1).toLowerCase();\n const parts = [methodPrefix, ...pathParts, suffix];\n return parts.join(\"\");\n}\n\nfunction generateRouteSchemas(\n routes: RouteInfo[],\n convertSchema: (schema: AnySchema) => string,\n): string[] {\n const lines: string[] = [];\n const schemaNames = new Set<string>();\n\n for (const route of routes) {\n const names = generateRouteSchemaNames(route);\n const pathParams = route.parameters.filter((p) => p.in === \"path\");\n const queryParams = route.parameters.filter((p) => p.in === \"query\");\n const headerParams = route.parameters.filter((p) => p.in === \"header\");\n\n if (names.paramsSchemaName && pathParams.length > 0) {\n if (!schemaNames.has(names.paramsSchemaName)) {\n schemaNames.add(names.paramsSchemaName);\n const properties: string[] = [];\n const required: string[] = [];\n for (const param of pathParams) {\n const zodExpr = convertSchema(param.schema);\n properties.push(`${quotePropertyName(param.name)}: ${zodExpr}`);\n if (param.required) {\n required.push(param.name);\n }\n }\n lines.push(\n `export const ${names.paramsSchemaName} = z.object({ ${properties.join(\", \")} });`,\n );\n }\n }\n\n if (names.querySchemaName && queryParams.length > 0) {\n if (!schemaNames.has(names.querySchemaName)) {\n schemaNames.add(names.querySchemaName);\n const properties: string[] = [];\n for (const param of queryParams) {\n let zodExpr = convertSchema(param.schema);\n if (!param.required) {\n zodExpr += \".optional()\";\n }\n properties.push(`${quotePropertyName(param.name)}: ${zodExpr}`);\n }\n lines.push(\n `export const ${names.querySchemaName} = z.object({ ${properties.join(\", \")} });`,\n );\n }\n }\n\n if (names.headersSchemaName && headerParams.length > 0) {\n if (!schemaNames.has(names.headersSchemaName)) {\n schemaNames.add(names.headersSchemaName);\n const properties: string[] = [];\n for (const param of headerParams) {\n let zodExpr = convertSchema(param.schema);\n if (!param.required) {\n zodExpr += \".optional()\";\n }\n properties.push(`${quotePropertyName(param.name)}: ${zodExpr}`);\n }\n lines.push(\n `export const ${names.headersSchemaName} = z.object({ ${properties.join(\", \")} });`,\n );\n }\n }\n\n if (names.bodySchemaName && route.requestBody) {\n if (!schemaNames.has(names.bodySchemaName)) {\n schemaNames.add(names.bodySchemaName);\n const zodExpr = convertSchema(route.requestBody);\n lines.push(`export const ${names.bodySchemaName} = ${zodExpr};`);\n }\n }\n\n // Generate schemas for ALL status codes, not just success\n for (const [statusCode, responseSchema] of Object.entries(\n route.responses,\n )) {\n if (!responseSchema) continue;\n\n const isSuccess = statusCode.startsWith(\"2\");\n const suffix = isSuccess\n ? `${statusCode}Response`\n : `${statusCode}ErrorResponse`;\n const responseSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n suffix,\n );\n\n if (!schemaNames.has(responseSchemaName)) {\n schemaNames.add(responseSchemaName);\n const zodExpr = convertSchema(responseSchema);\n lines.push(`export const ${responseSchemaName} = ${zodExpr};`);\n }\n }\n }\n\n return lines;\n}\n\nfunction generateRequestResponseObjects(routes: RouteInfo[]): string[] {\n const lines: string[] = [];\n const requestPaths: Record<string, Record<string, string[]>> = {};\n const responsePaths: Record<\n string,\n Record<string, Record<string, string>>\n > = {};\n\n for (const route of routes) {\n const names = generateRouteSchemaNames(route);\n const pathParams = route.parameters.filter((p) => p.in === \"path\");\n const queryParams = route.parameters.filter((p) => p.in === \"query\");\n const headerParams = route.parameters.filter((p) => p.in === \"header\");\n\n if (!requestPaths[route.path]) {\n requestPaths[route.path] = {};\n }\n const requestMethodObj = requestPaths[route.path]!;\n if (!requestMethodObj[route.method]) {\n requestMethodObj[route.method] = [];\n }\n\n const requestParts: string[] = [];\n if (names.paramsSchemaName && pathParams.length > 0) {\n requestParts.push(`params: ${names.paramsSchemaName}`);\n }\n if (names.querySchemaName && queryParams.length > 0) {\n requestParts.push(`query: ${names.querySchemaName}`);\n }\n if (names.headersSchemaName && headerParams.length > 0) {\n requestParts.push(`headers: ${names.headersSchemaName}`);\n }\n if (names.bodySchemaName && route.requestBody) {\n requestParts.push(`body: ${names.bodySchemaName}`);\n }\n\n if (requestParts.length > 0) {\n requestMethodObj[route.method] = requestParts;\n }\n\n // Store all status codes in nested structure\n if (!responsePaths[route.path]) {\n responsePaths[route.path] = {};\n }\n const responseMethodObj = responsePaths[route.path]!;\n if (!responseMethodObj[route.method]) {\n responseMethodObj[route.method] = {};\n }\n\n for (const [statusCode, responseSchema] of Object.entries(\n route.responses,\n )) {\n if (!responseSchema) continue;\n\n const isSuccess = statusCode.startsWith(\"2\");\n const suffix = isSuccess\n ? `${statusCode}Response`\n : `${statusCode}ErrorResponse`;\n const responseSchemaName = generateRouteSchemaName(\n route.path,\n route.method,\n suffix,\n );\n responseMethodObj[route.method]![statusCode] = responseSchemaName;\n }\n }\n\n lines.push(\"export const Request = {\");\n for (const [path, methods] of Object.entries(requestPaths)) {\n const methodEntries = Object.entries(methods).filter(\n ([, parts]) => parts.length > 0,\n );\n if (methodEntries.length > 0) {\n lines.push(` '${path}': {`);\n for (const [method, parts] of methodEntries) {\n lines.push(` ${method}: {`);\n for (const part of parts) {\n lines.push(` ${part},`);\n }\n lines.push(` },`);\n }\n lines.push(` },`);\n }\n }\n lines.push(\"} as const;\");\n lines.push(\"\");\n\n lines.push(\"export const Response = {\");\n for (const [path, methods] of Object.entries(responsePaths)) {\n const methodEntries = Object.entries(methods);\n if (methodEntries.length > 0) {\n lines.push(` '${path}': {`);\n for (const [method, statusCodes] of methodEntries) {\n lines.push(` ${method}: {`);\n for (const [statusCode, schemaName] of Object.entries(statusCodes)) {\n lines.push(` '${statusCode}': ${schemaName},`);\n }\n lines.push(` },`);\n }\n lines.push(` },`);\n }\n }\n lines.push(\"} as const;\");\n\n return lines;\n}\n\nexport const openApiToZodTsCode = (\n openapi: Record<string, unknown>,\n customImportLines?: string[],\n options?: { includeRoutes?: boolean },\n): string => {\n const components = (openapi as AnySchema)[\"components\"] as\n | AnySchema\n | undefined;\n const schemas: Record<string, AnySchema> =\n (components?.[\"schemas\"] as Record<string, AnySchema>) ?? {};\n\n const lines: string[] = [];\n lines.push(\"/**\");\n lines.push(\" * This file was automatically generated from OpenAPI schema\");\n lines.push(\" * Do not manually edit this file\");\n lines.push(\" */\");\n lines.push(\"\");\n lines.push(\"import { z } from 'zod';\");\n lines.push(...(customImportLines ?? []));\n lines.push(\"\");\n\n const sortedSchemaNames = topologicalSortSchemas(schemas);\n\n for (const name of sortedSchemaNames) {\n const schema = schemas[name];\n if (schema) {\n const zodExpr = convertSchemaToZodString(schema);\n const schemaName = `${name}Schema`;\n const typeName = name;\n lines.push(`export const ${schemaName} = ${zodExpr};`);\n lines.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);\n lines.push(\"\");\n }\n }\n\n if (options?.includeRoutes) {\n const routes = parseOpenApiPaths(openapi);\n if (routes.length > 0) {\n const routeSchemas = generateRouteSchemas(\n routes,\n convertSchemaToZodString,\n );\n if (routeSchemas.length > 0) {\n lines.push(...routeSchemas);\n lines.push(\"\");\n const requestResponseObjs = generateRequestResponseObjects(routes);\n lines.push(...requestResponseObjs);\n }\n }\n }\n\n return lines.join(\"\\n\");\n};\n"],"mappings":"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","names":["result","validIdentifierRegex","quotePropertyName","generateRouteSchemaName"]}
package/package.json CHANGED
@@ -1,10 +1,18 @@
1
1
  {
2
2
  "name": "@alt-stack/zod-openapi",
3
- "version": "1.0.3",
3
+ "version": "1.1.1",
4
4
  "description": "Convert OpenAPI schemas to Zod schemas with TypeScript code generation",
5
+ "type": "module",
5
6
  "main": "./dist/index.cjs",
6
7
  "module": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
8
16
  "bin": {
9
17
  "zod-openapi": "./bin/zod-openapi.js"
10
18
  },
package/src/cli.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { readFileSync, writeFileSync } from "node:fs";
4
+ import { resolve } from "node:path";
4
5
  import { openApiToZodTsCode } from "./to-typescript.js";
5
6
 
6
7
  const args = process.argv.slice(2);
@@ -12,11 +13,13 @@ Usage: npx zod-openapi <input> [options]
12
13
  Generate TypeScript types from OpenAPI schema
13
14
 
14
15
  Arguments:
15
- input OpenAPI schema file path or URL
16
+ input OpenAPI schema file path or URL
16
17
 
17
18
  Options:
18
- -o, --output <file> Output file path (default: generated-types.ts)
19
- -h, --help Show this help message
19
+ -o, --output <file> Output file path (default: generated-types.ts)
20
+ -r, --registry <file> Registry file that registers custom schemas
21
+ -i, --include <file> TypeScript file to include at top of generated output
22
+ -h, --help Show this help message
20
23
 
21
24
  Examples:
22
25
  # Generate from local file
@@ -27,9 +30,24 @@ Examples:
27
30
 
28
31
  # Specify output file
29
32
  npx zod-openapi openapi.json -o src/api-types.ts
33
+
34
+ # Use custom registry for format mappings
35
+ npx zod-openapi openapi.json -r ./my-registry.ts
36
+
37
+ # Include custom imports/schemas in generated output
38
+ npx zod-openapi openapi.json -i ./custom-schemas.ts
39
+
40
+ # Combine registry and include
41
+ npx zod-openapi openapi.json -r ./my-registry.ts -i ./custom-schemas.ts -o src/api-types.ts
30
42
  `);
31
43
  }
32
44
 
45
+ function getArgValue(shortFlag: string, longFlag: string): string | undefined {
46
+ let idx = args.indexOf(shortFlag);
47
+ if (idx === -1) idx = args.indexOf(longFlag);
48
+ return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
49
+ }
50
+
33
51
  async function fetchSchema(url: string): Promise<Record<string, unknown>> {
34
52
  const response = await fetch(url);
35
53
  if (!response.ok) {
@@ -64,18 +82,24 @@ async function main() {
64
82
  process.exit(1);
65
83
  }
66
84
 
67
- let outputIndex = args.indexOf("-o");
68
- if (outputIndex === -1) {
69
- outputIndex = args.indexOf("--output");
70
- }
71
- const outputArg =
72
- outputIndex !== -1 && outputIndex + 1 < args.length
73
- ? args[outputIndex + 1]
74
- : undefined;
75
- const output =
76
- typeof outputArg === "string" ? outputArg : "generated-types.ts";
85
+ const output = getArgValue("-o", "--output") ?? "generated-types.ts";
86
+ const registryFile = getArgValue("-r", "--registry");
87
+ const includeFile = getArgValue("-i", "--include");
77
88
 
78
89
  try {
90
+ // Load registry file if provided (populates global schema registry)
91
+ if (registryFile) {
92
+ console.log(`Loading registry from ${registryFile}...`);
93
+ await import(resolve(registryFile));
94
+ }
95
+
96
+ // Read include file contents if provided
97
+ let includeContent: string | undefined;
98
+ if (includeFile) {
99
+ console.log(`Reading include file from ${includeFile}...`);
100
+ includeContent = readFileSync(includeFile, "utf8");
101
+ }
102
+
79
103
  // Determine if input is URL or file path
80
104
  let schema: Record<string, unknown>;
81
105
  if (input.startsWith("http://") || input.startsWith("https://")) {
@@ -87,7 +111,8 @@ async function main() {
87
111
  }
88
112
 
89
113
  console.log("Generating TypeScript types...");
90
- const tsCode = openApiToZodTsCode(schema, undefined, {
114
+ const customImportLines = includeContent ? [includeContent] : undefined;
115
+ const tsCode = openApiToZodTsCode(schema, customImportLines, {
91
116
  includeRoutes: true,
92
117
  });
93
118
 
@@ -60,14 +60,14 @@ describe("openApiToZodTsCode with routes", () => {
60
60
  includeRoutes: true,
61
61
  });
62
62
 
63
- expect(result).toContain("export const GetUsersIdParamsSchema");
64
- expect(result).toContain("export const GetUsersIdResponseSchema");
63
+ expect(result).toContain("export const GetUsersIdParams");
64
+ expect(result).toContain("export const GetUsersId200Response");
65
65
  expect(result).toContain("export const Request = {");
66
66
  expect(result).toContain("export const Response = {");
67
67
  expect(result).toContain("'/users/{id}':");
68
68
  expect(result).toContain("GET:");
69
- expect(result).toContain("params: GetUsersIdParamsSchema");
70
- expect(result).toContain("GET: GetUsersIdResponseSchema");
69
+ expect(result).toContain("params: GetUsersIdParams");
70
+ expect(result).toContain("'200': GetUsersId200Response");
71
71
  });
72
72
 
73
73
  it("should generate Request with body schema", () => {
@@ -123,9 +123,9 @@ describe("openApiToZodTsCode with routes", () => {
123
123
  includeRoutes: true,
124
124
  });
125
125
 
126
- expect(result).toContain("export const PostUsersBodySchema");
127
- expect(result).toContain("export const PostUsersResponseSchema");
128
- expect(result).toContain("body: PostUsersBodySchema");
126
+ expect(result).toContain("export const PostUsersBody");
127
+ expect(result).toContain("export const PostUsers201Response");
128
+ expect(result).toContain("body: PostUsersBody");
129
129
  });
130
130
 
131
131
  it("should generate Request with query parameters", () => {
@@ -178,8 +178,8 @@ describe("openApiToZodTsCode with routes", () => {
178
178
  includeRoutes: true,
179
179
  });
180
180
 
181
- expect(result).toContain("export const GetUsersQuerySchema");
182
- expect(result).toContain("query: GetUsersQuerySchema");
181
+ expect(result).toContain("export const GetUsersQuery");
182
+ expect(result).toContain("query: GetUsersQuery");
183
183
  expect(result).toContain("limit: z.number().optional()");
184
184
  expect(result).toContain("offset: z.number().optional()");
185
185
  });
@@ -228,8 +228,8 @@ describe("openApiToZodTsCode with routes", () => {
228
228
  includeRoutes: true,
229
229
  });
230
230
 
231
- expect(result).toContain("export const GetUsersHeadersSchema");
232
- expect(result).toContain("headers: GetUsersHeadersSchema");
231
+ expect(result).toContain("export const GetUsersHeaders");
232
+ expect(result).toContain("headers: GetUsersHeaders");
233
233
  });
234
234
 
235
235
  it("should handle multiple 2xx responses as union", () => {
@@ -284,8 +284,8 @@ describe("openApiToZodTsCode with routes", () => {
284
284
  includeRoutes: true,
285
285
  });
286
286
 
287
- expect(result).toContain("export const PostUsersResponseSchema");
288
- expect(result).toContain("z.union([");
287
+ expect(result).toContain("export const PostUsers200Response");
288
+ expect(result).toContain("export const PostUsers201Response");
289
289
  });
290
290
 
291
291
  it("should not generate routes when includeRoutes is false", () => {
@@ -396,7 +396,59 @@ describe("openApiToZodTsCode with routes", () => {
396
396
  });
397
397
 
398
398
  expect(result).toContain("export const Response");
399
- expect(result).toContain("GET: GetUsersResponseSchema");
399
+ expect(result).toContain("'200': GetUsers200Response");
400
+ });
401
+
402
+ it("should quote hyphenated parameter names", () => {
403
+ const openapi = {
404
+ components: { schemas: {} },
405
+ paths: {
406
+ "/foo-bar/{user-id}": {
407
+ get: {
408
+ parameters: [
409
+ {
410
+ name: "user-id",
411
+ in: "path",
412
+ required: true,
413
+ schema: { type: "string" },
414
+ },
415
+ {
416
+ name: "page-size",
417
+ in: "query",
418
+ required: false,
419
+ schema: { type: "number" },
420
+ },
421
+ {
422
+ name: "x-custom-header",
423
+ in: "header",
424
+ required: true,
425
+ schema: { type: "string" },
426
+ },
427
+ ],
428
+ responses: {
429
+ "200": {
430
+ content: {
431
+ "application/json": {
432
+ schema: { type: "object", properties: {} },
433
+ },
434
+ },
435
+ },
436
+ },
437
+ },
438
+ },
439
+ },
440
+ };
441
+
442
+ const result = openApiToZodTsCode(openapi, undefined, {
443
+ includeRoutes: true,
444
+ });
445
+
446
+ expect(result).toContain("'user-id': z.string()");
447
+ expect(result).toContain("'page-size': z.number().optional()");
448
+ expect(result).toContain("'x-custom-header': z.string()");
449
+ expect(result).toContain("GetFooBarUserIdParams");
450
+ expect(result).toContain("GetFooBarUserIdQuery");
451
+ expect(result).toContain("GetFooBarUserIdHeaders");
400
452
  });
401
453
 
402
454
  it("should handle multiple methods on same path", () => {
@@ -7,6 +7,12 @@ import {
7
7
  type RouteInfo,
8
8
  } from "./routes";
9
9
 
10
+ const validIdentifierRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
11
+
12
+ function quotePropertyName(name: string): string {
13
+ return validIdentifierRegex.test(name) ? name : `'${name}'`;
14
+ }
15
+
10
16
  function generateRouteSchemaName(
11
17
  path: string,
12
18
  method: string,
@@ -21,7 +27,13 @@ function generateRouteSchemaName(
21
27
  }
22
28
  return p;
23
29
  })
24
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
30
+ .map((word) => {
31
+ // Convert hyphenated words to PascalCase (e.g., "timer-drafts" -> "TimerDrafts")
32
+ return word
33
+ .split(/[-_]/)
34
+ .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase())
35
+ .join("");
36
+ });
25
37
  const methodPrefix = method.charAt(0) + method.slice(1).toLowerCase();
26
38
  const parts = [methodPrefix, ...pathParts, suffix];
27
39
  return parts.join("");
@@ -47,7 +59,7 @@ function generateRouteSchemas(
47
59
  const required: string[] = [];
48
60
  for (const param of pathParams) {
49
61
  const zodExpr = convertSchema(param.schema);
50
- properties.push(`${param.name}: ${zodExpr}`);
62
+ properties.push(`${quotePropertyName(param.name)}: ${zodExpr}`);
51
63
  if (param.required) {
52
64
  required.push(param.name);
53
65
  }
@@ -67,7 +79,7 @@ function generateRouteSchemas(
67
79
  if (!param.required) {
68
80
  zodExpr += ".optional()";
69
81
  }
70
- properties.push(`${param.name}: ${zodExpr}`);
82
+ properties.push(`${quotePropertyName(param.name)}: ${zodExpr}`);
71
83
  }
72
84
  lines.push(
73
85
  `export const ${names.querySchemaName} = z.object({ ${properties.join(", ")} });`,
@@ -84,7 +96,7 @@ function generateRouteSchemas(
84
96
  if (!param.required) {
85
97
  zodExpr += ".optional()";
86
98
  }
87
- properties.push(`${param.name}: ${zodExpr}`);
99
+ properties.push(`${quotePropertyName(param.name)}: ${zodExpr}`);
88
100
  }
89
101
  lines.push(
90
102
  `export const ${names.headersSchemaName} = z.object({ ${properties.join(", ")} });`,
@@ -346,11 +346,15 @@ describe("openApiToZodTsCode", () => {
346
346
  },
347
347
  };
348
348
 
349
- const result = openApiToZodTsCode(openapi);
349
+ const customImports = [
350
+ "import { ObjectId } from 'bson';",
351
+ "import { DateTime } from 'luxon';",
352
+ ];
353
+
354
+ const result = openApiToZodTsCode(openapi, customImports);
350
355
  expect(result).toContain("import { z } from 'zod';");
351
356
  expect(result).toContain("import { ObjectId } from 'bson';");
352
357
  expect(result).toContain("import { DateTime } from 'luxon';");
353
- expect(result).toContain("import { LuxonDateSchema");
354
358
  });
355
359
  });
356
360
 
@@ -229,6 +229,43 @@ describe("convertOpenAPIObjectToZod", () => {
229
229
  });
230
230
  });
231
231
 
232
+ describe("hyphenated property names", () => {
233
+ it("should quote hyphenated property names", () => {
234
+ const result = convertOpenAPIObjectToZod(
235
+ {
236
+ type: "object",
237
+ properties: {
238
+ "first-name": { type: "string" },
239
+ "last-name": { type: "string" },
240
+ age: { type: "number" },
241
+ },
242
+ required: ["first-name"],
243
+ },
244
+ mockConvertSchema,
245
+ );
246
+ expect(result).toBe(
247
+ "z.object({ 'first-name': z.string(), 'last-name': z.string().optional(), age: z.number().optional() })",
248
+ );
249
+ });
250
+
251
+ it("should quote property names with special characters", () => {
252
+ const result = convertOpenAPIObjectToZod(
253
+ {
254
+ type: "object",
255
+ properties: {
256
+ "x-custom-header": { type: "string" },
257
+ "$special": { type: "string" },
258
+ "_private": { type: "string" },
259
+ },
260
+ },
261
+ mockConvertSchema,
262
+ );
263
+ expect(result).toBe(
264
+ "z.object({ 'x-custom-header': z.string().optional(), $special: z.string().optional(), _private: z.string().optional() })",
265
+ );
266
+ });
267
+ });
268
+
232
269
  describe("edge cases", () => {
233
270
  it("should handle properties with unknown schema types", () => {
234
271
  const result = convertOpenAPIObjectToZod(