(
command: LaunchCommand,
options: LaunchOptions = {}
)
| 130 | * the child's real exit facts (the 128+n contract). |
| 131 | */ |
| 132 | export function launchOpenerCommand( |
| 133 | command: LaunchCommand, |
| 134 | options: LaunchOptions = {} |
| 135 | ): Promise<LaunchResult> { |
| 136 | const spawnFn = options.spawnFn ?? defaultSpawn(); |
| 137 | |
| 138 | return new Promise((resolve, reject) => { |
| 139 | const launchFailure = (error: unknown): StoreError => |
| 140 | new StoreError( |
| 141 | `Could not launch ${command.label}: ${asErrorMessage(error)}`, |
| 142 | 'workset_launch_failed', |
| 143 | { |
| 144 | target: 'workset.tool', |
| 145 | fix: `Check that '${command.executable}' runs from this terminal, or pass --tool with another installed tool.`, |
| 146 | } |
| 147 | ); |
| 148 | |
| 149 | let child: ReturnType<typeof spawnFn>; |
| 150 | try { |
| 151 | child = spawnFn(command.executable, command.args, { |
| 152 | cwd: command.cwd, |
| 153 | stdio: 'inherit', |
| 154 | shell: false, |
| 155 | }); |
| 156 | } catch (error) { |
| 157 | // Some spawn failures throw synchronously (platform-dependent); |
| 158 | // they are the same launch failure. |
| 159 | reject(launchFailure(error)); |
| 160 | return; |
| 161 | } |
| 162 | |
| 163 | const ignoreSignal = (): void => undefined; |
| 164 | process.on('SIGINT', ignoreSignal); |
| 165 | process.on('SIGTERM', ignoreSignal); |
| 166 | const cleanup = (): void => { |
| 167 | process.removeListener('SIGINT', ignoreSignal); |
| 168 | process.removeListener('SIGTERM', ignoreSignal); |
| 169 | }; |
| 170 | |
| 171 | child.on('error', (error) => { |
| 172 | cleanup(); |
| 173 | reject(launchFailure(error)); |
| 174 | }); |
| 175 | |
| 176 | child.on('close', (code, signal) => { |
| 177 | cleanup(); |
| 178 | resolve({ code, signal }); |
| 179 | }); |
| 180 | }); |
| 181 | } |
| 182 | |
| 183 | /** 130 for SIGINT, 143 for SIGTERM - the shell's 128+n convention. */ |
| 184 | export function exitCodeForLaunch(result: LaunchResult): number { |
no test coverage detected