Skip to content

Isaacs/unit test config commands #1607

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

Closed
wants to merge 20 commits into from
Closed
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 15 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [10.x, 12.x, 14.x]
os: [ubuntu-latest, windows-latest, macOS-latest]

runs-on: ${{ matrix.os }}
node-version: [6.x, 8.x, 10.x, 12.x]
platform:
- os: ubuntu-latest
shell: bash
- os: macos-latest
shell: bash
- os: windows-latest
shell: bash
- os: windows-latest
shell: powershell

runs-on: ${{ matrix.platform.os }}
defaults:
run:
shell: ${{ matrix.platform.shell }}

steps:
# Checkout the npm/cli repo
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
*.swp
npm-debug.log
.nyc_output/
/.nyc_output
/test/output.log
/test/*/*/node_modules
/test/packages/npm-test-depends-on-spark/which-spark.log
Expand All @@ -25,3 +25,5 @@ npm-debug.log
/node_modules/.cache
.DS_Store
**/.DS_Store
/coverage
/*.tgz
18 changes: 0 additions & 18 deletions .travis.yml

This file was deleted.

4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ uninstall:
mandocs: $(mandocs)

htmldocs:
cd docs && node ../bin/npm-cli.js install && \
node ../bin/npm-cli.js run build:static echo>&2 && \
cd docs && node ../bin/npm-cli.js install --legacy-peer-deps --no-audit && \
node ../bin/npm-cli.js run build:static >&2 && \
rm -rf node_modules .cache public/*js public/*json public/404* public/page-data public/manifest*

docs: mandocs htmldocs
Expand Down
106 changes: 102 additions & 4 deletions bin/npx-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,123 @@ const cli = require('../lib/cli.js')
process.argv[1] = require.resolve('./npm-cli.js')
process.argv.splice(2, 0, 'exec')

// TODO: remove the affordances for removed items in npm v9
const removedSwitches = new Set([
'always-spawn',
'ignore-existing',
'shell-auto-fallback'
])

const removedOpts = new Set([
'npm',
'node-arg',
'n'
])

const removed = new Set([
...removedSwitches,
...removedOpts
])

const { types, shorthands } = require('../lib/config/defaults.js')
const npmSwitches = Object.entries(types)
.filter(([key, type]) => type === Boolean ||
(Array.isArray(type) && type.includes(Boolean)))
.map(([key, type]) => key)

// things that don't take a value
const switches = new Set([
...removedSwitches,
...npmSwitches,
'no-install',
'quiet',
'q',
'version',
'v',
'help',
'h'
])

// things that do take a value
const opts = new Set([
...removedOpts,
'package',
'p',
'cache',
'userconfig',
'call',
'c',
'shell',
'npm',
'node-arg',
'n'
])

// break out of loop when we find a positional argument or --
// If we find a positional arg, we shove -- in front of it, and
// let the normal npm cli handle the rest.
let i
let sawRemovedFlags = false
for (i = 3; i < process.argv.length; i++) {
const arg = process.argv[i]
if (arg === '--') {
break
} else if (/^-/.test(arg)) {
// `--package foo` treated the same as `--package=foo`
if (!arg.includes('=')) {
i++
const [key, ...v] = arg.replace(/^-+/, '').split('=')

switch (key) {
case 'p':
process.argv[i] = ['--package', ...v].join('=')
break

case 'shell':
process.argv[i] = ['--script-shell', ...v].join('=')
break

case 'no-install':
process.argv[i] = '--yes=false'
break

default:
// resolve shorthands and run again
if (shorthands[key] && !removed.has(key)) {
const a = [...shorthands[key]]
if (v.length) {
a.push(v.join('='))
}
process.argv.splice(i, 1, ...a)
i--
continue
}
break
}

if (removed.has(key)) {
console.error(`npx: the --${key} argument has been removed.`)
sawRemovedFlags = true
process.argv.splice(i, 1)
i--
}

if (v.length === 0 && !switches.has(key) &&
(opts.has(key) || !/^-/.test(process.argv[i + 1]))) {
// value will be next argument, skip over it.
if (removed.has(key)) {
// also remove the value for the cut key.
process.argv.splice(i + 1, 1)
} else {
i++
}
}
continue
} else {
// found a positional arg, put -- in front of it, and we're done
process.argv.splice(i, 0, '--')
break
}
}

if (sawRemovedFlags) {
console.error('See `npm help exec` for more information')
}

cli(process)
33 changes: 32 additions & 1 deletion docs/content/cli-commands/npm-exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ where all specified packages are available.

If any requested packages are not present in the local project
dependencies, then they are installed to a folder in the npm cache, which
is added to the `PATH` environment variable in the executed process.
is added to the `PATH` environment variable in the executed process. A
prompt is printed (which can be suppressed by providing either `--yes` or
`--no`).

Package names provided without a specifier will be matched with whatever
version exists in the local project. Package names with a specifier will
only be considered a match if they have the exact same name and version as
Expand Down Expand Up @@ -137,6 +140,34 @@ $ npm x -c 'eslint && say "hooray, lint passed"'
$ npx -c 'eslint && say "hooray, lint passed"'
```

### Compatibility with Older npx Versions

The `npx` binary was rewritten in npm v7.0.0, and the standalone `npx`
package deprecated at that time. `npx` uses the `npm exec`
command instead of a separate argument parser and install process, with
some affordances to maintain backwards compatibility with the arguments it
accepted in previous versions.

This resulted in some shifts in its functionality:

- Any `npm` config value may be provided.
- To prevent security and user-experience problems from mistyping package
names, `npx` prompts before installing anything. Suppress this
prompt with the `-y` or `--yes` option.
- The `--no-install` option is deprecated, and will be converted to `--no`.
- Shell fallback functionality is removed, as it is not advisable.
- The `-p` argument is a shorthand for `--parseable` in npm, but shorthand
for `--package` in npx. This is maintained, but only for the `npx`
executable.
- The `--ignore-existing` option is removed. Locally installed bins are
always present in the executed process `PATH`.
- The `--npm` option is removed. `npx` will always use the `npm` it ships
with.
- The `--node-arg` and `-n` options are removed.
- The `--always-spawn` option is redundant, and thus removed.
- The `--shell` option is replaced with `--script-shell`, but maintained
in the `npx` executable for backwards compatibility.

### See Also

* [npm run-script](/cli-commands/run-script)
Expand Down
33 changes: 32 additions & 1 deletion docs/content/cli-commands/npx.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ where all specified packages are available.

If any requested packages are not present in the local project
dependencies, then they are installed to a folder in the npm cache, which
is added to the `PATH` environment variable in the executed process.
is added to the `PATH` environment variable in the executed process. A
prompt is printed (which can be suppressed by providing either `--yes` or
`--no`).

Package names provided without a specifier will be matched with whatever
version exists in the local project. Package names with a specifier will
only be considered a match if they have the exact same name and version as
Expand Down Expand Up @@ -137,6 +140,34 @@ $ npm x -c 'eslint && say "hooray, lint passed"'
$ npx -c 'eslint && say "hooray, lint passed"'
```

### Compatibility with Older npx Versions

The `npx` binary was rewritten in npm v7.0.0, and the standalone `npx`
package deprecated at that time. `npx` uses the `npm exec`
command instead of a separate argument parser and install process, with
some affordances to maintain backwards compatibility with the arguments it
accepted in previous versions.

This resulted in some shifts in its functionality:

- Any `npm` config value may be provided.
- To prevent security and user-experience problems from mistyping package
names, `npx` prompts before installing anything. Suppress this
prompt with the `-y` or `--yes` option.
- The `--no-install` option is deprecated, and will be converted to `--no`.
- Shell fallback functionality is removed, as it is not advisable.
- The `-p` argument is a shorthand for `--parseable` in npm, but shorthand
for `--package` in npx. This is maintained, but only for the `npx`
executable.
- The `--ignore-existing` option is removed. Locally installed bins are
always present in the executed process `PATH`.
- The `--npm` option is removed. `npx` will always use the `npm` it ships
with.
- The `--node-arg` and `-n` options are removed.
- The `--always-spawn` option is redundant, and thus removed.
- The `--shell` option is replaced with `--script-shell`, but maintained
in the `npx` executable for backwards compatibility.

### See Also

* [npm run-script](/cli-commands/run-script)
Expand Down
Loading