@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.
445 lines • 37.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTSEDControllersCodeConfiguration = void 0;
const lodash_1 = require("lodash");
const models_1 = require("../models");
const SchemaGenerator_1 = require("./SchemaGenerator");
const Utils_1 = require("./Utils");
const getTSEDControllersCodeConfiguration = ({ requestGroupings, tagToEntityLabelMappings, schemaToEntityMappings, authenticateDecoratorImportPath, authorizeDecoratorImportPath, tsedControllerNamePrefix, tsedControllerNameSuffix, propagateRequestHeaders = false, openAPISpecification, }) => {
return Object.keys(requestGroupings).reduce((accumulator, tag) => {
const imports = (0, lodash_1.cloneDeep)(requestGroupings[tag].imports);
//#region Generate entity api request functions
const controllerMethodsCode = requestGroupings[tag].requests
.map((request) => {
const { method, operationName, description, requestPath: baseRequestPath, pathParameters, headerParameters, headerParametersModelReference, queryParameters, queryParametersModelReference, requestBody, requestBodySchemaName, requestBodyType, requestBodyTypeDependentSchemaName, successResponseSchemas, summary, } = request;
const streamAPIResponse = request['x-requestConfig']?.tsedControllerConfig?.streamAPIResponse;
const responseHeaders = request['x-requestConfig']?.tsedControllerConfig?.responseHeaders;
const permissions = request['x-requestConfig']?.tsedControllerConfig?.permissions;
const userDefinedRequestPath = request['x-requestConfig']?.tsedControllerConfig?.path;
const requestPath = userDefinedRequestPath ?? baseRequestPath;
const { controllerMethodDecorators, controllerMethodParametersCode, responseHeadersCode, apiFunctionCallArgumentsCode, } = (() => {
const controllerMethodRequestMethodName = method.toPascalCase();
const controllerRequestPath = requestPath
.replace(/(\/api\b|\/v\d+\b)/g, '')
.replace(new RegExp(`\\/${tagToEntityLabelMappings[tag]['kebab-case-entities']}\\b`, 'g'), '')
.replace(/\{(\w+?)\}/g, ':$1');
const controllerMethodDecorators = [
controllerRequestPath.length > 0
? `@${controllerMethodRequestMethodName}('${controllerRequestPath}')`
: `@${controllerMethodRequestMethodName}()`,
];
(0, Utils_1.addModuleImport)({
imports,
importName: controllerMethodRequestMethodName,
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
if (authorizeDecoratorImportPath &&
permissions &&
permissions.length > 0) {
const permissionsVariableNames = permissions.map((permissionCode) => {
return `${permissionCode
.replace(/\W+/g, '_')
.toUpperCase()}_PERMISSION`;
});
permissionsVariableNames.forEach((permissionsVariableName) => {
(0, Utils_1.addModuleImport)({
imports,
importName: permissionsVariableName,
importFilePath: '../permissions',
});
});
controllerMethodDecorators.push(`@Authorize(${permissionsVariableNames.join(', ')})`);
(0, Utils_1.addModuleImport)({
imports,
importName: 'Authorize',
importFilePath: authorizeDecoratorImportPath,
});
}
if (summary) {
(0, Utils_1.addModuleImport)({
imports,
importName: 'Summary',
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
controllerMethodDecorators.push(`@Summary('${summary}')`, '');
}
if (description) {
(0, Utils_1.addModuleImport)({
imports,
importName: 'Description',
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
controllerMethodDecorators.push(`@Description(${JSON.stringify(description)})`, '');
}
if (propagateRequestHeaders || responseHeaders) {
(0, Utils_1.addModuleImport)({
imports,
importName: 'Context',
importFilePath: models_1.TSED_COMMON_LIBRARY_PATH,
});
}
//#region Controller Method parameters code
const controllerMethodParametersCode = [
//#region Path parameters
...(() => {
if (pathParameters?.length) {
(0, Utils_1.addModuleImport)({
imports,
importName: 'PathParams',
importFilePath: models_1.TSED_COMMON_LIBRARY_PATH,
});
return pathParameters.map(({ name, schema, description }) => {
const decorators = [`@PathParams('${name}')`];
if (description) {
decorators.push(`@Description(${JSON.stringify(description)})`);
(0, Utils_1.addModuleImport)({
imports,
importName: 'Description',
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
}
if ('enum' in schema && schema.enum?.length) {
decorators.push(`@Enum(${schema.enum
.filter((value) => value.length > 0)
.map((value) => `'${value}'`)
.join(', ')})`);
(0, Utils_1.addModuleImport)({
imports,
importName: 'Enum',
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
}
return `${decorators.join(' ')} ${name}: ${(0, SchemaGenerator_1.getPrimitiveSchemaType)(schema)}`;
});
}
return [];
})(),
//#endregion
//#region Request body parameters
...(() => {
if (requestBody && (requestBodySchemaName || requestBodyType)) {
(0, Utils_1.addModuleImport)({
imports,
importName: 'BodyParams',
importFilePath: models_1.TSED_COMMON_LIBRARY_PATH,
});
if (requestBodySchemaName) {
const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[requestBodySchemaName]].PascalCaseEntities}`.trim();
(0, Utils_1.addModuleImport)({
imports,
importName: requestBodySchemaName,
importFilePath: schemaSource,
});
return [
`@BodyParams() requestPayload: ${requestBodySchemaName}`,
];
}
if (requestBodyType) {
if (requestBodyTypeDependentSchemaName) {
const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[requestBodyTypeDependentSchemaName]].PascalCaseEntities}`.trim();
(0, Utils_1.addModuleImport)({
imports,
importName: requestBodyTypeDependentSchemaName,
importFilePath: schemaSource,
});
}
return [`@BodyParams() requestPayload: ${requestBodyType}`];
}
}
return [];
})(),
//#endregion
//#region Header parameters
...(() => {
if (headerParametersModelReference &&
headerParameters &&
headerParameters.length > 0) {
(0, Utils_1.addModuleImport)({
imports,
importName: 'HeaderParams',
importFilePath: models_1.TSED_COMMON_LIBRARY_PATH,
});
const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[headerParametersModelReference]].PascalCaseEntities}`.trim();
(0, Utils_1.addModuleImport)({
imports,
importName: headerParametersModelReference,
importFilePath: schemaSource,
});
return [
`@HeaderParams() headers: ${headerParametersModelReference}`,
];
}
return [];
})(),
//#endregion
//#region Query parameters
...(() => {
if (queryParametersModelReference &&
queryParameters &&
queryParameters.length > 0) {
(0, Utils_1.addModuleImport)({
imports,
importName: 'QueryParams',
importFilePath: models_1.TSED_COMMON_LIBRARY_PATH,
});
const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[queryParametersModelReference]].PascalCaseEntities}`.trim();
(0, Utils_1.addModuleImport)({
imports,
importName: queryParametersModelReference,
importFilePath: schemaSource,
});
return [
`@QueryParams() queryParams: ${queryParametersModelReference}`,
];
}
return [];
})(),
//#endregion
//#region Context
...(() => {
if (propagateRequestHeaders || responseHeaders) {
return [`@Context() ctx: Context`];
}
return [];
})(),
//#endregion
].join(', ');
//#endregion
//#region Success response schemas
if (successResponseSchemas && successResponseSchemas.length > 0) {
successResponseSchemas.forEach((successResponseSchema) => {
const { httpStatusCode, description, contentType } = successResponseSchema;
(0, Utils_1.addModuleImport)({
imports,
importName: 'Returns',
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
if ('name' in successResponseSchema) {
const { name, isArray } = successResponseSchema;
if (!models_1.ENVIRONMENT_DEFINED_MODELS.includes(name)) {
(0, Utils_1.addModuleImport)({
imports,
importName: name,
importFilePath: `../models/${tagToEntityLabelMappings[schemaToEntityMappings[name]]
.PascalCaseEntities}`.trim(),
});
}
if (isArray) {
controllerMethodDecorators.push(`@Returns(${httpStatusCode}, Array).Of(${name})` +
(() => {
if (description) {
return `.Description(${JSON.stringify(description)})`;
}
return '';
})());
}
else {
controllerMethodDecorators.push(`@Returns(${httpStatusCode}, ${name})` +
(() => {
if (description) {
return `.Description(${JSON.stringify(description)})`;
}
return '';
})() +
(() => {
if (contentType) {
return `.ContentType(${JSON.stringify(contentType)})`;
}
})());
}
}
if ('type' in successResponseSchema) {
const { type } = successResponseSchema;
const typeModel = models_1.primitiveTypeToModelMapping[type];
let returnTypeDecorator = typeModel
? `@Returns(${httpStatusCode}, ${typeModel})`
: `@Returns(${httpStatusCode})`;
if (description) {
returnTypeDecorator += `.Description(${JSON.stringify(description)})`;
}
if (contentType) {
returnTypeDecorator += `.ContentType(${JSON.stringify(contentType)})`;
}
controllerMethodDecorators.push(returnTypeDecorator);
}
});
}
//#endregion
//#region Response headers code
const responseHeadersCode = (() => {
if (responseHeaders) {
return `ctx.response.setHeaders(${JSON.stringify(responseHeaders, null, 2)});`;
}
return '';
})();
//#endregion
//#region API function call arguments code
const apiFunctionCallArgumentsCode = [
//#region Path parameters
...(() => {
if (pathParameters?.length) {
return pathParameters.map(({ name }) => name);
}
return [];
})(),
//#endregion
//#region Request body parameters
...(() => {
if (requestBody && (requestBodySchemaName || requestBodyType)) {
return ['requestPayload'];
}
return [];
})(),
//#endregion
//#region Header parameters
...(() => {
if (headerParametersModelReference &&
headerParameters &&
headerParameters.length > 0) {
return ['headers'];
}
return [];
})(),
//#endregion
//#region Query parameters
...(() => {
if (queryParametersModelReference &&
queryParameters &&
queryParameters.length > 0) {
return [`queryParams`];
}
return [];
})(),
//#endregion
//#region Request options
...(() => {
if (propagateRequestHeaders) {
if (streamAPIResponse) {
return [
`{
unWrapResponse: false,
responseType: 'stream',
headers: (() => {
const headers = { ...ctx.request.headers };
['origin', 'host', 'content-length'].forEach((headerKey) => {
delete headers[headerKey];
});
return headers;
})(),
}`,
];
}
return [
`
{
headers: (() => {
const headers = { ...ctx.request.headers };
['origin', 'host', 'content-length'].forEach((headerKey) => {
delete headers[headerKey];
});
return headers;
})(),
}
`.trimIndent(),
];
}
if (streamAPIResponse) {
return [
`{
unWrapResponse: false,
responseType: 'stream'
}`,
];
}
return [];
})(),
//#endregion
].join(', ');
//#endregion
return {
controllerMethodDecorators: (() => {
if (controllerMethodDecorators.length > 0) {
return controllerMethodDecorators.join('\n');
}
return '';
})(),
controllerMethodParametersCode,
apiFunctionCallArgumentsCode,
responseHeadersCode,
};
})();
(0, Utils_1.addModuleImport)({
imports,
importName: operationName,
importFilePath: '../api',
});
return `
${controllerMethodDecorators}
async ${operationName}(${controllerMethodParametersCode}) {
${responseHeadersCode}
return ${operationName}(${apiFunctionCallArgumentsCode});
}
`.trimIndent();
})
.join('\n\n');
//#endregion
(0, Utils_1.addModuleImport)({
imports,
importName: 'Controller',
importFilePath: models_1.TSED_DEPENDENCY_INJECTION_LIBRARY_PATH,
});
(0, Utils_1.addModuleImport)({
imports,
importName: 'Docs',
importFilePath: models_1.TSED_SWAGGER_LIBRARY_PATH,
});
(0, Utils_1.addModuleImport)({
imports,
importName: 'Name',
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
let controllerName = tagToEntityLabelMappings[tag]['Entities Label'];
if (tsedControllerNamePrefix) {
controllerName = tsedControllerNamePrefix + controllerName;
}
if (tsedControllerNameSuffix) {
controllerName = controllerName + tsedControllerNameSuffix;
}
const classDecorators = [
`@Controller('/${tagToEntityLabelMappings[tag]['kebab-case-entities']}')`,
`@Docs('api-v1')`,
`@Name('${controllerName}')`,
];
const classDescription = openAPISpecification.tags.find(({ name }) => name === tag)?.description;
if (classDescription) {
classDecorators.push(`@Description(${JSON.stringify(classDescription)})`);
(0, Utils_1.addModuleImport)({
imports,
importName: 'Description',
importFilePath: models_1.TSED_SCHEMA_LIBRARY_PATH,
});
}
if (authenticateDecoratorImportPath) {
classDecorators.push(`@Authenticate()`);
(0, Utils_1.addModuleImport)({
imports,
importName: 'Authenticate',
importFilePath: authenticateDecoratorImportPath,
});
}
const outputCode = `
${classDecorators.join('\n')}
export class ${tagToEntityLabelMappings[tag].PascalCaseEntity}Controller {
${controllerMethodsCode}
}
`.trimIndent();
accumulator[tag] = {
outputCode,
imports,
};
return accumulator;
}, {});
};
exports.getTSEDControllersCodeConfiguration = getTSEDControllersCodeConfiguration;
//#endregion
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVFNFRENvbnRyb2xsZXJzQ29kZUdlbmVyYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvVFNFRENvbnRyb2xsZXJzQ29kZUdlbmVyYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtQ0FBbUM7QUFFbkMsc0NBV21CO0FBQ25CLHVEQUEyRDtBQUMzRCxtQ0FBMEM7QUFpRG5DLE1BQU0sbUNBQW1DLEdBQUcsQ0FBQyxFQUNsRCxnQkFBZ0IsRUFDaEIsd0JBQXdCLEVBQ3hCLHNCQUFzQixFQUN0QiwrQkFBK0IsRUFDL0IsNEJBQTRCLEVBQzVCLHdCQUF3QixFQUN4Qix3QkFBd0IsRUFDeEIsdUJBQXVCLEdBQUcsS0FBSyxFQUMvQixvQkFBb0IsR0FDNEIsRUFBRSxFQUFFO0lBQ3BELE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUUsRUFBRTtRQUMvRCxNQUFNLE9BQU8sR0FBRyxJQUFBLGtCQUFTLEVBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFekQsK0NBQStDO1FBQy9DLE1BQU0scUJBQXFCLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUTthQUN6RCxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNmLE1BQU0sRUFDSixNQUFNLEVBQ04sYUFBYSxFQUNiLFdBQVcsRUFDWCxXQUFXLEVBQUUsZUFBZSxFQUM1QixjQUFjLEVBQ2QsZ0JBQWdCLEVBQ2hCLDhCQUE4QixFQUM5QixlQUFlLEVBQ2YsNkJBQTZCLEVBQzdCLFdBQVcsRUFDWCxxQkFBcUIsRUFDckIsZUFBZSxFQUNmLGtDQUFrQyxFQUNsQyxzQkFBc0IsRUFDdEIsT0FBTyxHQUNSLEdBQUcsT0FBTyxDQUFDO1lBRVosTUFBTSxpQkFBaUIsR0FDckIsT0FBTyxDQUFDLGlCQUFpQixD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