Skip to content

Commit 65dc30c

Browse files
committed
Add more granular validation for agent and node version
1 parent 950885f commit 65dc30c

File tree

1 file changed

+61
-21
lines changed

1 file changed

+61
-21
lines changed

src/utils/package-environment.ts

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,17 @@ type EnvBase = {
161161
// Landed in npm v11.2.0.
162162
npmBuggyOverrides: boolean
163163
}
164+
nodeSupported: boolean
165+
nodeVersion: SemVer
164166
npmExecPath: string
165-
pkgSupported: boolean
166167
pkgRequirements: {
167168
agent: string
168169
node: string
169170
}
171+
pkgSupports: {
172+
agent: boolean
173+
node: boolean
174+
}
170175
}
171176

172177
export type EnvDetails = Readonly<
@@ -262,25 +267,30 @@ export async function detectPackageEnvironment({
262267
// Lazily access constants.minimumVersionByAgent.
263268
const minSupportedAgentVersion = constants.minimumVersionByAgent.get(agent)!
264269
const minSupportedNodeVersion = maintainedNodeVersions.last
270+
const nodeVersion = semver.coerce(process.version)!
265271
let lockSrc: string | undefined
272+
let pkgAgentRange: string | undefined
273+
let pkgNodeRange: string | undefined
266274
let pkgMinAgentVersion = minSupportedAgentVersion
267275
let pkgMinNodeVersion = minSupportedNodeVersion
268276
if (pkgJson) {
269277
const { engines } = pkgJson
270-
const agentRange = engines?.[agent]
271-
const nodeRange = engines?.['node']
272-
if (isNonEmptyString(agentRange)) {
278+
const engineAgentRange = engines?.[agent]
279+
const engineNodeRange = engines?.['node']
280+
if (isNonEmptyString(engineAgentRange)) {
281+
pkgAgentRange = engineAgentRange
273282
// Roughly check agent range as semver.coerce will strip leading
274283
// v's, carets (^), comparators (<,<=,>,>=,=), and tildes (~).
275-
const coerced = semver.coerce(agentRange)
284+
const coerced = semver.coerce(pkgAgentRange)
276285
if (coerced && semver.lt(coerced, pkgMinAgentVersion)) {
277286
pkgMinAgentVersion = coerced.version
278287
}
279288
}
280-
if (isNonEmptyString(nodeRange)) {
289+
if (isNonEmptyString(engineNodeRange)) {
290+
pkgNodeRange = engineNodeRange
281291
// Roughly check Node range as semver.coerce will strip leading
282292
// v's, carets (^), comparators (<,<=,>,>=,=), and tildes (~).
283-
const coerced = semver.coerce(nodeRange)
293+
const coerced = semver.coerce(pkgNodeRange)
284294
if (coerced && semver.lt(coerced, pkgMinNodeVersion)) {
285295
pkgMinNodeVersion = coerced.version
286296
}
@@ -313,13 +323,11 @@ export async function detectPackageEnvironment({
313323
!!agentVersion &&
314324
semver.satisfies(agentVersion, `>=${minSupportedAgentVersion}`)
315325

316-
// Does our minimum supported agent version meet the package's requirements?
317-
// Does our supported Node versions meet the package's requirements?
318-
const pkgSupported =
319-
semver.satisfies(minSupportedAgentVersion, `>=${pkgMinAgentVersion}`) &&
320-
maintainedNodeVersions.some(v =>
321-
semver.satisfies(v, `>=${pkgMinNodeVersion}`)
322-
)
326+
// Does the system Node version meet our minimum supported Node version?
327+
const nodeSupported = semver.satisfies(
328+
nodeVersion,
329+
`>=${minSupportedNodeVersion}`
330+
)
323331

324332
const npmBuggyOverrides =
325333
agent === NPM &&
@@ -335,13 +343,25 @@ export async function detectPackageEnvironment({
335343
lockName,
336344
lockPath,
337345
lockSrc,
346+
nodeSupported,
347+
nodeVersion,
338348
npmExecPath,
339349
pkgJson: editablePkgJson,
340350
pkgPath,
341-
pkgSupported,
342351
pkgRequirements: {
343-
agent: `>=${pkgMinAgentVersion}`,
344-
node: `>=${pkgMinNodeVersion}`
352+
agent: pkgAgentRange ?? `>=${pkgMinAgentVersion}`,
353+
node: pkgNodeRange ?? `>=${pkgMinNodeVersion}`
354+
},
355+
pkgSupports: {
356+
// Does our minimum supported agent version meet the package's requirements?
357+
agent: semver.satisfies(
358+
minSupportedAgentVersion,
359+
`>=${pkgMinAgentVersion}`
360+
),
361+
// Does our supported Node versions meet the package's requirements?
362+
node: maintainedNodeVersions.some(v =>
363+
semver.satisfies(v, `>=${pkgMinNodeVersion}`)
364+
)
345365
}
346366
}
347367
}
@@ -374,22 +394,42 @@ export async function detectAndValidatePackageEnvironment(
374394
)
375395
}
376396
})
377-
const { agent, agentVersion } = details
397+
const { agent, nodeVersion, pkgRequirements } = details
398+
const agentVersion = details.agentVersion ?? 'unknown'
378399
if (!details.agentSupported) {
379400
const minVersion = constants.minimumVersionByAgent.get(agent)!
380401
logger?.fail(
381402
cmdPrefixMessage(
382403
cmdName,
383-
`Requires ${agent} >=${minVersion}. Current version: ${agentVersion ?? 'unknown'}.`
404+
`Requires ${agent} >=${minVersion}. Current version: ${agentVersion}.`
405+
)
406+
)
407+
return
408+
}
409+
if (!details.nodeSupported) {
410+
const minVersion = constants.maintainedNodeVersions.last
411+
logger?.fail(
412+
cmdPrefixMessage(
413+
cmdName,
414+
`Requires Node >=${minVersion}. Current version: ${nodeVersion}.`
415+
)
416+
)
417+
return
418+
}
419+
if (!details.pkgSupports.agent) {
420+
logger?.fail(
421+
cmdPrefixMessage(
422+
cmdName,
423+
`Package engine "${agent}" requires ${pkgRequirements.agent}. Current version: ${agentVersion}`
384424
)
385425
)
386426
return
387427
}
388-
if (!details.pkgSupported) {
428+
if (!details.pkgSupports.node) {
389429
logger?.fail(
390430
cmdPrefixMessage(
391431
cmdName,
392-
`Package engine "node" or "${agent}" range not met`
432+
`Package engine "node" requires ${pkgRequirements.node}. Current version: ${nodeVersion}`
393433
)
394434
)
395435
return

0 commit comments

Comments
 (0)