(executable: string | Launcher, ...initialArgs: ArrayPlusOptions<Primitive, ProgramOptions>)
| 73 | async function processFactory(executable: string | Launcher, ...initialArgs: [...Primitive[], ProgramOptions & { noninteractive: true }]): Promise<CommandFunction>; |
| 74 | async function processFactory(executable: string | Launcher, ...initialArgs: ArrayPlusOptions<Primitive, ProgramOptions>): Promise<ProcessFunction>; |
| 75 | async function processFactory(executable: string | Launcher, ...initialArgs: ArrayPlusOptions<Primitive, ProgramOptions>): Promise<ProcessFunction | CommandFunction> { |
| 76 | let cmdlineArgs = primitives(initialArgs); |
| 77 | let opts = options(initialArgs); |
| 78 | let fullPath: Promise<string>; |
| 79 | |
| 80 | if (typeof executable === 'string') { |
| 81 | fullPath = lazy<string>(async () => { |
| 82 | if (!await filepath.isExecutable(executable)) { |
| 83 | // if they didn't pass in a valid executable path, let's see if we can figure it out. |
| 84 | |
| 85 | // if we were handed some choices, we'll look at them, otherwise we'll see what we can find on the PATH. |
| 86 | opts.choices ??= lazy(async () => new Finder(executable).scan(...await searchPaths).results); |
| 87 | // but before we look at any of that, let's see if someone else wants to take that off our hands |
| 88 | const bin = await emitNow<string>('select-binary', Descriptors.none, executable, is.promise(opts.choices) ? await opts.choices : new Set()); |
| 89 | return await filepath.isExecutable(bin) || // we have a good one coming back from the event |
| 90 | await filepath.isExecutable(first(opts.choices)) || // we're gonna pick the first one in the choices, if there are any. |
| 91 | fail(new Error(`Unable to find full path to binary '${executable}'`)); // we're out of options. |
| 92 | } |
| 93 | |
| 94 | // we were given a valid executable path, so we'll just check with the event listeners real quick. |
| 95 | const bin = await emitNow<string>('select-binary', Descriptors.none, executable, is.promise(opts.choices) ? await opts.choices : new Set()) || executable; |
| 96 | |
| 97 | // ensure that the executable is an absolute path |
| 98 | asserts.isAbsolute(bin); |
| 99 | // ensure that the executable exists and is executable |
| 100 | await asserts.isExecutable(bin); |
| 101 | return bin; |
| 102 | }); |
| 103 | } else { |
| 104 | cmdlineArgs = [...(executable as Launcher).cmdlineArgs, ...cmdlineArgs]; |
| 105 | opts = { ...opts, ...(executable as Launcher).options || {} }; |
| 106 | fullPath = (executable as Launcher).executable; |
| 107 | } |
| 108 | |
| 109 | let result: ProcessFunction | CommandFunction; |
| 110 | if (opts.noninteractive) { |
| 111 | // create launcher for non-interactive commands |
| 112 | result = (async (...moreArgs: ArrayPlusOptions<Primitive, ProgramOptions>): Promise<CommandResult> => { |
| 113 | // make sure the path is executable |
| 114 | |
| 115 | // Create Process instance |
| 116 | const moreOpts = options(moreArgs); |
| 117 | const subscribers = opts.on ? moreOpts.on ? [opts.on, moreOpts.on] : [opts.on] : moreOpts.on ? [moreOpts.on] : []; |
| 118 | |
| 119 | const proc = await new Process( |
| 120 | await fullPath, // executable |
| 121 | [...result.cmdlineArgs, ...primitives(moreArgs)], // arguments |
| 122 | result.options.cwd || moreOpts.cwd || process.cwd(), // cwd |
| 123 | { ...process.env, ...result.options.env, ...moreOpts.env }, // environment |
| 124 | false, // no stdin. |
| 125 | ...subscribers // event handlers |
| 126 | ); |
| 127 | |
| 128 | const code = await proc.exitCode; |
| 129 | return { |
| 130 | code, |
| 131 | stdio: proc.stdio, |
| 132 | error: proc.error |
no test coverage detected