Skip to content

Commit 3b16db9

Browse files
fengmk2claude
andcommitted
feat(migration): integrate batch import rewriting into migration command
Add NAPI bindings for rewrite_imports_in_directory to expose the Rust batch import rewriting functionality to TypeScript. The migration command now rewrites vite/vitest imports in all TypeScript/JavaScript files, not just config files. Changes: - Add BatchRewriteResult and BatchRewriteError NAPI structs - Add rewriteImportsInDirectory NAPI function - Call rewriteAllImports in both standalone and monorepo migrations - Display progress showing modified files and any errors 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 601e6f8 commit 3b16db9

5 files changed

Lines changed: 146 additions & 2 deletions

File tree

packages/global/binding/index.d.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
/* auto-generated by NAPI-RS */
22
/* eslint-disable */
3+
/** Error from batch import rewriting */
4+
export interface BatchRewriteError {
5+
/** The file path that had an error */
6+
path: string;
7+
/** The error message */
8+
message: string;
9+
}
10+
11+
/** Result of rewriting imports in multiple files */
12+
export interface BatchRewriteResult {
13+
/** Files that were modified */
14+
modifiedFiles: Array<string>;
15+
/** Files that had errors */
16+
errors: Array<BatchRewriteError>;
17+
}
18+
319
/**
420
* Configuration options passed from JavaScript to Rust.
521
*
@@ -177,6 +193,35 @@ export interface PathAccess {
177193
*/
178194
export declare function rewriteImport(viteConfigPath: string): RewriteResult;
179195

