UNPKG

@docyrus/tanstack-db-generator

Version:

Code generator utilities for TanStack Query / Database integration with Docyrus API

116 lines (115 loc) 4.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateInterfacesForNames = generateInterfacesForNames; function resolveSchema(schema, spec) { if (schema && schema.$ref) { const ref = schema.$ref; const path = ref.replace('#/', '').split('/'); let current = spec; for (const segment of path) { current = current?.[segment]; if (!current) break; } return (current || {}); } return (schema || {}); } function resolveSchemaProperties(schema, spec) { let properties = {}; if (schema.allOf) { for (const subSchema of schema.allOf) { const resolved = resolveSchema(subSchema, spec); if (resolved.properties) { const resolvedProps = {}; for (const [key, value] of Object.entries(resolved.properties)) { resolvedProps[key] = resolveSchema(value, spec); } properties = { ...properties, ...resolvedProps }; } } } if (schema.properties) { const resolvedProps = {}; for (const [key, value] of Object.entries(schema.properties)) { resolvedProps[key] = resolveSchema(value, spec); } properties = { ...properties, ...resolvedProps }; } return properties; } function getTypeScriptType(schema, spec) { if (schema.oneOf) { const types = schema.oneOf .map((s) => getTypeScriptType(resolveSchema(s, spec), spec)) .filter((type, index, self) => self.indexOf(type) === index); return types.join(' | '); } switch (schema.type) { case 'string': if (schema.enum) { return schema.enum.map((v) => `'${v}'`).join(' | '); } return 'string'; case 'number': case 'integer': return 'number'; case 'boolean': return 'boolean'; case 'array': if (schema.items) { return `Array<${getTypeScriptType(resolveSchema(schema.items, spec), spec)}>`; } return 'Array<any>'; case 'object': if (schema.properties) { const props = Object.entries(schema.properties) .map(([key, value]) => `${key}: ${getTypeScriptType(resolveSchema(value, spec), spec)}`) .join('; '); return `{ ${props} }`; } return 'Record<string, any>'; default: // If there is no explicit type, but $ref existed, we already resolved it above. if (schema.properties) { const props = Object.entries(schema.properties) .map(([key, value]) => `${key}: ${getTypeScriptType(resolveSchema(value, spec), spec)}`) .join('; '); return `{ ${props} }`; } return 'any'; } } function generateInterfaceFromSchema(name, schema, spec) { const properties = resolveSchemaProperties(schema, spec); const lines = []; for (const [propName, propSchema] of Object.entries(properties)) { const resolved = resolveSchema(propSchema, spec); const type = getTypeScriptType(resolved, spec); const isOptional = !schema.required?.includes(propName) || !!resolved.readOnly; const propDesc = resolved.description ? `\n /** ${sanitizeJsDoc(resolved.description)} */` : ''; lines.push(`${propDesc}\n ${propName}${isOptional ? '?' : ''}: ${type};`); } const ifaceDesc = schema.description ? `/** ${sanitizeJsDoc(schema.description)} */\n` : ''; return `${ifaceDesc}export interface ${name} { ${lines.join('\n')} }`; } function generateInterfacesForNames(spec, names) { const out = []; const unique = Array.from(new Set(names)).filter((n) => !!n); for (const name of unique) { const schema = spec.components?.schemas?.[name]; if (schema) { out.push(generateInterfaceFromSchema(name, schema, spec)); } else { // Fallback placeholder for refs that do not exist in components.schemas out.push(`/** Unresolved schema for ${name}. */\nexport interface ${name} { [key: string]: any }`); } } return out.join('\n\n'); } function sanitizeJsDoc(text) { return String(text).replace(/\*\//g, '*\/').trim(); }