UNPKG

@infinite-debugger/swagger-to-ts

Version:

swagger-to-ts is a powerful library that allows you to generate TypeScript code from Swagger documentation or OpenAPI specifications. It simplifies the process of integrating API definitions into your TypeScript projects, saving you time and effort.

272 lines 22.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateModelCode = void 0; const lodash_1 = require("lodash"); const models_1 = require("../../models"); const Utils_1 = require("../Utils"); const PropertySchemaCodeGenerator_1 = require("./PropertySchemaCodeGenerator"); /** * Generates model code for a given schema * * @param options The options to generate model code. * @returns The generated model code */ const generateModelCode = ({ schemaName, openAPISpecification, generateTsEDControllers, inferTypeFromValidationSchema = true, }) => { const schema = openAPISpecification.components.schemas[schemaName]; if ('type' in schema && schema.type === 'object' && 'properties' in schema && schema.properties) { const referencedSchemas = []; const generatedVariables = {}; const zodValidationSchemaName = `${schemaName}ValidationSchema`; const inferedTypeCode = `export type ${schemaName} = z.infer<typeof ${zodValidationSchemaName}>`; const imports = { zod: ['z'], }; const modelPropertiesCodeConfiguration = Object.entries(schema.properties).map(([propertyName, propertySchema]) => { const { referencedSchemas: propertyReferencedSchemas, imports: propertyImports, generatedVariables: propertyGeneratedVariables, ...propertySchemaCodeConfiguration } = (0, PropertySchemaCodeGenerator_1.generatePropertySchemaCode)({ schema, schemaName, propertySchema, propertyName, generateTsEDControllers, }); referencedSchemas.push(...propertyReferencedSchemas); Object.entries(propertyImports).forEach(([path, importVariables]) => { if (!(path in imports)) { imports[path] = []; } imports[path].push(...importVariables.filter((importVariable) => { return !imports[path].includes(importVariable); })); }); Object.assign(generatedVariables, propertyGeneratedVariables); return propertySchemaCodeConfiguration; }); const modelIsRecursive = referencedSchemas.includes(schemaName); const zodObjectPropertiesCode = modelPropertiesCodeConfiguration .map(({ propertyName, zodCodeString: baseZodCodeString, required, isNullable, openAPISpecification, }) => { let zodCodeString = baseZodCodeString; required || (zodCodeString += '.optional()'); isNullable && (zodCodeString += '.nullable()'); openAPISpecification.description && (zodCodeString += `.describe(${JSON.stringify(openAPISpecification.description)})`); return `'${propertyName}': ${zodCodeString}`; }) .join(',\n'); const zodValidationSchemaCode = modelIsRecursive ? `export const ${zodValidationSchemaName}: z.ZodType<${schemaName}> = z.lazy(() => z.object({${zodObjectPropertiesCode}}))` : `export const ${zodValidationSchemaName} = z.object({${zodObjectPropertiesCode}})`; const tsedModelPropertiesCode = modelPropertiesCodeConfiguration .map(({ decorators, accessModifier, propertyType, required, isNullable, propertyName: basePropertyName, openAPISpecification, }) => { if (generateTsEDControllers) { (0, Utils_1.addModuleImport)({ imports, importName: 'Property', importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH, }); } const propertyDecorators = ['@Property()', ...decorators]; if (openAPISpecification.description) { if (generateTsEDControllers) { (0, Utils_1.addModuleImport)({ imports, importName: 'Description', importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH, }); } propertyDecorators.push(`@Description(${JSON.stringify(openAPISpecification.description)})`); } if ('example' in openAPISpecification && openAPISpecification.example) { if (generateTsEDControllers) { (0, Utils_1.addModuleImport)({ imports, importName: 'Example', importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH, }); } propertyDecorators.push(`@Example(${JSON.stringify(openAPISpecification.example)})`); } if ('default' in openAPISpecification && openAPISpecification.default) { if (generateTsEDControllers) { (0, Utils_1.addModuleImport)({ imports, importName: 'Default', importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH, }); } propertyDecorators.push(`@Default(${JSON.stringify(openAPISpecification.default)})`); } if (isNullable) { if (generateTsEDControllers) { (0, Utils_1.addModuleImport)({ imports, importName: 'Nullable', importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH, }); } const nullableModel = (() => { if ('enum' in openAPISpecification) { return 'String'; } return (0, PropertySchemaCodeGenerator_1.getModelsReferencedByPropertyType)(propertyType)[0]; })(); propertyDecorators.push(`@Nullable(${nullableModel})`); } const propertyName = (() => { if (basePropertyName.match(/\W/g)) { if (generateTsEDControllers) { return basePropertyName.toCamelCase(); } else { return `'${basePropertyName}'`; } } return basePropertyName; })(); if (basePropertyName.match(/\W/g)) { propertyDecorators.push(`@Name('${basePropertyName}')`); if (generateTsEDControllers) { (0, Utils_1.addModuleImport)({ imports, importName: 'Name', importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH, }); } } const propertyTypeCode = isNullable ? `${propertyType} | null` : propertyType; const propertyValueSeparator = required ? '!:' : '?:'; const typeDefinitionSnippet = ` ${propertyDecorators.join('\n')} ${accessModifier} ${propertyName}${propertyValueSeparator} ${propertyTypeCode} `.trimIndent(); return typeDefinitionSnippet; }) .join(';\n\n'); const modelDecorators = []; if (schema.description) { if (generateTsEDControllers) { (0, Utils_1.addModuleImport)({ imports, importName: 'Description', importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH, }); } modelDecorators.push(`@Description(${JSON.stringify(schema.description)})`); } const tsedModelCode = ` ${modelDecorators.join('\n')} export class ${schemaName} { ${tsedModelPropertiesCode} } `.trimIndent(); const schemaCode = [ ...(() => { if (!(0, lodash_1.isEmpty)(generatedVariables)) { return Object.values(generatedVariables); } return []; })(), zodValidationSchemaCode, ...(() => { if (generateTsEDControllers && tsedModelCode) { return [tsedModelCode]; } if (!inferTypeFromValidationSchema || modelIsRecursive) { const interfacePropertiesCode = modelPropertiesCodeConfiguration .map(({ propertyName, propertyType, required, openAPISpecification, isNullable, }) => { const propertiesTypeCode = isNullable ? `${propertyType} | null` : propertyType; const propertyValueSeparator = required && propertiesTypeCode !== 'any' ? ': ' : '?: '; const propertyValueSnippet = `'${propertyName}'${propertyValueSeparator} ${propertiesTypeCode}`; const jsDocCommentLines = []; if ('description' in openAPISpecification && openAPISpecification.description) { jsDocCommentLines.push(openAPISpecification.description); } if ('example' in openAPISpecification && openAPISpecification.example) { if (typeof openAPISpecification.example === 'object') { jsDocCommentLines.push(`@example\n\`\`\`json\n${JSON.stringify(openAPISpecification.example, null, 2)}\n\`\`\``); } else { jsDocCommentLines.push(`@example ${JSON.stringify(openAPISpecification.example)}`); } } if ('default' in openAPISpecification && openAPISpecification.default) { jsDocCommentLines.push(`@default ${JSON.stringify(openAPISpecification.default)}`); } if (openAPISpecification.deprecated) { jsDocCommentLines.push(`@deprecated`); } if (jsDocCommentLines.length > 0) { const linesString = jsDocCommentLines .reduce((acumulator, line) => { acumulator.push(line); return acumulator; }, []) .map((line) => { return line .split('\n') .map((lineSlice) => ` * ${lineSlice}`) .join('\n'); }) .join('\n *\n'); const jsDocCommentCode = ` /** ${linesString} */ `.trimIndent(); return `${jsDocCommentCode}\n${propertyValueSnippet}`; } return propertyValueSnippet; }) .join(';\n\n'); const interfaceCode = ` export interface ${schemaName} { ${interfacePropertiesCode} } `.trimIndent(); return [interfaceCode]; } return [inferedTypeCode]; })(), ].join('\n\n'); return { zodValidationSchemaCode: ` //#region ${schemaName} ${schemaCode} //#endregion `.trimIndent(), referencedSchemas, zodValidationSchemaName, inferedTypeCode, imports, ...(() => { if (!(0, lodash_1.isEmpty)(generatedVariables)) { return { generatedVariables, }; } })(), ...(() => { if (generateTsEDControllers) { return { tsedModelCode, tsedModelName: schemaName, }; } })(), }; } }; exports.generateModelCode = generateModelCode; //#endregion //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTW9kZWxDb2RlR2VuZXJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9Nb2RlbENvZGVHZW5lcmF0b3IvTW9kZWxDb2RlR2VuZXJhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUFpQztBQUVqQyx5Q0FJc0I7QUFDdEIsb0NBQTJDO0FBQzNDLCtFQUd1QztBQXlCdkM7Ozs7O0dBS0c7QUFDSSxNQUFNLGlCQUFpQixHQUFHLENBQUMsRUFDaEMsVUFBVSxFQUNWLG9CQUFvQixFQUNwQix1QkFBdUIsRUFDdkIsNkJBQTZCLEdBQUcsSUFBSSxHQUNYLEVBQUUsRUFBRTtJQUM3QixNQUFNLE1BQU0sR0FBRyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ25FLElBQ0UsTUFBTSxJQUFJLE1BQU07UUFDaEIsTUFBTSxDQUFDLElBQUksS0FBSyxRQUFRO1FBQ3hCLFlBQVksSUFBSSxNQUFNO1FBQ3RCLE1BQU0sQ0FBQyxVQUFVLEVBQ2pCO1FBQ0EsTUFBTSxpQkFBaUIsR0FBYSxFQUFFLENBQUM7UUFDdkMsTUFBTSxrQkFBa0IsR0FBMkIsRUFBRSxDQUFDO1FBQ3RELE1BQU0sdUJBQXVCLEdBQUcsR0FBRyxVQUFVLGtCQUFrQixDQUFDO1FBQ2hFLE1BQU0sZUFBZSxHQUFHLGVBQWUsVUFBVSxxQkFBcUIsdUJBQXVCLEdBQUcsQ0FBQztRQUNqRyxNQUFNLE9BQU8sR0FBa0I7WUFDN0IsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDO1NBQ1gsQ0FBQztRQUVGLE1BQU0sZ0NBQWdDLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FDckQsTUFBTSxDQUFDLFVBQVUsQ0FDbEIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFlBQVksRUFBRSxjQUFjLENBQUMsRUFBRSxFQUFFO1lBQ3ZDLE1BQU0sRUFDSixpQkFBaUIsRUFBRSx5QkFBeUIsRUFDNUMsT0FBTyxFQUFFLGVB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