@pnpm/deps.graph-hasher 1100.2.11 → 1100.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/lib/index.d.ts +131 -0
- package/lib/index.js +41 -21
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @pnpm/calc-dep-state
|
|
2
2
|
|
|
3
|
+
## 1100.2.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Installing a local `file:` directory dependency with the global virtual store enabled no longer fails with `TypeError: Cannot read properties of undefined (reading 'split')` [#13335](https://github.com/pnpm/pnpm/issues/13335).
|
|
8
|
+
|
|
9
|
+
Local directory dependencies — `file:` directories and injected workspace packages — now get a global-virtual-store slot of their own per project. They used to share one slot across every project that depended on a directory of the same name, so a project could end up linked to another project's copy of the dependency.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies:
|
|
12
|
+
- @pnpm/deps.path@1100.0.12
|
|
13
|
+
- @pnpm/engine.runtime.system-version@1100.0.7
|
|
14
|
+
- @pnpm/lockfile.types@1100.0.17
|
|
15
|
+
- @pnpm/lockfile.utils@1100.1.6
|
|
16
|
+
- @pnpm/resolving.resolver-base@1100.5.5
|
|
17
|
+
- @pnpm/types@1101.7.0
|
|
18
|
+
|
|
19
|
+
## 1100.2.12
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Republished every package: the tarballs published by the v11.13.1 through v11.16.0 releases were missing most of their compiled files due to a packing bug [#13164](https://github.com/pnpm/pnpm/issues/13164).
|
|
24
|
+
|
|
25
|
+
- Updated dependencies:
|
|
26
|
+
- @pnpm/crypto.object-hasher@1100.0.1
|
|
27
|
+
- @pnpm/deps.path@1100.0.11
|
|
28
|
+
- @pnpm/engine.runtime.system-version@1100.0.6
|
|
29
|
+
- @pnpm/lockfile.types@1100.0.16
|
|
30
|
+
- @pnpm/lockfile.utils@1100.1.5
|
|
31
|
+
- @pnpm/resolving.resolver-base@1100.5.4
|
|
32
|
+
- @pnpm/types@1101.6.0
|
|
33
|
+
|
|
3
34
|
## 1100.2.11
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { LockfileObject, LockfileResolution, PackageSnapshot } from '@pnpm/lockfile.types';
|
|
2
|
+
import type { AllowBuild, DepPath, PkgIdWithPatchHash, SupportedArchitectures } from '@pnpm/types';
|
|
3
|
+
/**
|
|
4
|
+
* Scan an iterable of lockfile snapshot keys for the resolved
|
|
5
|
+
* `engines.runtime` / `devEngines.runtime` Node version and return
|
|
6
|
+
* its bare version string (e.g. `"22.11.0"`), or `undefined` when
|
|
7
|
+
* no snapshot pins a runtime.
|
|
8
|
+
*
|
|
9
|
+
* Pnpm's runtime resolver writes the pinned Node into the lockfile as
|
|
10
|
+
* a snapshot with key `node@runtime:<version>[(<peers>)]`
|
|
11
|
+
* (see [`engine/runtime/node-resolver/src/index.ts`](https://github.com/pnpm/pnpm/blob/29a42efc3b/engine/runtime/node-resolver/src/index.ts)).
|
|
12
|
+
* The first such key found is treated as authoritative. This is fine
|
|
13
|
+
* as an install-wide fallback (project-pin in the typical case), but
|
|
14
|
+
* snapshots that pin their own Node still need
|
|
15
|
+
* {@link readSnapshotRuntimePin} to get a per-snapshot result.
|
|
16
|
+
*
|
|
17
|
+
* Callers typically pass `Object.keys(lockfile.packages ?? {})` — the
|
|
18
|
+
* in-memory `LockfileObject` merges the on-disk `packages:` and
|
|
19
|
+
* `snapshots:` sections under a single `packages` field, so its keys
|
|
20
|
+
* include every snapshot key the install will hash.
|
|
21
|
+
*/
|
|
22
|
+
export declare function findRuntimeNodeVersion(snapshotKeys: Iterable<string>): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Read a single graph node's own `engines.runtime` Node pin from its
|
|
25
|
+
* `children` map. The resolver desugars `engines.runtime` declared on
|
|
26
|
+
* a dependency's manifest into `dependencies.node: 'runtime:<version>'`
|
|
27
|
+
* (see [`installing/deps-resolver/src/resolveDependencies.ts`](https://github.com/pnpm/pnpm/blob/29a42efc3b/installing/deps-resolver/src/resolveDependencies.ts)),
|
|
28
|
+
* which then becomes a `children.node` entry pointing at the
|
|
29
|
+
* `node@runtime:<version>[(peers)]` snapshot key.
|
|
30
|
+
*
|
|
31
|
+
* Returns the bare version (e.g. `"22.11.0"`) when this snapshot pins
|
|
32
|
+
* its own Node — or `undefined` when it doesn't and the caller should
|
|
33
|
+
* fall back to the install-wide pin / host probe.
|
|
34
|
+
*
|
|
35
|
+
* Per-snapshot resolution matters because the bin linker routes
|
|
36
|
+
* lifecycle-script spawns for a pinning package through *that
|
|
37
|
+
* package's* downloaded Node — anchoring the snapshot's GVS engine
|
|
38
|
+
* hash to an install-wide value would produce the wrong
|
|
39
|
+
* side-effects-cache key for cross-pinning installs.
|
|
40
|
+
*/
|
|
41
|
+
export declare function readSnapshotRuntimePin(children: Record<string, string> | undefined): string | undefined;
|
|
42
|
+
export type DepsGraph<T extends string> = Record<T, DepsGraphNode<T>>;
|
|
43
|
+
export interface DepsGraphNode<T extends string> {
|
|
44
|
+
children: {
|
|
45
|
+
[alias: string]: T;
|
|
46
|
+
};
|
|
47
|
+
pkgIdWithPatchHash?: PkgIdWithPatchHash;
|
|
48
|
+
resolution?: LockfileResolution;
|
|
49
|
+
fullPkgId?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface DepsStateCache {
|
|
52
|
+
[depPath: string]: string;
|
|
53
|
+
}
|
|
54
|
+
export declare function calcDepState<T extends string>(depsGraph: DepsGraph<T>, cache: DepsStateCache, depPath: string, opts: {
|
|
55
|
+
patchFileHash?: string;
|
|
56
|
+
includeDepGraphHash: boolean;
|
|
57
|
+
supportedArchitectures?: SupportedArchitectures;
|
|
58
|
+
/**
|
|
59
|
+
* Install-wide fallback `engines.runtime` / `devEngines.runtime`
|
|
60
|
+
* Node version (e.g. `"22.11.0"`). Used only when the snapshot at
|
|
61
|
+
* `depPath` doesn't itself pin a Node: per-snapshot pins take
|
|
62
|
+
* precedence so the side-effects-cache key reflects the actual
|
|
63
|
+
* script-runner Node the bin linker would spawn for the package
|
|
64
|
+
* (see {@link readSnapshotRuntimePin}). Typically computed once
|
|
65
|
+
* per install via {@link findRuntimeNodeVersion} over the
|
|
66
|
+
* lockfile's snapshot keys.
|
|
67
|
+
*/
|
|
68
|
+
nodeVersion?: string;
|
|
69
|
+
}): string;
|
|
70
|
+
export interface PkgMeta {
|
|
71
|
+
depPath: DepPath;
|
|
72
|
+
name: string;
|
|
73
|
+
version: string;
|
|
74
|
+
}
|
|
75
|
+
export type PkgMetaIterator<T extends PkgMeta> = IterableIterator<T>;
|
|
76
|
+
export interface HashedDepPath<T extends PkgMeta> {
|
|
77
|
+
pkgMeta: T;
|
|
78
|
+
hash: string;
|
|
79
|
+
}
|
|
80
|
+
export interface GraphNodeHashOptions {
|
|
81
|
+
allowBuild?: AllowBuild;
|
|
82
|
+
supportedArchitectures?: SupportedArchitectures;
|
|
83
|
+
/**
|
|
84
|
+
* Install-wide fallback `engines.runtime` / `devEngines.runtime`
|
|
85
|
+
* Node version. Used only for snapshots that don't pin their own
|
|
86
|
+
* Node; pinning snapshots get resolved per-snapshot via
|
|
87
|
+
* {@link readSnapshotRuntimePin} so the GVS engine hash matches
|
|
88
|
+
* the Node the bin linker would actually spawn for each package
|
|
89
|
+
* (see [`bins/linker/src/index.ts`](https://github.com/pnpm/pnpm/blob/29a42efc3b/bins/linker/src/index.ts)).
|
|
90
|
+
* Typically obtained via {@link findRuntimeNodeVersion} over the
|
|
91
|
+
* lockfile's snapshot keys. `undefined` falls back to
|
|
92
|
+
* {@link engineName}'s default (system `node --version`, with
|
|
93
|
+
* `process.version` as a last resort).
|
|
94
|
+
*/
|
|
95
|
+
nodeVersion?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Directory the lockfile lives in. Scopes the slots of local directory
|
|
98
|
+
* dependencies to the project that owns them — see
|
|
99
|
+
* {@link isLocalDirectoryResolution}. Omitting it leaves those packages on a
|
|
100
|
+
* shared slot, which is only safe for a lockfile known to have no directory
|
|
101
|
+
* dependencies.
|
|
102
|
+
*/
|
|
103
|
+
lockfileDir?: string;
|
|
104
|
+
}
|
|
105
|
+
export declare function iterateHashedGraphNodes<T extends PkgMeta>(graph: DepsGraph<DepPath>, pkgMetaIterator: PkgMetaIterator<T>, opts?: GraphNodeHashOptions): IterableIterator<HashedDepPath<T>>;
|
|
106
|
+
export declare function calcGraphNodeHash<T extends PkgMeta>({ graph, cache, builtDepPaths, buildRequiredCache, supportedArchitectures, nodeVersion, lockfileDir }: {
|
|
107
|
+
graph: DepsGraph<DepPath>;
|
|
108
|
+
cache: DepsStateCache;
|
|
109
|
+
builtDepPaths?: Set<DepPath>;
|
|
110
|
+
buildRequiredCache?: Record<string, boolean>;
|
|
111
|
+
supportedArchitectures?: SupportedArchitectures;
|
|
112
|
+
/** See {@link GraphNodeHashOptions.nodeVersion}. */
|
|
113
|
+
nodeVersion?: string;
|
|
114
|
+
/** See {@link GraphNodeHashOptions.lockfileDir}. */
|
|
115
|
+
lockfileDir?: string;
|
|
116
|
+
}, pkgMeta: T): string;
|
|
117
|
+
export declare function calcLeafGlobalVirtualStorePath(fullPkgId: string, name: string, version: string): string;
|
|
118
|
+
/**
|
|
119
|
+
* `subdepIds` maps each direct child's alias to its full pkg id
|
|
120
|
+
* (`${name}@${version}:${integrity}`). Each child contributes a leaf hash
|
|
121
|
+
* (no transitive walk) to the parent's hash, so the resulting path differs
|
|
122
|
+
* whenever the set or versions of children change. One level deep only —
|
|
123
|
+
* use {@link calcGraphNodeHash} when full graph traversal is needed.
|
|
124
|
+
*/
|
|
125
|
+
export declare function calcGlobalVirtualStorePathWithSubdeps(fullPkgId: string, name: string, version: string, subdepIds: Record<string, string>): string;
|
|
126
|
+
export interface PkgMetaAndSnapshot extends PkgMeta {
|
|
127
|
+
pkgSnapshot: PackageSnapshot;
|
|
128
|
+
pkgIdWithPatchHash: PkgIdWithPatchHash;
|
|
129
|
+
}
|
|
130
|
+
export declare function iteratePkgMeta(lockfile: LockfileObject, graph: DepsGraph<DepPath>): PkgMetaIterator<PkgMetaAndSnapshot>;
|
|
131
|
+
export declare function lockfileToDepGraph(lockfile: LockfileObject, supportedArchitectures?: SupportedArchitectures): DepsGraph<DepPath>;
|
package/lib/index.js
CHANGED
|
@@ -113,25 +113,12 @@ function calcDepGraphHash(depsGraph, cache, parents, depPath, supportedArchitect
|
|
|
113
113
|
});
|
|
114
114
|
return cache[depPath];
|
|
115
115
|
}
|
|
116
|
-
export function* iterateHashedGraphNodes(graph, pkgMetaIterator,
|
|
117
|
-
/**
|
|
118
|
-
* Install-wide fallback `engines.runtime` / `devEngines.runtime`
|
|
119
|
-
* Node version. Used only for snapshots that don't pin their own
|
|
120
|
-
* Node; pinning snapshots get resolved per-snapshot via
|
|
121
|
-
* {@link readSnapshotRuntimePin} so the GVS engine hash matches
|
|
122
|
-
* the Node the bin linker would actually spawn for each package
|
|
123
|
-
* (see [`bins/linker/src/index.ts`](https://github.com/pnpm/pnpm/blob/29a42efc3b/bins/linker/src/index.ts)).
|
|
124
|
-
* Typically obtained via {@link findRuntimeNodeVersion} over the
|
|
125
|
-
* lockfile's snapshot keys. `undefined` falls back to
|
|
126
|
-
* {@link engineName}'s default (system `node --version`, with
|
|
127
|
-
* `process.version` as a last resort).
|
|
128
|
-
*/
|
|
129
|
-
nodeVersion) {
|
|
116
|
+
export function* iterateHashedGraphNodes(graph, pkgMetaIterator, opts = {}) {
|
|
130
117
|
let builtDepPaths;
|
|
131
118
|
let entries;
|
|
132
|
-
if (allowBuild != null) {
|
|
119
|
+
if (opts.allowBuild != null) {
|
|
133
120
|
const pkgMetaList = Array.from(pkgMetaIterator);
|
|
134
|
-
builtDepPaths = computeBuiltDepPaths(pkgMetaList, allowBuild);
|
|
121
|
+
builtDepPaths = computeBuiltDepPaths(pkgMetaList, opts.allowBuild);
|
|
135
122
|
entries = pkgMetaList;
|
|
136
123
|
}
|
|
137
124
|
else {
|
|
@@ -142,8 +129,9 @@ nodeVersion) {
|
|
|
142
129
|
cache: {},
|
|
143
130
|
builtDepPaths,
|
|
144
131
|
buildRequiredCache: builtDepPaths !== undefined ? {} : undefined,
|
|
145
|
-
supportedArchitectures,
|
|
146
|
-
nodeVersion,
|
|
132
|
+
supportedArchitectures: opts.supportedArchitectures,
|
|
133
|
+
nodeVersion: opts.nodeVersion,
|
|
134
|
+
lockfileDir: opts.lockfileDir,
|
|
147
135
|
};
|
|
148
136
|
for (const pkgMeta of entries) {
|
|
149
137
|
yield {
|
|
@@ -152,7 +140,7 @@ nodeVersion) {
|
|
|
152
140
|
};
|
|
153
141
|
}
|
|
154
142
|
}
|
|
155
|
-
export function calcGraphNodeHash({ graph, cache, builtDepPaths, buildRequiredCache, supportedArchitectures, nodeVersion }, pkgMeta) {
|
|
143
|
+
export function calcGraphNodeHash({ graph, cache, builtDepPaths, buildRequiredCache, supportedArchitectures, nodeVersion, lockfileDir }, pkgMeta) {
|
|
156
144
|
const { name, version, depPath } = pkgMeta;
|
|
157
145
|
// When builtDepPaths is provided (derived from the allowBuilds config),
|
|
158
146
|
// we only include the engine name for packages that are allowed to build
|
|
@@ -169,8 +157,39 @@ export function calcGraphNodeHash({ graph, cache, builtDepPaths, buildRequiredCa
|
|
|
169
157
|
const ownPin = readSnapshotRuntimePin(graph[depPath]?.children);
|
|
170
158
|
const engine = includeEngine ? engineName(ownPin ?? nodeVersion) : null;
|
|
171
159
|
const deps = calcDepGraphHash(graph, cache, new Set(), depPath, supportedArchitectures);
|
|
172
|
-
const
|
|
173
|
-
|
|
160
|
+
const isLocalDirectory = isLocalDirectoryResolution(graph[depPath]?.resolution);
|
|
161
|
+
// Scoping the slot needs the project's identity; the segment only needs to
|
|
162
|
+
// know that the package is a local directory, so a caller that leaves
|
|
163
|
+
// `lockfileDir` out still gets a well-formed path.
|
|
164
|
+
const project = isLocalDirectory ? lockfileDir : undefined;
|
|
165
|
+
const hexDigest = project == null
|
|
166
|
+
? hashObjectWithoutSorting({ engine, deps }, { encoding: 'hex' })
|
|
167
|
+
: hashObjectWithoutSorting({ engine, deps, project }, { encoding: 'hex' });
|
|
168
|
+
return formatGlobalVirtualStorePath(name, isLocalDirectory ? LOCAL_DIRECTORY_SEGMENT : version, hexDigest);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Slot segment that stands in for the version of a package resolved from a
|
|
172
|
+
* local directory. pnpm omits the version from a directory snapshot, so the
|
|
173
|
+
* lockfile has none to offer — and the resolver, which does know it from the
|
|
174
|
+
* manifest, must agree with the lockfile or a re-install would relocate the
|
|
175
|
+
* package. The segment is decoration in a store listing; the digest that
|
|
176
|
+
* follows it is what identifies the slot.
|
|
177
|
+
*/
|
|
178
|
+
const LOCAL_DIRECTORY_SEGMENT = 'directory';
|
|
179
|
+
/**
|
|
180
|
+
* Whether the package came from a local directory — a `file:` directory
|
|
181
|
+
* dependency or an injected workspace package.
|
|
182
|
+
*
|
|
183
|
+
* Such a package needs a slot of its own per project. A directory resolution is
|
|
184
|
+
* the one resolution with no integrity: it is a path relative to the lockfile,
|
|
185
|
+
* so `file:dep` hashes identically in every project that happens to depend on a
|
|
186
|
+
* directory of that name. Sharing the slot would hand one project the files of
|
|
187
|
+
* whichever project installed first, and because the source directory is
|
|
188
|
+
* mutable pnpm re-imports it on every install — so the projects would go on
|
|
189
|
+
* overwriting each other's dependency.
|
|
190
|
+
*/
|
|
191
|
+
function isLocalDirectoryResolution(resolution) {
|
|
192
|
+
return resolution != null && 'type' in resolution && resolution.type === 'directory';
|
|
174
193
|
}
|
|
175
194
|
export function calcLeafGlobalVirtualStorePath(fullPkgId, name, version) {
|
|
176
195
|
const depsHash = hashObject({ id: fullPkgId, deps: {} });
|
|
@@ -244,6 +263,7 @@ export function lockfileToDepGraph(lockfile, supportedArchitectures) {
|
|
|
244
263
|
});
|
|
245
264
|
graph[depPath] = {
|
|
246
265
|
children,
|
|
266
|
+
resolution: pkgSnapshot.resolution,
|
|
247
267
|
fullPkgId: createFullPkgId(getPkgIdWithPatchHash(depPath), pkgSnapshot.resolution, supportedArchitectures),
|
|
248
268
|
};
|
|
249
269
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/deps.graph-hasher",
|
|
3
|
-
"version": "1100.2.
|
|
3
|
+
"version": "1100.2.13",
|
|
4
4
|
"description": "Calculates the state of a dependency",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -27,18 +27,18 @@
|
|
|
27
27
|
"!*.map"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@pnpm/crypto.object-hasher": "1100.0.
|
|
31
|
-
"@pnpm/deps.path": "1100.0.
|
|
32
|
-
"@pnpm/engine.runtime.system-version": "1100.0.
|
|
33
|
-
"@pnpm/lockfile.types": "1100.0.
|
|
34
|
-
"@pnpm/lockfile.utils": "1100.1.
|
|
35
|
-
"@pnpm/resolving.resolver-base": "1100.5.
|
|
36
|
-
"@pnpm/types": "1101.
|
|
30
|
+
"@pnpm/crypto.object-hasher": "1100.0.1",
|
|
31
|
+
"@pnpm/deps.path": "1100.0.12",
|
|
32
|
+
"@pnpm/engine.runtime.system-version": "1100.0.7",
|
|
33
|
+
"@pnpm/lockfile.types": "1100.0.17",
|
|
34
|
+
"@pnpm/lockfile.utils": "1100.1.6",
|
|
35
|
+
"@pnpm/resolving.resolver-base": "1100.5.5",
|
|
36
|
+
"@pnpm/types": "1101.7.0",
|
|
37
37
|
"detect-libc": "^2.1.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@jest/globals": "30.4.1",
|
|
41
|
-
"@pnpm/deps.graph-hasher": "1100.2.
|
|
41
|
+
"@pnpm/deps.graph-hasher": "1100.2.13"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=22.13"
|