UNPKG

dpdm-fast

Version:

Analyze circular dependencies in your JavaScript/TypeScript projects with Rust.

140 lines 6.53 kB
"use strict"; /*! * Copyright 2019 acrazing <joking.young@gmail.com>. All rights reserved. * @since 2019-07-17 18:45:32 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.parseDependencyTree = parseDependencyTree; const tslib_1 = require("tslib"); const fs_extra_1 = tslib_1.__importDefault(require("fs-extra")); const G = tslib_1.__importStar(require("glob")); const path_1 = tslib_1.__importDefault(require("path")); const typescript_1 = tslib_1.__importDefault(require("typescript")); const consts_1 = require("./consts"); const utils_1 = require("./utils"); const typescriptTransformOptions = { target: typescript_1.default.ScriptTarget.ESNext, module: typescript_1.default.ModuleKind.ESNext, jsx: typescript_1.default.JsxEmit.Preserve, isolatedModules: true, }; function parseTreeRecursive(context, request, options, output, resolve) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const id = yield resolve(context, request, options.extensions); if (!id || output[id]) { return id; } if (!options.include.test(id) || options.exclude.test(id)) { output[id] = null; return id; } if (options.js.indexOf(path_1.default.extname(id)) === -1) { output[id] = []; return id; } options.onProgress('start', id); const dependencies = (output[id] = []); const jobs = []; const newContext = path_1.default.dirname(id); function nodeVisitor(node) { let newRequest; let kind; if (typescript_1.default.isImportDeclaration(node)) { newRequest = node.moduleSpecifier.text; kind = consts_1.DependencyKind.StaticImport; } else if (typescript_1.default.isCallExpression(node) && node.expression.kind === typescript_1.default.SyntaxKind.ImportKeyword && node.arguments.length === 1 && typescript_1.default.isStringLiteral(node.arguments[0]) && !options.skipDynamicImports) { newRequest = node.arguments[0].text; kind = consts_1.DependencyKind.DynamicImport; } else if (typescript_1.default.isCallExpression(node) && typescript_1.default.isIdentifier(node.expression) && node.expression.escapedText === 'require' && node.arguments.length === 1 && typescript_1.default.isStringLiteral(node.arguments[0])) { newRequest = node.arguments[0].text; kind = consts_1.DependencyKind.CommonJS; } else if (typescript_1.default.isExportDeclaration(node) && node.moduleSpecifier && typescript_1.default.isStringLiteral(node.moduleSpecifier)) { newRequest = node.moduleSpecifier.text; kind = consts_1.DependencyKind.StaticExport; } else { typescript_1.default.forEachChild(node, nodeVisitor); return; } dependencies.push({ issuer: id, request: newRequest, kind: kind, id: null, }); jobs.push(parseTreeRecursive(newContext, newRequest, options, output, resolve)); } const code = yield fs_extra_1.default.readFile(id, 'utf8'); const ext = path_1.default.extname(id); let source; if (options.transform && (ext === typescript_1.default.Extension.Ts || ext === typescript_1.default.Extension.Tsx)) { typescript_1.default.transpileModule(code, { compilerOptions: typescriptTransformOptions, transformers: { after: [() => (node) => (source = node)], }, }); } else { source = typescript_1.default.createSourceFile(id, code, typescript_1.default.ScriptTarget.Latest, true, typescript_1.default.ScriptKind.TSX); } typescript_1.default.forEachChild(source, nodeVisitor); options.onProgress('end', id); return Promise.all(jobs).then((deps) => { deps.forEach((id, index) => (dependencies[index].id = id)); return id; }); }); } /** * @param entries - the entry glob list * @param options */ function parseDependencyTree(entries, options) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (!Array.isArray(entries)) { entries = [entries]; } const currentDirectory = process.cwd(); const output = {}; const fullOptions = (0, utils_1.normalizeOptions)(options); let resolve = utils_1.simpleResolver; if (options.tsconfig) { const compilerOptions = typescript_1.default.parseJsonConfigFileContent(typescript_1.default.readConfigFile(options.tsconfig, typescript_1.default.sys.readFile).config, typescript_1.default.sys, path_1.default.dirname(options.tsconfig)).options; const host = typescript_1.default.createCompilerHost(compilerOptions); resolve = (context, request, extensions) => tslib_1.__awaiter(this, void 0, void 0, function* () { const module = typescript_1.default.resolveModuleName(request, path_1.default.join(context, 'index.ts'), compilerOptions, host).resolvedModule; if (module && module.extension !== typescript_1.default.Extension.Dts) { return module.resolvedFileName; } else { const filename = yield (0, utils_1.simpleResolver)(context, request, extensions); if (filename === null && module) { return (0, utils_1.simpleResolver)(context, module.resolvedFileName.slice(0, -typescript_1.default.Extension.Dts.length), extensions); } return filename; } }); } yield Promise.all(entries.map((entry) => G.glob(entry).then((matches) => Promise.all(matches.map((filename) => parseTreeRecursive(currentDirectory, path_1.default.join(currentDirectory, filename), fullOptions, output, resolve)))))); if (fullOptions.context) { return (0, utils_1.shortenTree)(fullOptions.context, output); } return output; }); } //# sourceMappingURL=parser.js.map