UNPKG

hey-api-builders

Version:

A custom plugin for @hey-api/openapi-ts that generates mock data builders with a lightweight custom runtime, Zod integration, or static mock generation.

192 lines 6.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateZodSchema = generateZodSchema; /** * Generates a Zod schema string from a JSON schema * @param schema - JSON Schema * @param options - Generator options * @returns Zod schema code */ function generateZodSchema(schema, options = {}) { return generateZodSchemaInternal(schema, options); } function generateZodSchemaInternal(schema, options) { if (!schema || typeof schema !== 'object') { return 'z.unknown()'; } if (schema.anyOf && Array.isArray(schema.anyOf)) { const enumValues = schema.anyOf .filter((item) => item && typeof item === 'object' && 'const' in item) .map((item) => item.const); if (enumValues.length > 0) { const zodEnumValues = enumValues.map((val) => JSON.stringify(val)).join(', '); return `z.enum([${zodEnumValues}])`; } } if (schema.enum && Array.isArray(schema.enum)) { const zodEnumValues = schema.enum.map((val) => JSON.stringify(val)).join(', '); return `z.enum([${zodEnumValues}])`; } if (Array.isArray(schema.type)) { const types = schema.type.filter((t) => t !== 'null'); const isNullable = schema.type.includes('null'); if (types.length > 0 && types[0]) { let zodType = generateZodForSingleType(types[0], schema, options); if (isNullable) { zodType += '.nullable()'; } return zodType; } else if (types.length > 1) { const unionTypes = types.map((t) => generateZodForSingleType(t, schema, options)); let zodType = `z.union([${unionTypes.join(', ')}])`; if (isNullable) { zodType += '.nullable()'; } return zodType; } } if (typeof schema.type === 'string') { return generateZodForSingleType(schema.type, schema, options); } if (schema.properties && !schema.type) { return generateZodObject(schema, options); } if (schema.items && !schema.type) { return generateZodArray(schema, options); } return 'z.unknown()'; } function generateZodForSingleType(type, schema, options) { switch (type) { case 'string': return generateZodString(schema); case 'number': return generateZodNumber(schema); case 'integer': return generateZodInteger(schema); case 'boolean': return 'z.boolean()'; case 'null': return 'z.null()'; case 'array': return generateZodArray(schema, options); case 'object': return generateZodObject(schema, options); default: return 'z.unknown()'; } } function generateZodString(schema) { let zodType = 'z.string()'; if (schema.format) { switch (schema.format) { case 'uuid': zodType += '.uuid()'; break; case 'email': zodType += '.email()'; break; case 'uri': case 'url': zodType += '.url()'; break; case 'date': zodType += '.date()'; break; case 'date-time': zodType += '.datetime()'; break; case 'phone': zodType += '.regex(/^\\+?[1-9]\\d{1,14}$/)'; break; } } if (schema.pattern) { zodType += `.regex(/${schema.pattern}/)`; } if (typeof schema.minLength === 'number') { zodType += `.min(${schema.minLength})`; } if (typeof schema.maxLength === 'number') { zodType += `.max(${schema.maxLength})`; } return zodType; } function generateZodNumber(schema) { let zodType = 'z.number()'; if (typeof schema.minimum === 'number') { zodType += `.min(${schema.minimum})`; } if (typeof schema.maximum === 'number') { zodType += `.max(${schema.maximum})`; } if (typeof schema.exclusiveMinimum === 'number') { zodType += `.gt(${schema.exclusiveMinimum})`; } if (typeof schema.exclusiveMaximum === 'number') { zodType += `.lt(${schema.exclusiveMaximum})`; } return zodType; } function generateZodInteger(schema) { let zodType = 'z.number().int()'; if (typeof schema.minimum === 'number') { zodType += `.min(${schema.minimum})`; } if (typeof schema.maximum === 'number') { zodType += `.max(${schema.maximum})`; } if (typeof schema.exclusiveMinimum === 'number') { zodType += `.gt(${schema.exclusiveMinimum})`; } if (typeof schema.exclusiveMaximum === 'number') { zodType += `.lt(${schema.exclusiveMaximum})`; } return zodType; } function generateZodArray(schema, options) { let itemType = 'z.unknown()'; if (schema.items) { if (Array.isArray(schema.items)) { const tupleTypes = schema.items.map((item) => generateZodSchemaInternal(item, options)); return `z.tuple([${tupleTypes.join(', ')}])`; } else { itemType = generateZodSchemaInternal(schema.items, options); } } let zodType = `z.array(${itemType})`; if (typeof schema.minItems === 'number') { zodType += `.min(${schema.minItems})`; } if (typeof schema.maxItems === 'number') { zodType += `.max(${schema.maxItems})`; } return zodType; } function generateZodObject(schema, options) { if (!schema.properties) { return 'z.object({})'; } const properties = []; const required = new Set(schema.required || []); for (const [key, propSchema] of Object.entries(schema.properties)) { const safePropName = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key) ? key : `"${key}"`; let propType = generateZodSchemaInternal(propSchema, options); if (!required.has(key)) { propType += '.optional()'; } properties.push(`${safePropName}: ${propType}`); } let zodType = `z.object({\n ${properties.join(',\n ')}\n})`; if (schema.additionalProperties === false) { zodType += '.strict()'; } else if (schema.additionalProperties && typeof schema.additionalProperties === 'object') { const additionalType = generateZodSchemaInternal(schema.additionalProperties, options); zodType += `.catchall(${additionalType})`; } return zodType; } //# sourceMappingURL=zod-schema-generator.js.map