@@ -163,6 +163,10 @@ impl JsExecutor {
163163 /// If found, runs the local `dist/bin.js` directly. Otherwise, falls back
164164 /// to the global installation's `dist/bin.js`.
165165 ///
166+ /// Uses the project's runtime (from its `devEngines.runtime` configuration).
167+ /// This may write a `.node-version` file if the project has no version source.
168+ /// For side-effect-free commands like `--version`, use [`delegate_with_cli_runtime`] instead.
169+ ///
166170 /// # Arguments
167171 /// * `project_path` - Path to the project directory
168172 /// * `args` - Arguments to pass to the local CLI
@@ -175,7 +179,36 @@ impl JsExecutor {
175179 let runtime = self . ensure_project_runtime ( project_path) . await ?;
176180 let node_binary = runtime. get_binary_path ( ) ;
177181 let bin_prefix = runtime. get_bin_prefix ( ) ;
182+ self . run_js_entry ( project_path, & node_binary, & bin_prefix, args) . await
183+ }
178184
185+ /// Delegate to local or global vite-plus CLI using the CLI's own runtime.
186+ ///
187+ /// Like [`delegate_to_local_cli`], but uses the CLI's bundled runtime
188+ /// (from its own `devEngines.runtime` in `package.json`) instead of the
189+ /// project's runtime. This avoids side effects like writing `.node-version`
190+ /// when no version source exists in the project directory.
191+ ///
192+ /// Use this for read-only / side-effect-free commands like `--version`.
193+ pub async fn delegate_with_cli_runtime (
194+ & mut self ,
195+ project_path : & AbsolutePath ,
196+ args : & [ String ] ,
197+ ) -> Result < ExitStatus , Error > {
198+ let runtime = self . ensure_cli_runtime ( ) . await ?;
199+ let node_binary = runtime. get_binary_path ( ) ;
200+ let bin_prefix = runtime. get_bin_prefix ( ) ;
201+ self . run_js_entry ( project_path, & node_binary, & bin_prefix, args) . await
202+ }
203+
204+ /// Run a JS entry point with the given runtime, resolving local vite-plus first.
205+ async fn run_js_entry (
206+ & self ,
207+ project_path : & AbsolutePath ,
208+ node_binary : & AbsolutePath ,
209+ bin_prefix : & AbsolutePath ,
210+ args : & [ String ] ,
211+ ) -> Result < ExitStatus , Error > {
179212 // Try to resolve vite-plus from the project directory using oxc_resolver
180213 let entry_point = Self :: resolve_local_vite_plus ( project_path) . unwrap_or_else ( || {
181214 // Fall back to the global installation's bin.js
@@ -185,7 +218,7 @@ impl JsExecutor {
185218
186219 tracing:: debug!( "Delegating to CLI via JS entry point: {:?} {:?}" , entry_point, args) ;
187220
188- let mut cmd = Self :: create_js_command ( & node_binary, & bin_prefix) ;
221+ let mut cmd = Self :: create_js_command ( node_binary, bin_prefix) ;
189222 cmd. arg ( entry_point. as_path ( ) ) . args ( args) . current_dir ( project_path. as_path ( ) ) ;
190223
191224 let status = cmd. status ( ) . await ?;
0 commit comments