From b74d558369d6bdb4eb1b720d2b2604be2db7ef34 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 1 Jun 2021 23:01:02 +0200 Subject: [PATCH] codemods: implement core-imports codemod Signed-off-by: Patrik Oldsberg --- packages/codemods/package.json | 4 +- packages/codemods/transforms/core-imports.js | 72 +++++++++++++++++++- yarn.lock | 27 +++++++- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 875b523b09..36cbae4cd5 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -26,9 +26,11 @@ "dependencies": { "@backstage/cli-common": "0.1.1", "chalk": "^4.0.0", - "jscodeshift": "^0.12.0" + "jscodeshift": "^0.12.0", + "jscodeshift-add-imports": "^1.0.10" }, "devDependencies": { + "@types/jscodeshift": "^0.11.0", "@types/node": "^14.14.32", "commander": "^6.1.0", "ts-node": "^9.1.1" diff --git a/packages/codemods/transforms/core-imports.js b/packages/codemods/transforms/core-imports.js index ed1ddb3a84..44ade8272e 100644 --- a/packages/codemods/transforms/core-imports.js +++ b/packages/codemods/transforms/core-imports.js @@ -13,4 +13,74 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -console.log('hello'); + +const addImports = require('jscodeshift-add-imports'); +const { resolve: resolvePath } = require('path'); +const fs = require('fs'); + +function findExports(packageName) { + const packagePath = require.resolve(`${packageName}/package.json`); + const typesPath = resolvePath(packagePath, '../dist/index.d.ts'); + const content = fs.readFileSync(typesPath, 'utf8'); + const [, exportSymbols] = content.match(/export \{ (.*) \};/); + return exportSymbols + .split(', ') + .map(exported => exported.match(/.* as (.*)/)?.[1] || exported); +} + +const symbolTable = { + '@backstage/core-app-api': findExports('@backstage/core-app-api'), + '@backstage/core-components': findExports('@backstage/core-components'), + '@backstage/core-plugin-api': findExports('@backstage/core-plugin-api'), +}; + +const reverseSymbolTable = Object.entries(symbolTable).reduce( + (table, [pkg, symbols]) => { + for (const symbol of symbols) { + table[symbol] = pkg; + } + return table; + }, + {}, +); + +module.exports = (file, /** @type {import('jscodeshift').API} */ api) => { + const j = api.jscodeshift; + const root = j(file.source); + + // Find all import statements of @backstage/core + const imports = root.find(j.ImportDeclaration, { + source: { + value: '@backstage/core', + }, + }); + + // Then loop through all the import statement and collects each imported symbol + const importedSymbols = imports.nodes().flatMap(node => + (node.specifiers || []).flatMap(specifier => ({ + name: specifier.imported.name, // The symbol we're importing + local: specifier.local.name, // The local name, usually this is the same + })), + ); + + // Now that we gathered all the imports we want to add, we get rid of the old one + imports.remove(); + + // The convert the imports into actual import statements + const newImportStatements = importedSymbols.map(({ name, local }) => { + const targetPackage = reverseSymbolTable[name]; + if (!targetPackage) { + throw new Error(`No target package found for import of ${name}`); + } + + return j.importDeclaration( + [j.importSpecifier(j.identifier(name), j.identifier(local))], + j.literal(targetPackage), + ); + }); + + // And add the new imports. `addImports` will take care of resolving duplicates + addImports(root, newImportStatements); + + return root.toSource(); +}; diff --git a/yarn.lock b/yarn.lock index 3fcc785a4e..0bb99c9985 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1879,7 +1879,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/traverse@^7.14.0", "@babel/traverse@^7.14.2": +"@babel/traverse@^7.14.0", "@babel/traverse@^7.14.2", "@babel/traverse@^7.4.5": version "7.14.2" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz#9201a8d912723a831c2679c7ebbf2fe1416d765b" integrity sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA== @@ -6504,6 +6504,14 @@ resolved "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.0.tgz#d1a11688112091f2c711674df3a65ea2f47b5dfb" integrity sha512-4vlpCM5KPCL5CfGmTbpjwVKbISRYhduEJvvUWsH5EB7QInhEj94XPZ3ts/9FPiLZFqYO0xoW4ZL8z2AabTGgJA== +"@types/jscodeshift@^0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-0.11.0.tgz#7224cf1a4d0383b4fb2694ffed52f57b45c3325b" + integrity sha512-OcJgr5GznWCEx2Oeg4eMUZYwssTHFj/tU8grrNCKdFQtAEAa0ezDiPHbCdSkyWrRSurXrYbNbHdhxbbB76pXNg== + dependencies: + ast-types "^0.14.1" + recast "^0.20.3" + "@types/json-schema-merge-allof@^0.6.0": version "0.6.0" resolved "https://registry.npmjs.org/@types/json-schema-merge-allof/-/json-schema-merge-allof-0.6.0.tgz#0f587d8a3bcb41a55ef2e91d3ba96430c9bc1813" @@ -8444,7 +8452,7 @@ ast-types-flow@^0.0.7: resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@0.14.2, ast-types@^0.14.2: +ast-types@0.14.2, ast-types@^0.14.1, ast-types@^0.14.2: version "0.14.2" resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== @@ -17184,6 +17192,19 @@ jsbn@~0.1.0: resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jscodeshift-add-imports@^1.0.10: + version "1.0.10" + resolved "https://registry.npmjs.org/jscodeshift-add-imports/-/jscodeshift-add-imports-1.0.10.tgz#3d0f99d539d492cfa037aa4a63f04c4a626bcff5" + integrity sha512-VUe9DJ3zkWIR62zSRQnmsOVeyt77yD8knvYNna/PzRZlF9j799hJw5sqTZu4EX16XLIqS3FxWz3nXuGuiw9iyQ== + dependencies: + "@babel/traverse" "^7.4.5" + jscodeshift-find-imports "^2.0.2" + +jscodeshift-find-imports@^2.0.2: + version "2.0.4" + resolved "https://registry.npmjs.org/jscodeshift-find-imports/-/jscodeshift-find-imports-2.0.4.tgz#4dc427bff6c8f8c6c766a19043cdbee4e1d10782" + integrity sha512-HxOzjWDOFFSCf8EKSTQGqCxXeRFqZszOywnZ0HuMB9YPDFHVpxftGRsY+QS+Qq8o2qUojlmNU3JEHts5DWYS1A== + jscodeshift@^0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.12.0.tgz#de7302f3d3e1f4b3b36f9e484f451ba4ab7cc1f4" @@ -23074,7 +23095,7 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" -recast@^0.20.4: +recast@^0.20.3, recast@^0.20.4: version "0.20.4" resolved "https://registry.npmjs.org/recast/-/recast-0.20.4.tgz#db55983eac70c46b3fff96c8e467d65ffb4a7abc" integrity sha512-6qLIBGGRcwjrTZGIiBpJVC/NeuXpogXNyRQpqU1zWPUigCphvApoCs9KIwDYh1eDuJ6dAFlQoi/QUyE5KQ6RBQ==