migrate-barrel-imports 1.0.0 → 1.2.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/dist/index.js +5 -469
- package/package.json +86 -81
package/dist/index.js
CHANGED
@@ -1,470 +1,6 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
import
|
3
|
-
|
4
|
-
|
5
|
-
import $
|
6
|
-
|
7
|
-
import $cUHbR$babeltraverse from "@babel/traverse";
|
8
|
-
import {isVariableDeclaration as $cUHbR$isVariableDeclaration, isIdentifier as $cUHbR$isIdentifier, isExportSpecifier as $cUHbR$isExportSpecifier, isFunctionDeclaration as $cUHbR$isFunctionDeclaration, isImportSpecifier as $cUHbR$isImportSpecifier, importDeclaration as $cUHbR$importDeclaration, importSpecifier as $cUHbR$importSpecifier, stringLiteral as $cUHbR$stringLiteral} from "@babel/types";
|
9
|
-
import $cUHbR$fastglob from "fast-glob";
|
10
|
-
import $cUHbR$micromatch from "micromatch";
|
11
|
-
|
12
|
-
|
13
|
-
/**
|
14
|
-
* @fileoverview Tool for migrating TypeScript projects from barrel file exports to direct file imports
|
15
|
-
*
|
16
|
-
* This tool helps migrate TypeScript projects that use barrel files (index.ts files that re-export)
|
17
|
-
* to use direct imports from source files instead. This improves:
|
18
|
-
* - Tree-shaking efficiency
|
19
|
-
* - Build performance
|
20
|
-
* - Code maintainability
|
21
|
-
* - TypeScript compilation speed
|
22
|
-
*
|
23
|
-
* The migration process:
|
24
|
-
* 1. Scans source package for all exports
|
25
|
-
* 2. Finds all files importing from the package
|
26
|
-
* 3. Updates imports to point directly to source files
|
27
|
-
* 4. Preserves original import names and types
|
28
|
-
*/
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
// @ts-expect-error
|
37
|
-
const $1d95f64f52ade133$var$generate = (0, $cUHbR$babelgenerator).default || (0, $cUHbR$babelgenerator);
|
38
|
-
// @ts-expect-error
|
39
|
-
const $1d95f64f52ade133$var$traverse = (0, $cUHbR$babeltraverse).default || (0, $cUHbR$babeltraverse);
|
40
|
-
/**
|
41
|
-
* Reads and parses the package.json file for a given package path
|
42
|
-
*
|
43
|
-
* @param {string} packagePath - The path to the package directory
|
44
|
-
* @returns {Promise<PackageJson>} The parsed package.json contents
|
45
|
-
* @throws {Error} If package.json cannot be read or parsed
|
46
|
-
*/ async function $1d95f64f52ade133$var$getPackageInfo(packagePath) {
|
47
|
-
const packageJsonPath = (0, $cUHbR$join)(packagePath, 'package.json');
|
48
|
-
const content = (0, $cUHbR$readFileSync)(packageJsonPath, 'utf-8');
|
49
|
-
return JSON.parse(content);
|
50
|
-
}
|
51
|
-
/**
|
52
|
-
* Recursively finds all exports in a package by scanning all TypeScript files
|
53
|
-
*
|
54
|
-
* This function:
|
55
|
-
* 1. Scans all .ts and .tsx files in the package
|
56
|
-
* 2. Identifies both named exports and default exports
|
57
|
-
* 3. Skips re-exports to avoid circular dependencies
|
58
|
-
* 4. Filters out ignored files based on patterns
|
59
|
-
*
|
60
|
-
* @param {FindExportsParams} params - Parameters for finding exports
|
61
|
-
* @returns {Promise<ExportInfo[]>} Array of export information, including source file and exported names
|
62
|
-
*/ async function $1d95f64f52ade133$var$findExports({ packagePath: packagePath, ignoreSourceFiles: ignoreSourceFiles = [], stats: stats }) {
|
63
|
-
const exports = [];
|
64
|
-
console.log(`Scanning for TypeScript files in: ${packagePath}`);
|
65
|
-
const allFiles = await (0, $cUHbR$fastglob)('**/*.{ts,tsx}', {
|
66
|
-
cwd: packagePath,
|
67
|
-
ignore: [
|
68
|
-
'**/node_modules/**',
|
69
|
-
'**/dist/**',
|
70
|
-
'**/build/**'
|
71
|
-
]
|
72
|
-
});
|
73
|
-
console.log(`Found ${allFiles.length} TypeScript files`);
|
74
|
-
for (const file of allFiles){
|
75
|
-
// Mark files that match ignore patterns but still process them
|
76
|
-
const isIgnored = ignoreSourceFiles.some((pattern)=>(0, $cUHbR$micromatch).isMatch(file, pattern));
|
77
|
-
if (isIgnored) {
|
78
|
-
console.log(`File matches ignore pattern but will be preserved: ${file}`);
|
79
|
-
if (stats) stats.sourceFilesSkipped++;
|
80
|
-
}
|
81
|
-
const fullPath = (0, $cUHbR$join)(packagePath, file);
|
82
|
-
console.log(`\nProcessing file: ${file}`);
|
83
|
-
const content = (0, $cUHbR$readFileSync)(fullPath, 'utf-8');
|
84
|
-
try {
|
85
|
-
const ast = (0, $cUHbR$parse)(content, {
|
86
|
-
sourceType: 'module',
|
87
|
-
plugins: [
|
88
|
-
'typescript',
|
89
|
-
'jsx',
|
90
|
-
'decorators-legacy',
|
91
|
-
'classProperties',
|
92
|
-
'classPrivateProperties',
|
93
|
-
'classPrivateMethods',
|
94
|
-
'exportDefaultFrom',
|
95
|
-
'exportNamespaceFrom',
|
96
|
-
'functionBind',
|
97
|
-
'functionSent',
|
98
|
-
'dynamicImport',
|
99
|
-
'nullishCoalescingOperator',
|
100
|
-
'optionalChaining',
|
101
|
-
'objectRestSpread',
|
102
|
-
'asyncGenerators',
|
103
|
-
'doExpressions',
|
104
|
-
'importMeta',
|
105
|
-
'logicalAssignment',
|
106
|
-
'moduleBlocks',
|
107
|
-
'moduleStringNames',
|
108
|
-
'numericSeparator',
|
109
|
-
'partialApplication',
|
110
|
-
'privateIn',
|
111
|
-
'throwExpressions',
|
112
|
-
'topLevelAwait'
|
113
|
-
]
|
114
|
-
});
|
115
|
-
$1d95f64f52ade133$var$traverse(ast, {
|
116
|
-
ExportNamedDeclaration (path) {
|
117
|
-
console.log(`Found named export in ${file}`);
|
118
|
-
// Skip exports from other files (we only want direct exports)
|
119
|
-
if (path.node.source) {
|
120
|
-
console.log(`Skipping re-export from ${path.node.source.value}`);
|
121
|
-
return;
|
122
|
-
}
|
123
|
-
// Handle variable declarations with exports
|
124
|
-
if (path.node.declaration) {
|
125
|
-
if ((0, $cUHbR$isVariableDeclaration)(path.node.declaration)) {
|
126
|
-
const declarations = path.node.declaration.declarations;
|
127
|
-
const namedExports = declarations.map((d)=>{
|
128
|
-
if ((0, $cUHbR$isIdentifier)(d.id)) return d.id.name;
|
129
|
-
return null;
|
130
|
-
}).filter((name)=>name !== null);
|
131
|
-
if (namedExports.length > 0) {
|
132
|
-
console.log(`Named exports found: ${namedExports.join(', ')}`);
|
133
|
-
exports.push({
|
134
|
-
source: file,
|
135
|
-
exports: namedExports,
|
136
|
-
isIgnored: isIgnored
|
137
|
-
});
|
138
|
-
}
|
139
|
-
}
|
140
|
-
return;
|
141
|
-
}
|
142
|
-
// Handle export specifiers
|
143
|
-
const namedExports = path.node.specifiers.map((s)=>{
|
144
|
-
if ((0, $cUHbR$isExportSpecifier)(s)) {
|
145
|
-
const exported = s.exported;
|
146
|
-
return (0, $cUHbR$isIdentifier)(exported) ? exported.name : exported.value;
|
147
|
-
}
|
148
|
-
return null;
|
149
|
-
}).filter((name)=>name !== null);
|
150
|
-
if (namedExports.length > 0) {
|
151
|
-
console.log(`Named exports found: ${namedExports.join(', ')}`);
|
152
|
-
exports.push({
|
153
|
-
source: file,
|
154
|
-
exports: namedExports,
|
155
|
-
isIgnored: isIgnored
|
156
|
-
});
|
157
|
-
}
|
158
|
-
},
|
159
|
-
ExportDefaultDeclaration (path) {
|
160
|
-
console.log(`Found default export in ${file}`);
|
161
|
-
const exported = path.node.declaration;
|
162
|
-
if ((0, $cUHbR$isIdentifier)(exported)) {
|
163
|
-
console.log(`Default export name: ${exported.name}`);
|
164
|
-
exports.push({
|
165
|
-
source: file,
|
166
|
-
exports: [
|
167
|
-
exported.name
|
168
|
-
],
|
169
|
-
isIgnored: isIgnored
|
170
|
-
});
|
171
|
-
} else if ((0, $cUHbR$isFunctionDeclaration)(exported) && exported.id) {
|
172
|
-
console.log(`Default export name: ${exported.id.name}`);
|
173
|
-
exports.push({
|
174
|
-
source: file,
|
175
|
-
exports: [
|
176
|
-
exported.id.name
|
177
|
-
],
|
178
|
-
isIgnored: isIgnored
|
179
|
-
});
|
180
|
-
} else console.log('Default export is not an identifier or named function');
|
181
|
-
}
|
182
|
-
});
|
183
|
-
} catch (error) {
|
184
|
-
console.error(`Error parsing ${file}:`, error);
|
185
|
-
}
|
186
|
-
}
|
187
|
-
console.log(`\nTotal exports found: ${exports.length}`);
|
188
|
-
return exports;
|
189
|
-
}
|
190
|
-
/**
|
191
|
-
* Finds all files in the monorepo that import from a specific package
|
192
|
-
*
|
193
|
-
* This function:
|
194
|
-
* 1. Uses fast-glob to find all TypeScript files
|
195
|
-
* 2. Parses each file's AST to find imports
|
196
|
-
* 3. Handles both direct package imports and subpath imports
|
197
|
-
* 4. Excludes node_modules, dist, and build directories
|
198
|
-
*
|
199
|
-
* @param {FindImportsParams} params - Parameters for finding imports
|
200
|
-
* @returns {Promise<string[]>} Array of file paths that import from the package
|
201
|
-
*/ async function $1d95f64f52ade133$var$findImports({ packageName: packageName, monorepoRoot: monorepoRoot }) {
|
202
|
-
try {
|
203
|
-
const allFiles = new Set();
|
204
|
-
// Find all TypeScript files in the monorepo
|
205
|
-
const files = await (0, $cUHbR$fastglob)([
|
206
|
-
'**/*.{ts,tsx}'
|
207
|
-
], {
|
208
|
-
cwd: monorepoRoot,
|
209
|
-
absolute: true,
|
210
|
-
ignore: [
|
211
|
-
'**/node_modules/**',
|
212
|
-
'**/dist/**',
|
213
|
-
'**/build/**'
|
214
|
-
],
|
215
|
-
followSymbolicLinks: false
|
216
|
-
});
|
217
|
-
console.log(`Found ${files.length} TypeScript files to scan`);
|
218
|
-
// Scan each file for imports
|
219
|
-
for (const file of files)try {
|
220
|
-
const content = (0, $cUHbR$readFileSync)(file, 'utf-8');
|
221
|
-
const ast = (0, $cUHbR$parse)(content, {
|
222
|
-
sourceType: 'module',
|
223
|
-
plugins: [
|
224
|
-
'typescript',
|
225
|
-
'jsx'
|
226
|
-
]
|
227
|
-
});
|
228
|
-
$1d95f64f52ade133$var$traverse(ast, {
|
229
|
-
ImportDeclaration (path) {
|
230
|
-
const source = path.node.source.value;
|
231
|
-
// Check for exact package import or subpath import
|
232
|
-
if (source === packageName || source.startsWith(`${packageName}/`)) allFiles.add(file);
|
233
|
-
}
|
234
|
-
});
|
235
|
-
} catch (error) {
|
236
|
-
console.error(`Error processing file ${file}:`, error);
|
237
|
-
}
|
238
|
-
const uniqueFiles = Array.from(allFiles);
|
239
|
-
if (uniqueFiles.length > 0) {
|
240
|
-
console.log(`Found total of ${uniqueFiles.length} files with imports from ${packageName}`);
|
241
|
-
console.log('Files found:');
|
242
|
-
for (const file of uniqueFiles)console.log(` ${file}`);
|
243
|
-
} else console.log(`No files found importing from ${packageName}`);
|
244
|
-
return uniqueFiles;
|
245
|
-
} catch (error) {
|
246
|
-
console.error('Error finding imports:', error);
|
247
|
-
return [];
|
248
|
-
}
|
249
|
-
}
|
250
|
-
/**
|
251
|
-
* Updates imports in a file to point directly to source files instead of using barrel files
|
252
|
-
*
|
253
|
-
* This function:
|
254
|
-
* 1. Parses the file's AST to find imports from the package
|
255
|
-
* 2. For each import, finds the source file containing the export
|
256
|
-
* 3. Updates the import to point directly to the source file
|
257
|
-
* 4. Preserves original import names and types
|
258
|
-
* 5. Only modifies the file if changes are needed
|
259
|
-
*
|
260
|
-
* @param {UpdateImportsParams} params - Parameters for updating imports
|
261
|
-
* @returns {Promise<void>}
|
262
|
-
*/ async function $1d95f64f52ade133$var$updateImports({ filePath: filePath, packageName: packageName, exports: exports, includeExtension: includeExtension = true }) {
|
263
|
-
console.log(`\nProcessing file: ${filePath}`);
|
264
|
-
const content = (0, $cUHbR$readFileSync)(filePath, 'utf-8');
|
265
|
-
try {
|
266
|
-
const ast = (0, $cUHbR$parse)(content, {
|
267
|
-
sourceType: 'module',
|
268
|
-
plugins: [
|
269
|
-
'typescript',
|
270
|
-
'jsx',
|
271
|
-
'decorators-legacy',
|
272
|
-
'classProperties',
|
273
|
-
'classPrivateProperties',
|
274
|
-
'classPrivateMethods',
|
275
|
-
'exportDefaultFrom',
|
276
|
-
'exportNamespaceFrom',
|
277
|
-
'functionBind',
|
278
|
-
'functionSent',
|
279
|
-
'dynamicImport',
|
280
|
-
'nullishCoalescingOperator',
|
281
|
-
'optionalChaining',
|
282
|
-
'objectRestSpread',
|
283
|
-
'asyncGenerators',
|
284
|
-
'doExpressions',
|
285
|
-
'importMeta',
|
286
|
-
'logicalAssignment',
|
287
|
-
'moduleBlocks',
|
288
|
-
'moduleStringNames',
|
289
|
-
'numericSeparator',
|
290
|
-
'partialApplication',
|
291
|
-
'privateIn',
|
292
|
-
'throwExpressions',
|
293
|
-
'topLevelAwait'
|
294
|
-
]
|
295
|
-
});
|
296
|
-
let modified = false;
|
297
|
-
let importCount = 0;
|
298
|
-
$1d95f64f52ade133$var$traverse(ast, {
|
299
|
-
ImportDeclaration (path) {
|
300
|
-
if (path.node.source.value === packageName) {
|
301
|
-
importCount++;
|
302
|
-
console.log(`Found import from ${packageName}`);
|
303
|
-
const specifiers = path.node.specifiers;
|
304
|
-
const newImports = [];
|
305
|
-
for (const specifier of specifiers)if ((0, $cUHbR$isImportSpecifier)(specifier)) {
|
306
|
-
const imported = specifier.imported;
|
307
|
-
const importName = (0, $cUHbR$isIdentifier)(imported) ? imported.name : imported.value;
|
308
|
-
const exportInfo = exports.find((e)=>e.exports.includes(importName));
|
309
|
-
if (exportInfo) {
|
310
|
-
console.log(` Found export ${importName} in ${exportInfo.source}`);
|
311
|
-
// Skip modifying imports from ignored files
|
312
|
-
if (exportInfo.isIgnored) {
|
313
|
-
console.log(` Keeping original import for ignored file: ${exportInfo.source}`);
|
314
|
-
continue;
|
315
|
-
}
|
316
|
-
const importPath = includeExtension ? `${packageName}/${exportInfo.source}` : `${packageName}/${exportInfo.source.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/, '')}`;
|
317
|
-
newImports.push((0, $cUHbR$importDeclaration)([
|
318
|
-
(0, $cUHbR$importSpecifier)(specifier.local, specifier.imported)
|
319
|
-
], (0, $cUHbR$stringLiteral)(importPath)));
|
320
|
-
modified = true;
|
321
|
-
} else console.log(` Warning: Could not find export ${importName}`);
|
322
|
-
}
|
323
|
-
if (newImports.length > 0) {
|
324
|
-
// If there are any remaining specifiers that weren't moved to direct imports,
|
325
|
-
// create a new import declaration for them
|
326
|
-
const remainingSpecifiers = specifiers.filter((s)=>{
|
327
|
-
if (!(0, $cUHbR$isImportSpecifier)(s)) return true;
|
328
|
-
const importName = (0, $cUHbR$isIdentifier)(s.imported) ? s.imported.name : s.imported.value;
|
329
|
-
const exportInfo = exports.find((e)=>e.exports.includes(importName));
|
330
|
-
return !exportInfo || exportInfo.isIgnored;
|
331
|
-
});
|
332
|
-
if (remainingSpecifiers.length > 0) newImports.unshift((0, $cUHbR$importDeclaration)(remainingSpecifiers, (0, $cUHbR$stringLiteral)(packageName)));
|
333
|
-
path.replaceWithMultiple(newImports);
|
334
|
-
console.log(' Replaced import with direct imports from source files');
|
335
|
-
}
|
336
|
-
}
|
337
|
-
}
|
338
|
-
});
|
339
|
-
if (modified) {
|
340
|
-
console.log(`Writing changes to ${filePath}`);
|
341
|
-
const output = $1d95f64f52ade133$var$generate(ast, {
|
342
|
-
retainLines: false,
|
343
|
-
retainFunctionParens: true
|
344
|
-
}, content);
|
345
|
-
(0, $cUHbR$writeFileSync)(filePath, output.code);
|
346
|
-
} else if (importCount > 0) console.log(`No changes needed for ${importCount} imports`);
|
347
|
-
else console.log('No imports found to update');
|
348
|
-
} catch (error) {
|
349
|
-
console.error(`Error processing ${filePath}:`, error);
|
350
|
-
}
|
351
|
-
}
|
352
|
-
async function $1d95f64f52ade133$export$eb4d0c836e660010(options) {
|
353
|
-
const { sourcePath: sourcePath, targetPath: targetPath, ignoreSourceFiles: ignoreSourceFiles, ignoreTargetFiles: ignoreTargetFiles } = options;
|
354
|
-
// Track migration statistics
|
355
|
-
const stats = {
|
356
|
-
totalFiles: 0,
|
357
|
-
filesProcessed: 0,
|
358
|
-
filesSkipped: 0,
|
359
|
-
importsUpdated: 0,
|
360
|
-
filesWithNoUpdates: 0,
|
361
|
-
errors: 0,
|
362
|
-
totalExports: 0,
|
363
|
-
sourceFilesScanned: 0,
|
364
|
-
sourceFilesWithExports: 0,
|
365
|
-
sourceFilesSkipped: 0,
|
366
|
-
targetFilesFound: []
|
367
|
-
};
|
368
|
-
const packageInfo = await $1d95f64f52ade133$var$getPackageInfo(sourcePath);
|
369
|
-
const exports = await $1d95f64f52ade133$var$findExports({
|
370
|
-
packagePath: sourcePath,
|
371
|
-
ignoreSourceFiles: ignoreSourceFiles,
|
372
|
-
stats: stats
|
373
|
-
});
|
374
|
-
// Calculate total number of unique exports and source files
|
375
|
-
stats.totalExports = exports.reduce((total, exp)=>total + exp.exports.length, 0);
|
376
|
-
stats.sourceFilesWithExports = new Set(exports.map((exp)=>exp.source)).size;
|
377
|
-
stats.sourceFilesScanned = (await (0, $cUHbR$fastglob)('**/*.{ts,tsx}', {
|
378
|
-
cwd: sourcePath,
|
379
|
-
ignore: [
|
380
|
-
'**/node_modules/**',
|
381
|
-
'**/dist/**',
|
382
|
-
'**/build/**'
|
383
|
-
]
|
384
|
-
})).length;
|
385
|
-
const files = await $1d95f64f52ade133$var$findImports({
|
386
|
-
packageName: packageInfo.name,
|
387
|
-
monorepoRoot: targetPath
|
388
|
-
});
|
389
|
-
stats.totalFiles = files.length;
|
390
|
-
stats.targetFilesFound = files;
|
391
|
-
for (const file of files){
|
392
|
-
const relativeFile = (0, $cUHbR$nodepath).relative(targetPath, file);
|
393
|
-
if (ignoreTargetFiles.some((pattern)=>(0, $cUHbR$micromatch).isMatch(relativeFile, pattern))) {
|
394
|
-
console.log(`Skipping ignored file: ${file} (matches pattern in ${ignoreTargetFiles.join(', ')})`);
|
395
|
-
stats.filesSkipped++;
|
396
|
-
continue;
|
397
|
-
}
|
398
|
-
try {
|
399
|
-
const originalContent = (0, $cUHbR$readFileSync)(file, 'utf-8');
|
400
|
-
await $1d95f64f52ade133$var$updateImports({
|
401
|
-
filePath: file,
|
402
|
-
packageName: packageInfo.name,
|
403
|
-
exports: exports,
|
404
|
-
includeExtension: options.includeExtension
|
405
|
-
});
|
406
|
-
const updatedContent = (0, $cUHbR$readFileSync)(file, 'utf-8');
|
407
|
-
if (originalContent !== updatedContent) stats.importsUpdated++;
|
408
|
-
else stats.filesWithNoUpdates++;
|
409
|
-
stats.filesProcessed++;
|
410
|
-
} catch (error) {
|
411
|
-
stats.errors++;
|
412
|
-
console.error(`Error processing ${file}:`, error);
|
413
|
-
}
|
414
|
-
}
|
415
|
-
// Print migration summary
|
416
|
-
console.log('\nMigration Summary');
|
417
|
-
console.log(`Source files found: ${stats.sourceFilesScanned}`);
|
418
|
-
console.log(`Source files with exports: ${stats.sourceFilesWithExports}`);
|
419
|
-
console.log(`Source files skipped: ${stats.sourceFilesSkipped}`);
|
420
|
-
console.log(`Exports found: ${stats.totalExports}`);
|
421
|
-
console.log(`Target files found: ${stats.totalFiles}`);
|
422
|
-
console.log(`Target files processed: ${stats.filesProcessed}`);
|
423
|
-
console.log(`Target files with imports updated: ${stats.importsUpdated}`);
|
424
|
-
console.log(`Target files with no changes needed: ${stats.filesWithNoUpdates}`);
|
425
|
-
console.log(`Target files skipped: ${stats.filesSkipped}`);
|
426
|
-
if (stats.errors > 0) console.log(`\nWarning: ${stats.errors} errors encountered during processing`);
|
427
|
-
}
|
428
|
-
|
429
|
-
|
430
|
-
/**
|
431
|
-
* Configuration options for the migration process
|
432
|
-
* @property {string} sourcePath - Path to the package being migrated
|
433
|
-
* @property {string} targetPath - Path to the monorepo root to search for imports
|
434
|
-
* @property {string[]} ignoreSourceFiles - Patterns to ignore when scanning source files
|
435
|
-
* @property {string[]} ignoreTargetFiles - Patterns to ignore when scanning target files
|
436
|
-
* @property {boolean} [includeExtension] - Whether to include file extensions in imports
|
437
|
-
*/ const $bf36973fbb2420ae$export$ba43bf67f3d48107 = {
|
438
|
-
targetPath: '.',
|
439
|
-
ignoreSourceFiles: [],
|
440
|
-
ignoreTargetFiles: [],
|
441
|
-
includeExtension: false
|
442
|
-
};
|
443
|
-
|
444
|
-
|
445
|
-
async function $f2a4372f35794f3d$export$f22da7240b7add18() {
|
446
|
-
const program = new (0, $cUHbR$Command)();
|
447
|
-
program.name('migrate-barrel-imports').description('CLI tool to migrate barrel files imports to direct imports').argument('<source-path>', 'Path to the package containing barrel files').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(false).parse(process.argv);
|
448
|
-
const args = program.args;
|
449
|
-
if (!args[0]) {
|
450
|
-
console.error('Error: source-path is required');
|
451
|
-
process.exit(1);
|
452
|
-
}
|
453
|
-
const sourcePath = args[0];
|
454
|
-
const targetPath = args[1] || (0, $bf36973fbb2420ae$export$ba43bf67f3d48107).targetPath;
|
455
|
-
const options = program.opts();
|
456
|
-
await (0, $1d95f64f52ade133$export$eb4d0c836e660010)({
|
457
|
-
sourcePath: sourcePath,
|
458
|
-
targetPath: targetPath,
|
459
|
-
ignoreSourceFiles: options.ignoreSourceFiles ? options.ignoreSourceFiles.split(',') : (0, $bf36973fbb2420ae$export$ba43bf67f3d48107).ignoreSourceFiles,
|
460
|
-
ignoreTargetFiles: options.ignoreTargetFiles ? options.ignoreTargetFiles.split(',') : (0, $bf36973fbb2420ae$export$ba43bf67f3d48107).ignoreTargetFiles,
|
461
|
-
includeExtension: options.extension !== false ? true : (0, $bf36973fbb2420ae$export$ba43bf67f3d48107).includeExtension
|
462
|
-
});
|
463
|
-
}
|
464
|
-
|
465
|
-
|
466
|
-
(async ()=>{
|
467
|
-
await (0, $f2a4372f35794f3d$export$f22da7240b7add18)();
|
468
|
-
})();
|
469
|
-
|
470
|
-
|
2
|
+
import{Command as e}from"commander";import{readFileSync as o,writeFileSync as t}from"node:fs";import r,{join as 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 u,importDeclaration as g,importSpecifier as f,stringLiteral as m}from"@babel/types";import h from"fast-glob";import x from"micromatch";let F=i.default||i,$=l.default||l;async function S(e){return JSON.parse(o(s(e,"package.json"),"utf-8"))}async function y({packagePath:e,ignoreSourceFiles:t=[],stats:r}){let i=[];console.log(`Scanning for TypeScript files in: ${e}`);let l=await h("**/*.{ts,tsx}",{cwd:e,ignore:["**/node_modules/**","**/dist/**","**/build/**"]});for(let u of(console.log(`Found ${l.length} TypeScript files`),l)){let l=t.some(e=>x.isMatch(u,e));l&&(console.log(`File matches ignore pattern but will be preserved: ${u}`),r&&r.sourceFilesSkipped++);let g=s(e,u);console.log(`
|
3
|
+
Processing file: ${u}`);let f=o(g,"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"]});$(e,{ExportNamedDeclaration(e){if(console.log(`Found named export in ${u}`),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:u,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:u,exports:o,isIgnored:l}))},ExportDefaultDeclaration(e){console.log(`Found default export in ${u}`);let o=e.node.declaration;c(o)?(console.log(`Default export name: ${o.name}`),i.push({source:u,exports:[o.name],isIgnored:l})):d(o)&&o.id?(console.log(`Default export name: ${o.id.name}`),i.push({source:u,exports:[o.id.name],isIgnored:l})):console.log("Default export is not an identifier or named function")}})}catch(e){console.error(`Error parsing ${u}:`,e)}}return console.log(`
|
4
|
+
Total exports found: ${i.length}`),i}async function w({packageName:e,monorepoRoot:t}){try{let r=new Set,s=await h(["**/*.{ts,tsx}"],{cwd:t,absolute:!0,ignore:["**/node_modules/**","**/dist/**","**/build/**"],followSymbolicLinks:!1});for(let t of(console.log(`Found ${s.length} TypeScript files to scan`),s))try{let s=o(t,"utf-8"),i=n(s,{sourceType:"module",plugins:["typescript","jsx"]});$(i,{ImportDeclaration(o){let s=o.node.source.value;(s===e||s.startsWith(`${e}/`))&&r.add(t)}})}catch(e){console.error(`Error processing file ${t}:`,e)}let i=Array.from(r);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 E({filePath:e,packageName:r,exports:s,includeExtension:i=!0}){console.log(`
|
5
|
+
Processing file: ${e}`);let l=o(e,"utf-8");try{let o=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($(o,{ImportDeclaration(e){if(e.node.source.value===r){p++,console.log(`Found import from ${r}`);let o=e.node.specifiers,t=[];for(let e of o)if(u(e)){let o=e.imported,n=c(o)?o.name:o.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 o=i?`${r}/${l.source}`:`${r}/${l.source.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,"")}`;t.push(g([f(e.local,e.imported)],m(o))),a=!0}else console.log(` Warning: Could not find export ${n}`)}if(t.length>0){let i=o.filter(e=>{if(!u(e))return!0;let o=c(e.imported)?e.imported.name:e.imported.value,t=s.find(e=>e.exports.includes(o));return!t||t.isIgnored});i.length>0&&t.unshift(g(i,m(r))),e.replaceWithMultiple(t),console.log(" Replaced import with direct imports from source files")}}}}),a){console.log(`Writing changes to ${e}`);let r=F(o,{retainLines:!1,retainFunctionParens:!0},l);t(e,r.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 P(e){let{sourcePath:t,targetPath:s,ignoreSourceFiles:i,ignoreTargetFiles:n}=e,l={totalFiles:0,filesProcessed:0,filesSkipped:0,importsUpdated:0,filesWithNoUpdates:0,errors:0,totalExports:0,sourceFilesScanned:0,sourceFilesWithExports:0,sourceFilesSkipped:0,targetFilesFound:[]},a=await S(t),c=await y({packagePath:t,ignoreSourceFiles:i,stats:l});l.totalExports=c.reduce((e,o)=>e+o.exports.length,0),l.sourceFilesWithExports=new Set(c.map(e=>e.source)).size,l.sourceFilesScanned=(await h("**/*.{ts,tsx}",{cwd:t,ignore:["**/node_modules/**","**/dist/**","**/build/**"]})).length;let p=await w({packageName:a.name,monorepoRoot:s});for(let t of(l.totalFiles=p.length,l.targetFilesFound=p,p)){let i=r.relative(s,t);if(n.some(e=>x.isMatch(i,e))){console.log(`Skipping ignored file: ${t} (matches pattern in ${n.join(", ")})`),l.filesSkipped++;continue}try{let r=o(t,"utf-8");await E({filePath:t,packageName:a.name,exports:c,includeExtension:e.includeExtension});let s=o(t,"utf-8");r!==s?l.importsUpdated++:l.filesWithNoUpdates++,l.filesProcessed++}catch(e){l.errors++,console.error(`Error processing ${t}:`,e)}}console.log("\nMigration Summary"),console.log(`Source files found: ${l.sourceFilesScanned}`),console.log(`Source files with exports: ${l.sourceFilesWithExports}`),console.log(`Source files skipped: ${l.sourceFilesSkipped}`),console.log(`Exports found: ${l.totalExports}`),console.log(`Target files found: ${l.totalFiles}`),console.log(`Target files processed: ${l.filesProcessed}`),console.log(`Target files with imports updated: ${l.importsUpdated}`),console.log(`Target files with no changes needed: ${l.filesWithNoUpdates}`),console.log(`Target files skipped: ${l.filesSkipped}`),l.errors>0&&console.log(`
|
6
|
+
Warning: ${l.errors} errors encountered during processing`)}let b={targetPath:".",ignoreSourceFiles:[],ignoreTargetFiles:[],includeExtension:!1};async function k(){let o=new e;o.name("migrate-barrel-imports").description("CLI tool to migrate barrel files imports to direct imports").argument("<source-path>","Path to the package containing barrel files").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 t=o.args;t[0]||(console.error("Error: source-path is required"),process.exit(1));let r=t[0],s=t[1]||b.targetPath,i=o.opts();await P({sourcePath:r,targetPath:s,ignoreSourceFiles:i.ignoreSourceFiles?i.ignoreSourceFiles.split(","):b.ignoreSourceFiles,ignoreTargetFiles:i.ignoreTargetFiles?i.ignoreTargetFiles.split(","):b.ignoreTargetFiles,includeExtension:!1!==i.extension||b.includeExtension})}(async()=>{await k()})();
|
package/package.json
CHANGED
@@ -1,83 +1,88 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
2
|
+
"name": "migrate-barrel-imports",
|
3
|
+
"version": "1.2.0",
|
4
|
+
"description": "A CLI tool to migrate barrel imports in JavaScript/TypeScript monorepos",
|
5
|
+
"files": [
|
6
|
+
"dist/"
|
7
|
+
],
|
8
|
+
"main": "./dist/index.js",
|
9
|
+
"targets": {
|
10
|
+
"main": {
|
11
|
+
"optimize": true
|
12
|
+
}
|
13
|
+
},
|
14
|
+
"keywords": [
|
15
|
+
"typescript",
|
16
|
+
"javascript",
|
17
|
+
"monorepo",
|
18
|
+
"cli",
|
19
|
+
"tool",
|
20
|
+
"migrate",
|
21
|
+
"barrel",
|
22
|
+
"import",
|
23
|
+
"imports"
|
24
|
+
],
|
25
|
+
"repository": {
|
26
|
+
"type": "git",
|
27
|
+
"url": "git+https://github.com/brandhaug/migrate-barrel-imports.git"
|
28
|
+
},
|
29
|
+
"bugs": {
|
30
|
+
"url": "https://github.com/brandhaug/migrate-barrel-imports/issues"
|
31
|
+
},
|
32
|
+
"homepage": "https://github.com/brandhaug/migrate-barrel-imports#readme",
|
33
|
+
"type": "module",
|
34
|
+
"bin": {
|
35
|
+
"migrate-barrel-imports": "dist/index.js"
|
36
|
+
},
|
37
|
+
"scripts": {
|
38
|
+
"build": "parcel build src/index.ts --no-source-maps",
|
39
|
+
"start": "node dist/index.js",
|
40
|
+
"lint": "biome lint",
|
41
|
+
"check-write": "biome check --write",
|
42
|
+
"typecheck": "tsc",
|
43
|
+
"prepare": "husky",
|
44
|
+
"test": "vitest",
|
45
|
+
"validate": "npm run lint && npm run typecheck && npm run test"
|
46
|
+
},
|
47
|
+
"dependencies": {
|
48
|
+
"@babel/generator": "7.26.10",
|
49
|
+
"@babel/parser": "7.26.10",
|
50
|
+
"@babel/traverse": "7.26.10",
|
51
|
+
"@babel/types": "7.26.10",
|
52
|
+
"commander": "13.1.0",
|
53
|
+
"fast-glob": "3.3.3",
|
54
|
+
"micromatch": "4.0.8",
|
55
|
+
"ts-morph": "25.0.1"
|
56
|
+
},
|
57
|
+
"devDependencies": {
|
58
|
+
"@biomejs/biome": "1.9.4",
|
59
|
+
"@commitlint/cli": "19.8.0",
|
60
|
+
"@commitlint/config-conventional": "19.8.0",
|
61
|
+
"@semantic-release/changelog": "6.0.3",
|
62
|
+
"@types/babel__generator": "7.6.8",
|
63
|
+
"@types/babel__traverse": "7.20.6",
|
64
|
+
"@types/micromatch": "4.0.9",
|
65
|
+
"execa": "9.5.2",
|
66
|
+
"husky": "9.1.7",
|
67
|
+
"lint-staged": "15.5.0",
|
68
|
+
"parcel": "2.14.1",
|
69
|
+
"semantic-release": "24.2.3",
|
70
|
+
"tsc-files": "1.1.4",
|
71
|
+
"tsx": "4.19.3",
|
72
|
+
"typescript": "5.8.2",
|
73
|
+
"vitest": "3.0.9"
|
74
|
+
},
|
75
|
+
"author": "Martin Brandhaug",
|
76
|
+
"license": "MIT",
|
77
|
+
"lint-staged": {
|
78
|
+
"*.{ts,json}": [
|
79
|
+
"biome check --write"
|
80
|
+
],
|
81
|
+
"*.ts": [
|
82
|
+
"tsc-files"
|
83
|
+
]
|
84
|
+
},
|
85
|
+
"engines": {
|
86
|
+
"node": ">=20"
|
87
|
+
}
|
83
88
|
}
|