@es-toolkit/codemod
Version:
A codemod to transform lodash imports to es-toolkit/compat imports
78 lines (75 loc) • 2.86 kB
JavaScript
;
//#region src/detect-quote-style.ts
function detectQuoteStyle(source) {
const singleQuoteMatches = source.match(/import.*from\s+'/g) || [];
const doubleQuoteMatches = source.match(/import.*from\s+"/g) || [];
return doubleQuoteMatches.length > singleQuoteMatches.length ? "double" : "single";
}
//#endregion
//#region src/index.ts
function transform(file, api) {
const { jscodeshift: j } = api;
try {
const root = j(file.source);
let hasChanges = false;
hasChanges = transformLodashImports(root, j) || hasChanges;
const quoteStyle = detectQuoteStyle(file.source);
return hasChanges ? root.toSource({ quote: quoteStyle }) : null;
} catch (error) {
console.error(`Error transforming file ${file.path}:`, error);
return null;
}
}
function transformLodashImports(root, j) {
const transformers = [
transformLodashDefaultImports,
transformLodashEsImports,
transformLodashFunctionImports
];
const hasChanges = transformers.reduce((hasChanges$1, transform$1) => transform$1(root, j) || hasChanges$1, false);
return hasChanges;
}
function transformLodashDefaultImports(root, j) {
const lodashImports = root.find(j.ImportDeclaration, { source: { value: "lodash" } });
if (lodashImports.length === 0) return false;
lodashImports.replaceWith((path) => {
const { node } = path;
if (node.specifiers) {
const defaultSpecifier = node.specifiers.find((spec) => spec.type === "ImportDefaultSpecifier");
if (defaultSpecifier?.local) return j.importDeclaration([j.importNamespaceSpecifier(defaultSpecifier.local)], j.literal("es-toolkit/compat"));
return j.importDeclaration(node.specifiers, j.literal("es-toolkit/compat"));
}
return node;
});
return true;
}
function transformLodashEsImports(root, j) {
const lodashEsImports = root.find(j.ImportDeclaration, { source: { value: "lodash-es" } });
if (lodashEsImports.length === 0) return false;
lodashEsImports.replaceWith((path) => {
const { node } = path;
if (node.specifiers) return j.importDeclaration(node.specifiers, j.literal("es-toolkit/compat"));
return node;
});
return true;
}
function transformLodashFunctionImports(root, j) {
const lodashFunctionImports = root.find(j.ImportDeclaration).filter((path) => {
const source = path.node.source.value;
return typeof source === "string" && source.startsWith("lodash/");
});
if (lodashFunctionImports.length === 0) return false;
lodashFunctionImports.replaceWith((path) => {
const { node } = path;
const modulePath = node.source.value;
const functionName = modulePath.replace("lodash/", "");
if (node.specifiers?.[0]?.local) {
const localIdentifier = node.specifiers[0].local;
return j.importDeclaration([j.importDefaultSpecifier(localIdentifier)], j.literal(`es-toolkit/compat/${functionName}`));
}
return node;
});
return true;
}
//#endregion
module.exports = transform;