UNPKG

@ply-ct/ply

Version:

REST API Automated Testing

213 lines 9.04 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Ts = void 0; const path = __importStar(require("path")); const fs = __importStar(require("fs")); const ts = __importStar(require("typescript")); const glob = __importStar(require("glob")); class Ts { constructor(tsConfig = 'tsconfig.json', sourcePatterns = ['src/**/*.ts']) { let files = []; for (const sourcePattern of sourcePatterns) { files = [...files, ...glob.sync(sourcePattern)]; } const configPath = ts.findConfigFile('.', ts.sys.fileExists, tsConfig); if (!configPath) { throw new Error("Could not find a valid 'tsconfig.json' from " + path.resolve('.')); } const configContents = fs.readFileSync(configPath).toString(); const compilerOptions = ts.parseConfigFileTextToJson(configPath, configContents); this.program = ts.createProgram(files, compilerOptions); this.checker = this.program.getTypeChecker(); } scanClassDecorators(decs) { let decorators = []; for (const sourceFile of this.program .getSourceFiles() .filter((sf) => !sf.isDeclarationFile)) { ts.forEachChild(sourceFile, (node) => { if (ts.isClassDeclaration(node) && node.name && Ts.isExported(node)) { decorators = [ ...decorators, ...this.findClassDecorators(sourceFile, node, decs) ]; } }); } return decorators; } findClassDecorators(sourceFile, classDeclaration, decs) { const classDecs = []; const classSymbol = this.checker.getSymbolAtLocation(classDeclaration.name); if (classSymbol) { let decorators; if (ts.getDecorators) { decorators = ts.getDecorators(classDeclaration); } else { // old typescript compiler sdk incompatible decorators = classDeclaration.decorators; } if (decorators) { for (const decorator of decorators) { const decoratorSymbol = this.getDecoratorSymbol(decorator); if (decoratorSymbol) { const decoratorType = this.checker.getAliasedSymbol(decoratorSymbol).name; if (decs.includes(decoratorType)) { classDecs.push({ file: sourceFile.fileName, class: classSymbol.name, decorator: decoratorType, ...Ts.decoratorArgs(decorator) }); } } } } } return classDecs; } findMethodDecorators(classDecorator, decs) { const methodDecs = []; const classDeclaration = this.getClassDeclaration(classDecorator.file, classDecorator.class); if (classDeclaration) { for (const methodDeclaration of Ts.methodDeclarations(classDeclaration)) { const methodSymbol = this.checker.getSymbolAtLocation(methodDeclaration.name); let decorators; if (methodSymbol) { if (ts.getDecorators) { decorators = ts.getDecorators(methodDeclaration); } else { // old typescript compiler sdk incompatible decorators = methodDeclaration.decorators; } if (decorators) { for (const decorator of decorators) { const decoratorSymbol = this.getDecoratorSymbol(decorator); if (decoratorSymbol) { const decoratorType = this.checker.getAliasedSymbol(decoratorSymbol).name; if (decs.includes(decoratorType)) { methodDecs.push({ file: classDecorator.file, class: classDecorator.class, decorator: decoratorType, method: methodSymbol.name, ...Ts.decoratorArgs(decorator) }); } } } } } } } return methodDecs; } getClassDeclaration(file, className) { const sourceFile = this.program.getSourceFile(file); if (sourceFile) { let classDeclaration; ts.forEachChild(sourceFile, (node) => { if (ts.isClassDeclaration(node) && node.name && Ts.isExported(node)) { const classDecl = node; const classSymbol = this.checker.getSymbolAtLocation(classDecl.name); if ((classSymbol === null || classSymbol === void 0 ? void 0 : classSymbol.name) === className) { classDeclaration = classDecl; } } }); return classDeclaration; } } getDecoratorSymbol(decorator) { if (decorator.expression) { const firstToken = decorator.expression.getFirstToken(); if (firstToken) { return this.checker.getSymbolAtLocation(firstToken); } else { return this.checker.getSymbolAtLocation(decorator.expression); } } } static decoratorArgs(decorator) { const args = {}; if (decorator.expression.getChildCount() >= 3) { let text = decorator.expression.getChildAt(2).getText().trim(); if (decorator.expression.getChildAt(2).getChildCount() >= 3 && ts.isObjectLiteralExpression(decorator.expression.getChildAt(2).getChildAt(2))) { args.args = Ts.parseObjectLiteral(decorator.expression.getChildAt(2).getChildAt(2)); text = decorator.expression.getChildAt(2).getChildAt(0).getText().trim(); } args.arg = text.substring(1, text.length - 1); } return args; } static methodDeclarations(classDeclaration) { const methodDeclaration = []; classDeclaration.forEachChild((node) => { if (ts.isMethodDeclaration(node) && !ts.isPrivateIdentifier(node)) { methodDeclaration.push(node); } }); return methodDeclaration; } static symbolAtNode(node) { return node.symbol; } static isExported(node) { return ((ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 || (!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile)); } /** * Only handles simple types */ static parseObjectLiteral(objLit) { var _a; const res = {}; for (const prop of objLit.properties) { const propName = (_a = prop.name) === null || _a === void 0 ? void 0 : _a.getText(); if (propName && prop.initializer) { if (prop.initializer.text) { res[propName] = prop.initializer.text; } else { const textVal = prop.initializer.getText(); if (textVal === 'true' || textVal === 'false') { res[propName] = textVal === 'true'; } else if (parseInt(textVal)) { res[propName] = parseInt(textVal); } } } } return res; } } exports.Ts = Ts; //# sourceMappingURL=ts.js.map