196+
/**
197+
* Rewrite imports in all TypeScript/JavaScript files under a directory
198+
*
199+
* This function finds all TypeScript and JavaScript files in the specified directory
200+
* (respecting `.gitignore` rules), applies the import rewrite rules to each file,
201+
* and writes the modified content back to disk.
202+
*
203+
* # Arguments
204+
*
205+
* * `root` - The root directory to search for files
206+
*
207+
* # Returns
208+
*
209+
* Returns a `BatchRewriteResult` containing:
210+
* - `modifiedFiles`: Files that were changed
211+
* - `errors`: Files that had errors during processing
212+
*
213+
* # Example
214+
*
215+
* ```javascript
216+
* const result = rewriteImportsInDirectory('./src');
217+
* console.log(`Modified ${result.modifiedFiles.length} files`);
218+
* for (const file of result.modifiedFiles) {
219+
* console.log(` ${file}`);
220+
* }
221+
* ```
222+
*/
223+
export declare function rewriteImportsInDirectory(root: string): BatchRewriteResult;
224+
180225
/** Result of rewriting imports in vite config */
181226
export interface RewriteResult {
182227
/** The updated vite config content */

packages/global/binding/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ const {
767767
downloadPackageManager,
768768
mergeJsonConfig,
769769
rewriteImport,
770+
rewriteImportsInDirectory,
770771
rewriteScripts,
771772
run,
772773
runCommand,
@@ -775,6 +776,7 @@ export { detectWorkspace };
775776
export { downloadPackageManager };
776777
export { mergeJsonConfig };
777778
export { rewriteImport };
779+
export { rewriteImportsInDirectory };
778780
export { rewriteScripts };
779781
export { run };
780782
export { runCommand };

packages/global/binding/src/migration.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,68 @@ pub fn rewrite_import(vite_config_path: String) -> Result<RewriteResult> {
119119
.map_err(anyhow::Error::from)?;
120120
Ok(RewriteResult { content: result.content, updated: result.updated })
121121
}
122+
123+
/// Error from batch import rewriting
124+
#[napi(object)]
125+
pub struct BatchRewriteError {
126+
/// The file path that had an error
127+
pub path: String,
128+
/// The error message
129+
pub message: String,
130+
}
131+
132+
/// Result of rewriting imports in multiple files
133+
#[napi(object)]
134+
pub struct BatchRewriteResult {
135+
/// Files that were modified
136+
pub modified_files: Vec<String>,
137+
/// Files that had errors
138+
pub errors: Vec<BatchRewriteError>,
139+
}
140+
141+
/// Rewrite imports in all TypeScript/JavaScript files under a directory
142+
///
143+
/// This function finds all TypeScript and JavaScript files in the specified directory
144+
/// (respecting `.gitignore` rules), applies the import rewrite rules to each file,
145+
/// and writes the modified content back to disk.
146+
///
147+
/// # Arguments
148+
///
149+
/// * `root` - The root directory to search for files
150+
///
151+
/// # Returns
152+
///
153+
/// Returns a `BatchRewriteResult` containing:
154+
/// - `modifiedFiles`: Files that were changed
155+
/// - `errors`: Files that had errors during processing
156+
///
157+
/// # Example
158+
///
159+
/// ```javascript
160+
/// const result = rewriteImportsInDirectory('./src');
161+
/// console.log(`Modified ${result.modifiedFiles.length} files`);
162+
/// for (const file of result.modifiedFiles) {
163+
/// console.log(` ${file}`);
164+
/// }
165+
/// ```
166+
#[napi]
167+
pub fn rewrite_imports_in_directory(root: String) -> Result<BatchRewriteResult> {
168+
let result = vite_migration::rewrite_imports_in_directory(Path::new(&root))
169+
.map_err(anyhow::Error::from)?;
170+
171+
Ok(BatchRewriteResult {
172+
modified_files: result
173+
.modified_files
174+
.iter()
175+
.map(|p| p.to_string_lossy().to_string())
176+
.collect(),
177+
errors: result
178+
.errors
179+
.iter()
180+
.map(|(p, m)| BatchRewriteError {
181+
path: p.to_string_lossy().to_string(),
182+
message: m.clone(),
183+
})
184+
.collect(),
185+
})
186+
}

packages/global/snap-tests/migration-from-vitest/snap.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
1010
◆ ✅ Rewrote import in vitest.config.ts
1111
12+
◆ ✅ Rewrote imports in 1 file(s)
13+
14+
● test/hello.ts
15+
1216
└ ✨ Migration completed!
1317

1418

@@ -62,8 +66,8 @@ export default defineConfig({
6266
}
6367

6468
> cat test/hello.ts # check test/hello.ts
65-
import { server } from '@vitest/browser-playwright/context';
66-
import { test, describe, expect, it } from 'vitest';
69+
import { server } from '@voidzero-dev/vite-plus/test/browser-playwright/context';
70+
import { test, describe, expect, it } from '@voidzero-dev/vite-plus/test';
6771

6872
const { readFile } = server.commands;
6973

packages/global/src/migration/migrator.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
mergeJsonConfig,
1010
rewriteScripts,
1111
rewriteImport,
12+
rewriteImportsInDirectory,
1213
type DownloadPackageManagerResult,
1314
} from '../../binding/index.js';
1415
import { PackageManager, type WorkspaceInfo } from '../types/index.js';
@@ -131,6 +132,8 @@ export function rewriteStandaloneProject(projectPath: string, workspaceInfo: Wor
131132
rewriteNpmrc(projectPath);
132133
rewriteLintStagedConfigFile(projectPath);
133134
rewriteViteConfigFile(projectPath);
135+
// rewrite imports in all TypeScript/JavaScript files
136+
rewriteAllImports(projectPath);
134137
// set package manager
135138
setPackageManager(projectPath, workspaceInfo.downloadPackageManager);
136139
}
@@ -160,6 +163,8 @@ export function rewriteMonorepo(workspaceInfo: WorkspaceInfo): void {
160163
rewriteNpmrc(workspaceInfo.rootDir);
161164
rewriteLintStagedConfigFile(workspaceInfo.rootDir);
162165
rewriteViteConfigFile(workspaceInfo.rootDir);
166+
// rewrite imports in all TypeScript/JavaScript files
167+
rewriteAllImports(workspaceInfo.rootDir);
163168
// set package manager
164169
setPackageManager(workspaceInfo.rootDir, workspaceInfo.downloadPackageManager);
165170
}
@@ -623,6 +628,29 @@ function rewriteViteConfigImport(projectPath: string, viteConfigPath: string): v
623628
}
624629
}
625630

631+
/**
632+
* Rewrite imports in all TypeScript/JavaScript files under a directory
633+
* This rewrites vite/vitest imports to @voidzero-dev/vite-plus
634+
* @param projectPath - The root directory to search for files
635+
*/
636+
function rewriteAllImports(projectPath: string): void {
637+
const result = rewriteImportsInDirectory(projectPath);
638+
639+
if (result.modifiedFiles.length > 0) {
640+
prompts.log.success(`✅ Rewrote imports in ${result.modifiedFiles.length} file(s)`);
641+
for (const file of result.modifiedFiles) {
642+
prompts.log.info(` ${displayRelative(file)}`);
643+
}
644+
}
645+
646+
if (result.errors.length > 0) {
647+
prompts.log.warn(`⚠️ ${result.errors.length} file(s) had errors:`);
648+
for (const error of result.errors) {
649+
prompts.log.error(` ${displayRelative(error.path)}: ${error.message}`);
650+
}
651+
}
652+
}
653+
626654
function setPackageManager(
627655
projectDir: string,
628656
downloadPackageManager: DownloadPackageManagerResult,

0 commit comments

Comments
 (0)