22 spawnSync ,
33 type SpawnSyncOptionsWithStringEncoding ,
44} from 'child_process' ;
5+ import path from 'node:path' ;
56import { RootCommand } from '../src/t.js' ;
67
78const noop = ( ) => { } ;
@@ -37,18 +38,56 @@ function runCompletionCommand(
3738 const args = [ ...leadingArgs , 'complete' , '--' , ...safeCompletionArgs ] ;
3839 tabDebugLog ( 'spawn completion:' , command , args ) ;
3940
40- const result = spawnSync (
41- command ,
42- args ,
43- completionSpawnOptions
44- ) ;
41+ const result = spawnSync ( command , args , completionSpawnOptions ) ;
4542
4643 tabDebugLog ( 'spawn result:' , {
4744 status : result . status ,
4845 error : result . error ?. message ,
4946 stdout : result . stdout ,
5047 } ) ;
5148
49+ // Windows: npm may only produce a .ps1 shim; spawnSync won't resolve .ps1 via PATHEXT.
50+ // Fallback: invoke through powershell so .ps1 shims (e.g. nuxt.ps1) are discoverable.
51+ if (
52+ getErrnoCode ( result . error ) === 'ENOENT' &&
53+ process . platform === 'win32' &&
54+ path . extname ( command ) === ''
55+ ) {
56+ const psArgs = args . map ( powerShellQuote ) ;
57+ const psCommand = `& ${ command } ${ psArgs . join ( ' ' ) } ` . trimEnd ( ) ;
58+
59+ tabDebugLog ( 'powershell fallback:' , psCommand ) ;
60+
61+ const psResult = spawnSync (
62+ 'powershell.exe' ,
63+ [
64+ '-NoLogo' ,
65+ '-NoProfile' ,
66+ '-ExecutionPolicy' ,
67+ 'Bypass' ,
68+ '-Command' ,
69+ psCommand ,
70+ ] ,
71+ completionSpawnOptions
72+ ) ;
73+
74+ tabDebugLog ( 'powershell fallback result:' , {
75+ status : psResult . status ,
76+ error : psResult . error ?. message ,
77+ stdout : psResult . stdout ,
78+ } ) ;
79+
80+ if ( psResult . error ) {
81+ throw psResult . error ;
82+ }
83+ if ( typeof psResult . status === 'number' && psResult . status !== 0 ) {
84+ throw new Error (
85+ `Completion command "${ command } " (PowerShell fallback) exited with code ${ psResult . status } `
86+ ) ;
87+ }
88+ return ( psResult . stdout ?? '' ) . trim ( ) ;
89+ }
90+
5291 if ( result . error ) {
5392 throw result . error ;
5493 }
@@ -62,6 +101,19 @@ function runCompletionCommand(
62101 return ( result . stdout ?? '' ) . trim ( ) ;
63102}
64103
104+ function powerShellQuote ( value : string ) : string {
105+ // Use single quotes and escape embedded single quotes by doubling them.
106+ return `'${ value . replace ( / ' / g, "''" ) } '` ;
107+ }
108+
109+ function getErrnoCode ( error : unknown ) : string | undefined {
110+ if ( error && typeof error === 'object' && 'code' in error ) {
111+ const candidate = ( error as { code ?: unknown } ) . code ;
112+ if ( typeof candidate === 'string' ) return candidate ;
113+ }
114+ return undefined ;
115+ }
116+
65117async function checkCliHasCompletions (
66118 cliName : string ,
67119 packageManager : string
0 commit comments