fix: store every Node.js artifact's integrity separately in the lockfile (#9798)

* fix: store every Node.js artifact's integrity separately in the lockfile

* fix: store every Node.js artifact's integrity separately in the lockfile

* style: fix

* Potential fix for code scanning alert no. 76: Incomplete string escaping or encoding

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix: windows

* refactor: node install

* fix: test

* fix: test on Windows

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This commit is contained in:
Zoltan Kochan
2025-07-25 16:31:23 +02:00
committed by GitHub
parent 1073cec79b
commit f91922c938
13 changed files with 310 additions and 83 deletions

View File

@@ -0,0 +1,13 @@
---
"@pnpm/plugin-commands-deploy": major
"@pnpm/resolve-dependencies": major
"@pnpm/package-requester": major
"@pnpm/resolver-base": major
"@pnpm/client": major
"@pnpm/node.resolver": major
"@pnpm/node.fetcher": major
"@pnpm/core": major
"@pnpm/lockfile.types": major
---
Changed how the integrity of the node.js artifact is stored in the lockfile.

View File

@@ -6,12 +6,11 @@ import { fetchShasumsFile, pickFileChecksumFromShasumsFile } from '@pnpm/crypto.
import {
type FetchFromRegistry,
type RetryTimeoutOptions,
type Response,
} from '@pnpm/fetching-types'
import { createCafsStore } from '@pnpm/create-cafs-store'
import { type Cafs } from '@pnpm/cafs-types'
import { createTarballFetcher } from '@pnpm/tarball-fetcher'
import { type NodeRuntimeFetcher, type FetchResult } from '@pnpm/fetcher-base'
import { type NodeRuntimeFetcher, type FetchFunction } from '@pnpm/fetcher-base'
import { getNodeMirror, parseEnvSpecifier } from '@pnpm/node.resolver'
import { addFilesFromDir } from '@pnpm/worker'
import AdmZip from 'adm-zip'
@@ -22,6 +21,7 @@ import ssri from 'ssri'
import { getNodeArtifactAddress } from './getNodeArtifactAddress'
export function createNodeRuntimeFetcher (ctx: {
fetchFromRemoteTarball: FetchFunction
fetch: FetchFromRegistry
rawConfig: Record<string, string>
offline?: boolean
@@ -41,8 +41,7 @@ export function createNodeRuntimeFetcher (ctx: {
const nodeMirrorBaseUrl = getNodeMirror(ctx.rawConfig, releaseChannel)
const artifactInfo = await getNodeArtifactInfo(ctx.fetch, version, {
nodeMirrorBaseUrl,
expectedVersionIntegrity: resolution.integrity,
cachedShasumsFile: resolution._shasumsFileContent,
integrities: resolution.integrities,
})
const manifest = {
name: 'node',
@@ -65,7 +64,14 @@ export function createNodeRuntimeFetcher (ctx: {
}
return {
...await downloadAndUnpackTarball(ctx.fetch, artifactInfo, { cafs, filesIndexFile: opts.filesIndexFile }),
...await ctx.fetchFromRemoteTarball(cafs, {
tarball: artifactInfo.url,
integrity: artifactInfo.integrity,
}, {
filesIndexFile: opts.filesIndexFile,
lockfileDir: process.cwd(),
pkg: {},
}),
manifest,
}
}
@@ -155,8 +161,7 @@ async function getNodeArtifactInfo (
version: string,
opts: {
nodeMirrorBaseUrl: string
expectedVersionIntegrity?: string
cachedShasumsFile?: string
integrities?: Record<string, string>
}
): Promise<NodeArtifactInfo> {
const tarball = getNodeArtifactAddress({
@@ -170,11 +175,9 @@ async function getNodeArtifactInfo (
const shasumsFileUrl = `${tarball.dirname}/SHASUMS256.txt`
const url = `${tarball.dirname}/${tarballFileName}`
const integrity = opts.cachedShasumsFile
? pickFileChecksumFromShasumsFile(opts.cachedShasumsFile, tarballFileName)
: await loadArtifactIntegrity(fetch, tarballFileName, shasumsFileUrl, {
expectedVersionIntegrity: opts.expectedVersionIntegrity,
})
const integrity = opts.integrities
? opts.integrities[`${process.platform}-${process.arch}`]
: await loadArtifactIntegrity(fetch, tarballFileName, shasumsFileUrl)
return {
url,
@@ -256,30 +259,6 @@ async function downloadAndUnpackTarballToDir (
})
}
async function downloadAndUnpackTarball (
fetch: FetchFromRegistry,
artifactInfo: NodeArtifactInfo,
opts: FetchNodeOptions
): Promise<FetchResult> {
const getAuthHeader = () => undefined
const fetchers = createTarballFetcher(fetch, getAuthHeader, {
retry: opts.retry,
timeout: opts.fetchTimeout,
// These are not needed for fetching Node.js
rawConfig: {},
unsafePerm: false,
})
return fetchers.remoteTarball(opts.cafs, {
tarball: artifactInfo.url,
integrity: artifactInfo.integrity,
}, {
filesIndexFile: opts.filesIndexFile,
lockfileDir: process.cwd(),
pkg: {},
})
}
/**
* Downloads and unpacks a zip file containing Node.js.
*
@@ -293,11 +272,10 @@ async function downloadAndUnpackZip (
artifactInfo: NodeArtifactInfo,
targetDir: string
): Promise<void> {
const response = await fetchFromRegistry(artifactInfo.url)
const tmp = path.join(tempy.directory(), 'pnpm.zip')
try {
await downloadWithIntegrityCheck(response, tmp, artifactInfo.integrity)
await downloadWithIntegrityCheck(fetchFromRegistry, artifactInfo, tmp)
await extractZipToTarget(tmp, artifactInfo.basename, targetDir)
} finally {
// Clean up temporary file
@@ -311,18 +289,14 @@ async function downloadAndUnpackZip (
/**
* Downloads a file with integrity verification.
*
* @param response - Fetch response containing the file data
* @param tmpPath - Temporary file path to save the download
* @param expectedIntegrity - Expected SHA-256 integrity hash
* @param url - URL being downloaded (for error messages)
* @throws {PnpmError} When integrity verification fails
*/
async function downloadWithIntegrityCheck (
response: Response,
tmpPath: string,
expectedIntegrity: string
fetchFromRegistry: FetchFromRegistry,
{ url, integrity }: NodeArtifactInfo,
tmpPath: string
): Promise<void> {
const response = await fetchFromRegistry(url)
// Collect all chunks from the response
const chunks: Buffer[] = []
for await (const chunk of response.body!) {
@@ -330,8 +304,15 @@ async function downloadWithIntegrityCheck (
}
const data = Buffer.concat(chunks)
// Verify integrity if provided
ssri.checkData(data, expectedIntegrity, { error: true })
try {
// Verify integrity if provided
ssri.checkData(data, integrity, { error: true })
} catch (err) {
if (!(err instanceof Error) || !('expected' in err) || !('found' in err)) {
throw err
}
throw new PnpmError('TARBALL_INTEGRITY', `Got unexpected checksum for "${url}". Wanted "${err.expected as string}". Got "${err.found as string}".`)
}
// Write the verified data to file
await fsPromises.writeFile(tmpPath, data)

View File

@@ -35,7 +35,6 @@
"dependencies": {
"@pnpm/config": "workspace:*",
"@pnpm/constants": "workspace:*",
"@pnpm/crypto.hash": "workspace:*",
"@pnpm/crypto.shasums-file": "workspace:*",
"@pnpm/error": "workspace:*",
"@pnpm/fetching-types": "workspace:*",

View File

@@ -1,5 +1,4 @@
import { getNodeBinLocationForCurrentOS } from '@pnpm/constants'
import { createHash } from '@pnpm/crypto.hash'
import { fetchShasumsFile } from '@pnpm/crypto.shasums-file'
import { PnpmError } from '@pnpm/error'
import { type FetchFromRegistry } from '@pnpm/fetching-types'
@@ -34,7 +33,7 @@ export async function resolveNodeRuntime (
if (!version) {
throw new PnpmError('NODEJS_VERSION_NOT_FOUND', `Could not find a Node.js version that satisfies ${versionSpec}`)
}
const { versionIntegrity: integrity, shasumsFileContent } = await loadShasumsFile(ctx.fetchFromRegistry, nodeMirrorBaseUrl, version)
const integrities = await loadShasumsFile(ctx.fetchFromRegistry, nodeMirrorBaseUrl, version)
return {
id: `node@runtime:${version}` as PkgResolutionId,
normalizedBareSpecifier: `runtime:${versionSpec}`,
@@ -46,25 +45,36 @@ export async function resolveNodeRuntime (
},
resolution: {
type: 'nodeRuntime',
integrity,
_shasumsFileContent: shasumsFileContent,
integrities,
},
}
}
async function loadShasumsFile (fetch: FetchFromRegistry, nodeMirrorBaseUrl: string, version: string): Promise<{
shasumsFileContent: string
versionIntegrity: string
}> {
async function loadShasumsFile (fetch: FetchFromRegistry, nodeMirrorBaseUrl: string, version: string): Promise<Record<string, string>> {
const integritiesFileUrl = `${nodeMirrorBaseUrl}/v${version}/SHASUMS256.txt`
const shasumsFileContent = await fetchShasumsFile(fetch, integritiesFileUrl)
const lines = shasumsFileContent.split('\n')
const integrities: Record<string, string> = {}
const escaped = version.replace(/\\/g, '\\\\').replace(/\./g, '\\.')
const pattern = new RegExp(`^node-v${escaped}-([^-.]+)-([^.]+)\\.(?:tar\\.gz|zip)$`)
for (const line of lines) {
if (!line) continue
const [sha256, file] = line.trim().split(/\s+/)
const versionIntegrity = createHash(shasumsFileContent)
const match = pattern.exec(file)
if (!match) continue
return {
shasumsFileContent,
versionIntegrity,
const buffer = Buffer.from(sha256, 'hex')
const base64 = buffer.toString('base64')
const integrity = `sha256-${base64}`
let [, platform, arch] = match
if (platform === 'win') {
platform = 'win32'
}
integrities[`${platform}-${arch}`] = integrity
}
return integrities
}
interface NodeVersion {

View File

@@ -12,9 +12,6 @@
{
"path": "../../config/config"
},
{
"path": "../../crypto/hash"
},
{
"path": "../../crypto/shasums-file"
},

View File

@@ -111,7 +111,7 @@ export interface GitRepositoryResolution {
export interface NodeRuntimeResolution {
type: 'nodeRuntime'
integrity: string
integrities: Record<string, string>
}
export type Resolution =

View File

@@ -68,12 +68,14 @@ function createFetchers (
opts: Pick<ClientOptions, 'rawConfig' | 'retry' | 'gitShallowHosts' | 'resolveSymlinksInInjectedDirs' | 'unsafePerm' | 'includeOnlyPackageFiles' | 'offline'>,
customFetchers?: CustomFetchers
): Fetchers {
const tarballFetchers = createTarballFetcher(fetchFromRegistry, getAuthHeader, opts)
const defaultFetchers = {
...createTarballFetcher(fetchFromRegistry, getAuthHeader, opts),
...tarballFetchers,
...createGitFetcher(opts),
...createDirectoryFetcher({ resolveSymlinks: opts.resolveSymlinksInInjectedDirs, includeOnlyPackageFiles: opts.includeOnlyPackageFiles }),
...createNodeRuntimeFetcher({
fetch: fetchFromRegistry,
fetchFromRemoteTarball: tarballFetchers.remoteTarball,
offline: opts.offline,
rawConfig: opts.rawConfig,
}),

View File

@@ -6,6 +6,20 @@ import { sync as rimraf } from '@zkochan/rimraf'
import { sync as writeYamlFile } from 'write-yaml-file'
import { testDefaults } from '../utils'
const NODE_INTEGRITIES = {
'aix-ppc64': 'sha256-13Q/3fXoZxJPVVqR9scpEE/Vx12TgvEChsP7s/0S7wc=',
'darwin-arm64': 'sha256-6pbTSc+qZ6qHzuqj5bUskWf3rDAv2NH/Fi0HhencB4U=',
'darwin-x64': 'sha256-Qio4h/9UGPCkVS2Jz5k0arirUbtdOEZguqiLhETSwRE=',
'linux-arm64': 'sha256-HTVHImvn5ZrO7lx9Aan4/BjeZ+AVxaFdjPOFtuAtBis=',
'linux-armv7l': 'sha256-0h239Xxc4YKuwrmoPjKVq8N+FzGrtzmV09Vz4EQJl3w=',
'linux-ppc64le': 'sha256-OwmNzPVtRGu7gIRdNbvsvbdGEoYNFpDzohY4fJnJ1iA=',
'linux-s390x': 'sha256-fsX9rQyBnuoXkA60PB3pSNYgp4OxrJQGLKpDh3ipKzA=',
'linux-x64': 'sha256-dLsPOoAwfFKUIcPthFF7j1Q4Z3CfQeU81z35nmRCr00=',
'win32-arm64': 'sha256-N2Ehz0a9PAJcXmetrhkK/14l0zoLWPvA2GUtczULOPA=',
'win32-x64': 'sha256-MtY5tH1MCmUf+PjX1BpFQWij1ARb43mF+agQz4zvYXQ=',
'win32-x86': 'sha256-4BNPUBcVSjN2csf7zRVOKyx3S0MQkRhWAZINY9DEt9A=',
}
test('installing Node.js runtime', async () => {
const project = prepareEmpty()
const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['node@runtime:22.0.0'], testDefaults({ fastUnpack: false }))
@@ -31,7 +45,7 @@ test('installing Node.js runtime', async () => {
'node@runtime:22.0.0': {
hasBin: true,
resolution: {
integrity: 'sha256-NexAQ7DxOFuPb9J7KNeuLtuSeaxFVUGlTrqSqs7AEbo=',
integrities: NODE_INTEGRITIES,
type: 'nodeRuntime',
},
},
@@ -74,7 +88,7 @@ test('installing Node.js runtime', async () => {
'node@runtime:22.0.0': {
hasBin: true,
resolution: {
integrity: 'sha256-NexAQ7DxOFuPb9J7KNeuLtuSeaxFVUGlTrqSqs7AEbo=',
integrities: NODE_INTEGRITIES,
type: 'nodeRuntime',
},
},
@@ -128,7 +142,10 @@ test('installing Node.js runtime fails if integrity check fails', async () => {
'node@runtime:22.0.0': {
hasBin: true,
resolution: {
integrity: 'sha256-nEXaq7dXofUpB9j7knEUlTUsEAXfvugLtRQsQS7aeBO=',
integrities: {
...NODE_INTEGRITIES,
[`${process.platform}-${process.arch}`]: 'sha256-0000000000000000000000000000000000000000000=',
},
type: 'nodeRuntime',
},
},
@@ -143,5 +160,9 @@ test('installing Node.js runtime fails if integrity check fails', async () => {
node: 'runtime:22.0.0',
},
}
await expect(install(manifest, testDefaults({ frozenLockfile: true }))).rejects.toThrow(/The integrity of .* failed/)
await expect(install(manifest, testDefaults({ frozenLockfile: true }, {
retry: {
retries: 0,
},
}))).rejects.toThrow(/Got unexpected checksum for/)
})

View File

@@ -22,6 +22,7 @@ import { packageIsInstallable } from '@pnpm/package-is-installable'
import { readPackageJson } from '@pnpm/read-package-json'
import {
type DirectoryResolution,
type NodeRuntimeResolution,
type PreferredVersions,
type Resolution,
type ResolveFunction,
@@ -343,7 +344,9 @@ function getFilesIndexFilePath (
const target = path.join(ctx.storeDir, targetRelative)
const filesIndexFile = (opts.pkg.resolution as TarballResolution).integrity
? ctx.getIndexFilePathInCafs((opts.pkg.resolution as TarballResolution).integrity!, opts.pkg.id)
: path.join(target, opts.ignoreScripts ? 'integrity-not-built.json' : 'integrity.json')
: (opts.pkg.resolution as NodeRuntimeResolution).integrities?.[`${process.platform}-${process.arch}`]
? ctx.getIndexFilePathInCafs((opts.pkg.resolution as NodeRuntimeResolution).integrities[`${process.platform}-${process.arch}`], opts.pkg.id)
: path.join(target, opts.ignoreScripts ? 'integrity-not-built.json' : 'integrity.json')
return { filesIndexFile, target }
}

View File

@@ -11,7 +11,6 @@ import * as dp from '@pnpm/dependency-path'
import getNpmTarballUrl from 'get-npm-tarball-url'
import { type KeyValuePair } from 'ramda'
import partition from 'ramda/src/partition'
import omit from 'ramda/src/omit'
import { depPathToRef } from './depPathToRef'
import { type ResolvedPackage } from './resolveDependencies'
import { type DependenciesGraph } from '.'
@@ -183,9 +182,6 @@ function toLockfileResolution (
lockfileIncludeTarballUrl?: boolean
): LockfileResolution {
if (resolution.type !== undefined || !resolution['integrity']) {
if (resolution.type === 'nodeRuntime') {
return omit(['_shasumsFileContent'], resolution)
}
return resolution as LockfileResolution
}
if (lockfileIncludeTarballUrl) {

214
pnpm-lock.yaml generated
View File

@@ -810,7 +810,7 @@ importers:
version: link:../packages/logger
'@pnpm/meta-updater':
specifier: 'catalog:'
version: 2.0.6(@types/node@18.19.34)(typanion@3.14.0)
version: 2.0.6(@types/node@22.15.29)(typanion@3.14.0)
'@pnpm/object.key-sorting':
specifier: workspace:*
version: link:../object/key-sorting
@@ -2137,9 +2137,6 @@ importers:
'@pnpm/constants':
specifier: workspace:*
version: link:../../packages/constants
'@pnpm/crypto.hash':
specifier: workspace:*
version: link:../../crypto/hash
'@pnpm/crypto.shasums-file':
specifier: workspace:*
version: link:../../crypto/shasums-file
@@ -16714,6 +16711,28 @@ snapshots:
- supports-color
- typanion
'@pnpm/cli-utils@1000.1.5(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)':
dependencies:
'@pnpm/cli-meta': 1000.0.8
'@pnpm/config': 1003.1.1(@pnpm/logger@1001.0.0)
'@pnpm/config.deps-installer': 1000.0.5(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))
'@pnpm/default-reporter': 1002.0.1(@pnpm/logger@1001.0.0)
'@pnpm/error': 1000.0.2
'@pnpm/logger': 1001.0.0
'@pnpm/manifest-utils': 1001.0.1(@pnpm/logger@1001.0.0)
'@pnpm/package-is-installable': 1000.0.10(@pnpm/logger@1001.0.0)
'@pnpm/pnpmfile': 1001.2.2(@pnpm/logger@1001.0.0)
'@pnpm/read-project-manifest': 1000.0.11
'@pnpm/store-connection-manager': 1002.0.3(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)
'@pnpm/types': 1000.6.0
chalk: 4.1.2
load-json-file: 6.2.0
transitivePeerDependencies:
- '@pnpm/worker'
- domexception
- supports-color
- typanion
'@pnpm/client@1000.0.19(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@18.19.34))(typanion@3.14.0)':
dependencies:
'@pnpm/default-resolver': 1002.0.2(@pnpm/logger@1001.0.0)
@@ -16733,6 +16752,25 @@ snapshots:
- supports-color
- typanion
'@pnpm/client@1000.0.19(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)':
dependencies:
'@pnpm/default-resolver': 1002.0.2(@pnpm/logger@1001.0.0)
'@pnpm/directory-fetcher': 1000.1.7(@pnpm/logger@1001.0.0)
'@pnpm/fetch': 1000.2.2(@pnpm/logger@1001.0.0)
'@pnpm/fetching-types': 1000.1.0
'@pnpm/git-fetcher': 1001.0.8(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)
'@pnpm/network.auth-header': 1000.0.3
'@pnpm/resolver-base': 1003.0.1
'@pnpm/tarball-fetcher': 1001.0.8(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)
'@pnpm/types': 1000.6.0
ramda: '@pnpm/ramda@0.28.1'
transitivePeerDependencies:
- '@pnpm/logger'
- '@pnpm/worker'
- domexception
- supports-color
- typanion
'@pnpm/colorize-semver-diff@1.0.1':
dependencies:
chalk: 4.1.2
@@ -16766,6 +16804,28 @@ snapshots:
- domexception
- supports-color
'@pnpm/config.deps-installer@1000.0.5(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))':
dependencies:
'@pnpm/config.config-writer': 1000.0.5
'@pnpm/core-loggers': 1001.0.1(@pnpm/logger@1001.0.0)
'@pnpm/error': 1000.0.2
'@pnpm/fetch': 1000.2.2(@pnpm/logger@1001.0.0)
'@pnpm/logger': 1001.0.0
'@pnpm/network.auth-header': 1000.0.3
'@pnpm/npm-resolver': 1004.0.1(@pnpm/logger@1001.0.0)
'@pnpm/package-store': 1002.0.4(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))
'@pnpm/parse-wanted-dependency': 1001.0.0
'@pnpm/pick-registry-for-package': 1000.0.8
'@pnpm/read-modules-dir': 1000.0.0
'@pnpm/read-package-json': 1000.0.9
'@pnpm/types': 1000.6.0
'@zkochan/rimraf': 3.0.2
get-npm-tarball-url: 2.1.0
transitivePeerDependencies:
- '@pnpm/worker'
- domexception
- supports-color
'@pnpm/config.env-replace@1.1.0': {}
'@pnpm/config.env-replace@3.0.1': {}
@@ -17075,6 +17135,19 @@ snapshots:
- supports-color
- typanion
'@pnpm/git-fetcher@1001.0.8(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)':
dependencies:
'@pnpm/fetcher-base': 1000.0.11
'@pnpm/fs.packlist': 2.0.0
'@pnpm/logger': 1001.0.0
'@pnpm/prepare-package': 1000.0.16(@pnpm/logger@1001.0.0)(typanion@3.14.0)
'@pnpm/worker': 1000.1.7(@pnpm/logger@packages+logger)(@types/node@22.15.29)
'@zkochan/rimraf': 3.0.2
execa: safe-execa@0.1.2
transitivePeerDependencies:
- supports-color
- typanion
'@pnpm/git-resolver@1001.0.2(@pnpm/logger@1001.0.0)':
dependencies:
'@pnpm/fetch': 1000.2.2(@pnpm/logger@1001.0.0)
@@ -17221,6 +17294,24 @@ snapshots:
- supports-color
- typanion
'@pnpm/meta-updater@2.0.6(@types/node@22.15.29)(typanion@3.14.0)':
dependencies:
'@pnpm/find-workspace-dir': 1000.1.0
'@pnpm/logger': 1001.0.0
'@pnpm/types': 1000.6.0
'@pnpm/worker': 1000.1.7(@pnpm/logger@packages+logger)(@types/node@22.15.29)
'@pnpm/workspace.find-packages': 1000.0.25(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)
'@pnpm/workspace.read-manifest': 1000.1.5
load-json-file: 7.0.1
meow: 11.0.0
print-diff: 2.0.0
write-json-file: 5.0.0
transitivePeerDependencies:
- '@types/node'
- domexception
- supports-color
- typanion
'@pnpm/network.agent@2.0.3':
dependencies:
'@pnpm/network.config': 2.1.0
@@ -17401,6 +17492,30 @@ snapshots:
semver: 7.7.2
ssri: 10.0.5
'@pnpm/package-requester@1004.0.2(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))':
dependencies:
'@pnpm/core-loggers': 1001.0.1(@pnpm/logger@1001.0.0)
'@pnpm/dependency-path': 1000.0.9
'@pnpm/error': 1000.0.2
'@pnpm/fetcher-base': 1000.0.11
'@pnpm/graceful-fs': 1000.0.0
'@pnpm/logger': 1001.0.0
'@pnpm/package-is-installable': 1000.0.10(@pnpm/logger@1001.0.0)
'@pnpm/pick-fetcher': 1000.0.0
'@pnpm/read-package-json': 1000.0.9
'@pnpm/resolver-base': 1003.0.1
'@pnpm/store-controller-types': 1003.0.2
'@pnpm/store.cafs': 1000.0.13
'@pnpm/types': 1000.6.0
'@pnpm/worker': 1000.1.7(@pnpm/logger@packages+logger)(@types/node@22.15.29)
p-defer: 3.0.0
p-limit: 3.1.0
p-queue: 6.6.2
promise-share: 1.0.0
ramda: '@pnpm/ramda@0.28.1'
semver: 7.7.2
ssri: 10.0.5
'@pnpm/package-store@1002.0.4(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@18.19.34))':
dependencies:
'@pnpm/create-cafs-store': 1000.0.14(@pnpm/logger@1001.0.0)
@@ -17417,6 +17532,22 @@ snapshots:
ramda: '@pnpm/ramda@0.28.1'
ssri: 10.0.5
'@pnpm/package-store@1002.0.4(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))':
dependencies:
'@pnpm/create-cafs-store': 1000.0.14(@pnpm/logger@1001.0.0)
'@pnpm/fetcher-base': 1000.0.11
'@pnpm/logger': 1001.0.0
'@pnpm/package-requester': 1004.0.2(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))
'@pnpm/resolver-base': 1003.0.1
'@pnpm/store-controller-types': 1003.0.2
'@pnpm/store.cafs': 1000.0.13
'@pnpm/types': 1000.6.0
'@pnpm/worker': 1000.1.7(@pnpm/logger@packages+logger)(@types/node@22.15.29)
'@zkochan/rimraf': 3.0.2
load-json-file: 6.2.0
ramda: '@pnpm/ramda@0.28.1'
ssri: 10.0.5
'@pnpm/parse-overrides@1000.0.2':
dependencies:
'@pnpm/catalogs.resolver': 1000.0.2
@@ -17633,6 +17764,25 @@ snapshots:
- supports-color
- typanion
'@pnpm/store-connection-manager@1002.0.3(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)':
dependencies:
'@pnpm/cli-meta': 1000.0.8
'@pnpm/client': 1000.0.19(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)
'@pnpm/config': 1003.1.1(@pnpm/logger@1001.0.0)
'@pnpm/error': 1000.0.2
'@pnpm/logger': 1001.0.0
'@pnpm/package-store': 1002.0.4(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))
'@pnpm/server': 1001.0.4(@pnpm/logger@1001.0.0)
'@pnpm/store-path': 1000.0.2
'@zkochan/diable': 1.0.2
delay: 5.0.0
dir-is-case-sensitive: 2.0.0
transitivePeerDependencies:
- '@pnpm/worker'
- domexception
- supports-color
- typanion
'@pnpm/store-controller-types@1001.0.3':
dependencies:
'@pnpm/fetcher-base': 1000.0.5
@@ -17706,6 +17856,28 @@ snapshots:
- supports-color
- typanion
'@pnpm/tarball-fetcher@1001.0.8(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)':
dependencies:
'@pnpm/core-loggers': 1001.0.1(@pnpm/logger@1001.0.0)
'@pnpm/error': 1000.0.2
'@pnpm/fetcher-base': 1000.0.11
'@pnpm/fetching-types': 1000.1.0
'@pnpm/fs.packlist': 2.0.0
'@pnpm/graceful-fs': 1000.0.0
'@pnpm/logger': 1001.0.0
'@pnpm/prepare-package': 1000.0.16(@pnpm/logger@1001.0.0)(typanion@3.14.0)
'@pnpm/worker': 1000.1.7(@pnpm/logger@packages+logger)(@types/node@22.15.29)
'@zkochan/retry': 0.2.0
lodash.throttle: 4.1.1
p-map-values: 1.0.0
path-temp: 2.1.0
ramda: '@pnpm/ramda@0.28.1'
rename-overwrite: 6.0.3
transitivePeerDependencies:
- domexception
- supports-color
- typanion
'@pnpm/tarball-resolver@1002.0.2':
dependencies:
'@pnpm/fetching-types': 1000.1.0
@@ -17753,6 +17925,26 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
'@pnpm/worker@1000.1.7(@pnpm/logger@packages+logger)(@types/node@22.15.29)':
dependencies:
'@pnpm/cafs-types': 1000.0.0
'@pnpm/create-cafs-store': 1000.0.14(@pnpm/logger@1001.0.0)
'@pnpm/crypto.polyfill': 1000.1.0
'@pnpm/error': 1000.0.2
'@pnpm/exec.pkg-requires-build': 1000.0.8
'@pnpm/fs.hard-link-dir': 1000.0.1(@pnpm/logger@1001.0.0)
'@pnpm/graceful-fs': 1000.0.0
'@pnpm/logger': link:packages/logger
'@pnpm/store.cafs': 1000.0.13
'@pnpm/symlink-dependency': 1000.0.9(@pnpm/logger@1001.0.0)
'@rushstack/worker-pool': 0.4.9(@types/node@22.15.29)
is-windows: 1.0.2
load-json-file: 6.2.0
p-limit: 3.1.0
shell-quote: 1.8.3
transitivePeerDependencies:
- '@types/node'
'@pnpm/workspace.find-packages@1000.0.15(@pnpm/logger@1000.0.0)':
dependencies:
'@pnpm/cli-utils': 1000.0.15(@pnpm/logger@1000.0.0)
@@ -17776,6 +17968,20 @@ snapshots:
- supports-color
- typanion
'@pnpm/workspace.find-packages@1000.0.25(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)':
dependencies:
'@pnpm/cli-utils': 1000.1.5(@pnpm/logger@1001.0.0)(@pnpm/worker@1000.1.7(@pnpm/logger@1001.0.0)(@types/node@22.15.29))(typanion@3.14.0)
'@pnpm/constants': 1001.1.0
'@pnpm/fs.find-packages': 1000.0.11
'@pnpm/logger': 1001.0.0
'@pnpm/types': 1000.6.0
'@pnpm/util.lex-comparator': 3.0.2
transitivePeerDependencies:
- '@pnpm/worker'
- domexception
- supports-color
- typanion
'@pnpm/workspace.manifest-writer@1000.1.4':
dependencies:
'@pnpm/constants': 1001.1.0

View File

@@ -188,7 +188,7 @@ function convertPackageSnapshot (inputSnapshot: PackageSnapshot, opts: ConvertOp
const resolvedPath = path.resolve(opts.lockfileDir, inputResolution.directory)
const directory = normalizePath(path.relative(opts.deployDir, resolvedPath))
outputResolution = { ...inputResolution, directory }
} else if (inputResolution.type === 'git') {
} else if (inputResolution.type === 'git' || inputResolution.type === 'nodeRuntime') {
outputResolution = inputResolution
} else {
const resolution: never = inputResolution // `never` is the type guard to force fixing this code when adding new type of resolution

View File

@@ -34,8 +34,7 @@ export interface GitResolution {
export interface NodeRuntimeResolution {
type: 'nodeRuntime'
integrity: string
_shasumsFileContent?: string
integrities: Record<string, string>
}
export type Resolution =