From f57fdeceb60d95f2799de0dc950196f1f7fd5e75 Mon Sep 17 00:00:00 2001 From: homersimpsons Date: Thu, 27 Jul 2023 01:30:23 +0200 Subject: [PATCH] Add `cwd` error property (#565) --- index.d.ts | 11 +++++++++-- index.test-d.ts | 4 ++++ lib/error.js | 4 +++- readme.md | 6 ++++++ test/error.js | 13 ++++++++++++- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/index.d.ts b/index.d.ts index bbf581a914..c9cb28f11b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -364,6 +364,11 @@ export type ExecaReturnBase = { If a signal terminated the process, this property is defined and included in the error message. Otherwise it is `undefined`. It is also `undefined` when the signal is very uncommon which should seldomly happen. */ signalDescription?: string; + + /** + The `cwd` of the command if provided in the command options. Otherwise it is `process.cwd()`. + */ + cwd: string; }; export type ExecaSyncReturnValue = { @@ -596,7 +601,8 @@ try { failed: true, timedOut: false, isCanceled: false, - killed: false + killed: false, + cwd: '/path/to/cwd' } \*\/ } @@ -679,7 +685,8 @@ try { failed: true, timedOut: false, isCanceled: false, - killed: false + killed: false, + cwd: '/path/to/cwd' } \*\/ } diff --git a/index.test-d.ts b/index.test-d.ts index 284545b4f9..46e3572c60 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -71,6 +71,7 @@ try { expectType(unicornsResult.killed); expectType(unicornsResult.signal); expectType(unicornsResult.signalDescription); + expectType(unicornsResult.cwd); } catch (error: unknown) { const execaError = error as ExecaError; @@ -85,6 +86,7 @@ try { expectType(execaError.killed); expectType(execaError.signal); expectType(execaError.signalDescription); + expectType(execaError.cwd); expectType(execaError.shortMessage); expectType(execaError.originalMessage); } @@ -106,6 +108,7 @@ try { expectType(unicornsResult.killed); expectType(unicornsResult.signal); expectType(unicornsResult.signalDescription); + expectType(unicornsResult.cwd); } catch (error: unknown) { const execaError = error as ExecaSyncError; @@ -120,6 +123,7 @@ try { expectType(execaError.killed); expectType(execaError.signal); expectType(execaError.signalDescription); + expectType(execaError.cwd); expectType(execaError.shortMessage); expectType(execaError.originalMessage); } diff --git a/lib/error.js b/lib/error.js index b12c144428..5e80c5273b 100644 --- a/lib/error.js +++ b/lib/error.js @@ -1,3 +1,4 @@ +import process from 'node:process'; import {signalsByName} from 'human-signals'; const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { @@ -36,7 +37,7 @@ export const makeError = ({ timedOut, isCanceled, killed, - parsed: {options: {timeout}}, + parsed: {options: {timeout, cwd = process.cwd()}}, }) => { // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. // We normalize them to `undefined` @@ -67,6 +68,7 @@ export const makeError = ({ error.signalDescription = signalDescription; error.stdout = stdout; error.stderr = stderr; + error.cwd = cwd; if (all !== undefined) { error.all = all; diff --git a/readme.md b/readme.md index 2f14ff0513..2975b39c97 100644 --- a/readme.md +++ b/readme.md @@ -461,6 +461,12 @@ A human-friendly description of the signal that was used to terminate the proces If a signal terminated the process, this property is defined and included in the error message. Otherwise it is `undefined`. It is also `undefined` when the signal is very uncommon which should seldomly happen. +#### cwd + +Type: `string` + +The `cwd` of the command if provided in the [command options](#cwd-1). Otherwise it is `process.cwd()`. + #### message Type: `string` diff --git a/test/error.js b/test/error.js index 36bc0ec413..3d7c124a53 100644 --- a/test/error.js +++ b/test/error.js @@ -3,7 +3,7 @@ import childProcess from 'node:child_process'; import {promisify} from 'node:util'; import test from 'ava'; import {execa, execaSync} from '../index.js'; -import {setFixtureDir} from './helpers/fixtures-dir.js'; +import {FIXTURES_DIR, setFixtureDir} from './helpers/fixtures-dir.js'; const pExec = promisify(childProcess.exec); @@ -212,3 +212,14 @@ test('error.code is defined on failure if applicable', async t => { const {code} = await t.throwsAsync(execa('noop.js', {cwd: 1})); t.is(code, 'ERR_INVALID_ARG_TYPE'); }); + +test('error.cwd is defined on failure if applicable', async t => { + const {cwd} = await t.throwsAsync(execa('noop-throw.js', [], {cwd: FIXTURES_DIR})); + t.is(cwd, FIXTURES_DIR); +}); + +test('error.cwd is undefined on failure if not passed as options', async t => { + const expectedCwd = process.cwd(); + const {cwd} = await t.throwsAsync(execa('noop-throw.js')); + t.is(cwd, expectedCwd); +});