1+ import { execFileSync , spawnSync } from "node:child_process" ;
2+ import { platform } from "node:os" ;
3+
4+ /**
5+ * Get the platform-specific executable name
6+ */
7+ export function getExecutableName ( command : string ) : string {
8+ if ( platform ( ) === "win32" && ! command . endsWith ( ".exe" ) ) {
9+ return `${ command } .exe` ;
10+ }
11+ return command ;
12+ }
13+
14+ /**
15+ * Find executable in PATH
16+ */
17+ export function findExecutable ( command : string ) : string | null {
18+ const execName = getExecutableName ( command ) ;
19+
20+ if ( platform ( ) === "win32" ) {
21+ try {
22+ const result = execFileSync ( "where" , [ execName ] , { encoding : "utf-8" } ) ;
23+ return result . trim ( ) . split ( "\n" ) [ 0 ] ;
24+ } catch {
25+ return null ;
26+ }
27+ } else {
28+ try {
29+ const result = execFileSync ( "which" , [ execName ] , { encoding : "utf-8" } ) ;
30+ return result . trim ( ) ;
31+ } catch {
32+ return null ;
33+ }
34+ }
35+ }
36+
37+ /**
38+ * Execute command with cross-platform support
39+ */
40+ export function execFileSyncCrossPlatform (
41+ command : string ,
42+ args : string [ ] ,
43+ options ?: Parameters < typeof execFileSync > [ 2 ]
44+ ) : ReturnType < typeof execFileSync > {
45+ const executable = findExecutable ( command ) ;
46+ if ( ! executable ) {
47+ throw new Error ( `Command '${ command } ' not found in PATH` ) ;
48+ }
49+ return execFileSync ( executable , args , options ) ;
50+ }
51+
52+ /**
53+ * Spawn command with cross-platform support
54+ */
55+ export function spawnSyncCrossPlatform (
56+ command : string ,
57+ args : string [ ] ,
58+ options ?: Parameters < typeof spawnSync > [ 2 ]
59+ ) {
60+ const executable = findExecutable ( command ) ;
61+ if ( ! executable ) {
62+ throw new Error ( `Command '${ command } ' not found in PATH` ) ;
63+ }
64+ return spawnSync ( executable , args , options ) ;
65+ }
0 commit comments