diff --git a/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js b/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js index 175ec55f0b9e0..c050bde53a345 100644 --- a/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js +++ b/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js @@ -21,6 +21,7 @@ const removeFromOthers = (name, type, pkg) => { break case 'peer': case 'peerOptional': + others.delete('devDependencies') others.delete('peerDependencies') others.delete('peerDependenciesMeta') break @@ -44,9 +45,9 @@ const addSingle = ({pkg, spec, saveBundle, saveType}) => { const { name, rawSpec } = spec removeFromOthers(name, saveType, pkg) const type = saveType === 'prod' ? 'dependencies' - : saveType === 'dev' ? 'devDependencies' : saveType === 'optional' ? 'optionalDependencies' : saveType === 'peer' || saveType === 'peerOptional' ? 'peerDependencies' + : saveType === 'dev' ? 'devDependencies' : /* istanbul ignore next */ null pkg[type] = pkg[type] || {} @@ -62,6 +63,10 @@ const addSingle = ({pkg, spec, saveBundle, saveType}) => { pdm[name].optional = true pkg.peerDependenciesMeta = pdm } + // peerDeps are often also a devDep, so that they can be tested when + // using package managers that don't auto-install peer deps + if (pkg.devDependencies && pkg.devDependencies[name] !== undefined) + pkg.devDependencies[name] = pkg.peerDependencies[name] } if (saveBundle) { @@ -82,16 +87,16 @@ const getSaveType = (pkg, spec) => { peerDependenciesMeta: peerDepsMeta, } = pkg - if (devDeps && devDeps[name] !== undefined) - return 'dev' - else if (optDeps && optDeps[name] !== undefined) - return 'optional' - else if (peerDeps && peerDeps[name] !== undefined) { + if (peerDeps && peerDeps[name] !== undefined) { if (peerDepsMeta && peerDepsMeta[name] && peerDepsMeta[name].optional) return 'peerOptional' else return 'peer' - } else + } else if (devDeps && devDeps[name] !== undefined) + return 'dev' + else if (optDeps && optDeps[name] !== undefined) + return 'optional' + else return 'prod' } diff --git a/node_modules/@npmcli/arborist/lib/arborist/rebuild.js b/node_modules/@npmcli/arborist/lib/arborist/rebuild.js index 24d437bc3a9cf..fd7be340bb719 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/rebuild.js +++ b/node_modules/@npmcli/arborist/lib/arborist/rebuild.js @@ -8,6 +8,7 @@ const binLinks = require('bin-links') const runScript = require('@npmcli/run-script') const promiseCallLimit = require('promise-call-limit') const {resolve} = require('path') +const { isNodeGypPackage } = require('@npmcli/node-gyp') const boolEnv = b => b ? '1' : '' const sortNodes = (a, b) => (a.depth - b.depth) || a.path.localeCompare(b.path) @@ -22,6 +23,7 @@ const _linkAllBins = Symbol('linkAllBins') const _runScripts = Symbol('runScripts') const _buildQueues = Symbol('buildQueues') const _addToBuildSet = Symbol('addToBuildSet') +const _checkBins = Symbol.for('checkBins') const _queues = Symbol('queues') const _scriptShell = Symbol('scriptShell') @@ -126,6 +128,18 @@ module.exports = cls => class Builder extends cls { process.emit('timeEnd', 'build:queue') } + async [_checkBins] (node) { + // if the node is a global top, and we're not in force mode, then + // any existing bins need to either be missing, or a symlink into + // the node path. Otherwise a package can have a preinstall script + // that unlinks something, to allow them to silently overwrite system + // binaries, which is unsafe and insecure. + if (!node.globalTop || this[_force]) + return + const { path, package: pkg } = node + await binLinks.checkBins({ pkg, path, top: true, global: true }) + } + async [_addToBuildSet] (node, set) { if (set.has(node)) return @@ -161,8 +175,17 @@ module.exports = cls => class Builder extends cls { } } - if (bin || preinstall || install || postinstall) + if (bin || preinstall || install || postinstall) { + if (bin) + await this[_checkBins](node) set.add(node) + } else if (!install && !preinstall && await isNodeGypPackage(node.path)) { + // Rebuild node-gyp dependencies lacking an install or preinstall script + // note that 'scripts' might be missing entirely. + scripts.install = 'node-gyp rebuild' + node.package.scripts = scripts + set.add(node) + } } async [_runScripts] (event) { diff --git a/node_modules/@npmcli/arborist/lib/arborist/reify.js b/node_modules/@npmcli/arborist/lib/arborist/reify.js index 480da9cbb99fc..8fe88edb8f722 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -42,6 +42,8 @@ const _createSparseTree = Symbol.for('createSparseTree') const _loadShrinkwrapsAndUpdateTrees = Symbol.for('loadShrinkwrapsAndUpdateTrees') const _reifyNode = Symbol.for('reifyNode') const _extractOrLink = Symbol('extractOrLink') +// defined by rebuild mixin +const _checkBins = Symbol.for('checkBins') const _symlink = Symbol('symlink') const _warnDeprecated = Symbol('warnDeprecated') const _loadAncientPackageDetails = Symbol('loadAncientPackageDetails') @@ -377,6 +379,7 @@ module.exports = cls => class Reifier extends cls { this.addTracker('reify', node.name, node.location) const p = Promise.resolve() + .then(() => this[_checkBins](node)) .then(() => this[_extractOrLink](node)) .then(() => this[_warnDeprecated](node)) .then(() => this[_loadAncientPackageDetails](node)) diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json index 8f38d96e7a3a7..24b0b99fe96d7 100644 --- a/node_modules/@npmcli/arborist/package.json +++ b/node_modules/@npmcli/arborist/package.json @@ -1,14 +1,15 @@ { "name": "@npmcli/arborist", - "version": "0.0.28", + "version": "0.0.29", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", - "@npmcli/map-workspaces": "0.0.0-pre.1", + "@npmcli/map-workspaces": "^1.0.1", "@npmcli/metavuln-calculator": "^1.0.0", "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^1.0.0", "@npmcli/run-script": "^1.3.1", - "bin-links": "^2.1.4", + "bin-links": "^2.2.1", "cacache": "^15.0.3", "common-ancestor-path": "^1.0.1", "json-parse-even-better-errors": "^2.3.1", diff --git a/node_modules/@npmcli/map-workspaces/index.js b/node_modules/@npmcli/map-workspaces/index.js index 0a789d2445e05..b06662154a83a 100644 --- a/node_modules/@npmcli/map-workspaces/index.js +++ b/node_modules/@npmcli/map-workspaces/index.js @@ -87,7 +87,7 @@ async function mapWorkspaces (opts = {}) { const { workspaces = [] } = opts.pkg const patterns = getPatterns(workspaces) const results = new Map() - const seen = new Set() + const seen = new Map() if (isEmpty(patterns)) { return results @@ -126,7 +126,7 @@ async function mapWorkspaces (opts = {}) { if (item.negate) { results.delete(packagePathname, name) } else { - if (seen.has(name)) { + if (seen.has(name) && seen.get(name) !== packagePathname) { throw getError({ Type: Error, message: 'must not have multiple workspaces with the same name', @@ -134,7 +134,7 @@ async function mapWorkspaces (opts = {}) { }) } - seen.add(name) + seen.set(name, packagePathname) results.set(packagePathname, name) } } diff --git a/node_modules/@npmcli/map-workspaces/package.json b/node_modules/@npmcli/map-workspaces/package.json index 7f959d070eb3c..2a66a74240d6d 100644 --- a/node_modules/@npmcli/map-workspaces/package.json +++ b/node_modules/@npmcli/map-workspaces/package.json @@ -1,9 +1,12 @@ { "name": "@npmcli/map-workspaces", - "version": "0.0.0-pre.1", + "version": "1.0.1", "files": [ "index.js" ], + "engines": { + "node": ">=10" + }, "description": "Retrieves a name:pathname Map for a given workspaces config", "repository": "https://github.com/npm/map-workspaces", "keywords": [ @@ -25,6 +28,7 @@ "license": "ISC", "scripts": { "lint": "standard", + "pretest": "npm run lint", "test": "tap test*.js", "snap": "tap test*.js", "preversion": "npm test", @@ -41,13 +45,13 @@ }, "devDependencies": { "require-inject": "^1.4.4", - "standard": "^14.3.1", - "tap": "^14.10.7" + "standard": "^14.3.4", + "tap": "^14.10.8" }, "dependencies": { "@npmcli/name-from-folder": "^1.0.1", "glob": "^7.1.6", "minimatch": "^3.0.4", - "read-package-json-fast": "^1.1.3" + "read-package-json-fast": "^1.2.1" } } diff --git a/node_modules/@npmcli/run-script/lib/run-script-pkg.js b/node_modules/@npmcli/run-script/lib/run-script-pkg.js index 1a3a76d6858a9..bf273e590d003 100644 --- a/node_modules/@npmcli/run-script/lib/run-script-pkg.js +++ b/node_modules/@npmcli/run-script/lib/run-script-pkg.js @@ -1,11 +1,12 @@ const makeSpawnArgs = require('./make-spawn-args.js') const promiseSpawn = require('@npmcli/promise-spawn') const packageEnvs = require('./package-envs.js') +const { isNodeGypPackage, defaultGypInstallScript } = require('@npmcli/node-gyp') // you wouldn't like me when I'm angry... const bruce = (id, event, cmd) =>`\n> ${id ? id + ' ' : ''}${event}\n> ${cmd}\n` -const runScriptPkg = options => { +const runScriptPkg = async options => { const { event, path, @@ -19,11 +20,19 @@ const runScriptPkg = options => { banner = true, } = options - const cmd = options.cmd ? options.cmd - : pkg.scripts && pkg.scripts[event] - ? pkg.scripts[event] + - args.map(a => ` ${JSON.stringify(a)}`).join('') - : null + let cmd = null + if (options.cmd) { + cmd = options.cmd + } else if (pkg.scripts && pkg.scripts[event]) { + cmd = pkg.scripts[event] + args.map(a => ` ${JSON.stringify(a)}`).join('') + } else if ( // If there is no preinstall or install script, default to rebuilding node-gyp packages. + event === 'install' && + ! pkg.scripts.install && + ! pkg.scripts.preinstall && + await isNodeGypPackage(path) + ) { + cmd = defaultGypInstallScript + } if (!cmd) return Promise.resolve({ code: 0, signal: null }) diff --git a/node_modules/@npmcli/run-script/package.json b/node_modules/@npmcli/run-script/package.json index 0328cf451c893..1fe8e82c50356 100644 --- a/node_modules/@npmcli/run-script/package.json +++ b/node_modules/@npmcli/run-script/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/run-script", - "version": "1.6.0", + "version": "1.7.0", "description": "Run a lifecycle script for a package (descendant of npm-lifecycle)", "author": "Isaac Z. Schlueter (https://izs.me)", "license": "ISC", @@ -20,6 +20,7 @@ "tap": "^14.10.6" }, "dependencies": { + "@npmcli/node-gyp": "^1.0.0", "@npmcli/promise-spawn": "^1.2.0", "infer-owner": "^1.0.4", "node-gyp": "^7.1.0", diff --git a/package-lock.json b/package-lock.json index 66b467c2c3f12..3fdd5efa81cd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,10 +76,10 @@ ], "license": "Artistic-2.0", "dependencies": { - "@npmcli/arborist": "^0.0.28", + "@npmcli/arborist": "^0.0.29", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.1.8", - "@npmcli/run-script": "^1.6.0", + "@npmcli/run-script": "^1.7.0", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", @@ -379,17 +379,18 @@ } }, "node_modules/@npmcli/arborist": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.28.tgz", - "integrity": "sha512-E0yscLZ8yOPbbFnODRIRMsG+Lz7ffP/FWu4tq2mz0Omk3DQN+pllBbDHiOIjekrfJsLFBpmvGTltH71bKAMeCw==", + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.29.tgz", + "integrity": "sha512-QbLzHlfJoExnrLpZYAdf14pYQfk+KpMkpQabjeusrJabrNsfHtfY+rr5HIcG4AAmb0VaiubcUdadqzpBVXgkcQ==", "inBundle": true, "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", - "@npmcli/map-workspaces": "0.0.0-pre.1", + "@npmcli/map-workspaces": "^1.0.1", "@npmcli/metavuln-calculator": "^1.0.0", "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^1.0.0", "@npmcli/run-script": "^1.3.1", - "bin-links": "^2.1.4", + "bin-links": "^2.2.1", "cacache": "^15.0.3", "common-ancestor-path": "^1.0.1", "json-parse-even-better-errors": "^2.3.1", @@ -466,15 +467,18 @@ } }, "node_modules/@npmcli/map-workspaces": { - "version": "0.0.0-pre.1", - "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-0.0.0-pre.1.tgz", - "integrity": "sha512-IovEVdr17hW/Stt0kpPjz1r0ZxRX3RGah7ww3tQpi5NtyOapJwbUffWuWETyQkOjud5soC45mnjOOBtfTggtng==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.1.tgz", + "integrity": "sha512-w6mVyJ2ngWV7O7f9zPjLrQzRDv7leFmNLVnewNuhouV1MYxXz61DXn2ja3AQj6xlnIp9Z/0GdV0/Ut14eVT8Vw==", "inBundle": true, "dependencies": { "@npmcli/name-from-folder": "^1.0.1", "glob": "^7.1.6", "minimatch": "^3.0.4", - "read-package-json-fast": "^1.1.3" + "read-package-json-fast": "^1.2.1" + }, + "engines": { + "node": ">=10" } }, "node_modules/@npmcli/metavuln-calculator": { @@ -506,6 +510,12 @@ "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==", "inBundle": true }, + "node_modules/@npmcli/node-gyp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.0.tgz", + "integrity": "sha512-BBlx5ZCPCmTrPI2BpynmWpL1hQTRVXSIZ0zI/a9AQsIDXUReA8V/WRJo85TF6Wf0YVBtLibKH3OHrxnbxilthw==", + "inBundle": true + }, "node_modules/@npmcli/promise-spawn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.2.0.tgz", @@ -516,11 +526,12 @@ } }, "node_modules/@npmcli/run-script": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.6.0.tgz", - "integrity": "sha512-2BHum2b8MBXkiWGR6c1JOQ+2eAnE8kygwtT8F5bRam7ErDJqxxcHZSksIU6/qxqnA3WuiuyvxNdnptIJr8YQ8Q==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.7.0.tgz", + "integrity": "sha512-GaWLYT88H6NzOVGyXeCigijJ+eo2sdBfI67VqgkBDcR/5vElpXQH3crdfLYySPuOMZQSQXh0EsW+gC5LciFsMQ==", "inBundle": true, "dependencies": { + "@npmcli/node-gyp": "^1.0.0", "@npmcli/promise-spawn": "^1.2.0", "infer-owner": "^1.0.4", "node-gyp": "^7.1.0", @@ -8500,16 +8511,17 @@ } }, "@npmcli/arborist": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.28.tgz", - "integrity": "sha512-E0yscLZ8yOPbbFnODRIRMsG+Lz7ffP/FWu4tq2mz0Omk3DQN+pllBbDHiOIjekrfJsLFBpmvGTltH71bKAMeCw==", + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.29.tgz", + "integrity": "sha512-QbLzHlfJoExnrLpZYAdf14pYQfk+KpMkpQabjeusrJabrNsfHtfY+rr5HIcG4AAmb0VaiubcUdadqzpBVXgkcQ==", "requires": { "@npmcli/installed-package-contents": "^1.0.5", - "@npmcli/map-workspaces": "0.0.0-pre.1", + "@npmcli/map-workspaces": "^1.0.1", "@npmcli/metavuln-calculator": "^1.0.0", "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^1.0.0", "@npmcli/run-script": "^1.3.1", - "bin-links": "^2.1.4", + "bin-links": "^2.2.1", "cacache": "^15.0.3", "common-ancestor-path": "^1.0.1", "json-parse-even-better-errors": "^2.3.1", @@ -8573,14 +8585,14 @@ } }, "@npmcli/map-workspaces": { - "version": "0.0.0-pre.1", - "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-0.0.0-pre.1.tgz", - "integrity": "sha512-IovEVdr17hW/Stt0kpPjz1r0ZxRX3RGah7ww3tQpi5NtyOapJwbUffWuWETyQkOjud5soC45mnjOOBtfTggtng==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.1.tgz", + "integrity": "sha512-w6mVyJ2ngWV7O7f9zPjLrQzRDv7leFmNLVnewNuhouV1MYxXz61DXn2ja3AQj6xlnIp9Z/0GdV0/Ut14eVT8Vw==", "requires": { "@npmcli/name-from-folder": "^1.0.1", "glob": "^7.1.6", "minimatch": "^3.0.4", - "read-package-json-fast": "^1.1.3" + "read-package-json-fast": "^1.2.1" } }, "@npmcli/metavuln-calculator": { @@ -8606,6 +8618,11 @@ "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==" }, + "@npmcli/node-gyp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.0.tgz", + "integrity": "sha512-BBlx5ZCPCmTrPI2BpynmWpL1hQTRVXSIZ0zI/a9AQsIDXUReA8V/WRJo85TF6Wf0YVBtLibKH3OHrxnbxilthw==" + }, "@npmcli/promise-spawn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.2.0.tgz", @@ -8615,10 +8632,11 @@ } }, "@npmcli/run-script": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.6.0.tgz", - "integrity": "sha512-2BHum2b8MBXkiWGR6c1JOQ+2eAnE8kygwtT8F5bRam7ErDJqxxcHZSksIU6/qxqnA3WuiuyvxNdnptIJr8YQ8Q==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.7.0.tgz", + "integrity": "sha512-GaWLYT88H6NzOVGyXeCigijJ+eo2sdBfI67VqgkBDcR/5vElpXQH3crdfLYySPuOMZQSQXh0EsW+gC5LciFsMQ==", "requires": { + "@npmcli/node-gyp": "^1.0.0", "@npmcli/promise-spawn": "^1.2.0", "infer-owner": "^1.0.4", "node-gyp": "^7.1.0", diff --git a/package.json b/package.json index 9569cb24d409d..b8bfd16cedeb9 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,10 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^0.0.28", + "@npmcli/arborist": "^0.0.29", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.1.8", - "@npmcli/run-script": "^1.6.0", + "@npmcli/run-script": "^1.7.0", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3",