11import path from 'node:path'
22import process from 'node:process'
33
4- import { fork } from './promise-fork'
4+ import spawn from '@npmcli/promise-spawn'
5+
6+ import { isObject } from '@socketsecurity/registry/lib/objects'
7+
58import constants from '../constants'
69
7- import type { ForkOptions , ForkResult } from './promise-fork'
8- import type { Serializable } from 'node:child_process'
10+ type SpawnOption = Exclude < Parameters < typeof spawn > [ 2 ] , undefined >
911
1012const { abortSignal } = constants
1113
12- type ShadowNpmInstallOptions = ForkOptions & {
14+ type ShadowNpmInstallOptions = SpawnOption & {
1315 flags ?: string [ ]
14- ipc ?: Serializable
16+ ipc ?: object
1517}
1618
17- export function shadowNpmInstall < O extends ShadowNpmInstallOptions > (
18- opts ?: ShadowNpmInstallOptions
19- ) {
20- const { flags = [ ] , ipc, ...forkOptions } = { __proto__ : null , ...opts }
19+ export function shadowNpmInstall ( opts ?: ShadowNpmInstallOptions ) {
20+ const { flags = [ ] , ipc, ...spawnOptions } = { __proto__ : null , ...opts }
21+ const useIpc = isObject ( ipc )
2122 // Lazily access constants.ENV.
2223 const { SOCKET_CLI_DEBUG } = constants . ENV
23- const promise = fork (
24- // Lazily access constants.rootBinPath .
25- path . join ( constants . rootBinPath , 'npm-cli.js' ) ,
24+ const promise = spawn (
25+ // Lazily access constants.execPath .
26+ constants . execPath ,
2627 [
28+ // Lazily access constants.rootBinPath.
29+ path . join ( constants . rootBinPath , 'npm-cli.js' ) ,
2730 'install' ,
2831 // Even though the 'silent' flag is passed npm will still run through code
2932 // paths for 'audit' and 'fund' unless '--no-audit' and '--no-fund' flags
@@ -35,16 +38,26 @@ export function shadowNpmInstall<O extends ShadowNpmInstallOptions>(
3538 ] ,
3639 {
3740 signal : abortSignal ,
38- // Lazily access constants.ENV.
39- stdio : SOCKET_CLI_DEBUG ? 'inherit' : 'ignore' ,
40- ...forkOptions ,
41+ // Set stdio to include 'ipc'.
42+ // See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
43+ // and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
44+ stdio : SOCKET_CLI_DEBUG
45+ ? // 'inherit'
46+ useIpc
47+ ? [ 0 , 1 , 2 , 'ipc' ]
48+ : 'inherit'
49+ : // 'ignore'
50+ useIpc
51+ ? [ 'ignore' , 'ignore' , 'ignore' , 'ipc' ]
52+ : 'ignore' ,
53+ ...spawnOptions ,
4154 env : {
4255 ...process . env ,
43- ...forkOptions . env
56+ ...spawnOptions . env
4457 }
4558 }
46- ) as ForkResult < O extends { stdioString : false } ? Buffer : string , undefined >
47- if ( ipc ) {
59+ )
60+ if ( useIpc ) {
4861 promise . process . send ( ipc )
4962 }
5063 return promise
0 commit comments