+765
-3
lines changedFilter options
+765
-3
lines changed Original file line number Diff line number Diff line change
@@ -1129,6 +1129,32 @@ Like the `os` option, you can also block architectures:
1129
1129
1130
1130
The host architecture is determined by `process.arch`
1131
1131
1132
+
### devEngines
1133
+
1134
+
The `devEngines` field aids engineers working on a codebase to all be using the same tooling.
1135
+
1136
+
You can specify a `devEngines` property in your `package.json` which will run before `install`, `ci`, and `run` commands.
1137
+
1138
+
> Note: `engines` and `devEngines` differ in object shape. They also function very differently. `engines` is designed to alert the user when a dependency uses a differening npm or node version that the project it's being used in, whereas `devEngines` is used to alert people interacting with the source code of a project.
1139
+
1140
+
The supported keys under the `devEngines` property are `cpu`, `os`, `libc`, `runtime`, and `packageManager`. Each property can be an object or an array of objects. Objects must contain `name`, and optionally can specify `version`, and `onFail`. `onFail` can be `warn`, `error`, or `ignore`, and if left undefined is of the same value as `error`. `npm` will assume that you're running with `node`.
1141
+
Here's an example of a project that will fail if the environment is not `node` and `npm`. If you set `runtime.name` or `packageManager.name` to any other string, it will fail within the npm CLI.
1142
+
1143
+
```json
1144
+
{
1145
+
"devEngines": {
1146
+
"runtime": {
1147
+
"name": "node",
1148
+
"onFail": "error"
1149
+
},
1150
+
"packageManager": {
1151
+
"name": "npm",
1152
+
"onFail": "error"
1153
+
}
1154
+
}
1155
+
}
1156
+
```
1157
+
1132
1158
### private
1133
1159
1134
1160
If you set `"private": true` in your package.json, then npm will refuse to
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ class ArboristCmd extends BaseCommand {
18
18
19
19
static workspaces = true
20
20
static ignoreImplicitWorkspace = false
21
+
static checkDevEngines = true
21
22
22
23
constructor (npm) {
23
24
super(npm)
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
1
1
const { log } = require('proc-log')
2
2
3
3
class BaseCommand {
4
+
// these defaults can be overridden by individual commands
4
5
static workspaces = false
5
6
static ignoreImplicitWorkspace = true
7
+
static checkDevEngines = false
6
8
7
-
// these are all overridden by individual commands
9
+
// these should always be overridden by individual commands
8
10
static name = null
9
11
static description = null
10
12
static params = null
@@ -129,6 +131,63 @@ class BaseCommand {
129
131
}
130
132
}
131
133
134
+
// Checks the devEngines entry in the package.json at this.localPrefix
135
+
async checkDevEngines () {
136
+
const force = this.npm.flatOptions.force
137
+
138
+
const { devEngines } = await require('@npmcli/package-json')
139
+
.normalize(this.npm.config.localPrefix)
140
+
.then(p => p.content)
141
+
.catch(() => ({}))
142
+
143
+
if (typeof devEngines === 'undefined') {
144
+
return
145
+
}
146
+
147
+
const { checkDevEngines, currentEnv } = require('npm-install-checks')
148
+
const current = currentEnv.devEngines({
149
+
nodeVersion: this.npm.nodeVersion,
150
+
npmVersion: this.npm.version,
151
+
})
152
+
153
+
const failures = checkDevEngines(devEngines, current)
154
+
const warnings = failures.filter(f => f.isWarn)
155
+
const errors = failures.filter(f => f.isError)
156
+
157
+
const genMsg = (failure, i = 0) => {
158
+
return [...new Set([
159
+
// eslint-disable-next-line
160
+
i === 0 ? 'The developer of this package has specified the following through devEngines' : '',
161
+
`${failure.message}`,
162
+
`${failure.errors.map(e => e.message).join('\n')}`,
163
+
])].filter(v => v).join('\n')
164
+
}
165
+
166
+
[...warnings, ...(force ? errors : [])].forEach((failure, i) => {
167
+
const message = genMsg(failure, i)
168
+
log.warn('EBADDEVENGINES', message)
169
+
log.warn('EBADDEVENGINES', {
170
+
current: failure.current,
171
+
required: failure.required,
172
+
})
173
+
})
174
+
175
+
if (force) {
176
+
return
177
+
}
178
+
179
+
if (errors.length) {
180
+
const failure = errors[0]
181
+
const message = genMsg(failure)
182
+
throw Object.assign(new Error(message), {
183
+
engine: failure.engine,
184
+
code: 'EBADDEVENGINES',
185
+
current: failure.current,
186
+
required: failure.required,
187
+
})
188
+
}
189
+
}
190
+
132
191
async setWorkspaces () {
133
192
const { relative } = require('node:path')
134
193
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ class RunScript extends BaseCommand {
21
21
static workspaces = true
22
22
static ignoreImplicitWorkspace = false
23
23
static isShellout = true
24
+
static checkDevEngines = true
24
25
25
26
static async completion (opts, npm) {
26
27
const argv = opts.conf.argv.remain
Original file line number Diff line number Diff line change
@@ -247,6 +247,10 @@ class Npm {
247
247
execWorkspaces = true
248
248
}
249
249
250
+
if (command.checkDevEngines && !this.global) {
251
+
await command.checkDevEngines()
252
+
}
253
+
250
254
return time.start(`command:${cmd}`, () =>
251
255
execWorkspaces ? command.execWorkspaces(args) : command.exec(args))
252
256
}
Original file line number Diff line number Diff line change
@@ -200,6 +200,13 @@ const errorMessage = (er, npm) => {
200
200
].join('\n')])
201
201
break
202
202
203
+
case 'EBADDEVENGINES': {
204
+
const { current, required } = er
205
+
summary.push(['EBADDEVENGINES', er.message])
206
+
detail.push(['EBADDEVENGINES', { current, required }])
207
+
break
208
+
}
209
+
203
210
case 'EBADPLATFORM': {
204
211
const actual = er.current
205
212
const expected = { ...er.required }
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4