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.

445 lines 37.4 kB
"use strict"; 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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