migrate-barrel-imports 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -4
- package/dist/index.js +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
@@ -30,7 +30,7 @@ npx migrate-barrel-imports <source-path> [target-path] [options]
|
|
30
30
|
|
31
31
|
### Arguments
|
32
32
|
|
33
|
-
- `source-path`:
|
33
|
+
- `source-path`: Directory pattern for source packages (e.g. "libs/*", "packages/{ui,core}") (required)
|
34
34
|
- `target-path`: Path to the directory where imports should be migrated (default: current directory)
|
35
35
|
|
36
36
|
### Options
|
@@ -44,11 +44,17 @@ Options can be specified either before or after the arguments:
|
|
44
44
|
## Example
|
45
45
|
|
46
46
|
```bash
|
47
|
-
#
|
47
|
+
# Migrate a single package
|
48
48
|
migrate-barrel-imports ./packages/my-lib --ignore-source-files "**/__tests__/**,**/__mocks__/**" --ignore-target-files "**/*.test.ts"
|
49
49
|
|
50
|
-
#
|
51
|
-
migrate-barrel-imports --no-extension
|
50
|
+
# Migrate multiple packages using glob pattern
|
51
|
+
migrate-barrel-imports "libs/*" --no-extension
|
52
|
+
|
53
|
+
# Migrate specific packages using glob pattern
|
54
|
+
migrate-barrel-imports "packages/{ui,core,utils}" --ignore-target-files "**/*.test.ts"
|
55
|
+
|
56
|
+
# Migrate all packages in a monorepo
|
57
|
+
migrate-barrel-imports "**/src" --no-extension
|
52
58
|
|
53
59
|
# Mix of options before and after arguments
|
54
60
|
migrate-barrel-imports --no-extension ./packages/my-lib --ignore-target-files "**/*.test.ts"
|
package/dist/index.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
import{Command as e}from"commander";import{readFileSync as
|
3
|
-
Processing file: ${
|
4
|
-
Total exports found: ${i.length}`),i}async function
|
5
|
-
Processing file: ${e}`);let l=
|
6
|
-
|
2
|
+
import{Command as e}from"commander";import o,{readFileSync as r,writeFileSync as t}from"node:fs";import s from"node:path";import i from"@babel/generator";import{parse as n}from"@babel/parser";import l from"@babel/traverse";import{isVariableDeclaration as a,isIdentifier as c,isExportSpecifier as p,isFunctionDeclaration as d,isImportSpecifier as g,importDeclaration as u,importSpecifier as f,stringLiteral as m}from"@babel/types";import h from"fast-glob";import x from"micromatch";let $=i.default||i,S=l.default||l;async function F(e){return JSON.parse(r(s.join(e,"package.json"),"utf-8"))}async function k({packagePath:e,ignoreSourceFiles:o=[],stats:t}){let i=[];console.log(`Scanning for TypeScript and JavaScript files in: ${e}`);let l=await h("**/*.{ts,tsx,js,jsx}",{cwd:e,ignore:["**/node_modules/**","**/dist/**","**/build/**"]});for(let g of(console.log(`Found ${l.length} files`),l)){let l=o.some(e=>x.isMatch(g,e));l&&(console.log(`File matches ignore pattern but will be preserved: ${g}`),t&&t.sourceFilesSkipped++);let u=s.join(e,g);console.log(`
|
3
|
+
Processing file: ${g}`);let f=r(u,"utf-8");try{let e=n(f,{sourceType:"module",plugins:["typescript","jsx","decorators-legacy","classProperties","classPrivateProperties","classPrivateMethods","exportDefaultFrom","exportNamespaceFrom","functionBind","functionSent","dynamicImport","nullishCoalescingOperator","optionalChaining","objectRestSpread","asyncGenerators","doExpressions","importMeta","logicalAssignment","moduleBlocks","moduleStringNames","numericSeparator","partialApplication","privateIn","throwExpressions","topLevelAwait"]});S(e,{ExportNamedDeclaration(e){if(console.log(`Found named export in ${g}`),e.node.source){console.log(`Skipping re-export from ${e.node.source.value}`);return}if(e.node.declaration){if(a(e.node.declaration)){let o=e.node.declaration.declarations.map(e=>c(e.id)?e.id.name:null).filter(e=>null!==e);o.length>0&&(console.log(`Named exports found: ${o.join(", ")}`),i.push({source:g,exports:o,isIgnored:l}))}return}let o=e.node.specifiers.map(e=>{if(p(e)){let o=e.exported;return c(o)?o.name:o.value}return null}).filter(e=>null!==e);o.length>0&&(console.log(`Named exports found: ${o.join(", ")}`),i.push({source:g,exports:o,isIgnored:l}))},ExportDefaultDeclaration(e){console.log(`Found default export in ${g}`);let o=e.node.declaration;c(o)?(console.log(`Default export name: ${o.name}`),i.push({source:g,exports:[o.name],isIgnored:l})):d(o)&&o.id?(console.log(`Default export name: ${o.id.name}`),i.push({source:g,exports:[o.id.name],isIgnored:l})):console.log("Default export is not an identifier or named function")}})}catch(e){console.error(`Error parsing ${g}:`,e)}}return console.log(`
|
4
|
+
Total exports found: ${i.length}`),i}async function y({packageName:e,monorepoRoot:o}){try{let t=new Set,s=await h(["**/*.{ts,tsx,js,jsx}"],{cwd:o,absolute:!0,ignore:["**/node_modules/**","**/dist/**","**/build/**"],followSymbolicLinks:!1});for(let o of(console.log(`Found ${s.length} files to scan`),s))try{let s=r(o,"utf-8"),i=n(s,{sourceType:"module",plugins:["typescript","jsx"]});S(i,{ImportDeclaration(r){let s=r.node.source.value;(s===e||s.startsWith(`${e}/`))&&t.add(o)}})}catch(e){console.error(`Error processing file ${o}:`,e)}let i=Array.from(t);if(i.length>0)for(let o of(console.log(`Found total of ${i.length} files with imports from ${e}`),console.log("Files found:"),i))console.log(` ${o}`);else console.log(`No files found importing from ${e}`);return i}catch(e){return console.error("Error finding imports:",e),[]}}async function w({filePath:e,packageName:o,exports:s,includeExtension:i=!0}){console.log(`
|
5
|
+
Processing file: ${e}`);let l=r(e,"utf-8");try{let r=n(l,{sourceType:"module",plugins:["typescript","jsx","decorators-legacy","classProperties","classPrivateProperties","classPrivateMethods","exportDefaultFrom","exportNamespaceFrom","functionBind","functionSent","dynamicImport","nullishCoalescingOperator","optionalChaining","objectRestSpread","asyncGenerators","doExpressions","importMeta","logicalAssignment","moduleBlocks","moduleStringNames","numericSeparator","partialApplication","privateIn","throwExpressions","topLevelAwait"]}),a=!1,p=0;if(S(r,{ImportDeclaration(e){if(e.node.source.value===o){p++,console.log(`Found import from ${o}`);let r=e.node.specifiers,t=[];for(let e of r)if(g(e)){let r=e.imported,n=c(r)?r.name:r.value,l=s.find(e=>e.exports.includes(n));if(l){if(console.log(` Found export ${n} in ${l.source}`),l.isIgnored){console.log(` Keeping original import for ignored file: ${l.source}`);continue}let r=i?`${o}/${l.source}`:`${o}/${l.source.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,"")}`;t.push(u([f(e.local,e.imported)],m(r))),a=!0}else console.log(` Warning: Could not find export ${n}`)}if(t.length>0){let i=r.filter(e=>{if(!g(e))return!0;let o=c(e.imported)?e.imported.name:e.imported.value,r=s.find(e=>e.exports.includes(o));return!r||r.isIgnored});i.length>0&&t.unshift(u(i,m(o))),e.replaceWithMultiple(t),console.log(" Replaced import with direct imports from source files")}}}}),a){console.log(`Writing changes to ${e}`);let o=$(r,{retainLines:!1,retainFunctionParens:!0},l);t(e,o.code)}else p>0?console.log(`No changes needed for ${p} imports`):console.log("No imports found to update")}catch(o){console.error(`Error processing ${e}:`,o)}}async function b(e){let{sourcePath:t,targetPath:i,ignoreSourceFiles:n,ignoreTargetFiles:l}=e,a={totalFiles:0,filesProcessed:0,filesSkipped:0,importsUpdated:0,filesWithNoUpdates:0,errors:0,totalExports:0,sourceFilesScanned:0,sourceFilesWithExports:0,sourceFilesSkipped:0,targetFilesFound:[],packagesProcessed:0,packagesSkipped:0},c=await h(t,{cwd:i,absolute:!0,ignore:["**/node_modules/**","**/dist/**","**/build/**","**/target-app/**"],followSymbolicLinks:!1,onlyDirectories:!0}),p=[];for(let e of c){let r=s.join(e,"package.json");try{await o.promises.access(r),p.push(r)}catch{console.log(`No package.json found in ${e}, skipping`)}}for(let o of(console.log(`Found ${p.length} source packages to process`),p))try{let t=s.dirname(o);console.log(`
|
6
|
+
Processing package: ${t}`);let c=await F(t),p=await k({packagePath:t,ignoreSourceFiles:n,stats:a});a.totalExports+=p.reduce((e,o)=>e+o.exports.length,0),a.sourceFilesWithExports+=new Set(p.map(e=>e.source)).size,a.sourceFilesScanned+=(await h("**/*.{ts,tsx}",{cwd:t,ignore:["**/node_modules/**","**/dist/**","**/build/**"]})).length;let d=await y({packageName:c.name,monorepoRoot:i});for(let o of(a.totalFiles+=d.length,a.targetFilesFound.push(...d),d)){let t=s.relative(i,o);if(l.some(e=>x.isMatch(t,e))){console.log(`Skipping ignored file: ${o} (matches pattern in ${l.join(", ")})`),a.filesSkipped++;continue}try{let t=r(o,"utf-8");await w({filePath:o,packageName:c.name,exports:p,includeExtension:e.includeExtension});let s=r(o,"utf-8");t!==s?a.importsUpdated++:a.filesWithNoUpdates++,a.filesProcessed++}catch(e){a.errors++,console.error(`Error processing ${o}:`,e)}}a.packagesProcessed++}catch(e){a.packagesSkipped++,console.error(`Error processing package ${o}:`,e)}console.log("\nMigration Summary"),console.log(`Source packages found: ${p.length}`),console.log(`Source packages processed: ${a.packagesProcessed}`),console.log(`Source packages skipped: ${a.packagesSkipped}`),console.log(`Source files found: ${a.sourceFilesScanned}`),console.log(`Source files with exports: ${a.sourceFilesWithExports}`),console.log(`Source files skipped: ${a.sourceFilesSkipped}`),console.log(`Exports found: ${a.totalExports}`),console.log(`Target files found: ${a.totalFiles}`),console.log(`Target files processed: ${a.filesProcessed}`),console.log(`Target files with imports updated: ${a.importsUpdated}`),console.log(`Target files with no changes needed: ${a.filesWithNoUpdates}`),console.log(`Target files skipped: ${a.filesSkipped}`),a.errors>0&&console.log(`
|
7
|
+
Warning: ${a.errors} errors encountered during processing`)}let P={targetPath:".",ignoreSourceFiles:[],ignoreTargetFiles:[],includeExtension:!1};async function E(){let o=new e;o.name("migrate-barrel-imports").description("CLI tool to migrate barrel files imports to direct imports").argument("<source-path>",'Glob pattern for source packages containing barrel files (e.g. "libs/*")').argument("[target-path]","Path to the directory where imports should be migrated (default: current directory)").option("--ignore-source-files <patterns>","Comma-separated list of file patterns to ignore in source directory").option("--ignore-target-files <patterns>","Comma-separated list of file patterns to ignore in target directory").option("--no-extension","Exclude js|jsx|ts|tsx|mjs|cjs file extensions from import statements").allowUnknownOption(!1).parse(process.argv);let r=o.args;r[0]||(console.error("Error: source-path is required"),process.exit(1));let t=r[0],s=r[1]||P.targetPath,i=o.opts();await b({sourcePath:t,targetPath:s,ignoreSourceFiles:i.ignoreSourceFiles?i.ignoreSourceFiles.split(","):P.ignoreSourceFiles,ignoreTargetFiles:i.ignoreTargetFiles?i.ignoreTargetFiles.split(","):P.ignoreTargetFiles,includeExtension:!1!==i.extension||P.includeExtension})}(async()=>{await E()})();
|