@typescript-generate-swagger/swagger-tegg
Version:
357 lines (356 loc) • 14 kB
JavaScript
;
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;
}
}
}
}