|
| 1 | +import { readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs' |
| 2 | +import { resolve } from 'node:path' |
| 3 | +import type { ParseResult } from '@babel/parser' |
| 4 | +import { parse } from '@babel/parser' |
| 5 | +import type { File } from '@babel/types' |
| 6 | +import colors from 'picocolors' |
| 7 | +import MagicString from 'magic-string' |
| 8 | + |
| 9 | +export function rewriteImports( |
| 10 | + fileOrDir: string, |
| 11 | + rewrite: (importPath: string, currentFile: string) => string | void |
| 12 | +): void { |
| 13 | + walkDir(fileOrDir, (file) => { |
| 14 | + rewriteFileImports(file, (importPath) => { |
| 15 | + return rewrite(importPath, file) |
| 16 | + }) |
| 17 | + }) |
| 18 | +} |
| 19 | + |
| 20 | +export function slash(p: string): string { |
| 21 | + return p.replace(/\\/g, '/') |
| 22 | +} |
| 23 | + |
| 24 | +function walkDir(dir: string, handleFile: (file: string) => void): void { |
| 25 | + if (statSync(dir).isDirectory()) { |
| 26 | + const files = readdirSync(dir) |
| 27 | + for (const file of files) { |
| 28 | + const resolved = resolve(dir, file) |
| 29 | + walkDir(resolved, handleFile) |
| 30 | + } |
| 31 | + } else { |
| 32 | + handleFile(dir) |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | +function rewriteFileImports( |
| 37 | + file: string, |
| 38 | + rewrite: (importPath: string) => string | void |
| 39 | +): void { |
| 40 | + const content = readFileSync(file, 'utf-8') |
| 41 | + const str = new MagicString(content) |
| 42 | + let ast: ParseResult<File> |
| 43 | + try { |
| 44 | + ast = parse(content, { |
| 45 | + sourceType: 'module', |
| 46 | + plugins: ['typescript', 'classProperties'] |
| 47 | + }) |
| 48 | + } catch (e) { |
| 49 | + console.log(colors.red(`failed to parse ${file}`)) |
| 50 | + throw e |
| 51 | + } |
| 52 | + for (const statement of ast.program.body) { |
| 53 | + if ( |
| 54 | + statement.type === 'ImportDeclaration' || |
| 55 | + statement.type === 'ExportNamedDeclaration' || |
| 56 | + statement.type === 'ExportAllDeclaration' |
| 57 | + ) { |
| 58 | + const source = statement.source |
| 59 | + if (source?.value) { |
| 60 | + const newImportPath = rewrite(source.value) |
| 61 | + if (newImportPath) { |
| 62 | + str.overwrite( |
| 63 | + source.start!, |
| 64 | + source.end!, |
| 65 | + JSON.stringify(newImportPath) |
| 66 | + ) |
| 67 | + } |
| 68 | + } |
| 69 | + } |
| 70 | + } |
| 71 | + writeFileSync(file, str.toString()) |
| 72 | +} |
0 commit comments