Skip to content

Commit 93ab929

Browse files
authored
Allow cwd and localDir options to be URLs (#492)
1 parent e4b9295 commit 93ab929

File tree

5 files changed

+39
-5
lines changed

5 files changed

+39
-5
lines changed

index.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ export interface CommonOptions<EncodingType> {
3333
/**
3434
Preferred path to find locally installed binaries in (use with `preferLocal`).
3535
36+
Using a `URL` is only supported in Node.js `14.18.0`, `16.14.0` or above.
37+
3638
@default process.cwd()
3739
*/
38-
readonly localDir?: string;
40+
readonly localDir?: string | URL;
3941

4042
/**
4143
Path to the Node.js executable to use in child processes.
@@ -111,9 +113,11 @@ export interface CommonOptions<EncodingType> {
111113
/**
112114
Current working directory of the child process.
113115
116+
Using a `URL` is only supported in Node.js `14.18.0`, `16.14.0` or above.
117+
114118
@default process.cwd()
115119
*/
116-
readonly cwd?: string;
120+
readonly cwd?: string | URL;
117121

118122
/**
119123
Environment key-value pairs. Extends automatically from `process.env`. Set `extendEnv` to `false` if you don't want this.

index.test-d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ try {
9090
execa('unicorns', {cleanup: false});
9191
execa('unicorns', {preferLocal: false});
9292
execa('unicorns', {localDir: '.'});
93+
execa('unicorns', {localDir: new URL('file:///test')});
9394
execa('unicorns', {execPath: '/path'});
9495
execa('unicorns', {buffer: false});
9596
execa('unicorns', {input: ''});
@@ -121,6 +122,7 @@ execa('unicorns', {reject: false});
121122
execa('unicorns', {stripFinalNewline: false});
122123
execa('unicorns', {extendEnv: false});
123124
execa('unicorns', {cwd: '.'});
125+
execa('unicorns', {cwd: new URL('file:///test')});
124126
// eslint-disable-next-line @typescript-eslint/naming-convention
125127
execa('unicorns', {env: {PATH: ''}});
126128
execa('unicorns', {argv0: ''});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"get-node": "^12.0.0",
5959
"is-running": "^2.1.0",
6060
"p-event": "^5.0.1",
61+
"semver": "^7.3.5",
6162
"tempfile": "^4.0.0",
6263
"tsd": "^0.18.0",
6364
"xo": "^0.46.4"

readme.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,13 @@ If you `$ npm install foo`, you can then `execa('foo')`.
357357

358358
#### localDir
359359

360-
Type: `string`\
360+
Type: `string | URL`\
361361
Default: `process.cwd()`
362362

363363
Preferred path to find locally installed binaries in (use with `preferLocal`).
364364

365+
Using a `URL` is only supported in Node.js `14.18.0`, `16.14.0` or above.
366+
365367
#### execPath
366368

367369
Type: `string`\
@@ -446,11 +448,13 @@ Execa also accepts the below options which are the same as the options for [`chi
446448

447449
#### cwd
448450

449-
Type: `string`\
451+
Type: `string | URL`\
450452
Default: `process.cwd()`
451453

452454
Current working directory of the child process.
453455

456+
Using a `URL` is only supported in Node.js `14.18.0`, `16.14.0` or above.
457+
454458
#### env
455459

456460
Type: `object`\

test/test.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import path from 'node:path';
22
import process from 'node:process';
3-
import {fileURLToPath} from 'node:url';
3+
import {fileURLToPath, pathToFileURL} from 'node:url';
44
import test from 'ava';
55
import isRunning from 'is-running';
66
import getNode from 'get-node';
7+
import semver from 'semver';
78
import {execa, execaSync} from '../index.js';
89

910
process.env.PATH = fileURLToPath(new URL('./fixtures', import.meta.url)) + path.delimiter + process.env.PATH;
@@ -198,6 +199,28 @@ test('do not extend environment with `extendEnv: false`', async t => {
198199
t.deepEqual(stdout.split('\n'), ['undefined', 'bar']);
199200
});
200201

202+
test('can use `options.cwd` as a string', async t => {
203+
const cwd = '/';
204+
const {stdout} = await execa('node', ['-p', 'process.cwd()'], {cwd});
205+
t.is(path.toNamespacedPath(stdout), path.toNamespacedPath(cwd));
206+
});
207+
208+
if (semver.satisfies(process.version, '^14.18.0 || >=16.4.0')) {
209+
test('localDir option can be a URL', async t => {
210+
const command = process.platform === 'win32' ? 'echo %PATH%' : 'echo $PATH';
211+
const {stdout} = await execa(command, {shell: true, preferLocal: true, localDir: pathToFileURL('/test')});
212+
const envPaths = stdout.split(path.delimiter);
213+
t.true(envPaths.some(envPath => envPath.endsWith('.bin')));
214+
});
215+
216+
test('can use `options.cwd` as a URL', async t => {
217+
const cwd = '/';
218+
const cwdUrl = pathToFileURL(cwd);
219+
const {stdout} = await execa('node', ['-p', 'process.cwd()'], {cwd: cwdUrl});
220+
t.is(path.toNamespacedPath(stdout), path.toNamespacedPath(cwd));
221+
});
222+
}
223+
201224
test('can use `options.shell: true`', async t => {
202225
const {stdout} = await execa('node test/fixtures/noop.js foo', {shell: true});
203226
t.is(stdout, 'foo');

0 commit comments

Comments
 (0)