UNPKG

@typescript-generate-swagger/swagger-tegg

Version:
357 lines (356 loc) 14 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parserController = exports.getControllerFiles = void 0; const ts = __importStar(require("typescript")); const swagger_generate_1 = require("@typescript-generate-swagger/swagger-generate"); const swagger_generate_2 = require("@typescript-generate-swagger/swagger-generate"); const swagger_generate_3 = require("@typescript-generate-swagger/swagger-generate"); const swagger_generate_4 = require("@typescript-generate-swagger/swagger-generate"); const swagger_generate_5 = require("@typescript-generate-swagger/swagger-generate"); const path_1 = __importDefault(require("path")); function getHttpMethodModifyArg(modifiers) { for (let modifier of modifiers) { if (ts.isDecorator(modifier)) { let { expression } = modifier; if (!ts.isCallExpression(expression)) { continue; } if (!ts.isIdentifier(expression.expression)) { continue; } if (expression.expression.escapedText == 'HTTPMethod') { let arg = expression.arguments[0]; if (ts.isObjectLiteralExpression(arg)) { return arg; } } } } } function getPathMethod(modifiers) { if (!modifiers) { return; } let http = swagger_generate_2.HttpMethod.GET; let path = ''; let arg = getHttpMethodModifyArg(modifiers); if (!arg) { return; } let { properties } = arg; properties.forEach(propertie => { if (!ts.isPropertyAssignment(propertie)) { return; } let { name, initializer } = propertie; if (name.getText() == 'method') { if (ts.isPropertyAccessExpression(initializer)) { http = initializer.name.getText().toLowerCase(); } } if (name.getText() == 'path') { if (ts.isStringLiteral(initializer)) { path = initializer.getText().slice(1, -1); } } }); return { http, path }; } function getControllerBasePath(modifiers) { for (let modifier of modifiers) { if (ts.isDecorator(modifier)) { let { expression, } = modifier; if (ts.isCallExpression(expression)) { let name = expression.expression.getText(); let arg = expression.arguments[0]; if (name == 'HTTPController') { let basePath = ''; if (ts.isObjectLiteralExpression(arg)) { for (let property of arg.properties) { if (ts.isPropertyAssignment(property)) { let { name, initializer } = property; if (name.getText() == 'path') { if (ts.isStringLiteral(initializer)) { basePath = initializer.getText().slice(1, -1); return basePath; } } } } } } } } } } function getParameterDecoratorModifers(modifiers) { if (!modifiers) { return []; } return modifiers.filter(modifier => modifier.kind == ts.SyntaxKind.Decorator); } function isHttpQuery(modifiers) { return modifiers.find(modifier => { return modifier.getText() == '@HTTPQuery()'; }); } function isHttpBody(modifiers) { return modifiers.find(modifier => { return modifier.getText() == '@HTTPBody()'; }); } function processClassMemberQueryParameters(parameters) { let typeNodeInfoQuery = { type: swagger_generate_2.SwaggerTypes.object, properties: {}, }; parameters.forEach(parameter => { let { type, questionToken, name, modifiers } = parameter; // console.log(name.getText()) let modiferDecorators = getParameterDecoratorModifers(modifiers); if (isHttpQuery(modiferDecorators)) { let { name, typeNodeInfo } = processQuery(parameter); typeNodeInfoQuery.properties[name] = typeNodeInfo; } }); function processQuery(parameter) { let { type, questionToken, name, modifiers } = parameter; let typeText = (0, swagger_generate_1.getDocType)(type); let description = (0, swagger_generate_3.getTsNodeComment)(parameter); let nameText = name.getText(); let required = !questionToken; let typeNodeInfo = { type: typeText, description: description, }; if (required) { typeNodeInfo.required = required; } return { name: nameText, typeNodeInfo, }; } return typeNodeInfoQuery; } function findCtxQueryType(BodyBlock) { let statements = BodyBlock.statements; for (let statement of statements) { if (!ts.isVariableStatement(statement)) { continue; } let declarations = statement.declarationList.declarations; for (let declaration of declarations) { let { initializer, name } = declaration; if (!initializer) { continue; } function getCtxQueryPropertyAccessExpression(initExpression) { if (ts.isAsExpression(initExpression)) { let { expression } = initExpression; return getCtxQueryPropertyAccessExpression(expression); } if (ts.isPropertyAccessExpression(initExpression)) { let { name } = initExpression; let nameText = name.getText(); if (nameText == 'query') { let nextExpress = initExpression.expression; if (ts.isIdentifier(nextExpress)) { let nextName = nextExpress.getText(); if (nextName == 'ctx') { return initExpression; } } } } } let hasCtxQuery = getCtxQueryPropertyAccessExpression(initializer); if (hasCtxQuery) { return initializer; } } } } function getControllerFiles(programe) { let files = programe.getSourceFiles(); return files.filter(file => { return file.fileName.match(new RegExp(`/app/module/.*controller`, 'i')); }); } exports.getControllerFiles = getControllerFiles; const parserController = (parserTypeInfo) => { let programe = parserTypeInfo.programe; let checker = parserTypeInfo.checker; let controllers = getControllerFiles(programe); let pathInfo = {}; controllers.forEach(controller => { let controllerInfo = new ParserControllerInfo(checker, parserTypeInfo, programe); let currentPathInfo = controllerInfo.getControllerInfo(controller); // let currentPathInfo = processController(checker, controller) pathInfo = { ...pathInfo, ...currentPathInfo, }; }); let schemas = parserTypeInfo.getSchemaTypeInfo(); (0, swagger_generate_5.createDoc)(pathInfo, schemas); }; exports.parserController = parserController; class ParserControllerInfo { checker; parserTypeInfo; programe; constructor(checker, parserTypeInfo, programe) { this.checker = checker; this.parserTypeInfo = parserTypeInfo; this.programe = programe; } getControllerInfo(controller) { let checker = this.checker; let pathInfo = {}; for (let statement of controller.statements) { if (ts.isClassDeclaration(statement)) { let { members, modifiers = [] } = statement; let basePath = getControllerBasePath(modifiers); if (basePath === undefined) { continue; } let classType = this.parserTypeInfo.checker.getTypeAtLocation(statement); let allMemebers = classType.getProperties().map(item => item.getDeclarations()[0]); let currentPathInfo = this.getControllerPath(allMemebers, basePath); pathInfo = { ...pathInfo, ...currentPathInfo }; } } return pathInfo; } getControllerPath(members, basePath) { let checker = this.checker; let pathInfo = {}; for (let member of members) { if (ts.isMethodDeclaration(member)) { let response = this.parserTypeInfo.getReturnType(checker, member); let currentPathInfo = this.processPathInfo(checker, member, response, basePath); if (currentPathInfo) { let fullPath = path_1.default.posix.join(basePath, currentPathInfo.path); let { http, httpContent } = currentPathInfo; let currentPath = pathInfo[fullPath] = pathInfo[fullPath] || {}; currentPath[http] = httpContent; } } } return pathInfo; } processPathInfo(checker, member, response, basePath = '') { let { modifiers } = member; const { summary, description, router } = (0, swagger_generate_1.getCommentTags)(member); const [docMethod, docPath] = router.split(' ').map(item => item.trim()); let pathMethod = getPathMethod(modifiers); let path = '', http = ''; if (pathMethod) { http = pathMethod.http; path = pathMethod.path; } else { http = docMethod; path = docPath; } if (!http && !path) { return; } http = http.toLowerCase(); let { parameters, requestBody } = this.processClassMemberParameters(checker, member); let currentPathInfo = {}; if (parameters.length) { currentPathInfo.parameters = parameters; } if (http != swagger_generate_2.HttpMethod.GET && requestBody) { currentPathInfo.requestBody = requestBody; } if (response) { currentPathInfo.responses = (0, swagger_generate_5.convertTypeNodeInfoToSwaggerResponse)(response); } // let { summary, description } = getCommentTags(member) // fs.writeFileSync(`${__dirname}/teggController.ts`, file.text) return { path, http: http, httpContent: { summary, description, ...currentPathInfo, } }; } processClassMemberParameters(checker, member) { let { parameters, body } = member; let swaggerParameters = []; let queryParamentersTypeNodeInfo = processClassMemberQueryParameters(parameters); swaggerParameters = (0, swagger_generate_4.convertTypeNodeToSwggerParameters)(queryParamentersTypeNodeInfo); if (body) { let queryInFunctionBody = this.processClassMemberQueryInFunctionBody(checker, body); if (queryInFunctionBody) { swaggerParameters = swaggerParameters.concat((0, swagger_generate_4.convertTypeNodeToSwggerParameters)(queryInFunctionBody)); } } let requestBody = this.processClassMemberBodyParameters(checker, member); let swaggerRequestBody = (0, swagger_generate_4.convertTypeNodeInfoToSwaggerRequestBody)(requestBody); return { parameters: swaggerParameters, requestBody: swaggerRequestBody }; } processClassMemberQueryInFunctionBody(checker, BodyBlock) { let expression = findCtxQueryType(BodyBlock); if (!expression) { return; } let type = checker.getTypeAtLocation(expression); let symbolNode = type.getSymbol(); if (symbolNode) { return this.parserTypeInfo.getTypeNode(type, { cacheSchema: false }); } } processClassMemberBodyParameters(checker, member) { let { parameters, body } = member; for (let parameter of parameters) { let { type, questionToken, name, modifiers } = parameter; let modiferDecorators = getParameterDecoratorModifers(modifiers); let isBody = isHttpBody(modiferDecorators); if (isBody && type) { let typeObject = checker.getTypeAtLocation(type); let response = this.parserTypeInfo.getTypeNode(typeObject); return response; } } } }