From 8069d174d24904e8d5d02d42f797153866298bb9 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Sun, 31 Mar 2024 10:50:06 +0300 Subject: [PATCH] feat: let `nothrow` be a filter closes #714 --- src/core.ts | 28 +++++++++++++++++++++++----- test/core.test.js | 24 +++++++++++++++++++++++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/core.ts b/src/core.ts index aea3be1b58..cea4002880 100644 --- a/src/core.ts +++ b/src/core.ts @@ -62,7 +62,7 @@ export interface Options { sync: boolean env: NodeJS.ProcessEnv shell: string | boolean - nothrow: boolean + nothrow: boolean | number[] | ((status: number | null) => boolean) prefix: string postfix: string quote: typeof quote @@ -123,6 +123,15 @@ function checkShell() { } } +function checkStatus(status: number | null, nothrow: Options['nothrow']) { + return ( + status === 0 || + (typeof nothrow === 'function' + ? nothrow(status) + : (nothrow as number[])?.includes?.(status as number) ?? nothrow) + ) +} + function getStore() { return storage.getStore() || defaults } @@ -199,7 +208,7 @@ export class ProcessPromise extends Promise { private _reject: Resolve = noop private _snapshot = getStore() private _stdio: [IO, IO, IO] = ['inherit', 'pipe', 'pipe'] - private _nothrow?: boolean + private _nothrow?: Options['nothrow'] private _quiet?: boolean private _timeout?: number private _timeoutSignal = 'SIGTERM' @@ -306,7 +315,7 @@ export class ProcessPromise extends Promise { message ) self._output = output - if (status === 0 || (self._nothrow ?? $.nothrow)) { + if (checkStatus(status, self._nothrow ?? $.nothrow)) { self._resolve(output) } else { self._reject(output) @@ -429,8 +438,17 @@ export class ProcessPromise extends Promise { return this } - nothrow(): ProcessPromise { - this._nothrow = true + nothrow( + ...codes: number[] | [(status: number | null) => boolean] + ): ProcessPromise { + if (codes.length === 0) { + this._nothrow = true + } else if (typeof codes[0] === 'function') { + this._nothrow = codes[0] + } else { + this._nothrow = codes as number[] + } + return this } diff --git a/test/core.test.js b/test/core.test.js index d7f164474c..da58f833e6 100644 --- a/test/core.test.js +++ b/test/core.test.js @@ -516,7 +516,7 @@ describe('core', () => { assert.equal(await $`[[ -f README.md ]]`.exitCode, 0) }) - test('nothrow() do not throw', async () => { + test('nothrow() does not throw', async () => { let { exitCode } = await $`exit 42`.nothrow() assert.equal(exitCode, 42) { @@ -526,6 +526,28 @@ describe('core', () => { } }) + test('nothrow() accepts a filter', async () => { + assert.equal((await $`exit 42`.nothrow(42)).exitCode, 42) + assert.equal((await $({ nothrow: [42] })`exit 42`).exitCode, 42) + assert.equal( + ( + await $({ + nothrow(code) { + return code === 42 + }, + })`exit 42` + ).exitCode, + 42 + ) + + try { + await $`exit 42`.nothrow(1) + assert.unreachable('should throw') + } catch (p) { + assert.equal(p.exitCode, 42) + } + }) + test('malformed cmd error', async () => { assert.throws(() => $`\033`, /malformed/i) })