Skip to content

Commit ca7a548

Browse files
committed
fix(migrate): rewrite tools invoked through bunx
1 parent 6779fb8 commit ca7a548

8 files changed

Lines changed: 395 additions & 49 deletions

File tree

crates/vite_migration/src/eslint.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,20 @@ mod tests {
156156
"cross-env NODE_ENV=test CI=true vp lint ."
157157
);
158158
}
159+
160+
#[test]
161+
fn test_rewrite_eslint_bunx() {
162+
assert_eq!(
163+
rewrite_eslint_script("bunx --bun eslint --cache --fix ."),
164+
"bunx --bun vp lint --fix ."
165+
);
166+
assert_eq!(
167+
rewrite_eslint_script("dotenv -e .env -- bunx --bun eslint --ext .ts ."),
168+
"dotenv -e .env -- bunx --bun vp lint ."
169+
);
170+
assert_eq!(
171+
rewrite_eslint_script("bunx --bun eslint-plugin-foo"),
172+
"bunx --bun eslint-plugin-foo"
173+
);
174+
}
159175
}

crates/vite_migration/src/package.rs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use ast_grep_language::SupportLang;
33
use serde_json::{Map, Value};
44
use vite_error::Error;
55

6-
use crate::{ast_grep, eslint::rewrite_eslint_script, prettier::rewrite_prettier_script};
6+
use crate::{
7+
ast_grep, eslint::rewrite_eslint_script, prettier::rewrite_prettier_script,
8+
script_rewrite::rewrite_bunx_commands,
9+
};
710

811
// Marker to replace "cross-env " before ast-grep processing
912
// Using a fake env var assignment that won't match our rules
@@ -22,8 +25,11 @@ fn rewrite_script(script: &str, rules: &[RuleConfig<SupportLang>]) -> String {
2225
script.to_string()
2326
};
2427

25-
// Step 2: Process with ast-grep
26-
let result = ast_grep::apply_loaded_rules(&preprocessed, rules);
28+
// Step 2: Rewrite commands behind bunx only when their inner command
29+
// matches an active rule, then process ordinary commands.
30+
let rewritten_bunx =
31+
rewrite_bunx_commands(&preprocessed, |inner| ast_grep::apply_loaded_rules(inner, rules));
32+
let result = ast_grep::apply_loaded_rules(&rewritten_bunx, rules);
2733

2834
// Step 3: Replace cross-env marker back with "cross-env " (only if we replaced it)
2935

@@ -172,6 +178,15 @@ rule:
172178
regex: '^vitest$'
173179
fix: vp test
174180
181+
# lint-staged => vp staged
182+
---
183+
id: replace-lint-staged
184+
language: bash
185+
rule:
186+
kind: command_name
187+
regex: '^lint-staged$'
188+
fix: vp staged
189+
175190
# tsdown => vp pack
176191
---
177192
id: replace-tsdown
@@ -276,6 +291,43 @@ fix: vp pack
276291
rewrite_script("NODE_ENV=test oxlint --type-aware", &rules),
277292
"NODE_ENV=test vp lint --type-aware"
278293
);
294+
// bunx and its flags are preserved while managed commands are rewritten
295+
assert_eq!(rewrite_script("bunx --bun vite build", &rules), "bunx --bun vp build");
296+
assert_eq!(rewrite_script("bunx --bun vite preview", &rules), "bunx --bun vp preview");
297+
assert_eq!(rewrite_script("bunx --bun vitest run", &rules), "bunx --bun vp test run");
298+
assert_eq!(
299+
rewrite_script("bunx --bun oxlint --type-aware", &rules),
300+
"bunx --bun vp lint --type-aware"
301+
);
302+
assert_eq!(
303+
rewrite_script("bunx --bun oxfmt --check .", &rules),
304+
"bunx --bun vp fmt --check ."
305+
);
306+
assert_eq!(
307+
rewrite_script("bunx --bun tsdown --watch", &rules),
308+
"bunx --bun vp pack --watch"
309+
);
310+
assert_eq!(rewrite_script("bunx --bun lint-staged", &rules), "bunx --bun vp staged");
311+
assert_eq!(
312+
rewrite_script("NODE_ENV=development portless --tailscale run bunx --bun vite", &rules,),
313+
"NODE_ENV=development portless --tailscale run bunx --bun vp dev"
314+
);
315+
assert_eq!(
316+
rewrite_script("dotenv -e .env.test -- bunx --bun vitest run", &rules),
317+
"dotenv -e .env.test -- bunx --bun vp test run"
318+
);
319+
// unrelated executor calls and non-launcher arguments stay unchanged
320+
assert_eq!(
321+
rewrite_script("bunx --bun playwright test", &rules),
322+
"bunx --bun playwright test"
323+
);
324+
assert_eq!(rewrite_script("bunx --bun vp build", &rules), "bunx --bun vp build");
325+
assert_eq!(
326+
rewrite_script("echo bunx --bun vite build", &rules),
327+
"echo bunx --bun vite build"
328+
);
329+
assert_eq!(rewrite_script("npx vite build", &rules), "npx vite build");
330+
assert_eq!(rewrite_script("bun x vite build", &rules), "bun x vite build");
279331
// oxlint commands
280332
assert_eq!(rewrite_script("oxlint", &rules), "vp lint");
281333
assert_eq!(rewrite_script("oxlint --type-aware", &rules), "vp lint --type-aware");

crates/vite_migration/src/prettier.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ mod tests {
130130
"if [ -f .prettierrc ]; then vp fmt .; fi"
131131
);
132132

133-
// npx wrappers unchanged
133+
// non-Bun package executors remain outside this migration rule
134134
assert_eq!(rewrite_prettier_script("npx prettier --write ."), "npx prettier --write .");
135135

136136
// already rewritten (no-op)
@@ -191,6 +191,22 @@ mod tests {
191191
);
192192
}
193193

194+
#[test]
195+
fn test_rewrite_prettier_bunx() {
196+
assert_eq!(
197+
rewrite_prettier_script("bunx --bun prettier --write --single-quote ."),
198+
"bunx --bun vp fmt ."
199+
);
200+
assert_eq!(
201+
rewrite_prettier_script("dotenv -e .env -- bunx --bun prettier --check ."),
202+
"dotenv -e .env -- bunx --bun vp fmt --check ."
203+
);
204+
assert_eq!(
205+
rewrite_prettier_script("bunx --bun prettier-plugin-foo"),
206+
"bunx --bun prettier-plugin-foo"
207+
);
208+
}
209+
194210
#[test]
195211
fn test_rewrite_prettier_list_different_to_check() {
196212
// --list-different → --check

0 commit comments

Comments
 (0)