UNPKG

arela

Version:

AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.

121 lines (119 loc) 4.67 kB
/** * Generate Zod schemas from OpenAPI schemas for runtime validation */ export function generateSchemas(spec) { let output = `/** * Auto-generated Zod schemas from OpenAPI spec * DO NOT EDIT - This file is generated by Arela * @see https://zod.dev */ import { z } from 'zod'; `; const schemas = spec.components?.schemas || {}; for (const [name, schema] of Object.entries(schemas)) { output += generateZodSchema(name, schema, schemas); output += '\n\n'; } return output; } function generateZodSchema(name, schema, allSchemas) { const zodType = schemaToZod(schema, allSchemas); return `export const ${name}Schema = ${zodType};`; } export function schemaToZod(schema, allSchemas = {}) { if (!schema) return 'z.any()'; // Handle $ref if (schema.$ref) { const refName = schema.$ref.split('/').pop(); return `${refName}Schema`; } // Handle enum if (schema.enum && schema.enum.length > 0) { const values = schema.enum.map((e) => (typeof e === 'string' ? `'${e}'` : e)); return `z.enum([${values.join(', ')}])`; } // Handle oneOf, anyOf, allOf if (schema.oneOf) { return `z.union([${schema.oneOf.map((s) => schemaToZod(s, allSchemas)).join(', ')}])`; } if (schema.anyOf) { return `z.union([${schema.anyOf.map((s) => schemaToZod(s, allSchemas)).join(', ')}])`; } if (schema.allOf) { return `z.intersection(${schema.allOf.map((s) => schemaToZod(s, allSchemas)).join(', ')})`; } switch (schema.type) { case 'string': let stringSchema = 'z.string()'; if (schema.format === 'email') stringSchema += '.email()'; if (schema.format === 'uuid') stringSchema += '.uuid()'; if (schema.format === 'date') stringSchema += '.datetime()'; if (schema.format === 'date-time') stringSchema += '.datetime()'; if (schema.minLength !== undefined) stringSchema += `.min(${schema.minLength})`; if (schema.maxLength !== undefined) stringSchema += `.max(${schema.maxLength})`; return stringSchema; case 'number': let numberSchema = 'z.number()'; if (schema.minimum !== undefined) numberSchema += `.min(${schema.minimum})`; if (schema.maximum !== undefined) numberSchema += `.max(${schema.maximum})`; return numberSchema; case 'integer': let intSchema = 'z.number().int()'; if (schema.minimum !== undefined) intSchema += `.min(${schema.minimum})`; if (schema.maximum !== undefined) intSchema += `.max(${schema.maximum})`; return intSchema; case 'boolean': return 'z.boolean()'; case 'null': return 'z.null()'; case 'array': if (!schema.items) return 'z.array(z.any())'; const itemSchema = schemaToZod(schema.items, allSchemas); let arraySchema = `z.array(${itemSchema})`; if (schema.minItems !== undefined) arraySchema += `.min(${schema.minItems})`; if (schema.maxItems !== undefined) arraySchema += `.max(${schema.maxItems})`; return arraySchema; case 'object': { if (schema.additionalProperties === false && !schema.properties) { return 'z.object({})'; } if (!schema.properties) { return 'z.record(z.any())'; } const required = schema.required || []; const props = Object.entries(schema.properties) .map(([key, val]) => { const valSchema = schemaToZod(val, allSchemas); const isRequired = required.includes(key); return `${key}: ${isRequired ? valSchema : `${valSchema}.optional()`}`; }) .join(',\n '); let objectSchema = `z.object({\n ${props}\n})`; if (schema.additionalProperties === true) { objectSchema += '.passthrough()'; } else if (typeof schema.additionalProperties === 'object') { const additionalSchema = schemaToZod(schema.additionalProperties, allSchemas); objectSchema += `.and(z.record(${additionalSchema}))`; } return objectSchema; } default: return 'z.any()'; } } //# sourceMappingURL=schema-generator.js.map