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

Drop support for Node 12 #497

Merged
merged 5 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ jobs:
fail-fast: false
matrix:
node-version:
- 18
- 16
- 14
- 12
os:
- ubuntu-latest
- macos-latest
# - windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
- uses: codecov/codecov-action@v2
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 16
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 18
with:
fail_ci_if_error: true
9 changes: 2 additions & 7 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {Stream, Readable as ReadableStream} from 'node:stream';

export type StdioOption =
| 'pipe'
| 'overlapped'
| 'ipc'
| 'ignore'
| 'inherit'
Expand Down Expand Up @@ -33,8 +34,6 @@ export interface CommonOptions<EncodingType> {
/**
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.

@default process.cwd()
*/
readonly localDir?: string | URL;
Expand Down Expand Up @@ -113,8 +112,6 @@ export interface CommonOptions<EncodingType> {
/**
Current working directory of the child process.

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

@default process.cwd()
*/
readonly cwd?: string | URL;
Expand All @@ -136,15 +133,13 @@ export interface CommonOptions<EncodingType> {

@default 'pipe'
*/
readonly stdio?: 'pipe' | 'ignore' | 'inherit' | readonly StdioOption[];
readonly stdio?: 'pipe' | 'overlapped' | 'ignore' | 'inherit' | readonly StdioOption[];

/**
Specify the kind of serialization used for sending messages between processes when using the `stdio: 'ipc'` option or `execaNode()`:
- `json`: Uses `JSON.stringify()` and `JSON.parse()`.
- `advanced`: Uses [`v8.serialize()`](https://nodejs.org/api/v8.html#v8_v8_serialize_value)

Requires Node.js `13.2.0` or later.

[More info.](https://nodejs.org/api/child_process.html#child_process_advanced_serialization)

@default 'json'
Expand Down
6 changes: 5 additions & 1 deletion index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,23 @@ execa('unicorns', {input: ''});
execa('unicorns', {input: Buffer.from('')});
execa('unicorns', {input: process.stdin});
execa('unicorns', {stdin: 'pipe'});
execa('unicorns', {stdin: 'overlapped'});
execa('unicorns', {stdin: 'ipc'});
execa('unicorns', {stdin: 'ignore'});
execa('unicorns', {stdin: 'inherit'});
execa('unicorns', {stdin: process.stdin});
execa('unicorns', {stdin: 1});
execa('unicorns', {stdin: undefined});
execa('unicorns', {stdout: 'pipe'});
execa('unicorns', {stdout: 'overlapped'});
execa('unicorns', {stdout: 'ipc'});
execa('unicorns', {stdout: 'ignore'});
execa('unicorns', {stdout: 'inherit'});
execa('unicorns', {stdout: process.stdout});
execa('unicorns', {stdout: 1});
execa('unicorns', {stdout: undefined});
execa('unicorns', {stderr: 'pipe'});
execa('unicorns', {stderr: 'overlapped'});
execa('unicorns', {stderr: 'ipc'});
execa('unicorns', {stderr: 'ignore'});
execa('unicorns', {stderr: 'inherit'});
Expand All @@ -127,10 +130,11 @@ execa('unicorns', {cwd: new URL('file:///test')});
execa('unicorns', {env: {PATH: ''}});
execa('unicorns', {argv0: ''});
execa('unicorns', {stdio: 'pipe'});
execa('unicorns', {stdio: 'overlapped'});
execa('unicorns', {stdio: 'ignore'});
execa('unicorns', {stdio: 'inherit'});
execa('unicorns', {
stdio: ['pipe', 'ipc', 'ignore', 'inherit', process.stdin, 1, undefined],
stdio: ['pipe', 'overlapped', 'ipc', 'ignore', 'inherit', process.stdin, 1, undefined],
});
execa('unicorns', {serialization: 'advanced'});
execa('unicorns', {detached: true});
Expand Down
4 changes: 1 addition & 3 deletions lib/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import mergeStream from 'merge-stream';

// `input` option
export const handleInput = (spawned, input) => {
// Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852
// @todo remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0
if (input === undefined || spawned.stdin === undefined) {
if (input === undefined) {
return;
}

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"type": "module",
"exports": "./index.js",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
"node": "^14.18.0 || ^16.14.0 || >=18.0.0"
},
"scripts": {
"test": "xo && c8 ava && tsd"
Expand Down Expand Up @@ -58,7 +58,6 @@
"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.19.1",
"xo": "^0.48.0"
Expand Down
6 changes: 0 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,6 @@ 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.

#### execPath

Type: `string`\
Expand Down Expand Up @@ -452,8 +450,6 @@ 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 Expand Up @@ -483,8 +479,6 @@ Specify the kind of serialization used for sending messages between processes wh
- `json`: Uses `JSON.stringify()` and `JSON.parse()`.
- `advanced`: Uses [`v8.serialize()`](https://nodejs.org/api/v8.html#v8_v8_serialize_value)

Requires Node.js `13.2.0` or later.

[More info.](https://nodejs.org/api/child_process.html#child_process_advanced_serialization)

#### detached
Expand Down
5 changes: 1 addition & 4 deletions test/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,7 @@ test('error.shortMessage does not contain stdout/stderr', async t => {

test('Original error.message is kept', async t => {
const {originalMessage} = await t.throwsAsync(execa('noop.js', {cwd: 1}));
// On Node >=14.18.0, the error message is
// `The "options.cwd" property must be of type string or an instance of Buffer or URL. Received type number (1)`
t.true(originalMessage.startsWith('The "options.cwd" property must be of type string'));
t.true(originalMessage.includes('. Received type number'));
t.true(originalMessage.startsWith('The "options.cwd" property must be of type string or an instance of Buffer or URL. Received type number'));
});

test('failed is false on success', async t => {
Expand Down
1 change: 0 additions & 1 deletion test/override-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import process from 'node:process';
import {fileURLToPath} from 'node:url';
import test from 'ava';
// The helper module overrides Promise on import so has to be imported before `execa`.
// Can't use top-level await (TLA) + `import(…)` since Node.js 12 doesn't support TLA.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I do not see how a top-level await could be used in this instance, so I just removed the comment.

import {restorePromise} from './helpers/override-promise.js';
// eslint-disable-next-line import/order
import {execa} from '../index.js';
Expand Down
31 changes: 13 additions & 18 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ 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 @@ -167,9 +166,7 @@ if (process.platform !== 'win32') {
});

test('execa() rejects with correct error and doesn\'t throw if running non-executable with input', async t => {
// On Node <12.6.0, `EACCESS` is emitted on `childProcess`.
// On Node >=12.6.0, `EPIPE` is emitted on `childProcess.stdin`.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This comment was invalid: EACCES is used on Node >=12.6.0, and EPIPE on <12.6.0.

await t.throwsAsync(execa('non-executable.js', {input: 'Hey!'}), {message: /EACCES|EPIPE/});
await t.throwsAsync(execa('non-executable.js', {input: 'Hey!'}), {message: /EACCES/});
});
}

Expand Down Expand Up @@ -207,21 +204,19 @@ test('can use `options.cwd` as a string', async t => {
t.is(path.toNamespacedPath(stdout), path.toNamespacedPath(cwd));
});

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('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.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});
Expand Down