* Starts this command, piping output, error and close events onto the corresponding observables.
()
| 196 | * Starts this command, piping output, error and close events onto the corresponding observables. |
| 197 | */ |
| 198 | start() { |
| 199 | const child = this.spawn(this.command, this.spawnOpts); |
| 200 | this.changeState('started'); |
| 201 | this.process = child; |
| 202 | this.pid = child.pid; |
| 203 | const startDate = new Date(Date.now()); |
| 204 | const highResStartTime = process.hrtime(); |
| 205 | this.timer.next({ startDate }); |
| 206 | |
| 207 | this.subscriptions = [...this.maybeSetupIPC(child)]; |
| 208 | Rx.fromEvent(child, 'error').subscribe((event) => { |
| 209 | this.cleanUp(); |
| 210 | const endDate = new Date(Date.now()); |
| 211 | this.timer.next({ startDate, endDate }); |
| 212 | this.error.next(event); |
| 213 | this.changeState('errored'); |
| 214 | }); |
| 215 | Rx.fromEvent(child, 'close') |
| 216 | .pipe(Rx.map((event) => event as [number | null, NodeJS.Signals | null])) |
| 217 | .subscribe(([exitCode, signal]) => { |
| 218 | this.cleanUp(); |
| 219 | |
| 220 | // Don't override error event |
| 221 | if (this.state !== 'errored') { |
| 222 | this.changeState('exited'); |
| 223 | } |
| 224 | |
| 225 | const endDate = new Date(Date.now()); |
| 226 | this.timer.next({ startDate, endDate }); |
| 227 | const [durationSeconds, durationNanoSeconds] = process.hrtime(highResStartTime); |
| 228 | this.close.next({ |
| 229 | command: this, |
| 230 | index: this.index, |
| 231 | exitCode: exitCode ?? String(signal), |
| 232 | killed: this.killed, |
| 233 | timings: { |
| 234 | startDate, |
| 235 | endDate, |
| 236 | durationSeconds: durationSeconds + durationNanoSeconds / 1e9, |
| 237 | }, |
| 238 | }); |
| 239 | }); |
| 240 | if (child.stdout) { |
| 241 | pipeTo( |
| 242 | Rx.fromEvent(child.stdout, 'data').pipe(Rx.map((event) => event as Buffer)), |
| 243 | this.stdout, |
| 244 | ); |
| 245 | } |
| 246 | if (child.stderr) { |
| 247 | pipeTo( |
| 248 | Rx.fromEvent(child.stderr, 'data').pipe(Rx.map((event) => event as Buffer)), |
| 249 | this.stderr, |
| 250 | ); |
| 251 | } |
| 252 | this.stdin = child.stdin || undefined; |
| 253 | } |
| 254 | |
| 255 | private changeState(state: Exclude<CommandState, 'stopped'>) { |
no test coverage detected