Skip to content

Commit 669a1b2

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 e58b040 commit 669a1b2

13 files changed

Lines changed: 176 additions & 115 deletions

File tree

crates/vite_migration/src/file_walker.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use std::path::{Path, PathBuf};
33
use ignore::WalkBuilder;
44
use vite_error::Error;
55

6+
// TODO: only support esm files for now
67
/// File extensions to process for import rewriting
7-
const TS_JS_EXTENSIONS: &[&str] = &["ts", "tsx", "mts", "cts", "js", "jsx", "mjs", "cjs"];
8+
const TS_JS_EXTENSIONS: &[&str] = &["ts", "tsx", "mts", "js", "jsx", "mjs"];
89

910
/// Result of walking TypeScript/JavaScript files
1011
#[derive(Debug)]
@@ -163,7 +164,7 @@ mod tests {
163164

164165
let result = find_ts_files(temp.path()).unwrap();
165166

166-
assert_eq!(result.files.len(), 8);
167+
assert_eq!(result.files.len(), 6);
167168
}
168169

169170
#[test]

crates/vite_migration/src/import_rewriter.rs

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ fix: $NEW_IMPORT
116116

117117
/// Result of rewriting imports in a file
118118
#[derive(Debug)]
119-
pub struct RewriteResult {
119+
struct RewriteResult {
120120
/// The updated file content
121121
pub content: String,
122122
/// Whether any changes were made
@@ -134,40 +134,6 @@ pub struct BatchRewriteResult {
134134
pub errors: Vec<(PathBuf, String)>,
135135
}
136136

137-
/// Rewrite imports in a TypeScript/JavaScript file from vite/vitest to @voidzero-dev/vite-plus
138-
///
139-
/// This function reads a file and rewrites the import statements
140-
/// to use '@voidzero-dev/vite-plus' instead of 'vite', 'vitest', or '@vitest/*'.
141-
///
142-
/// # Arguments
143-
///
144-
/// * `file_path` - Path to the TypeScript/JavaScript file
145-
///
146-
/// # Returns
147-
///
148-
/// Returns a `RewriteResult` containing:
149-
/// - `content`: The updated file content
150-
/// - `updated`: Whether any changes were made
151-
///
152-
/// # Example
153-
///
154-
/// ```ignore
155-
/// use std::path::Path;
156-
/// use vite_migration::rewrite_import;
157-
///
158-
/// let result = rewrite_import(Path::new("src/app.ts"))?;
159-
/// if result.updated {
160-
/// std::fs::write("src/app.ts", &result.content)?;
161-
/// }
162-
/// ```
163-
pub fn rewrite_import(file_path: &Path) -> Result<RewriteResult, Error> {
164-
// Read the file
165-
let content = std::fs::read_to_string(file_path)?;
166-
167-
// Rewrite the imports
168-
rewrite_import_content(&content)
169-
}
170-
171137
/// Rewrite imports in all TypeScript/JavaScript files under a directory
172138
///
173139
/// This function finds all TypeScript and JavaScript files in the specified directory
@@ -229,6 +195,40 @@ pub fn rewrite_imports_in_directory(root: &Path) -> Result<BatchRewriteResult, E
229195
Ok(result)
230196
}
231197

198+
/// Rewrite imports in a TypeScript/JavaScript file from vite/vitest to @voidzero-dev/vite-plus
199+
///
200+
/// This function reads a file and rewrites the import statements
201+
/// to use '@voidzero-dev/vite-plus' instead of 'vite', 'vitest', or '@vitest/*'.
202+
///
203+
/// # Arguments
204+
///
205+
/// * `file_path` - Path to the TypeScript/JavaScript file
206+
///
207+
/// # Returns
208+
///
209+
/// Returns a `RewriteResult` containing:
210+
/// - `content`: The updated file content
211+
/// - `updated`: Whether any changes were made
212+
///
213+
/// # Example
214+
///
215+
/// ```ignore
216+
/// use std::path::Path;
217+
/// use vite_migration::rewrite_import;
218+
///
219+
/// let result = rewrite_import(Path::new("src/app.ts"))?;
220+
/// if result.updated {
221+
/// std::fs::write("src/app.ts", &result.content)?;
222+
/// }
223+
/// ```
224+
fn rewrite_import(file_path: &Path) -> Result<RewriteResult, Error> {
225+
// Read the file
226+
let content = std::fs::read_to_string(file_path)?;
227+
228+
// Rewrite the imports
229+
rewrite_import_content(&content)
230+
}
231+
232232
/// Rewrite imports in content from vite/vitest to @voidzero-dev/vite-plus
233233
///
234234
/// This is the internal function that performs the actual rewrite using ast-grep.

crates/vite_migration/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ mod package;
55
mod vite_config;
66

77
pub use file_walker::{WalkResult, find_ts_files};
8-
pub use import_rewriter::{
9-
BatchRewriteResult, RewriteResult, rewrite_import, rewrite_imports_in_directory,
10-
};
8+
pub use import_rewriter::{BatchRewriteResult, rewrite_imports_in_directory};
119
pub use package::rewrite_scripts;
1210
pub use vite_config::{MergeResult, merge_json_config};

packages/global/binding/index.d.ts

Lines changed: 30 additions & 17 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
*
@@ -154,36 +170,33 @@ export interface PathAccess {
154170
}
155171

156172
/**
157-
* Rewrite imports in vite config from 'vite' or 'vitest/config' to '@voidzero-dev/vite-plus'
173+
* Rewrite imports in all TypeScript/JavaScript files under a directory
174+
*
175+
* This function finds all TypeScript and JavaScript files in the specified directory
176+
* (respecting `.gitignore` rules), applies the import rewrite rules to each file,
177+
* and writes the modified content back to disk.
158178
*
159179
* # Arguments
160180
*
161-
* * `vite_config_path` - Path to the vite.config.ts or vite.config.js file
181+
* * `root` - The root directory to search for files
162182
*
163183
* # Returns
164184
*
165-
* Returns a `RewriteResult` containing:
166-
* - `content`: The updated vite config content
167-
* - `updated`: Whether any changes were made
185+
* Returns a `BatchRewriteResult` containing:
186+
* - `modifiedFiles`: Files that were changed
187+
* - `errors`: Files that had errors during processing
168188
*
169189
* # Example
170190
*
171191
* ```javascript
172-
* const result = rewriteImport('vite.config.ts');
173-
* if (result.updated) {
174-
* fs.writeFileSync('vite.config.ts', result.content);
192+
* const result = rewriteImportsInDirectory('./src');
193+
* console.log(`Modified ${result.modifiedFiles.length} files`);
194+
* for (const file of result.modifiedFiles) {
195+
* console.log(` ${file}`);
175196
* }
176197
* ```
177198
*/
178-
export declare function rewriteImport(viteConfigPath: string): RewriteResult;
179-
180-
/** Result of rewriting imports in vite config */
181-
export interface RewriteResult {
182-
/** The updated vite config content */
183-
content: string;
184-
/** Whether any changes were made */
185-
updated: boolean;
186-
}
199+
export declare function rewriteImportsInDirectory(root: string): BatchRewriteResult;
187200

188201
/**
189202
* Rewrite scripts json content using rules from rules_yaml

packages/global/binding/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -766,15 +766,15 @@ const {
766766
detectWorkspace,
767767
downloadPackageManager,
768768
mergeJsonConfig,
769-
rewriteImport,
769+
rewriteImportsInDirectory,
770770
rewriteScripts,
771771
run,
772772
runCommand,
773773
} = nativeBinding;
774774
export { detectWorkspace };
775775
export { downloadPackageManager };
776776
export { mergeJsonConfig };
777-
export { rewriteImport };
777+
export { rewriteImportsInDirectory };
778778
export { rewriteScripts };
779779
export { run };
780780
export { runCommand };

packages/global/binding/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use vite_path::current_dir;
1515

1616
use crate::cli::Args;
1717
pub use crate::{
18-
migration::{merge_json_config, rewrite_import, rewrite_scripts},
18+
migration::{merge_json_config, rewrite_imports_in_directory, rewrite_scripts},
1919
package_manager::{detect_workspace, download_package_manager},
2020
};
2121

packages/global/binding/src/migration.rs

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -84,38 +84,67 @@ pub fn merge_json_config(
8484
})
8585
}
8686

87-
/// Result of rewriting imports in vite config
87+
/// Error from batch import rewriting
8888
#[napi(object)]
89-
pub struct RewriteResult {
90-
/// The updated vite config content
91-
pub content: String,
92-
/// Whether any changes were made
93-
pub updated: bool,
89+
pub struct BatchRewriteError {
90+
/// The file path that had an error
91+
pub path: String,
92+
/// The error message
93+
pub message: String,
9494
}
9595

96-
/// Rewrite imports in vite config from 'vite' or 'vitest/config' to '@voidzero-dev/vite-plus'
96+
/// Result of rewriting imports in multiple files
97+
#[napi(object)]
98+
pub struct BatchRewriteResult {
99+
/// Files that were modified
100+
pub modified_files: Vec<String>,
101+
/// Files that had errors
102+
pub errors: Vec<BatchRewriteError>,
103+
}
104+
105+
/// Rewrite imports in all TypeScript/JavaScript files under a directory
106+
///
107+
/// This function finds all TypeScript and JavaScript files in the specified directory
108+
/// (respecting `.gitignore` rules), applies the import rewrite rules to each file,
109+
/// and writes the modified content back to disk.
97110
///
98111
/// # Arguments
99112
///
100-
/// * `vite_config_path` - Path to the vite.config.ts or vite.config.js file
113+
/// * `root` - The root directory to search for files
101114
///
102115
/// # Returns
103116
///
104-
/// Returns a `RewriteResult` containing:
105-
/// - `content`: The updated vite config content
106-
/// - `updated`: Whether any changes were made
117+
/// Returns a `BatchRewriteResult` containing:
118+
/// - `modifiedFiles`: Files that were changed
119+
/// - `errors`: Files that had errors during processing
107120
///
108121
/// # Example
109122
///
110123
/// ```javascript
111-
/// const result = rewriteImport('vite.config.ts');
112-
/// if (result.updated) {
113-
/// fs.writeFileSync('vite.config.ts', result.content);
124+
/// const result = rewriteImportsInDirectory('./src');
125+
/// console.log(`Modified ${result.modifiedFiles.length} files`);
126+
/// for (const file of result.modifiedFiles) {
127+
/// console.log(` ${file}`);
114128
/// }
115129
/// ```
116130
#[napi]
117-
pub fn rewrite_import(vite_config_path: String) -> Result<RewriteResult> {
118-
let result = vite_migration::rewrite_import(Path::new(&vite_config_path))
131+
pub fn rewrite_imports_in_directory(root: String) -> Result<BatchRewriteResult> {
132+
let result = vite_migration::rewrite_imports_in_directory(Path::new(&root))
119133
.map_err(anyhow::Error::from)?;
120-
Ok(RewriteResult { content: result.content, updated: result.updated })
134+
135+
Ok(BatchRewriteResult {
136+
modified_files: result
137+
.modified_files
138+
.iter()
139+
.map(|p| p.to_string_lossy().to_string())
140+
.collect(),
141+
errors: result
142+
.errors
143+
.iter()
144+
.map(|(p, m)| BatchRewriteError {
145+
path: p.to_string_lossy().to_string(),
146+
message: m.clone(),
147+
})
148+
.collect(),
149+
})
121150
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
88
● pnpm@<semver> installed
99
10-
◆ ✅ Rewrote import in vitest.config.ts
10+
◆ ✅ Rewrote imports in 2 file(s)
11+
12+
● test/hello.ts
13+
│ vitest.config.ts
1114
1215
└ ✨ Migration completed!
1316

@@ -41,8 +44,6 @@ export default defineConfig({
4144
"devDependencies": {
4245
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
4346
"vitest": "npm:@voidzero-dev/vite-plus-test@latest",
44-
"@vitest/browser": "^4.0.0",
45-
"@vitest/browser-playwright": "^4.0.0",
4647
"@voidzero-dev/vite-plus": "latest"
4748
},
4849
"scripts": {
@@ -62,8 +63,8 @@ export default defineConfig({
6263
}
6364

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

6869
const { readFile } = server.commands;
6970

packages/global/snap-tests/migration-merge-vite-config-ts/snap.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
88
● pnpm@<semver> installed
99
10-
◆ ✅ Rewrote import in vite.config.ts
11-
12-
◆ ✅ Rewrote import in vitest.config.ts
13-
1410
◆ ✅ Merged .oxlintrc.json into vite.config.ts
1511
1612
◆ ✅ Merged .oxfmtrc.json into vite.config.ts
1713
14+
◆ ✅ Rewrote imports in 2 file(s)
15+
16+
● vite.config.ts
17+
│ vitest.config.ts
18+
1819
└ ✨ Migration completed!
1920

2021

packages/global/snap-tests/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
66
● pnpm@<semver> installed
77
8-
◆ ✅ Rewrote import in vite.config.ts
8+
◆ ✅ Rewrote imports in 1 file(s)
9+
10+
● vite.config.ts
911
1012
└ ✨ Migration completed!
1113

0 commit comments

Comments
 (0)