Skip to content

Commit 11449ee

Browse files
committed
feat: throw on non-zero exit
This is a breaking change which causes the process to throw when a non-zero exit code is encountered. If the exit code is `null`, we will not throw since it means something went very wrong anyway (the process is still running and shouldn't be, since we saw the `close` event by then). If the exit code is greater than `0`, we will throw a `NonZeroExitError` which has an `exitCode` property. For example: ```ts try { await x('foo'); } catch (err) { if (err instanceof NonZeroExitCode) { err.exitCode; // the exit code err.result; // the tinyexec process err.result.killed; // getters on tinyexec process } } ```
1 parent 64154fe commit 11449ee

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

Diff for: src/main.ts

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import {computeEnv} from './env.js';
66
import {combineStreams} from './stream.js';
77
import readline from 'node:readline';
88
import {_parse} from 'cross-spawn';
9+
import {NonZeroExitError} from './non-zero-exit-error.js';
10+
11+
export {NonZeroExitError};
912

1013
export interface Output {
1114
stderr: string;
@@ -188,6 +191,10 @@ export class ExecProcess implements Result {
188191
if (this._thrownError) {
189192
throw this._thrownError;
190193
}
194+
195+
if (this.exitCode !== 0 && this.exitCode !== undefined) {
196+
throw new NonZeroExitError(this);
197+
}
191198
}
192199

193200
protected async _waitForOutput(): Promise<Output> {
@@ -224,6 +231,10 @@ export class ExecProcess implements Result {
224231
throw this._thrownError;
225232
}
226233

234+
if (this.exitCode !== 0 && this.exitCode !== undefined) {
235+
throw new NonZeroExitError(this);
236+
}
237+
227238
const result: Output = {
228239
stderr,
229240
stdout

Diff for: src/non-zero-exit-error.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type {Result} from './main.js';
2+
3+
export class NonZeroExitError extends Error {
4+
public readonly result: Result;
5+
6+
public get exitCode(): number | undefined {
7+
if (this.result.exitCode !== null) {
8+
return this.result.exitCode;
9+
}
10+
return undefined;
11+
}
12+
13+
public constructor(result: Result) {
14+
super(`Process exited with non-zero status (${result.exitCode})`);
15+
16+
this.result = result;
17+
}
18+
}

Diff for: src/test/main_test.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {x} from '../main.js';
1+
import {x, NonZeroExitError} from '../main.js';
22
import * as assert from 'node:assert/strict';
33
import {test} from 'node:test';
44
import os from 'node:os';
@@ -19,6 +19,14 @@ test('exec', async (t) => {
1919
assert.equal(proc.exitCode, 0);
2020
});
2121

22+
await t.test('non-zero exitCode throws', async () => {
23+
const proc = x('node', ['-e', 'process.exit(1);']);
24+
await assert.rejects(async () => {
25+
await proc;
26+
}, NonZeroExitError);
27+
assert.equal(proc.exitCode, 1);
28+
});
29+
2230
await t.test('async iterator gets correct output', async () => {
2331
const proc = x('node', ['-e', "console.log('foo'); console.log('bar');"]);
2432
const lines = [];

0 commit comments

Comments
 (0)