Skip to content

Instantly share code, notes, and snippets.

@dlebedynskyi
Last active September 12, 2022 21:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dlebedynskyi/63823eb5c656f375c7dce89dc15fbcf2 to your computer and use it in GitHub Desktop.
Save dlebedynskyi/63823eb5c656f375c7dce89dc15fbcf2 to your computer and use it in GitHub Desktop.
jscodeshift transform to update imports from one package to another
module.exports.parser = 'tsx';
module.exports = function transformer(file, api, options) {
const j = api.jscodeshift;
const root = j(file.source);
const { from: fromPath, to: toPath } = options;
const jestLookFor = ["mock", "doMock"];
replaceImports();
replaceRequires();
replaceJestMocks();
return root.toSource({
objectCurlySpacing: false,
quote: "single",
});
// import x from 'test', import {a,b} from 'test/path'
function replaceImports() {
const importDeclarations = root.find(j.ImportDeclaration);
importDeclarations.forEach((path) => {
const importPath = path.value.source.value;
const newImportPath = splitPath(importPath, fromPath, toPath);
if (newImportPath) {
path.value.source.value = newImportPath;
}
});
}
// require('test'), require('test/a')
function replaceRequires() {
root
.find(j.CallExpression, { callee: { name: "require" } })
// find statements
.filter(
(x) =>
x.value.arguments.length === 1 &&
x.value.arguments[0].type === "StringLiteral" &&
x.value.arguments[0].value &&
x.value.arguments[0].value.startsWith(fromPath)
)
.forEach((x) => {
const importPath = x.value.arguments[0].value;
const newImport = splitPath(importPath, fromPath, toPath);
if (newImport) {
j(x).replaceWith(
j.callExpression(j.identifier("require"), [j.stringLiteral(newImport)])
);
}
});
}
// jest.mock, jest.doMock etc
function replaceJestMocks() {
root
.find(j.CallExpression, {
callee: {
type: "MemberExpression",
object: { name: "jest" }
}
})
.filter((x) => jestLookFor.indexOf(x.value.callee.property.name) >= 0)
.forEach((x) => {
const [testArg, ...rest] = x.value.arguments;
if (typeof testArg.value === "string") {
const newImport = splitPath(testArg.value, fromPath, toPath);
if (newImport) {
j(x).replaceWith(
j.callExpression(x.value.callee, [j.stringLiteral(newImport), ...rest])
);
}
}
});
}
function splitPath(importPath, fromPath, toPath) {
let frags = importPath.split("/");
if (frags[0] == fromPath) {
return importPath.replace(new RegExp(`^(${fromPath})`), toPath);
}
return undefined;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment