diff --git a/deps/npm/docs/content/configuring-npm/package-json.md b/deps/npm/docs/content/configuring-npm/package-json.md index 856adb3366cb05..5d61aac52a1822 100644 --- a/deps/npm/docs/content/configuring-npm/package-json.md +++ b/deps/npm/docs/content/configuring-npm/package-json.md @@ -871,6 +871,109 @@ if (foo) { Entries in `optionalDependencies` will override entries of the same name in `dependencies`, so it's usually best to only put in one place. +### overrides + +If you need to make specific changes to dependencies of your dependencies, for +example replacing the version of a dependency with a known security issue, +replacing an existing dependency with a fork, or making sure that the same +version of a package is used everywhere, then you may add an override. + +Overrides provide a way to replace a package in your dependency tree with +another version, or another package entirely. These changes can be scoped as +specific or as vague as desired. + +To make sure the package `foo` is always installed as version `1.0.0` no matter +what version your dependencies rely on: + +```json +{ + "overrides": { + "foo": "1.0.0" + } +} +``` + +The above is a short hand notation, the full object form can be used to allow +overriding a package itself as well as a child of the package. This will cause +`foo` to always be `1.0.0` while also making `bar` at any depth beyond `foo` +also `1.0.0`: + +```json +{ + "overrides": { + "foo": { + ".": "1.0.0", + "bar": "1.0.0" + } + } +} +``` + +To only override `foo` to be `1.0.0` when it's a child (or grandchild, or great +grandchild, etc) of the package `bar`: + +```json +{ + "overrides": { + "bar": { + "foo": "1.0.0" + } + } +} +``` + +Keys can be nested to any arbitrary length. To override `foo` only when it's a +child of `bar` and only when `bar` is a child of `baz`: + +```json +{ + "overrides": { + "baz": { + "bar": { + "foo": "1.0.0" + } + } + } +} +``` + +The key of an override can also include a version, or range of versions. +To override `foo` to `1.0.0`, but only when it's a child of `bar@2.0.0`: + +```json +{ + "overrides": { + "bar@2.0.0": { + "foo": "1.0.0" + } + } +} +``` + +You may not set an override for a package that you directly depend on unless +both the dependency and the override itself share the exact same spec. To make +this limitation easier to deal with, overrides may also be defined as a +reference to a spec for a direct dependency by prefixing the name of the +package you wish the version to match with a `$`. + +```json +{ + "dependencies": { + "foo": "^1.0.0" + }, + "overrides": { + // BAD, will throw an EOVERRIDE error + // "foo": "^2.0.0" + // GOOD, specs match so override is allowed + // "foo": "^1.0.0" + // BEST, the override is defined as a reference to the dependency + "foo": "$foo", + // the referenced package does not need to match the overridden one + "bar": "$foo" + } +} +``` + ### engines You can specify the version of node that your stuff works on: diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index 9fd0fb148aae03..2e313801aaea14 100644 --- a/deps/npm/docs/output/commands/npm-ls.html +++ b/deps/npm/docs/output/commands/npm-ls.html @@ -160,7 +160,7 @@
npm ls promzard
in npm's source tree will show:
-npm@8.2.0 /path/to/npm
+npm@8.3.0 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html
index 8f1c16a4426975..6fb69cf3a8b022 100644
--- a/deps/npm/docs/output/commands/npm.html
+++ b/deps/npm/docs/output/commands/npm.html
@@ -149,7 +149,7 @@ Table of contents
npm <command> [args]
Version
-8.2.0
+8.3.0
Description
npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency
diff --git a/deps/npm/docs/output/configuring-npm/package-json.html b/deps/npm/docs/output/configuring-npm/package-json.html
index 33957dae49fdcd..590749131e99b4 100644
--- a/deps/npm/docs/output/configuring-npm/package-json.html
+++ b/deps/npm/docs/output/configuring-npm/package-json.html
@@ -142,7 +142,7 @@
package.json
Table of contents
-- Description
- name
- version
- description
- keywords
- homepage
- bugs
- license
- people fields: author, contributors
- funding
- files
- main
- browser
- bin
- man
- directories
- repository
- scripts
- config
- dependencies
- devDependencies
- peerDependencies
- peerDependenciesMeta
- bundledDependencies
- optionalDependencies
- engines
- os
- cpu
- private
- publishConfig
- workspaces
- DEFAULT VALUES
- SEE ALSO
+- Description
- name
- version
- description
- keywords
- homepage
- bugs
- license
- people fields: author, contributors
- funding
- files
- main
- browser
- bin
- man
- directories
- repository
- scripts
- config
- dependencies
- devDependencies
- peerDependencies
- peerDependenciesMeta
- bundledDependencies
- optionalDependencies
- overrides
- engines
- os
- cpu
- private
- publishConfig
- workspaces
- DEFAULT VALUES
- SEE ALSO
Description
@@ -800,6 +800,88 @@ optionalDependencies
Entries in optionalDependencies
will override entries of the same name in
dependencies
, so it's usually best to only put in one place.
+overrides
+If you need to make specific changes to dependencies of your dependencies, for
+example replacing the version of a dependency with a known security issue,
+replacing an existing dependency with a fork, or making sure that the same
+version of a package is used everywhere, then you may add an override.
+Overrides provide a way to replace a package in your dependency tree with
+another version, or another package entirely. These changes can be scoped as
+specific or as vague as desired.
+To make sure the package foo
is always installed as version 1.0.0
no matter
+what version your dependencies rely on:
+{
+ "overrides": {
+ "foo": "1.0.0"
+ }
+}
+
+The above is a short hand notation, the full object form can be used to allow
+overriding a package itself as well as a child of the package. This will cause
+foo
to always be 1.0.0
while also making bar
at any depth beyond foo
+also 1.0.0
:
+{
+ "overrides": {
+ "foo": {
+ ".": "1.0.0",
+ "bar": "1.0.0"
+ }
+ }
+}
+
+To only override foo
to be 1.0.0
when it's a child (or grandchild, or great
+grandchild, etc) of the package bar
:
+{
+ "overrides": {
+ "bar": {
+ "foo": "1.0.0"
+ }
+ }
+}
+
+Keys can be nested to any arbitrary length. To override foo
only when it's a
+child of bar
and only when bar
is a child of baz
:
+{
+ "overrides": {
+ "baz": {
+ "bar": {
+ "foo": "1.0.0"
+ }
+ }
+ }
+}
+
+The key of an override can also include a version, or range of versions.
+To override foo
to 1.0.0
, but only when it's a child of bar@2.0.0
:
+{
+ "overrides": {
+ "bar@2.0.0": {
+ "foo": "1.0.0"
+ }
+ }
+}
+
+You may not set an override for a package that you directly depend on unless
+both the dependency and the override itself share the exact same spec. To make
+this limitation easier to deal with, overrides may also be defined as a
+reference to a spec for a direct dependency by prefixing the name of the
+package you wish the version to match with a $
.
+{
+ "dependencies": {
+ "foo": "^1.0.0"
+ },
+ "overrides": {
+ // BAD, will throw an EOVERRIDE error
+ // "foo": "^2.0.0"
+ // GOOD, specs match so override is allowed
+ // "foo": "^1.0.0"
+ // BEST, the override is defined as a reference to the dependency
+ "foo": "$foo",
+ // the referenced package does not need to match the overridden one
+ "bar": "$foo"
+ }
+}
+
engines
You can specify the version of node that your stuff works on:
{
diff --git a/deps/npm/lib/commands/config.js b/deps/npm/lib/commands/config.js
index eb1d570c6ea259..96524e00817f5d 100644
--- a/deps/npm/lib/commands/config.js
+++ b/deps/npm/lib/commands/config.js
@@ -2,7 +2,7 @@
const configDefs = require('../utils/config/index.js')
const mkdirp = require('mkdirp-infer-owner')
-const { dirname } = require('path')
+const { dirname, resolve } = require('path')
const { promisify } = require('util')
const fs = require('fs')
const readFile = promisify(fs.readFile)
@@ -11,6 +11,7 @@ const { spawn } = require('child_process')
const { EOL } = require('os')
const ini = require('ini')
const localeCompare = require('@isaacs/string-locale-compare')('en')
+const rpj = require('read-package-json-fast')
const log = require('../utils/log-shim.js')
// take an array of `[key, value, k2=v2, k3, v3, ...]` and turn into
@@ -28,7 +29,17 @@ const keyValues = args => {
return kv
}
-const publicVar = k => !/^(\/\/[^:]+:)?_/.test(k)
+const publicVar = k => {
+ // _password
+ if (k.startsWith('_')) {
+ return false
+ }
+ // //localhost:8080/:_password
+ if (k.startsWith('//') && k.includes(':_')) {
+ return false
+ }
+ return true
+}
const BaseCommand = require('../base-command.js')
class Config extends BaseCommand {
@@ -147,7 +158,7 @@ class Config extends BaseCommand {
const out = []
for (const key of keys) {
if (!publicVar(key)) {
- throw `The ${key} option is protected, and cannot be retrieved in this way`
+ throw new Error(`The ${key} option is protected, and cannot be retrieved in this way`)
}
const pref = keys.length > 1 ? `${key}=` : ''
@@ -257,6 +268,23 @@ ${defData}
`; HOME = ${process.env.HOME}`,
'; Run `npm config ls -l` to show all defaults.'
)
+ msg.push('')
+ }
+
+ if (!this.npm.config.get('global')) {
+ const pkgPath = resolve(this.npm.prefix, 'package.json')
+ const pkg = await rpj(pkgPath).catch(() => ({}))
+
+ if (pkg.publishConfig) {
+ msg.push(`; "publishConfig" from ${pkgPath}`)
+ msg.push('; This set of config values will be used at publish-time.', '')
+ const pkgKeys = Object.keys(pkg.publishConfig).sort(localeCompare)
+ for (const k of pkgKeys) {
+ const v = publicVar(k) ? JSON.stringify(pkg.publishConfig[k]) : '(protected)'
+ msg.push(`${k} = ${v}`)
+ }
+ msg.push('')
+ }
}
this.npm.output(msg.join('\n').trim())
diff --git a/deps/npm/lib/commands/publish.js b/deps/npm/lib/commands/publish.js
index ad538668b63a38..b8209374925fe2 100644
--- a/deps/npm/lib/commands/publish.js
+++ b/deps/npm/lib/commands/publish.js
@@ -104,11 +104,15 @@ class Publish extends BaseCommand {
const resolved = npa.resolve(manifest.name, manifest.version)
const registry = npmFetch.pickRegistry(resolved, opts)
const creds = this.npm.config.getCredentialsByURI(registry)
+ const outputRegistry = replaceInfo(registry)
if (!creds.token && !creds.username) {
- throw Object.assign(new Error('This command requires you to be logged in.'), {
- code: 'ENEEDAUTH',
- })
+ throw Object.assign(
+ new Error(`This command requires you to be logged in to ${outputRegistry}`), {
+ code: 'ENEEDAUTH',
+ }
+ )
}
+ log.notice('', `Publishing to ${outputRegistry}`)
await otplease(opts, opts => libpub(manifest, tarballData, opts))
}
diff --git a/deps/npm/lib/utils/exit-handler.js b/deps/npm/lib/utils/exit-handler.js
index 32434662422ae9..22c774101751b7 100644
--- a/deps/npm/lib/utils/exit-handler.js
+++ b/deps/npm/lib/utils/exit-handler.js
@@ -116,6 +116,7 @@ const exitHandler = err => {
exitCode = err.code
noLogMessage = true
} else if (typeof err === 'string') {
+ // XXX: we should stop throwing strings
log.error('', err)
noLogMessage = true
} else if (!(err instanceof Error)) {
diff --git a/deps/npm/lib/utils/log-file.js b/deps/npm/lib/utils/log-file.js
index b37fd23e079c04..0bf1e0054ea2bf 100644
--- a/deps/npm/lib/utils/log-file.js
+++ b/deps/npm/lib/utils/log-file.js
@@ -8,6 +8,8 @@ const fsMiniPass = require('fs-minipass')
const log = require('./log-shim')
const withChownSync = require('./with-chown-sync')
+const padZero = (n, length) => n.toString().padStart(length.toString().length, '0')
+
const _logHandler = Symbol('logHandler')
const _formatLogItem = Symbol('formatLogItem')
const _getLogFilePath = Symbol('getLogFilePath')
@@ -34,7 +36,7 @@ class LogFiles {
// here for infinite loops that still log. This is also partially handled
// by the config.get('max-files') option, but this is a failsafe to
// prevent runaway log file creation
- #MAX_LOG_FILES_PER_PROCESS = null
+ #MAX_FILES_PER_PROCESS = null
#fileLogCount = 0
#totalLogCount = 0
@@ -48,7 +50,7 @@ class LogFiles {
} = {}) {
this.#logId = LogFiles.logId(new Date())
this.#MAX_LOGS_PER_FILE = maxLogsPerFile
- this.#MAX_LOG_FILES_PER_PROCESS = maxFilesPerProcess
+ this.#MAX_FILES_PER_PROCESS = maxFilesPerProcess
this.on()
}
@@ -56,10 +58,6 @@ class LogFiles {
return d.toISOString().replace(/[.:]/g, '_')
}
- static fileName (prefix, suffix) {
- return `${prefix}-debug-${suffix}.log`
- }
-
static format (count, level, title, ...args) {
let prefix = `${count} ${level}`
if (title) {
@@ -149,7 +147,7 @@ class LogFiles {
if (this.#fileLogCount >= this.#MAX_LOGS_PER_FILE) {
// Write last chunk to the file and close it
this[_endStream](logOutput)
- if (this.#files.length >= this.#MAX_LOG_FILES_PER_PROCESS) {
+ if (this.#files.length >= this.#MAX_FILES_PER_PROCESS) {
// but if its way too many then we just stop listening
this.off()
} else {
@@ -166,23 +164,21 @@ class LogFiles {
return LogFiles.format(this.#totalLogCount++, ...args)
}
- [_getLogFilePath] (prefix, suffix) {
- return path.resolve(this.#dir, LogFiles.fileName(prefix, suffix))
+ [_getLogFilePath] (prefix, suffix, sep = '-') {
+ return path.resolve(this.#dir, prefix + sep + 'debug' + sep + suffix + '.log')
}
[_openLogFile] () {
// Count in filename will be 0 indexed
const count = this.#files.length
- // Pad with zeros so that our log files are always sorted properly
- // We never want to write files ending in `-9.log` and `-10.log` because
- // log file cleaning is done by deleting the oldest so in this example
- // `-10.log` would be deleted next
- const countDigits = this.#MAX_LOG_FILES_PER_PROCESS.toString().length
-
try {
const logStream = withChownSync(
- this[_getLogFilePath](this.#logId, count.toString().padStart(countDigits, '0')),
+ // Pad with zeros so that our log files are always sorted properly
+ // We never want to write files ending in `-9.log` and `-10.log` because
+ // log file cleaning is done by deleting the oldest so in this example
+ // `-10.log` would be deleted next
+ this[_getLogFilePath](this.#logId, padZero(count, this.#MAX_FILES_PER_PROCESS)),
// Some effort was made to make the async, but we need to write logs
// during process.on('exit') which has to be synchronous. So in order
// to never drop log messages, it is easiest to make it sync all the time
@@ -214,14 +210,13 @@ class LogFiles {
return
}
- // Add 1 to account for the current log file and make
- // minimum config 0 so current log file is never deleted
- // XXX: we should make a separate documented option to
- // disable log file writing
- const max = Math.max(this.#logsMax, 0) + 1
try {
- const files = await glob(this[_getLogFilePath]('*', '*'))
- const toDelete = files.length - max
+ // Handle the old (prior to 8.2.0) log file names which did not have an counter suffix
+ // so match by anything after `-debug` and before `.log` (including nothing)
+ const logGlob = this[_getLogFilePath]('*-', '*', '')
+ // Always ignore the currently written files
+ const files = await glob(logGlob, { ignore: this.#files })
+ const toDelete = files.length - this.#logsMax
if (toDelete <= 0) {
return
@@ -233,7 +228,7 @@ class LogFiles {
try {
await rimraf(file)
} catch (e) {
- log.warn('logfile', 'error removing log file', file, e)
+ log.silly('logfile', 'error removing log file', file, e)
}
}
} catch (e) {
diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1
index 5320cc51fbf810..61db54629dc7e4 100644
--- a/deps/npm/man/man1/npm-ls.1
+++ b/deps/npm/man/man1/npm-ls.1
@@ -26,7 +26,7 @@ example, running \fBnpm ls promzard\fP in npm's source tree will show:
.P
.RS 2
.nf
-npm@8\.2\.0 /path/to/npm
+npm@8\.3\.0 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.fi
diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1
index bddb695d5548e6..1ee03685317a08 100644
--- a/deps/npm/man/man1/npm.1
+++ b/deps/npm/man/man1/npm.1
@@ -10,7 +10,7 @@ npm [args]
.RE
.SS Version
.P
-8\.2\.0
+8\.3\.0
.SS Description
.P
npm is the package manager for the Node JavaScript platform\. It puts
diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5
index 6f38ff876b9aa5..6306a8cb6c3285 100644
--- a/deps/npm/man/man5/package-json.5
+++ b/deps/npm/man/man5/package-json.5
@@ -960,6 +960,120 @@ if (foo) {
.P
Entries in \fBoptionalDependencies\fP will override entries of the same name in
\fBdependencies\fP, so it's usually best to only put in one place\.
+.SS overrides
+.P
+If you need to make specific changes to dependencies of your dependencies, for
+example replacing the version of a dependency with a known security issue,
+replacing an existing dependency with a fork, or making sure that the same
+version of a package is used everywhere, then you may add an override\.
+.P
+Overrides provide a way to replace a package in your dependency tree with
+another version, or another package entirely\. These changes can be scoped as
+specific or as vague as desired\.
+.P
+To make sure the package \fBfoo\fP is always installed as version \fB1\.0\.0\fP no matter
+what version your dependencies rely on:
+.P
+.RS 2
+.nf
+{
+ "overrides": {
+ "foo": "1\.0\.0"
+ }
+}
+.fi
+.RE
+.P
+The above is a short hand notation, the full object form can be used to allow
+overriding a package itself as well as a child of the package\. This will cause
+\fBfoo\fP to always be \fB1\.0\.0\fP while also making \fBbar\fP at any depth beyond \fBfoo\fP
+also \fB1\.0\.0\fP:
+.P
+.RS 2
+.nf
+{
+ "overrides": {
+ "foo": {
+ "\.": "1\.0\.0",
+ "bar": "1\.0\.0"
+ }
+ }
+}
+.fi
+.RE
+.P
+To only override \fBfoo\fP to be \fB1\.0\.0\fP when it's a child (or grandchild, or great
+grandchild, etc) of the package \fBbar\fP:
+.P
+.RS 2
+.nf
+{
+ "overrides": {
+ "bar": {
+ "foo": "1\.0\.0"
+ }
+ }
+}
+.fi
+.RE
+.P
+Keys can be nested to any arbitrary length\. To override \fBfoo\fP only when it's a
+child of \fBbar\fP and only when \fBbar\fP is a child of \fBbaz\fP:
+.P
+.RS 2
+.nf
+{
+ "overrides": {
+ "baz": {
+ "bar": {
+ "foo": "1\.0\.0"
+ }
+ }
+ }
+}
+.fi
+.RE
+.P
+The key of an override can also include a version, or range of versions\.
+To override \fBfoo\fP to \fB1\.0\.0\fP, but only when it's a child of \fBbar@2\.0\.0\fP:
+.P
+.RS 2
+.nf
+{
+ "overrides": {
+ "bar@2\.0\.0": {
+ "foo": "1\.0\.0"
+ }
+ }
+}
+.fi
+.RE
+.P
+You may not set an override for a package that you directly depend on unless
+both the dependency and the override itself share the exact same spec\. To make
+this limitation easier to deal with, overrides may also be defined as a
+reference to a spec for a direct dependency by prefixing the name of the
+package you wish the version to match with a \fB$\fP\|\.
+.P
+.RS 2
+.nf
+{
+ "dependencies": {
+ "foo": "^1\.0\.0"
+ },
+ "overrides": {
+ // BAD, will throw an EOVERRIDE error
+ // "foo": "^2\.0\.0"
+ // GOOD, specs match so override is allowed
+ // "foo": "^1\.0\.0"
+ // BEST, the override is defined as a reference to the dependency
+ "foo": "$foo",
+ // the referenced package does not need to match the overridden one
+ "bar": "$foo"
+ }
+}
+.fi
+.RE
.SS engines
.P
You can specify the version of node that your stuff works on:
diff --git a/deps/npm/node_modules/@npmcli/arborist/README.md b/deps/npm/node_modules/@npmcli/arborist/README.md
index 4c19fab8b78c26..8722b7a43cc2fa 100644
--- a/deps/npm/node_modules/@npmcli/arborist/README.md
+++ b/deps/npm/node_modules/@npmcli/arborist/README.md
@@ -4,8 +4,8 @@ Inspect and manage `node_modules` trees.
![a tree with the word ARBORIST superimposed on it](https://raw.githubusercontent.com/npm/arborist/main/docs/logo.svg?sanitize=true)
-There's more documentation [in the notes
-folder](https://github.com/npm/arborist/tree/main/notes).
+There's more documentation [in the docs
+folder](https://github.com/npm/arborist/tree/main/docs).
## USAGE
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
index aa37acfe52d316..899d92ca937cca 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
@@ -379,6 +379,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
optional: false,
global: this[_global],
legacyPeerDeps: this.legacyPeerDeps,
+ loadOverrides: true,
})
if (root.isLink) {
root.target = new Node({
@@ -676,6 +677,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
// calls rather than walking over everything in the tree.
const set = this.idealTree.inventory
.filter(n => this[_shouldUpdateNode](n))
+ // XXX add any invalid edgesOut to the queue
for (const node of set) {
for (const edge of node.edgesIn) {
this.addTracker('idealTree', edge.from.name, edge.from.location)
@@ -772,7 +774,10 @@ This is a one-time fix-up, please be patient...
[_buildDeps] () {
process.emit('time', 'idealTree:buildDeps')
const tree = this.idealTree.target
+ tree.assertRootOverrides()
this[_depsQueue].push(tree)
+ // XXX also push anything that depends on a node with a name
+ // in the override list
this.log.silly('idealTree', 'buildDeps')
this.addTracker('idealTree', tree.name, '')
return this[_buildDepStep]()
@@ -1112,6 +1117,7 @@ This is a one-time fix-up, please be patient...
path: node.realpath,
sourceReference: node,
legacyPeerDeps: this.legacyPeerDeps,
+ overrides: node.overrides,
})
// also need to set up any targets from any link deps, so that
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
index a232bf32b32d06..0d260858d81c6b 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
@@ -127,6 +127,7 @@ module.exports = cls => class ActualLoader extends cls {
realpath: real,
pkg: {},
global,
+ loadOverrides: true,
})
return this[_loadActualActually]({ root, ignoreMissing, global })
}
@@ -135,8 +136,11 @@ module.exports = cls => class ActualLoader extends cls {
this[_actualTree] = await this[_loadFSNode]({
path: this.path,
real: await realpath(this.path, this[_rpcache], this[_stcache]),
+ loadOverrides: true,
})
+ this[_actualTree].assertRootOverrides()
+
// Note: hidden lockfile will be rejected if it's not the latest thing
// in the folder, or if any of the entries in the hidden lockfile are
// missing.
@@ -236,13 +240,26 @@ module.exports = cls => class ActualLoader extends cls {
this[_actualTree] = root
}
- [_loadFSNode] ({ path, parent, real, root }) {
+ [_loadFSNode] ({ path, parent, real, root, loadOverrides }) {
if (!real) {
return realpath(path, this[_rpcache], this[_stcache])
.then(
- real => this[_loadFSNode]({ path, parent, real, root }),
+ real => this[_loadFSNode]({
+ path,
+ parent,
+ real,
+ root,
+ loadOverrides,
+ }),
// if realpath fails, just provide a dummy error node
- error => new Node({ error, path, realpath: path, parent, root })
+ error => new Node({
+ error,
+ path,
+ realpath: path,
+ parent,
+ root,
+ loadOverrides,
+ })
)
}
@@ -271,6 +288,7 @@ module.exports = cls => class ActualLoader extends cls {
error,
parent,
root,
+ loadOverrides,
})
})
.then(node => {
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
index 7761380e9f71fe..4d65e3da6f6831 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
@@ -72,6 +72,7 @@ module.exports = cls => class VirtualLoader extends cls {
this[rootOptionProvided] = options.root
await this[loadFromShrinkwrap](s, root)
+ root.assertRootOverrides()
return treeCheck(this.virtualTree)
}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/edge.js b/deps/npm/node_modules/@npmcli/arborist/lib/edge.js
index 1881001ef143e1..87439e7645366a 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/edge.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/edge.js
@@ -29,6 +29,7 @@ class ArboristEdge {}
const printableEdge = (edge) => {
const edgeFrom = edge.from && edge.from.location
const edgeTo = edge.to && edge.to.location
+ const override = edge.overrides && edge.overrides.value
return Object.assign(new ArboristEdge(), {
name: edge.name,
@@ -38,12 +39,13 @@ const printableEdge = (edge) => {
...(edgeTo ? { to: edgeTo } : {}),
...(edge.error ? { error: edge.error } : {}),
...(edge.peerConflicted ? { peerConflicted: true } : {}),
+ ...(override ? { overridden: override } : {}),
})
}
class Edge {
constructor (options) {
- const { type, name, spec, accept, from } = options
+ const { type, name, spec, accept, from, overrides } = options
if (typeof spec !== 'string') {
throw new TypeError('must provide string spec')
@@ -55,6 +57,10 @@ class Edge {
this[_spec] = spec
+ if (overrides !== undefined) {
+ this.overrides = overrides
+ }
+
if (accept !== undefined) {
if (typeof accept !== 'string') {
throw new TypeError('accept field must be a string if provided')
@@ -82,8 +88,11 @@ class Edge {
}
satisfiedBy (node) {
- return node.name === this.name &&
- depValid(node, this.spec, this.accept, this.from)
+ if (node.name !== this.name) {
+ return false
+ }
+
+ return depValid(node, this.spec, this.accept, this.from)
}
explain (seen = []) {
@@ -101,6 +110,10 @@ class Edge {
type: this.type,
name: this.name,
spec: this.spec,
+ ...(this.rawSpec !== this.spec ? {
+ rawSpec: this.rawSpec,
+ overridden: true,
+ } : {}),
...(bundled ? { bundled } : {}),
...(error ? { error } : {}),
...(from ? { from: from.explain(null, seen) } : {}),
@@ -143,7 +156,28 @@ class Edge {
return this[_name]
}
+ get rawSpec () {
+ return this[_spec]
+ }
+
get spec () {
+ if (this.overrides && this.overrides.value && this.overrides.name === this.name) {
+ if (this.overrides.value.startsWith('$')) {
+ const ref = this.overrides.value.slice(1)
+ const pkg = this.from.root.package
+ const overrideSpec = (pkg.devDependencies && pkg.devDependencies[ref]) ||
+ (pkg.optionalDependencies && pkg.optionalDependencies[ref]) ||
+ (pkg.dependencies && pkg.dependencies[ref]) ||
+ (pkg.peerDependencies && pkg.peerDependencies[ref])
+
+ if (overrideSpec) {
+ return overrideSpec
+ }
+
+ throw new Error(`Unable to resolve reference ${this.overrides.value}`)
+ }
+ return this.overrides.value
+ }
return this[_spec]
}
@@ -213,6 +247,7 @@ class Edge {
if (node.edgesOut.has(this.name)) {
node.edgesOut.get(this.name).detach()
}
+
node.addEdgeOut(this)
this.reload()
}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/node.js b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
index d311b6a8378172..45c288bcf6cf73 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/node.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
@@ -32,6 +32,7 @@ const semver = require('semver')
const nameFromFolder = require('@npmcli/name-from-folder')
const Edge = require('./edge.js')
const Inventory = require('./inventory.js')
+const OverrideSet = require('./override-set.js')
const { normalize } = require('read-package-json-fast')
const { getPaths: getBinPaths } = require('bin-links')
const npa = require('npm-package-arg')
@@ -88,6 +89,8 @@ class Node {
legacyPeerDeps = false,
linksIn,
hasShrinkwrap,
+ overrides,
+ loadOverrides = false,
extraneous = true,
dev = true,
optional = true,
@@ -190,6 +193,17 @@ class Node {
// because this.package is read when adding to inventory
this[_package] = pkg && typeof pkg === 'object' ? pkg : {}
+ if (overrides) {
+ this.overrides = overrides
+ } else if (loadOverrides) {
+ const overrides = this[_package].overrides || {}
+ if (Object.keys(overrides).length > 0) {
+ this.overrides = new OverrideSet({
+ overrides: this[_package].overrides,
+ })
+ }
+ }
+
// only relevant for the root and top nodes
this.meta = meta
@@ -963,6 +977,11 @@ class Node {
return false
}
+ // XXX need to check for two root nodes?
+ if (node.overrides !== this.overrides) {
+ return false
+ }
+
ignorePeers = new Set(ignorePeers)
// gather up all the deps of this node and that are only depended
@@ -1208,6 +1227,10 @@ class Node {
this[_changePath](newPath)
}
+ if (parent.overrides) {
+ this.overrides = parent.overrides.getNodeRule(this)
+ }
+
// clobbers anything at that path, resets all appropriate references
this.root = parent.root
}
@@ -1279,11 +1302,33 @@ class Node {
}
}
+ assertRootOverrides () {
+ if (!this.isProjectRoot || !this.overrides) {
+ return
+ }
+
+ for (const edge of this.edgesOut.values()) {
+ // if these differ an override has been applied, those are not allowed
+ // for top level dependencies so throw an error
+ if (edge.spec !== edge.rawSpec && !edge.spec.startsWith('$')) {
+ throw Object.assign(new Error(`Override for ${edge.name}@${edge.rawSpec} conflicts with direct dependency`), { code: 'EOVERRIDE' })
+ }
+ }
+ }
+
addEdgeOut (edge) {
+ if (this.overrides) {
+ edge.overrides = this.overrides.getEdgeRule(edge)
+ }
+
this.edgesOut.set(edge.name, edge)
}
addEdgeIn (edge) {
+ if (edge.overrides) {
+ this.overrides = edge.overrides
+ }
+
this.edgesIn.add(edge)
// try to get metadata from the yarn.lock file
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/override-set.js b/deps/npm/node_modules/@npmcli/arborist/lib/override-set.js
new file mode 100644
index 00000000000000..e2e04e03e911ef
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/override-set.js
@@ -0,0 +1,123 @@
+const npa = require('npm-package-arg')
+const semver = require('semver')
+
+class OverrideSet {
+ constructor ({ overrides, key, parent }) {
+ this.parent = parent
+ this.children = new Map()
+
+ if (typeof overrides === 'string') {
+ overrides = { '.': overrides }
+ }
+
+ // change a literal empty string to * so we can use truthiness checks on
+ // the value property later
+ if (overrides['.'] === '') {
+ overrides['.'] = '*'
+ }
+
+ if (parent) {
+ const spec = npa(key)
+ if (!spec.name) {
+ throw new Error(`Override without name: ${key}`)
+ }
+
+ this.name = spec.name
+ spec.name = ''
+ this.key = key
+ this.keySpec = spec.rawSpec === '' ? '' : spec.toString()
+ this.value = overrides['.'] || this.keySpec
+ }
+
+ for (const [key, childOverrides] of Object.entries(overrides)) {
+ if (key === '.') {
+ continue
+ }
+
+ const child = new OverrideSet({
+ parent: this,
+ key,
+ overrides: childOverrides,
+ })
+
+ this.children.set(child.key, child)
+ }
+ }
+
+ getEdgeRule (edge) {
+ for (const rule of this.ruleset.values()) {
+ if (rule.name !== edge.name) {
+ continue
+ }
+
+ if (rule.keySpec === '' ||
+ semver.intersects(edge.spec, rule.keySpec)) {
+ return rule
+ }
+ }
+
+ return this
+ }
+
+ getNodeRule (node) {
+ for (const rule of this.ruleset.values()) {
+ if (rule.name !== node.name) {
+ continue
+ }
+
+ if (rule.keySpec === '' ||
+ semver.satisfies(node.version, rule.keySpec) ||
+ semver.satisfies(node.version, rule.value)) {
+ return rule
+ }
+ }
+
+ return this
+ }
+
+ getMatchingRule (node) {
+ for (const rule of this.ruleset.values()) {
+ if (rule.name !== node.name) {
+ continue
+ }
+
+ if (rule.keySpec === '' ||
+ semver.satisfies(node.version, rule.keySpec) ||
+ semver.satisfies(node.version, rule.value)) {
+ return rule
+ }
+ }
+
+ return null
+ }
+
+ * ancestry () {
+ for (let ancestor = this; ancestor; ancestor = ancestor.parent) {
+ yield ancestor
+ }
+ }
+
+ get isRoot () {
+ return !this.parent
+ }
+
+ get ruleset () {
+ const ruleset = new Map()
+
+ for (const override of this.ancestry()) {
+ for (const kid of override.children.values()) {
+ if (!ruleset.has(kid.key)) {
+ ruleset.set(kid.key, kid)
+ }
+ }
+
+ if (!override.isRoot && !ruleset.has(override.key)) {
+ ruleset.set(override.key, override)
+ }
+ }
+
+ return ruleset
+ }
+}
+
+module.exports = OverrideSet
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js b/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js
index be735d5fc1c4b6..c0cbe91fe3667f 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js
@@ -295,6 +295,7 @@ class PlaceDep {
integrity: dep.integrity,
legacyPeerDeps: this.legacyPeerDeps,
error: dep.errors[0],
+ ...(dep.overrides ? { overrides: dep.overrides } : {}),
...(dep.isLink ? { target: dep.target, realpath: dep.realpath } : {}),
})
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/printable.js b/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
index 018e569b1d2f16..7c8d52a4207aaf 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
@@ -1,6 +1,5 @@
// helper function to output a clearer visualization
// of the current node and its descendents
-
const localeCompare = require('@isaacs/string-locale-compare')('en')
const util = require('util')
const relpath = require('./relpath.js')
@@ -65,6 +64,11 @@ class ArboristNode {
this.errors = tree.errors.map(treeError)
}
+ if (tree.overrides) {
+ this.overrides = new Map([...tree.overrides.ruleset.values()]
+ .map((override) => [override.key, override.value]))
+ }
+
// edgesOut sorted by name
if (tree.edgesOut.size) {
this.edgesOut = new Map([...tree.edgesOut.entries()]
@@ -126,7 +130,10 @@ class Edge {
constructor (edge) {
this.type = edge.type
this.name = edge.name
- this.spec = edge.spec || '*'
+ this.spec = edge.rawSpec || '*'
+ if (edge.rawSpec !== edge.spec) {
+ this.override = edge.spec
+ }
if (edge.error) {
this.error = edge.error
}
@@ -145,6 +152,8 @@ class EdgeOut extends Edge {
[util.inspect.custom] () {
return `{ ${this.type} ${this.name}@${this.spec}${
+ this.override ? ` overridden:${this.override}` : ''
+ }${
this.to ? ' -> ' + this.to : ''
}${
this.error ? ' ' + this.error : ''
diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json
index 34d38572d38d75..cea3d5ecd7e4e5 100644
--- a/deps/npm/node_modules/@npmcli/arborist/package.json
+++ b/deps/npm/node_modules/@npmcli/arborist/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/arborist",
- "version": "4.0.5",
+ "version": "4.1.1",
"description": "Manage node_modules trees",
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
@@ -24,7 +24,7 @@
"npm-pick-manifest": "^6.1.0",
"npm-registry-fetch": "^11.0.0",
"pacote": "^12.0.2",
- "parse-conflict-json": "^1.1.1",
+ "parse-conflict-json": "^2.0.1",
"proc-log": "^1.0.0",
"promise-all-reject-late": "^1.0.0",
"promise-call-limit": "^1.0.1",
@@ -37,10 +37,11 @@
"walk-up-path": "^1.0.0"
},
"devDependencies": {
- "@npmcli/template-oss": "^2.3.0",
+ "@npmcli/template-oss": "^2.3.1",
"benchmark": "^2.1.4",
"chalk": "^4.1.0",
"minify-registry-metadata": "^2.1.0",
+ "nock": "^13.2.0",
"tap": "^15.1.2",
"tcompare": "^5.0.6"
},
@@ -93,7 +94,7 @@
"engines": {
"node": "^12.13.0 || ^14.15.0 || >=16"
},
- "templateVersion": "2.3.0",
+ "templateVersion": "2.3.1",
"eslintIgnore": [
"test/fixtures/",
"!test/fixtures/*.js"
diff --git a/deps/npm/node_modules/just-diff-apply/index.mjs b/deps/npm/node_modules/just-diff-apply/index.mjs
new file mode 100644
index 00000000000000..fcd26c2f5a23e8
--- /dev/null
+++ b/deps/npm/node_modules/just-diff-apply/index.mjs
@@ -0,0 +1,110 @@
+/*
+ const obj1 = {a: 3, b: 5};
+ diffApply(obj1,
+ [
+ { "op": "remove", "path": ['b'] },
+ { "op": "replace", "path": ['a'], "value": 4 },
+ { "op": "add", "path": ['c'], "value": 5 }
+ ]
+ );
+ obj1; // {a: 4, c: 5}
+
+ // using converter to apply jsPatch standard paths
+ // see http://jsonpatch.com
+ import {diff, jsonPatchPathConverter} from 'just-diff'
+ const obj2 = {a: 3, b: 5};
+ diffApply(obj2, [
+ { "op": "remove", "path": '/b' },
+ { "op": "replace", "path": '/a', "value": 4 }
+ { "op": "add", "path": '/c', "value": 5 }
+ ], jsonPatchPathConverter);
+ obj2; // {a: 4, c: 5}
+
+ // arrays
+ const obj3 = {a: 4, b: [1, 2, 3]};
+ diffApply(obj3, [
+ { "op": "replace", "path": ['a'], "value": 3 }
+ { "op": "replace", "path": ['b', 2], "value": 4 }
+ { "op": "add", "path": ['b', 3], "value": 9 }
+ ]);
+ obj3; // {a: 3, b: [1, 2, 4, 9]}
+
+ // nested paths
+ const obj4 = {a: 4, b: {c: 3}};
+ diffApply(obj4, [
+ { "op": "replace", "path": ['a'], "value": 5 }
+ { "op": "remove", "path": ['b', 'c']}
+ { "op": "add", "path": ['b', 'd'], "value": 4 }
+ ]);
+ obj4; // {a: 5, b: {d: 4}}
+*/
+
+var REMOVE = 'remove';
+var REPLACE = 'replace';
+var ADD = 'add';
+
+function diffApply(obj, diff, pathConverter) {
+ if (!obj || typeof obj != 'object') {
+ throw new Error('base object must be an object or an array');
+ }
+
+ if (!Array.isArray(diff)) {
+ throw new Error('diff must be an array');
+ }
+
+ var diffLength = diff.length;
+ for (var i = 0; i < diffLength; i++) {
+ var thisDiff = diff[i];
+ var subObject = obj;
+ var thisOp = thisDiff.op;
+ var thisPath = thisDiff.path;
+ if (pathConverter) {
+ thisPath = pathConverter(thisPath);
+ if (!Array.isArray(thisPath)) {
+ throw new Error('pathConverter must return an array');
+ }
+ } else {
+ if (!Array.isArray(thisPath)) {
+ throw new Error(
+ 'diff path must be an array, consider supplying a path converter'
+ );
+ }
+ }
+ var pathCopy = thisPath.slice();
+ var lastProp = pathCopy.pop();
+ if (lastProp == null) {
+ return false;
+ }
+ var thisProp;
+ while ((thisProp = pathCopy.shift()) != null) {
+ if (!(thisProp in subObject)) {
+ subObject[thisProp] = {};
+ }
+ subObject = subObject[thisProp];
+ }
+ if (thisOp === REMOVE || thisOp === REPLACE) {
+ if (!subObject.hasOwnProperty(lastProp)) {
+ throw new Error(
+ ['expected to find property', thisDiff.path, 'in object', obj].join(
+ ' '
+ )
+ );
+ }
+ }
+ if (thisOp === REMOVE) {
+ Array.isArray(subObject)
+ ? subObject.splice(lastProp, 1)
+ : delete subObject[lastProp];
+ }
+ if (thisOp === REPLACE || thisOp === ADD) {
+ subObject[lastProp] = thisDiff.value;
+ }
+ }
+ return subObject;
+}
+
+function jsonPatchPathConverter(stringPath) {
+ return stringPath.split('/').slice(1);
+}
+
+export {diffApply, jsonPatchPathConverter};
diff --git a/deps/npm/node_modules/just-diff-apply/package.json b/deps/npm/node_modules/just-diff-apply/package.json
index a5cc8a1feee9ec..c38bd47aa6990d 100644
--- a/deps/npm/node_modules/just-diff-apply/package.json
+++ b/deps/npm/node_modules/just-diff-apply/package.json
@@ -1,10 +1,18 @@
{
"name": "just-diff-apply",
- "version": "3.0.0",
+ "version": "4.0.1",
"description": "Apply a diff to an object. Optionally supports jsonPatch protocol",
"main": "index.js",
+ "module": "index.mjs",
+ "exports": {
+ ".": {
+ "require": "./index.js",
+ "default": "./index.mjs"
+ }
+ },
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "rollup -c"
},
"repository": "https://github.com/angus-c/just",
"keywords": [
diff --git a/deps/npm/node_modules/just-diff-apply/rollup.config.js b/deps/npm/node_modules/just-diff-apply/rollup.config.js
new file mode 100644
index 00000000000000..fb9d24a3d845b1
--- /dev/null
+++ b/deps/npm/node_modules/just-diff-apply/rollup.config.js
@@ -0,0 +1,3 @@
+const createRollupConfig = require('../../config/createRollupConfig');
+
+module.exports = createRollupConfig(__dirname);
diff --git a/deps/npm/node_modules/just-diff/index.mjs b/deps/npm/node_modules/just-diff/index.mjs
new file mode 100644
index 00000000000000..8da5b5cea8dab2
--- /dev/null
+++ b/deps/npm/node_modules/just-diff/index.mjs
@@ -0,0 +1,146 @@
+/*
+ const obj1 = {a: 4, b: 5};
+ const obj2 = {a: 3, b: 5};
+ const obj3 = {a: 4, c: 5};
+
+ diff(obj1, obj2);
+ [
+ { "op": "replace", "path": ['a'], "value": 3 }
+ ]
+
+ diff(obj2, obj3);
+ [
+ { "op": "remove", "path": ['b'] },
+ { "op": "replace", "path": ['a'], "value": 4 }
+ { "op": "add", "path": ['c'], "value": 5 }
+ ]
+
+ // using converter to generate jsPatch standard paths
+ // see http://jsonpatch.com
+ import {diff, jsonPatchPathConverter} from 'just-diff'
+ diff(obj1, obj2, jsonPatchPathConverter);
+ [
+ { "op": "replace", "path": '/a', "value": 3 }
+ ]
+
+ diff(obj2, obj3, jsonPatchPathConverter);
+ [
+ { "op": "remove", "path": '/b' },
+ { "op": "replace", "path": '/a', "value": 4 }
+ { "op": "add", "path": '/c', "value": 5 }
+ ]
+
+ // arrays
+ const obj4 = {a: 4, b: [1, 2, 3]};
+ const obj5 = {a: 3, b: [1, 2, 4]};
+ const obj6 = {a: 3, b: [1, 2, 4, 5]};
+
+ diff(obj4, obj5);
+ [
+ { "op": "replace", "path": ['a'], "value": 3 }
+ { "op": "replace", "path": ['b', 2], "value": 4 }
+ ]
+
+ diff(obj5, obj6);
+ [
+ { "op": "add", "path": ['b', 3], "value": 5 }
+ ]
+
+ // nested paths
+ const obj7 = {a: 4, b: {c: 3}};
+ const obj8 = {a: 4, b: {c: 4}};
+ const obj9 = {a: 5, b: {d: 4}};
+
+ diff(obj7, obj8);
+ [
+ { "op": "replace", "path": ['b', 'c'], "value": 4 }
+ ]
+
+ diff(obj8, obj9);
+ [
+ { "op": "replace", "path": ['a'], "value": 5 }
+ { "op": "remove", "path": ['b', 'c']}
+ { "op": "add", "path": ['b', 'd'], "value": 4 }
+ ]
+*/
+
+function diff(obj1, obj2, pathConverter) {
+ if (!obj1 || typeof obj1 != 'object' || !obj2 || typeof obj2 != 'object') {
+ throw new Error('both arguments must be objects or arrays');
+ }
+
+ pathConverter ||
+ (pathConverter = function(arr) {
+ return arr;
+ });
+
+ function getDiff(obj1, obj2, basePath, diffs) {
+ var obj1Keys = Object.keys(obj1);
+ var obj1KeysLength = obj1Keys.length;
+ var obj2Keys = Object.keys(obj2);
+ var obj2KeysLength = obj2Keys.length;
+ var path;
+
+ for (var i = 0; i < obj1KeysLength; i++) {
+ var key = Array.isArray(obj1) ? Number(obj1Keys[i]) : obj1Keys[i];
+ if (!(key in obj2)) {
+ path = basePath.concat(key);
+ diffs.remove.push({
+ op: 'remove',
+ path: pathConverter(path),
+ });
+ }
+ }
+
+ for (var i = 0; i < obj2KeysLength; i++) {
+ var key = Array.isArray(obj2) ? Number(obj2Keys[i]) : obj2Keys[i];
+ var obj1AtKey = obj1[key];
+ var obj2AtKey = obj2[key];
+ if (!(key in obj1)) {
+ path = basePath.concat(key);
+ var obj2Value = obj2[key];
+ diffs.add.push({
+ op: 'add',
+ path: pathConverter(path),
+ value: obj2Value,
+ });
+ } else if (obj1AtKey !== obj2AtKey) {
+ if (
+ Object(obj1AtKey) !== obj1AtKey ||
+ Object(obj2AtKey) !== obj2AtKey
+ ) {
+ path = pushReplace(path, basePath, key, diffs, pathConverter, obj2);
+ } else {
+ if (
+ !Object.keys(obj1AtKey).length &&
+ !Object.keys(obj2AtKey).length &&
+ String(obj1AtKey) != String(obj2AtKey)
+ ) {
+ path = pushReplace(path, basePath, key, diffs, pathConverter, obj2);
+ } else {
+ getDiff(obj1[key], obj2[key], basePath.concat(key), diffs);
+ }
+ }
+ }
+ }
+
+ return diffs.remove.reverse().concat(diffs.replace).concat(diffs.add);
+ }
+ return getDiff(obj1, obj2, [], {remove: [], replace: [], add: []});
+}
+
+function pushReplace(path, basePath, key, diffs, pathConverter, obj2) {
+ path = basePath.concat(key);
+ diffs.replace.push({
+ op: 'replace',
+ path: pathConverter(path),
+ value: obj2[key],
+ });
+ return path;
+}
+
+function jsonPatchPathConverter(arrayPath) {
+ return [''].concat(arrayPath).join('/');
+}
+
+export {diff, jsonPatchPathConverter};
diff --git a/deps/npm/node_modules/just-diff/index.tests.ts b/deps/npm/node_modules/just-diff/index.tests.ts
index c7ebb70d3dc649..91eaecd8d49e8b 100644
--- a/deps/npm/node_modules/just-diff/index.tests.ts
+++ b/deps/npm/node_modules/just-diff/index.tests.ts
@@ -1,4 +1,4 @@
-import diffObj = require('./index');
+import * as diffObj from './index'
const {diff, jsonPatchPathConverter} = diffObj;
const obj1 = {a: 2, b: 3};
diff --git a/deps/npm/node_modules/just-diff/package.json b/deps/npm/node_modules/just-diff/package.json
index 00be1d50fddbcb..bab8a29ae93a4d 100644
--- a/deps/npm/node_modules/just-diff/package.json
+++ b/deps/npm/node_modules/just-diff/package.json
@@ -1,11 +1,19 @@
{
"name": "just-diff",
- "version": "3.1.1",
+ "version": "5.0.1",
"description": "Return an object representing the diffs between two objects. Supports jsonPatch protocol",
"main": "index.js",
+ "module": "index.mjs",
+ "exports": {
+ ".": {
+ "require": "./index.js",
+ "default": "./index.mjs"
+ }
+ },
"types": "index.d.ts",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "rollup -c"
},
"repository": "https://github.com/angus-c/just",
"keywords": [
@@ -20,4 +28,4 @@
"bugs": {
"url": "https://github.com/angus-c/just/issues"
}
-}
\ No newline at end of file
+}
diff --git a/deps/npm/node_modules/just-diff/rollup.config.js b/deps/npm/node_modules/just-diff/rollup.config.js
new file mode 100644
index 00000000000000..fb9d24a3d845b1
--- /dev/null
+++ b/deps/npm/node_modules/just-diff/rollup.config.js
@@ -0,0 +1,3 @@
+const createRollupConfig = require('../../config/createRollupConfig');
+
+module.exports = createRollupConfig(__dirname);
diff --git a/deps/npm/node_modules/minipass/index.js b/deps/npm/node_modules/minipass/index.js
index ae134a066d77f0..1835dd9bcf5121 100644
--- a/deps/npm/node_modules/minipass/index.js
+++ b/deps/npm/node_modules/minipass/index.js
@@ -165,7 +165,12 @@ module.exports = class Minipass extends Stream {
// because we're mid-write, so that'd be bad.
if (this[BUFFERLENGTH] !== 0)
this[FLUSH](true)
- this.emit('data', chunk)
+
+ // if we are still flowing after flushing the buffer we can emit the
+ // chunk otherwise we have to buffer it.
+ this.flowing
+ ? this.emit('data', chunk)
+ : this[BUFFERPUSH](chunk)
} else
this[BUFFERPUSH](chunk)
diff --git a/deps/npm/node_modules/minipass/package.json b/deps/npm/node_modules/minipass/package.json
index 165fa662ab4a7c..1728e5108c4c20 100644
--- a/deps/npm/node_modules/minipass/package.json
+++ b/deps/npm/node_modules/minipass/package.json
@@ -1,6 +1,6 @@
{
"name": "minipass",
- "version": "3.1.5",
+ "version": "3.1.6",
"description": "minimal implementation of a PassThrough stream",
"main": "index.js",
"dependencies": {
diff --git a/deps/npm/node_modules/parse-conflict-json/LICENSE b/deps/npm/node_modules/parse-conflict-json/LICENSE
deleted file mode 100644
index 20a47625409237..00000000000000
--- a/deps/npm/node_modules/parse-conflict-json/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) npm, Inc. and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/parse-conflict-json/LICENSE.md b/deps/npm/node_modules/parse-conflict-json/LICENSE.md
new file mode 100644
index 00000000000000..5fc208ff122e08
--- /dev/null
+++ b/deps/npm/node_modules/parse-conflict-json/LICENSE.md
@@ -0,0 +1,20 @@
+
+
+ISC License
+
+Copyright npm, Inc.
+
+Permission to use, copy, modify, and/or distribute this
+software for any purpose with or without fee is hereby
+granted, provided that the above copyright notice and this
+permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/parse-conflict-json/index.js b/deps/npm/node_modules/parse-conflict-json/lib/index.js
similarity index 74%
rename from deps/npm/node_modules/parse-conflict-json/index.js
rename to deps/npm/node_modules/parse-conflict-json/lib/index.js
index 8b5dbde40c08b5..21b295d04b902c 100644
--- a/deps/npm/node_modules/parse-conflict-json/index.js
+++ b/deps/npm/node_modules/parse-conflict-json/lib/index.js
@@ -2,13 +2,16 @@ const parseJSON = require('json-parse-even-better-errors')
const { diff } = require('just-diff')
const { diffApply } = require('just-diff-apply')
+const globalObjectProperties = Object.getOwnPropertyNames(Object.prototype)
+
const stripBOM = content => {
content = content.toString()
// Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
// because the buffer-to-string conversion in `fs.readFileSync()`
// translates it to FEFF, the UTF-16 BOM.
- if (content.charCodeAt(0) === 0xFEFF)
+ if (content.charCodeAt(0) === 0xFEFF) {
content = content.slice(1)
+ }
return content
}
@@ -22,37 +25,42 @@ const isDiff = str =>
const parseConflictJSON = (str, reviver, prefer) => {
prefer = prefer || 'ours'
- if (prefer !== 'theirs' && prefer !== 'ours')
+ if (prefer !== 'theirs' && prefer !== 'ours') {
throw new TypeError('prefer param must be "ours" or "theirs" if set')
+ }
str = stripBOM(str)
- if (!isDiff(str))
+ if (!isDiff(str)) {
return parseJSON(str)
+ }
const pieces = str.split(/[\n\r]+/g).reduce((acc, line) => {
- if (line.match(PARENT_RE))
+ if (line.match(PARENT_RE)) {
acc.state = 'parent'
- else if (line.match(OURS_RE))
+ } else if (line.match(OURS_RE)) {
acc.state = 'ours'
- else if (line.match(THEIRS_RE))
+ } else if (line.match(THEIRS_RE)) {
acc.state = 'theirs'
- else if (line.match(END_RE))
+ } else if (line.match(END_RE)) {
acc.state = 'top'
- else {
- if (acc.state === 'top' || acc.state === 'ours')
+ } else {
+ if (acc.state === 'top' || acc.state === 'ours') {
acc.ours += line
- if (acc.state === 'top' || acc.state === 'theirs')
+ }
+ if (acc.state === 'top' || acc.state === 'theirs') {
acc.theirs += line
- if (acc.state === 'top' || acc.state === 'parent')
+ }
+ if (acc.state === 'top' || acc.state === 'parent') {
acc.parent += line
+ }
}
return acc
}, {
state: 'top',
ours: '',
theirs: '',
- parent: ''
+ parent: '',
})
// this will throw if either piece is not valid JSON, that's intended
@@ -70,8 +78,9 @@ const isObj = obj => obj && typeof obj === 'object'
const copyPath = (to, from, path, i) => {
const p = path[i]
if (isObj(to[p]) && isObj(from[p]) &&
- Array.isArray(to[p]) === Array.isArray(from[p]))
+ Array.isArray(to[p]) === Array.isArray(from[p])) {
return copyPath(to[p], from[p], path, i + 1)
+ }
to[p] = from[p]
}
@@ -80,6 +89,9 @@ const copyPath = (to, from, path, i) => {
const resolve = (parent, ours, theirs) => {
const dours = diff(parent, ours)
for (let i = 0; i < dours.length; i++) {
+ if (globalObjectProperties.find(prop => dours[i].path.includes(prop))) {
+ continue
+ }
try {
diffApply(theirs, [dours[i]])
} catch (e) {
diff --git a/deps/npm/node_modules/parse-conflict-json/package.json b/deps/npm/node_modules/parse-conflict-json/package.json
index 3962e22f339012..bb633e158b5d13 100644
--- a/deps/npm/node_modules/parse-conflict-json/package.json
+++ b/deps/npm/node_modules/parse-conflict-json/package.json
@@ -1,32 +1,44 @@
{
"name": "parse-conflict-json",
- "version": "1.1.1",
+ "version": "2.0.1",
"description": "Parse a JSON string that has git merge conflicts, resolving if possible",
- "author": "Isaac Z. Schlueter (https://izs.me)",
+ "author": "GitHub Inc.",
"license": "ISC",
+ "main": "lib",
"scripts": {
"test": "tap",
"snap": "tap",
"preversion": "npm test",
"postversion": "npm publish",
- "postpublish": "git push origin --follow-tags"
+ "postpublish": "git push origin --follow-tags",
+ "lint": "eslint '**/*.js'",
+ "postlint": "npm-template-check",
+ "lintfix": "npm run lint -- --fix",
+ "prepublishOnly": "git push origin --follow-tags",
+ "posttest": "npm run lint"
},
"tap": {
"check-coverage": true
},
"devDependencies": {
- "tap": "^14.6.1"
+ "@npmcli/template-oss": "^2.3.1",
+ "tap": "^15.1.5"
},
"dependencies": {
- "just-diff": "^3.0.1",
- "just-diff-apply": "^3.0.0",
- "json-parse-even-better-errors": "^2.3.0"
+ "json-parse-even-better-errors": "^2.3.1",
+ "just-diff": "^5.0.1",
+ "just-diff-apply": "^4.0.1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/npm/parse-conflict-json.git"
},
"files": [
- "index.js"
- ]
+ "bin",
+ "lib"
+ ],
+ "templateVersion": "2.3.1",
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16"
+ }
}
diff --git a/deps/npm/package.json b/deps/npm/package.json
index f9ba8cd3c801b6..636ef21e5fb643 100644
--- a/deps/npm/package.json
+++ b/deps/npm/package.json
@@ -1,5 +1,5 @@
{
- "version": "8.2.0",
+ "version": "8.3.0",
"name": "npm",
"description": "a package manager for JavaScript",
"workspaces": [
@@ -55,7 +55,7 @@
},
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
- "@npmcli/arborist": "^4.0.5",
+ "@npmcli/arborist": "^4.1.1",
"@npmcli/ci-detect": "^1.4.0",
"@npmcli/config": "^2.3.2",
"@npmcli/map-workspaces": "^2.0.0",
@@ -91,7 +91,7 @@
"libnpmteam": "^2.0.3",
"libnpmversion": "^2.0.1",
"make-fetch-happen": "^9.1.0",
- "minipass": "^3.1.3",
+ "minipass": "^3.1.6",
"minipass-pipeline": "^1.2.4",
"mkdirp": "^1.0.4",
"mkdirp-infer-owner": "^2.0.0",
@@ -108,7 +108,7 @@
"npmlog": "^6.0.0",
"opener": "^1.5.2",
"pacote": "^12.0.2",
- "parse-conflict-json": "^1.1.1",
+ "parse-conflict-json": "^2.0.1",
"proc-log": "^1.0.0",
"qrcode-terminal": "^0.12.0",
"read": "~1.0.7",
diff --git a/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
index 12cd631045a869..35c8e616591379 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
@@ -342,3 +342,44 @@ userconfig = "{HOME}/.npmrc"
; HOME = {HOME}
; Run \`npm config ls -l\` to show all defaults.
`
+
+exports[`test/lib/commands/config.js TAP config list with publishConfig > output matches snapshot 1`] = `
+; "cli" config from command line options
+
+cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-with-publishConfig-sandbox/cache"
+prefix = "{LOCALPREFIX}"
+userconfig = "{HOME}/.npmrc"
+
+; node bin location = {EXECPATH}
+; cwd = {NPMDIR}
+; HOME = {HOME}
+; Run \`npm config ls -l\` to show all defaults.
+
+; "publishConfig" from {LOCALPREFIX}/package.json
+; This set of config values will be used at publish-time.
+
+_authToken = (protected)
+registry = "https://some.registry"
+; "env" config from environment
+
+; cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-with-publishConfig-sandbox/cache" ; overridden by cli
+global-prefix = "{LOCALPREFIX}"
+globalconfig = "{GLOBALPREFIX}/npmrc"
+init-module = "{HOME}/.npm-init.js"
+local-prefix = "{LOCALPREFIX}"
+; prefix = "{LOCALPREFIX}" ; overridden by cli
+user-agent = "npm/{NPM-VERSION} node/{NODE-VERSION} {PLATFORM} {ARCH} workspaces/false"
+; userconfig = "{HOME}/.npmrc" ; overridden by cli
+
+; "cli" config from command line options
+
+cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-with-publishConfig-sandbox/cache"
+global = true
+prefix = "{LOCALPREFIX}"
+userconfig = "{HOME}/.npmrc"
+
+; node bin location = {EXECPATH}
+; cwd = {NPMDIR}
+; HOME = {HOME}
+; Run \`npm config ls -l\` to show all defaults.
+`
diff --git a/deps/npm/test/lib/commands/config.js b/deps/npm/test/lib/commands/config.js
index b37088c06b9cd1..8217131479fe4a 100644
--- a/deps/npm/test/lib/commands/config.js
+++ b/deps/npm/test/lib/commands/config.js
@@ -107,6 +107,26 @@ t.test('config list --json', async t => {
t.matchSnapshot(sandbox.output, 'output matches snapshot')
})
+t.test('config list with publishConfig', async t => {
+ const temp = t.testdir({
+ project: {
+ 'package.json': JSON.stringify({
+ publishConfig: {
+ registry: 'https://some.registry',
+ _authToken: 'mytoken',
+ },
+ }),
+ },
+ })
+ const project = join(temp, 'project')
+
+ const sandbox = new Sandbox(t, { project })
+ await sandbox.run('config', ['list', ''])
+ await sandbox.run('config', ['list', '--global'])
+
+ t.matchSnapshot(sandbox.output, 'output matches snapshot')
+})
+
t.test('config delete no args', async t => {
const sandbox = new Sandbox(t)
@@ -333,7 +353,13 @@ t.test('config get private key', async t => {
await t.rejects(
sandbox.run('config', ['get', '_authToken']),
- '_authToken is protected',
+ /_authToken option is protected/,
+ 'rejects with protected string'
+ )
+
+ await t.rejects(
+ sandbox.run('config', ['get', '//localhost:8080/:_password']),
+ /_password option is protected/,
'rejects with protected string'
)
})
diff --git a/deps/npm/test/lib/commands/publish.js b/deps/npm/test/lib/commands/publish.js
index 1178cd6ee1edf4..2a591fd4c75340 100644
--- a/deps/npm/test/lib/commands/publish.js
+++ b/deps/npm/test/lib/commands/publish.js
@@ -341,8 +341,10 @@ t.test('can publish a tarball', async t => {
t.test('should check auth for default registry', async t => {
t.plan(2)
- const Publish = t.mock('../../../lib/commands/publish.js')
const npm = mockNpm()
+ const registry = npm.config.get('registry')
+ const errorMessage = `This command requires you to be logged in to ${registry}`
+ const Publish = t.mock('../../../lib/commands/publish.js')
npm.config.getCredentialsByURI = uri => {
t.same(uri, npm.config.get('registry'), 'gets credentials for expected registry')
return {}
@@ -351,7 +353,7 @@ t.test('should check auth for default registry', async t => {
await t.rejects(
publish.exec([]),
- { message: 'This command requires you to be logged in.', code: 'ENEEDAUTH' },
+ { message: errorMessage, code: 'ENEEDAUTH' },
'throws when not logged in'
)
})
@@ -359,6 +361,7 @@ t.test('should check auth for default registry', async t => {
t.test('should check auth for configured registry', async t => {
t.plan(2)
const registry = 'https://some.registry'
+ const errorMessage = 'This command requires you to be logged in to https://some.registry'
const Publish = t.mock('../../../lib/commands/publish.js')
const npm = mockNpm({
flatOptions: { registry },
@@ -371,7 +374,7 @@ t.test('should check auth for configured registry', async t => {
await t.rejects(
publish.exec([]),
- { message: 'This command requires you to be logged in.', code: 'ENEEDAUTH' },
+ { message: errorMessage, code: 'ENEEDAUTH' },
'throws when not logged in'
)
})
@@ -379,6 +382,7 @@ t.test('should check auth for configured registry', async t => {
t.test('should check auth for scope specific registry', async t => {
t.plan(2)
const registry = 'https://some.registry'
+ const errorMessage = 'This command requires you to be logged in to https://some.registry'
const testDir = t.testdir({
'package.json': JSON.stringify(
{
@@ -402,7 +406,7 @@ t.test('should check auth for scope specific registry', async t => {
await t.rejects(
publish.exec([testDir]),
- { message: 'This command requires you to be logged in.', code: 'ENEEDAUTH' },
+ { message: errorMessage, code: 'ENEEDAUTH' },
'throws when not logged in'
)
})
@@ -735,7 +739,7 @@ t.test('private workspaces', async t => {
})
t.test('unexpected error', async t => {
- t.plan(1)
+ t.plan(2)
const Publish = t.mock('../../../lib/commands/publish.js', {
...mocks,
@@ -749,7 +753,9 @@ t.test('private workspaces', async t => {
},
},
'proc-log': {
- notice () {},
+ notice (__, msg) {
+ t.match(msg, 'Publishing to https://registry.npmjs.org/')
+ },
verbose () {},
},
})
diff --git a/deps/npm/test/lib/utils/log-file.js b/deps/npm/test/lib/utils/log-file.js
index adc1a2e03ff3d8..007ce221b09406 100644
--- a/deps/npm/test/lib/utils/log-file.js
+++ b/deps/npm/test/lib/utils/log-file.js
@@ -12,15 +12,20 @@ t.cleanSnapshot = (path) => cleanCwd(path)
const last = arr => arr[arr.length - 1]
const range = (n) => Array.from(Array(n).keys())
-const makeOldLogs = (count) => {
+const makeOldLogs = (count, oldStyle) => {
const d = new Date()
d.setHours(-1)
d.setSeconds(0)
- return range(count / 2).reduce((acc, i) => {
+ return range(oldStyle ? count : (count / 2)).reduce((acc, i) => {
const cloneDate = new Date(d.getTime())
cloneDate.setSeconds(i)
- acc[LogFile.fileName(LogFile.logId(cloneDate), 0)] = 'hello'
- acc[LogFile.fileName(LogFile.logId(cloneDate), 1)] = 'hello'
+ const dateId = LogFile.logId(cloneDate)
+ if (oldStyle) {
+ acc[`${dateId}-debug.log`] = 'hello'
+ } else {
+ acc[`${dateId}-debug-0.log`] = 'hello'
+ acc[`${dateId}-debug-1.log`] = 'hello'
+ }
return acc
}, {})
}
@@ -247,6 +252,18 @@ t.test('glob error', async t => {
t.match(last(logs).content, /error cleaning log files .* bad glob/)
})
+t.test('cleans old style logs too', async t => {
+ const logsMax = 5
+ const oldLogs = 10
+ const { readLogs } = await loadLogFile(t, {
+ logsMax,
+ testdir: makeOldLogs(oldLogs, false),
+ })
+
+ const logs = await readLogs()
+ t.equal(logs.length, logsMax + 1)
+})
+
t.test('rimraf error', async t => {
const logsMax = 5
const oldLogs = 10