Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow cwd and localDir options to be URLs #492

Merged
merged 6 commits into from Feb 12, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions index.d.ts
Expand Up @@ -35,7 +35,7 @@ export interface CommonOptions<EncodingType> {

@default process.cwd()
*/
readonly localDir?: string;
readonly localDir?: string | URL;

/**
Path to the Node.js executable to use in child processes.
Expand Down Expand Up @@ -113,7 +113,7 @@ export interface CommonOptions<EncodingType> {

@default process.cwd()
*/
readonly cwd?: string;
readonly cwd?: string | URL;

/**
Environment key-value pairs. Extends automatically from `process.env`. Set `extendEnv` to `false` if you don't want this.
Expand Down
2 changes: 2 additions & 0 deletions index.test-d.ts
Expand Up @@ -90,6 +90,7 @@ try {
execa('unicorns', {cleanup: false});
execa('unicorns', {preferLocal: false});
execa('unicorns', {localDir: '.'});
execa('unicorns', {localDir: new URL('file:///test')});
execa('unicorns', {execPath: '/path'});
execa('unicorns', {buffer: false});
execa('unicorns', {input: ''});
Expand Down Expand Up @@ -121,6 +122,7 @@ execa('unicorns', {reject: false});
execa('unicorns', {stripFinalNewline: false});
execa('unicorns', {extendEnv: false});
execa('unicorns', {cwd: '.'});
execa('unicorns', {cwd: new URL('file:///test')});
// eslint-disable-next-line @typescript-eslint/naming-convention
execa('unicorns', {env: {PATH: ''}});
execa('unicorns', {argv0: ''});
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -58,6 +58,7 @@
"get-node": "^12.0.0",
"is-running": "^2.1.0",
"p-event": "^5.0.1",
"semver": "^7.3.5",
"tempfile": "^4.0.0",
"tsd": "^0.18.0",
"xo": "^0.46.4"
Expand Down
8 changes: 6 additions & 2 deletions readme.md
Expand Up @@ -357,11 +357,13 @@ If you `$ npm install foo`, you can then `execa('foo')`.

#### localDir

Type: `string`\
Type: `string | URL`\
Default: `process.cwd()`

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

Using a `URL` is only supported in Node.js `14.18.0`, `16.14.0` or above.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing from the TS docs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! 👍


#### execPath

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

#### cwd

Type: `string`\
Type: `string | URL`\
Default: `process.cwd()`

Current working directory of the child process.

Using a `URL` is only supported in Node.js `14.18.0`, `16.14.0` or above.

#### env

Type: `object`\
Expand Down
25 changes: 24 additions & 1 deletion test/test.js
@@ -1,9 +1,10 @@
import path from 'node:path';
import process from 'node:process';
import {fileURLToPath} from 'node:url';
import {fileURLToPath, pathToFileURL} from 'node:url';
import test from 'ava';
import isRunning from 'is-running';
import getNode from 'get-node';
import semver from 'semver';
import {execa, execaSync} from '../index.js';

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

test('can use `options.cwd` as a string', async t => {
const cwd = '/';
const {stdout} = await execa('node', ['-p', 'process.cwd()'], {cwd});
t.is(path.toNamespacedPath(stdout), path.toNamespacedPath(cwd));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

process.cwd() returns the drive letter on Windows, but path.normalize() does not, so we have to use path.toNamespacedPath().

});

if (semver.satisfies(process.version, '^14.18.0 || >=16.4.0')) {
test('localDir option can be a URL', async t => {
const command = process.platform === 'win32' ? 'echo %PATH%' : 'echo $PATH';
const {stdout} = await execa(command, {shell: true, preferLocal: true, localDir: pathToFileURL('/test')});
const envPaths = stdout.split(path.delimiter);
t.true(envPaths.some(envPath => envPath.endsWith('.bin')));
});

test('can use `options.cwd` as a URL', async t => {
const cwd = '/';
const cwdUrl = pathToFileURL(cwd);
const {stdout} = await execa('node', ['-p', 'process.cwd()'], {cwd: cwdUrl});
t.is(path.toNamespacedPath(stdout), path.toNamespacedPath(cwd));
});
}

test('can use `options.shell: true`', async t => {
const {stdout} = await execa('node test/fixtures/noop.js foo', {shell: true});
t.is(stdout, 'foo');
Expand Down