Files
pnpm/engine/runtime/node-resolver/src/parseNodeSpecifier.ts
Zoltan Kochan dba4153767 refactor: rename packages and consolidate runtime resolvers (#10999)
* refactor: rename workspace.sort-packages and workspace.pkgs-graph

- workspace.sort-packages -> workspace.projects-sorter
- workspace.pkgs-graph -> workspace.projects-graph

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename packages/ to core/ and pkg-manifest.read-package-json to reader

- Rename packages/ directory to core/ for clarity
- Rename pkg-manifest/read-package-json to pkg-manifest/reader (@pnpm/pkg-manifest.reader)
- Update all tsconfig, package.json, and lockfile references

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: consolidate runtime resolvers under engine/runtime domain

- Remove unused @pnpm/engine.runtime.node.fetcher package
- Rename engine/runtime/node.resolver to node-resolver (dash convention)
- Move resolving/bun-resolver to engine/runtime/bun-resolver
- Move resolving/deno-resolver to engine/runtime/deno-resolver
- Update all package names, tsconfig paths, and lockfile references

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update lockfile after removing node.fetcher

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: sort tsconfig references and package.json deps alphabetically

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: auto-fix import sorting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update __typings__ paths in tsconfig.lint.json for moved resolvers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove deno-resolver from deps of bun-resolver

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 00:19:58 +01:00

52 lines
2.2 KiB
TypeScript

import { PnpmError } from '@pnpm/error'
export interface NodeSpecifier {
releaseChannel: string
versionSpecifier: string
}
const RELEASE_CHANNELS = ['nightly', 'rc', 'test', 'v8-canary', 'release']
const isStableVersion = (version: string): boolean => /^\d+\.\d+\.\d+$/.test(version)
export function parseNodeSpecifier (specifier: string): NodeSpecifier {
// Handle "channel/version" format: "rc/18", "rc/18.0.0-rc.4", "release/22.0.0", "nightly/latest"
if (specifier.includes('/')) {
const [releaseChannel, versionSpecifier] = specifier.split('/', 2)
if (!RELEASE_CHANNELS.includes(releaseChannel)) {
throw new PnpmError('INVALID_NODE_RELEASE_CHANNEL', `"${releaseChannel}" is not a valid Node.js release channel`, {
hint: `Valid release channels are: ${RELEASE_CHANNELS.join(', ')}`,
})
}
return { releaseChannel, versionSpecifier }
}
// Exact prerelease version with a recognized release channel suffix.
// e.g. "22.0.0-rc.4", "22.0.0-nightly20250315d765e70802", "22.0.0-v8-canary2025..."
const prereleaseChannelMatch = specifier.match(/^\d+\.\d+\.\d+-(nightly|rc|test|v8-canary)/)
if (prereleaseChannelMatch != null) {
return { releaseChannel: prereleaseChannelMatch[1], versionSpecifier: specifier }
}
// Exact stable version: "22.0.0"
if (isStableVersion(specifier)) {
return { releaseChannel: 'release', versionSpecifier: specifier }
}
// Standalone release channel name means "latest from that channel".
// e.g. "nightly" → latest nightly, "rc" → latest rc, "release" → latest release
if (RELEASE_CHANNELS.includes(specifier)) {
return { releaseChannel: specifier, versionSpecifier: 'latest' }
}
// Well-known version aliases on the stable release channel
if (specifier === 'lts' || specifier === 'latest') {
return { releaseChannel: 'release', versionSpecifier: specifier }
}
// Semver ranges ("18", "^18", ">=18", "18.x") and LTS codenames ("argon", "iron", "hydrogen")
// are all passed through as versionSpecifier on the release channel.
// Any truly invalid input will fail at resolution time with NODEJS_VERSION_NOT_FOUND.
return { releaseChannel: 'release', versionSpecifier: specifier }
}