UNPKG

@trapi/metadata

Version:

Generate REST-API metadata scheme from TypeScript Decorators.

140 lines 5.46 kB
"use strict"; /* * Copyright (c) 2022-2023. * Author Peter Placzek (tada5hi) * For the full copyright and license information, * view the LICENSE file that was distributed with this source code. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MetadataGenerator = void 0; const minimatch_1 = require("minimatch"); const typescript_1 = require("typescript"); const cache_1 = require("../../cache"); const decorator_1 = require("../../decorator"); const resolver_1 = require("../../resolver"); const controller_1 = require("../controller"); class MetadataGenerator { // ------------------------------------------------------------------------- constructor(context) { this.referenceTypes = {}; this.circularDependencyResolvers = new Array(); this.nodes = []; this.config = context.options; this.cache = new cache_1.CacheClient(context.options.cache); this.decoratorResolver = new decorator_1.DecoratorResolver(); this.program = (0, typescript_1.createProgram)(context.sourceFiles, context.compilerOptions || {}); this.typeChecker = this.program.getTypeChecker(); resolver_1.TypeNodeResolver.clearCache(); } // ------------------------------------------------------------------------- async generate() { const sourceFileSize = this.buildNodesFromSourceFiles(); let cache = await this.cache.get(sourceFileSize); if (!cache) { if (this.config.decorators) { this.decoratorResolver.apply(this.config.decorators); } if (this.config.preset) { await this.decoratorResolver.applyPreset(this.config.preset); } this.buildControllers(); this.circularDependencyResolvers.forEach((resolve) => resolve(this.referenceTypes)); cache = { controllers: this.controllers, referenceTypes: this.referenceTypes, sourceFilesSize: sourceFileSize, }; await this.cache.save(cache); } return { controllers: cache.controllers, referenceTypes: cache.referenceTypes, }; } buildNodesFromSourceFiles() { let endSize = 0; this.program.getSourceFiles().forEach((sf) => { if (this.isIgnoredPath(sf.fileName) && !this.isAllowedPath(sf.fileName)) { return; } endSize += sf.end; (0, typescript_1.forEachChild)(sf, (node) => { if ((0, typescript_1.isModuleDeclaration)(node)) { /** * For some reason unknown to me, TS resolves both `declare module` and `namespace` to * the same kind (`ModuleDeclaration`). In order to figure out whether it's one or the other, * we check the node flags. They tell us whether it is a namespace or not. */ // tslint:disable-next-line:no-bitwise if ((node.flags & typescript_1.NodeFlags.Namespace) === 0 && node.body && (0, typescript_1.isModuleBlock)(node.body)) { node.body.statements.forEach((statement) => { this.nodes.push(statement); }); return; } } this.nodes.push(node); }); }); return endSize; } // ------------------------------------------------------------------------- /** * Check if the source file path is in the ignored path list. * * @param filePath * @protected */ isIgnoredPath(filePath) { if (typeof this.config.ignore === 'undefined') { return false; } return this.config.ignore.some((item) => (0, minimatch_1.minimatch)(filePath, item)); } /** * Check if the source file path is in the ignored path list. * * @param filePath * @protected */ isAllowedPath(filePath) { if (typeof this.config.allow === 'undefined') { return false; } return this.config.allow.some((item) => (0, minimatch_1.minimatch)(filePath, item)); } // ------------------------------------------------------------------------- isExportedNode(node) { return true; } // ------------------------------------------------------------------------- addReferenceType(referenceType) { if (!referenceType.refName) { return; } this.referenceTypes[referenceType.refName] = referenceType; } getReferenceType(refName) { return this.referenceTypes[refName]; } registerDependencyResolver(callback) { this.circularDependencyResolvers.push(callback); } buildControllers() { this.controllers = []; for (let i = 0; i < this.nodes.length; i++) { const node = this.nodes[i]; if (!(0, typescript_1.isClassDeclaration)(node)) { continue; } const generator = new controller_1.ControllerGenerator(node, this); if (!generator.isValid()) { continue; } this.controllers.push(generator.generate()); } } } exports.MetadataGenerator = MetadataGenerator; //# sourceMappingURL=module.js.map