@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
JavaScript
;
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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