Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/install.js22
-rw-r--r--package-lock.json1
-rw-r--r--package.json1
-rw-r--r--test/lib/install.js140
4 files changed, 162 insertions, 2 deletions
diff --git a/lib/install.js b/lib/install.js
index 661176397..1589ff589 100644
--- a/lib/install.js
+++ b/lib/install.js
@@ -8,6 +8,8 @@ const log = require('npmlog')
const { resolve, join } = require('path')
const Arborist = require('@npmcli/arborist')
const runScript = require('@npmcli/run-script')
+const pacote = require('pacote')
+const checks = require('npm-install-checks')
const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js')
class Install extends ArboristWorkspaceCmd {
@@ -126,6 +128,23 @@ class Install extends ArboristWorkspaceCmd {
const ignoreScripts = this.npm.config.get('ignore-scripts')
const isGlobalInstall = this.npm.config.get('global')
const where = isGlobalInstall ? globalTop : this.npm.prefix
+ const forced = this.npm.config.get('force')
+ const isDev = this.npm.config.get('dev')
+ const scriptShell = this.npm.config.get('script-shell') || undefined
+
+ // be very strict about engines when trying to update npm itself
+ const npmInstall = args.find(arg => arg.startsWith('npm@') || arg === 'npm')
+ if (isGlobalInstall && npmInstall) {
+ const npmManifest = await pacote.manifest(npmInstall)
+ try {
+ checks.checkEngine(npmManifest, npmManifest.version, process.version)
+ } catch (e) {
+ if (forced)
+ this.npm.log.warn('install', `Forcing global npm install with incompatible version ${npmManifest.version} into node ${process.version}`)
+ else
+ throw e
+ }
+ }
// don't try to install the prefix into itself
args = args.filter(a => resolve(a) !== this.npm.prefix)
@@ -135,7 +154,7 @@ class Install extends ArboristWorkspaceCmd {
args = ['.']
// TODO: Add warnings for other deprecated flags? or remove this one?
- if (this.npm.config.get('dev'))
+ if (isDev)
log.warn('install', 'Usage of the `--dev` option is deprecated. Use `--include=dev` instead.')
const opts = {
@@ -150,7 +169,6 @@ class Install extends ArboristWorkspaceCmd {
await arb.reify(opts)
if (!args.length && !isGlobalInstall && !ignoreScripts) {
- const scriptShell = this.npm.config.get('script-shell') || undefined
const scripts = [
'preinstall',
'install',
diff --git a/package-lock.json b/package-lock.json
index 9abe13a85..8546bd714 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -127,6 +127,7 @@
"node-gyp": "^7.1.2",
"nopt": "^5.0.0",
"npm-audit-report": "^2.1.5",
+ "npm-install-checks": "^4.0.0",
"npm-package-arg": "^8.1.5",
"npm-pick-manifest": "^6.1.1",
"npm-profile": "^5.0.3",
diff --git a/package.json b/package.json
index e0363a49b..4531d1508 100644
--- a/package.json
+++ b/package.json
@@ -97,6 +97,7 @@
"node-gyp": "^7.1.2",
"nopt": "^5.0.0",
"npm-audit-report": "^2.1.5",
+ "npm-install-checks": "^4.0.0",
"npm-package-arg": "^8.1.5",
"npm-pick-manifest": "^6.1.1",
"npm-profile": "^5.0.3",
diff --git a/test/lib/install.js b/test/lib/install.js
index 6412b34c1..2cbee02e6 100644
--- a/test/lib/install.js
+++ b/test/lib/install.js
@@ -126,6 +126,146 @@ t.test('should install globally using Arborist', (t) => {
})
})
+t.test('npm i -g npm engines check success', (t) => {
+ const Install = t.mock('../../lib/install.js', {
+ '../../lib/utils/reify-finish.js': async () => {},
+ '@npmcli/arborist': function () {
+ this.reify = () => {}
+ },
+ pacote: {
+ manifest: () => {
+ return {
+ version: '100.100.100',
+ engines: {
+ node: '>1',
+ },
+ }
+ },
+ },
+ })
+ const npm = mockNpm({
+ globalDir: 'path/to/node_modules/',
+ config: {
+ global: true,
+ },
+ })
+ const install = new Install(npm)
+ install.exec(['npm'], er => {
+ if (er)
+ throw er
+ t.end()
+ })
+})
+
+t.test('npm i -g npm engines check failure', (t) => {
+ const Install = t.mock('../../lib/install.js', {
+ pacote: {
+ manifest: () => {
+ return {
+ _id: 'npm@1.2.3',
+ version: '100.100.100',
+ engines: {
+ node: '>1000',
+ },
+ }
+ },
+ },
+ })
+ const npm = mockNpm({
+ globalDir: 'path/to/node_modules/',
+ config: {
+ global: true,
+ },
+ })
+ const install = new Install(npm)
+ install.exec(['npm'], er => {
+ t.match(er, {
+ message: 'Unsupported engine',
+ pkgid: 'npm@1.2.3',
+ current: {
+ node: process.version,
+ npm: '100.100.100',
+ },
+ required: {
+ node: '>1000',
+ },
+ code: 'EBADENGINE',
+ })
+ t.end()
+ })
+})
+
+t.test('npm i -g npm engines check failure forced override', (t) => {
+ const Install = t.mock('../../lib/install.js', {
+ '../../lib/utils/reify-finish.js': async () => {},
+ '@npmcli/arborist': function () {
+ this.reify = () => {}
+ },
+ pacote: {
+ manifest: () => {
+ return {
+ _id: 'npm@1.2.3',
+ version: '100.100.100',
+ engines: {
+ node: '>1000',
+ },
+ }
+ },
+ },
+ })
+ const npm = mockNpm({
+ globalDir: 'path/to/node_modules/',
+ config: {
+ force: true,
+ global: true,
+ },
+ })
+ const install = new Install(npm)
+ install.exec(['npm'], er => {
+ if (er)
+ throw er
+ t.end()
+ })
+})
+
+t.test('npm i -g npm@version engines check failure', (t) => {
+ const Install = t.mock('../../lib/install.js', {
+ pacote: {
+ manifest: () => {
+ return {
+ _id: 'npm@1.2.3',
+ version: '100.100.100',
+ engines: {
+ node: '>1000',
+ },
+ }
+ },
+ },
+ })
+ const npm = mockNpm({
+ globalDir: 'path/to/node_modules/',
+ config: {
+ global: true,
+ },
+ })
+ const install = new Install(npm)
+ install.exec(['npm@100'], er => {
+ t.match(er, {
+ message: 'Unsupported engine',
+ pkgid: 'npm@1.2.3',
+ current: {
+ node: process.version,
+ npm: '100.100.100',
+ },
+ required: {
+ node: '>1000',
+ },
+ code: 'EBADENGINE',
+ })
+ t.end()
+ })
+})
+
t.test('completion to folder', async t => {
const Install = t.mock('../../lib/install.js', {
'../../lib/utils/reify-finish.js': async () => {},