UNPKG

@nrwl/workspace

Version:

Smart, Fast and Extensible Build System.

148 lines 5.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.updateImports = void 0; const devkit_1 = require("@nrwl/devkit"); const ts = require("typescript"); const typescript_1 = require("../../../utilities/typescript"); const find_nodes_1 = require("../../../utilities/typescript/find-nodes"); const utils_1 = require("./utils"); /** * Updates all the imports in the workspace and modifies the tsconfig appropriately. * * @param schema The options provided to the schematic */ function updateImports(tree, schema, project) { if (project.projectType === 'application') { // These shouldn't be imported anywhere? return; } const { npmScope, libsDir } = (0, devkit_1.getWorkspaceLayout)(tree); const projects = (0, devkit_1.getProjects)(tree); // use the source root to find the from location // this attempts to account for libs that have been created with --importPath const tsConfigPath = (0, typescript_1.getRootTsConfigPathInTree)(tree); let tsConfig; let fromPath; if (tree.exists(tsConfigPath)) { tsConfig = JSON.parse(tree.read(tsConfigPath).toString('utf-8')); fromPath = Object.keys(tsConfig.compilerOptions.paths).find((path) => tsConfig.compilerOptions.paths[path].some((x) => x.startsWith(project.sourceRoot))); } const projectRef = { from: fromPath || (0, utils_1.normalizeSlashes)(`@${npmScope}/${project.root.slice(libsDir.length + 1)}`), to: schema.importPath, }; if (schema.updateImportPath) { const replaceProjectRef = new RegExp(projectRef.from, 'g'); for (const [name, definition] of Array.from(projects.entries())) { if (name === schema.projectName) { continue; } (0, devkit_1.visitNotIgnoredFiles)(tree, definition.root, (file) => { const contents = tree.read(file, 'utf-8'); replaceProjectRef.lastIndex = 0; if (!replaceProjectRef.test(contents)) { return; } updateImportPaths(tree, file, projectRef.from, projectRef.to); }); } } const projectRoot = { from: project.root.slice(libsDir.length + 1), to: schema.destination, }; if (tsConfig) { const path = tsConfig.compilerOptions.paths[projectRef.from]; if (!path) { throw new Error([ `unable to find "${projectRef.from}" in`, `${tsConfigPath} compilerOptions.paths`, ].join(' ')); } const updatedPath = path.map((x) => x.replace(new RegExp(projectRoot.from, 'g'), projectRoot.to)); if (schema.updateImportPath) { tsConfig.compilerOptions.paths[projectRef.to] = updatedPath; delete tsConfig.compilerOptions.paths[projectRef.from]; } else { tsConfig.compilerOptions.paths[projectRef.from] = updatedPath; } (0, devkit_1.writeJson)(tree, tsConfigPath, tsConfig); } } exports.updateImports = updateImports; /** * Changes imports in a file from one import to another */ function updateImportPaths(tree, path, from, to) { const contents = tree.read(path, 'utf-8'); const sourceFile = ts.createSourceFile(path, contents, ts.ScriptTarget.Latest, true); // Apply changes on the various types of imports const newContents = (0, devkit_1.applyChangesToString)(contents, [ ...updateImportDeclarations(sourceFile, from, to), ...updateDynamicImports(sourceFile, from, to), ]); tree.write(path, newContents); } /** * Update the module specifiers on static imports */ function updateImportDeclarations(sourceFile, from, to) { const importDecls = (0, find_nodes_1.findNodes)(sourceFile, ts.SyntaxKind.ImportDeclaration); const changes = []; for (const { moduleSpecifier } of importDecls) { if (ts.isStringLiteral(moduleSpecifier)) { changes.push(...updateModuleSpecifier(moduleSpecifier, from, to)); } } return changes; } /** * Update the module specifiers on dynamic imports and require statements */ function updateDynamicImports(sourceFile, from, to) { const expressions = (0, find_nodes_1.findNodes)(sourceFile, ts.SyntaxKind.CallExpression); const changes = []; for (const { expression, arguments: args } of expressions) { const moduleSpecifier = args[0]; // handle dynamic import statements if (expression.kind === ts.SyntaxKind.ImportKeyword && moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) { changes.push(...updateModuleSpecifier(moduleSpecifier, from, to)); } // handle require statements if (ts.isIdentifier(expression) && expression.text === 'require' && moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) { changes.push(...updateModuleSpecifier(moduleSpecifier, from, to)); } } return changes; } /** * Replace the old module specifier with a the new path */ function updateModuleSpecifier(moduleSpecifier, from, to) { if (moduleSpecifier.text === from || moduleSpecifier.text.startsWith(`${from}/`)) { return [ { type: devkit_1.ChangeType.Delete, start: moduleSpecifier.getStart() + 1, length: moduleSpecifier.text.length, }, { type: devkit_1.ChangeType.Insert, index: moduleSpecifier.getStart() + 1, text: moduleSpecifier.text.replace(new RegExp(from, 'g'), to), }, ]; } else { return []; } } //# sourceMappingURL=update-imports.js.map