UNPKG

@o3r/schematics

Version:

Schematics module of the Otter framework

91 lines 5.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.updateImportsInFile = updateImportsInFile; const ast_utils_1 = require("@schematics/angular/utility/ast-utils"); const ts = require("typescript"); const escapeRegExp = (str) => str.replace(/[$()*+./?[\\\]^{|}-]/g, '\\$&'); /** * Update the imports of a given file according to replace mapping * @param logger Logger to report messages * @param tree File System tree * @param sourceFile Source file to analyze * @param importsRegexp Regexp of the imports to replace * @param renamePackagesRegexp Regexp of the packages to replace * @param mapImports Map of the import to replace * @param renamedPackages Map of the import package to replace */ function updateImportsInFile(logger, tree, sourceFile, importsRegexp, renamePackagesRegexp, mapImports = {}, renamedPackages = {}) { const oldImportedSymbolsPerPackage = {}; const unResolvedImports = []; const importNodes = []; // First we look for all imports lines targeting an Otter package for which we know a mapping (0, ast_utils_1.findNodes)(sourceFile, ts.SyntaxKind.ImportDeclaration).map((nodeImp) => { const imp = nodeImp; const importFrom = imp.moduleSpecifier.getText().replace(/["']/g, ''); const renamePackageMatch = importFrom.match(renamePackagesRegexp); const otterPackage = renamePackageMatch?.[0] || importFrom.match(importsRegexp)?.[0]; // If the import matched an Otter package if (otterPackage) { if (!oldImportedSymbolsPerPackage[otterPackage]) { oldImportedSymbolsPerPackage[otterPackage] = []; } // We store the import line to be able to remove it afterwards importNodes.push(imp); // We retrieve all the symbols listed in the import statement const namedImport = imp.importClause?.namedBindings; const isTypeOnlyImport = !!imp.importClause && ts.isTypeOnlyImportDeclaration(imp.importClause); const imports = namedImport && ts.isNamedImports(namedImport) ? namedImport.elements.map((element) => ({ symbol: element.getText(), isTypeOnlyImport, location: importFrom })) : []; // And associate them to the Otter package oldImportedSymbolsPerPackage[otterPackage].push(...imports); } }); // If did not capture any interesting import line, do nothing if (importNodes.length === 0) { return 0; } // Iterate over the imports and look into the renamed packages and into the map to see the import new module // If no mapping is found, we keep the original import location const resolvedImports = Object.entries(oldImportedSymbolsPerPackage).reduce((acc, [oldPackageName, importsFromOldPackage]) => { importsFromOldPackage.forEach((importSymbol) => { const newPackageNameImport = renamedPackages[oldPackageName] ? importSymbol.location.replace(oldPackageName, renamedPackages[oldPackageName]) : mapImports[oldPackageName]?.[importSymbol.symbol]?.newPackage; const importFrom = newPackageNameImport || importSymbol.location; if (!newPackageNameImport) { unResolvedImports.push(importSymbol); } if (!acc[importFrom]) { acc[importFrom] = []; } const newNameForExportedValue = mapImports[oldPackageName]?.[importSymbol.symbol]?.newValue; acc[importFrom].push(`${importSymbol.isTypeOnlyImport ? 'type ' : ''}${newNameForExportedValue || importSymbol.symbol}`); }); return acc; }, {}); let fileContent = tree.readText(sourceFile.fileName); // Remove captured imports fileContent = fileContent.replace(new RegExp(`(${importNodes.map((node) => escapeRegExp(node.getText())).join('|')})[\\n\\r]*`, 'g'), ''); // Replace imported values const valuesToReplace = Object.fromEntries(Object.values(mapImports).flatMap((mapImport) => Object.entries(mapImport) .filter(([_, value]) => value.newValue) .map(([key, value]) => [key, value.newValue]))); if (Object.keys(valuesToReplace).length > 0) { const matcher = new RegExp(Object.keys(valuesToReplace).map((oldValue) => `\\b${escapeRegExp(oldValue)}\\b`).join('|'), 'g'); const replacer = (match) => valuesToReplace[match]; fileContent = fileContent.replace(matcher, replacer); } // Add the computed imports at the top of the file fileContent = Object.entries(resolvedImports) .map(([importFrom, imports]) => `import {${imports.join(', ')}} from '${importFrom}';`) .join('\n') + '\n' + fileContent; tree.overwrite(sourceFile.fileName, fileContent); // Log details about imports for which we could not find an associated sub-entry if (unResolvedImports.length > 0) { logger.warn(`Some imports in file ${sourceFile.fileName} could not be resolved:`); unResolvedImports.forEach((unResolvedImport) => logger.warn(` |-- symbol "${unResolvedImport.symbol}" from module "${unResolvedImport.location}"`)); } return unResolvedImports.length; } //# sourceMappingURL=update-imports.js.map