zyrk 0.5.4 → 0.5.5
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/README.md +4 -1
- package/VERSION +1 -1
- package/dist/install/import-npm-workspace.d.ts.map +1 -1
- package/dist/install/import-npm-workspace.js +1 -3
- package/dist/install/import-npm.d.ts.map +1 -1
- package/dist/install/import-npm.js +10 -28
- package/dist/install/lock.d.ts.map +1 -1
- package/dist/install/lock.js +8 -6
- package/dist/install/platform.d.ts +5 -0
- package/dist/install/platform.d.ts.map +1 -0
- package/dist/install/platform.js +97 -0
- package/dist/install/run.d.ts +3 -0
- package/dist/install/run.d.ts.map +1 -1
- package/dist/install/run.js +19 -48
- package/dist/install/workspace-graph.d.ts +1 -0
- package/dist/install/workspace-graph.d.ts.map +1 -1
- package/dist/install/workspace-graph.js +12 -3
- package/dist/install/workspace-install.d.ts.map +1 -1
- package/dist/install/workspace-install.js +5 -5
- package/dist/install/workspace-lock.d.ts +1 -1
- package/dist/install/workspace-lock.d.ts.map +1 -1
- package/dist/install/workspace-lock.js +11 -1
- package/dist/lockfile/fingerprints.js +0 -1
- package/dist/lockfile/read.d.ts +1 -1
- package/dist/lockfile/read.d.ts.map +1 -1
- package/dist/lockfile/read.js +11 -1
- package/dist/lockfile/types.d.ts +1 -0
- package/dist/lockfile/types.d.ts.map +1 -1
- package/dist/lockfile/types.js +1 -0
- package/dist/lockfile/write.d.ts.map +1 -1
- package/dist/lockfile/write.js +1 -0
- package/dist/resolve/resolver.d.ts +1 -21
- package/dist/resolve/resolver.d.ts.map +1 -1
- package/dist/resolve/resolver.js +13 -1
- package/dist/util/engines.d.ts +2 -0
- package/dist/util/engines.d.ts.map +1 -0
- package/dist/util/engines.js +23 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -122,7 +122,10 @@ registry; private names never fall back to a public endpoint. Disabled TLS
|
|
|
122
122
|
verification is rejected before lookup. Git sources and non-workspace local sources remain unsupported;
|
|
123
123
|
they fail explicitly. Optional dependencies incompatible with the selected platform
|
|
124
124
|
are omitted; missing packages, integrity failures, and other optional failures
|
|
125
|
-
remain errors.
|
|
125
|
+
remain errors. Locks retain exact platform-qualified optional variants; each machine
|
|
126
|
+
selects its compatible local closure without rewriting the lock or recording store
|
|
127
|
+
paths. Older platform-pruned locks need an intentional non-frozen refresh; incomplete
|
|
128
|
+
npm locks must be freshly resolved before portable adoption. macOS, Windows, and
|
|
126
129
|
broad framework compatibility have not passed their release gates.
|
|
127
130
|
|
|
128
131
|
### Workspaces
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v0.5.
|
|
1
|
+
v0.5.5
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-npm-workspace.d.ts","sourceRoot":"","sources":["../../src/install/import-npm-workspace.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"import-npm-workspace.d.ts","sourceRoot":"","sources":["../../src/install/import-npm-workspace.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAOvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,sBAAsB,CAAC;AA6V9B,oEAAoE;AACpE,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAC1C,cAAc,CAWhB"}
|
|
@@ -8,7 +8,6 @@ import { canonicalJson } from "../util/json.js";
|
|
|
8
8
|
import { importNpmLock } from "./import-npm.js";
|
|
9
9
|
import { lockMismatch, cleanUrl } from "./lock.js";
|
|
10
10
|
import { ZyrkError } from "../errors.js";
|
|
11
|
-
import { assertWorkspacePlatform } from "./workspace-graph.js";
|
|
12
11
|
function importNpmWorkspaceLockPass(doc, project, origin, overrideState) {
|
|
13
12
|
if (!doc ||
|
|
14
13
|
typeof doc !== "object" ||
|
|
@@ -173,7 +172,6 @@ function importNpmWorkspaceLockPass(doc, project, origin, overrideState) {
|
|
|
173
172
|
peers: {},
|
|
174
173
|
optionalPeers: [],
|
|
175
174
|
};
|
|
176
|
-
assertWorkspacePlatform({ nodes: [node], importers: {}, omissions: [] });
|
|
177
175
|
graph.nodes.push(node);
|
|
178
176
|
locations.set(contextKey, node);
|
|
179
177
|
contexts.set(node.key, selectedOverride.context);
|
|
@@ -230,7 +228,7 @@ function importNpmWorkspaceLockPass(doc, project, origin, overrideState) {
|
|
|
230
228
|
continue;
|
|
231
229
|
}
|
|
232
230
|
if (requirement.kind === "optional")
|
|
233
|
-
|
|
231
|
+
throw lockMismatch("npm workspace lock lacks an exact optional selection; restore a complete npm lock or intentionally resolve fresh without the pruned lock");
|
|
234
232
|
throw lockMismatch("npm workspace lock is missing a required selection");
|
|
235
233
|
}
|
|
236
234
|
let target;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-npm.d.ts","sourceRoot":"","sources":["../../src/install/import-npm.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import-npm.d.ts","sourceRoot":"","sources":["../../src/install/import-npm.ts"],"names":[],"mappings":"AACA,qFAAqF;AACrF,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,wBAAwB,CAAC;AAKhC,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,EAC3C,SAAS,GAAE,cAAwC,GAClD,cAAc,CAkLhB"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { normalizeEngineConstraints } from "../util/engines.js";
|
|
1
2
|
/** Adopt npm v2/v3 exact selections without asking the registry to pick versions. */
|
|
2
3
|
import { createRootOverrides, } from "../resolve/overrides.js";
|
|
3
4
|
import { validateLockDoc } from "../lockfile/read.js";
|
|
4
5
|
import { canonicalStrongSri } from "../util/integrity.js";
|
|
5
|
-
import { valid,
|
|
6
|
+
import { valid, satisfies } from "semver";
|
|
6
7
|
import { parseRequirement } from "../resolve/spec.js";
|
|
7
8
|
import { sourceIdOf, sha512Hex } from "../util/hash.js";
|
|
8
9
|
import { cleanUrl, lockMismatch, packageName } from "./lock.js";
|
|
@@ -75,30 +76,10 @@ export function importNpmLock(doc, requirements, origin, overrides = createRootO
|
|
|
75
76
|
edges: [],
|
|
76
77
|
peerBindings: [],
|
|
77
78
|
};
|
|
78
|
-
if (entry.engines !== undefined)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
for (const value of entry.engines) {
|
|
83
|
-
const match = typeof value === "string"
|
|
84
|
-
? /^([a-z][a-z0-9._-]*)\s+(.+)$/.exec(value)
|
|
85
|
-
: null;
|
|
86
|
-
if (!match ||
|
|
87
|
-
Object.hasOwn(engines, match[1]) ||
|
|
88
|
-
validRange(match[2]) === null)
|
|
89
|
-
throw lockMismatch("invalid npm engine constraint");
|
|
90
|
-
engines[match[1]] = match[2];
|
|
91
|
-
}
|
|
92
|
-
node.engines = engines;
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
if (typeof entry.engines !== "object" ||
|
|
96
|
-
entry.engines === null ||
|
|
97
|
-
Object.values(entry.engines).some((value) => typeof value !== "string"))
|
|
98
|
-
throw lockMismatch("invalid npm engine constraint");
|
|
99
|
-
node.engines = entry.engines;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
79
|
+
if (entry.engines !== undefined)
|
|
80
|
+
node.engines = normalizeEngineConstraints(entry.engines, () => {
|
|
81
|
+
throw lockMismatch("invalid npm engine constraint");
|
|
82
|
+
});
|
|
102
83
|
if (typeof entry.bin === "object" &&
|
|
103
84
|
entry.bin !== null &&
|
|
104
85
|
!Array.isArray(entry.bin)) {
|
|
@@ -141,11 +122,12 @@ export function importNpmLock(doc, requirements, origin, overrides = createRootO
|
|
|
141
122
|
const meta = entry.peerDependenciesMeta;
|
|
142
123
|
const optionalPeer = requirement.kind === "peer" && meta?.[dep]?.optional === true;
|
|
143
124
|
if (!targetLocation) {
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
node.peerBindings.push({ name: dep, target: null, optional: true });
|
|
125
|
+
if (optionalPeer) {
|
|
126
|
+
node.peerBindings.push({ name: dep, target: null, optional: true });
|
|
147
127
|
continue;
|
|
148
128
|
}
|
|
129
|
+
if (requirement.kind === "optional")
|
|
130
|
+
throw lockMismatch("npm lock lacks an exact optional selection; restore a complete npm lock or intentionally resolve fresh without the pruned lock");
|
|
149
131
|
throw lockMismatch("npm lock is missing a required dependency");
|
|
150
132
|
}
|
|
151
133
|
const target = load(targetLocation, dep, requirement.spec, selected.context);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/install/lock.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAKvD,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,wBAAwB,CAAC;AAKhC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD;AACD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAa/C;AACD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CASnD;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/install/lock.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAKvD,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,wBAAwB,CAAC;AAKhC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD;AACD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAa/C;AACD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CASnD;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,cAAc,CA+M3D;AAYD,kFAAkF;AAClF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAK,GAAG,IAAI,CAM3E"}
|
package/dist/install/lock.js
CHANGED
|
@@ -39,6 +39,7 @@ export function lockedGraph(doc) {
|
|
|
39
39
|
Object.keys(ext).some((key) => ![
|
|
40
40
|
"version",
|
|
41
41
|
"resolver",
|
|
42
|
+
"platformPolicy",
|
|
42
43
|
"contextCanonicalization",
|
|
43
44
|
"manifest",
|
|
44
45
|
"scripts",
|
|
@@ -48,6 +49,7 @@ export function lockedGraph(doc) {
|
|
|
48
49
|
].includes(key)) ||
|
|
49
50
|
![ext.manifest, ext.scripts, ext.config].every((value) => typeof value === "string" && /^sha512-[A-Za-z0-9+/]{86}==$/.test(value)) ||
|
|
50
51
|
ext.resolver !== ZYRK_RESOLVER_POLICY ||
|
|
52
|
+
ext.platformPolicy !== "portable-optional/1" ||
|
|
51
53
|
ext.contextCanonicalization !== CONTEXT_CANONICALIZATION_VERSION ||
|
|
52
54
|
!record(ext.nodes) ||
|
|
53
55
|
!record(ext.roots) ||
|
|
@@ -180,7 +182,7 @@ export function lockedGraph(doc) {
|
|
|
180
182
|
sourceId: raw.source,
|
|
181
183
|
tarballUrl: raw.tarball,
|
|
182
184
|
bin,
|
|
183
|
-
engines,
|
|
185
|
+
...(raw.engines === undefined ? {} : { engines }),
|
|
184
186
|
platform,
|
|
185
187
|
edges,
|
|
186
188
|
peerBindings: peers,
|
|
@@ -204,11 +206,11 @@ export function lockedGraph(doc) {
|
|
|
204
206
|
// npm publishes this canonical GitHub sponsorship link in funding metadata.
|
|
205
207
|
// Keep source/archive URL validation query-free, and allow no other query here.
|
|
206
208
|
function githubFundingUrl(value) {
|
|
207
|
-
return /^https:\/\/github\.com\/[A-Za-z0-9_-]+\/[A-Za-z0-9_.-]+\?sponsor=1$/.test(value);
|
|
209
|
+
return (/^https:\/\/github\.com\/[A-Za-z0-9_-]+\/[A-Za-z0-9_.-]+\?sponsor=1$/.test(value) && new URL(value).href === value);
|
|
208
210
|
}
|
|
209
211
|
/** Preserved metadata is subject to the same portability boundary as new data. */
|
|
210
212
|
export function assertPortableLockMetadata(value, field = "") {
|
|
211
|
-
visitPortableLockMetadata(value, field, field === "funding" ? "
|
|
213
|
+
visitPortableLockMetadata(value, field, field === "funding" ? "funding" : undefined);
|
|
212
214
|
}
|
|
213
215
|
function visitPortableLockMetadata(value, field, funding) {
|
|
214
216
|
if (typeof value === "string") {
|
|
@@ -222,7 +224,7 @@ function visitPortableLockMetadata(value, field, funding) {
|
|
|
222
224
|
}
|
|
223
225
|
if (Array.isArray(value)) {
|
|
224
226
|
for (const item of value)
|
|
225
|
-
visitPortableLockMetadata(item, field, funding === "
|
|
227
|
+
visitPortableLockMetadata(item, field, funding === "funding" ? "entry" : undefined);
|
|
226
228
|
return;
|
|
227
229
|
}
|
|
228
230
|
if (value && typeof value === "object")
|
|
@@ -245,8 +247,8 @@ function visitPortableLockMetadata(value, field, funding) {
|
|
|
245
247
|
].includes(field))
|
|
246
248
|
throw lockMismatch("portable metadata contains a credential field");
|
|
247
249
|
visitPortableLockMetadata(item, key, key === "funding"
|
|
248
|
-
? "
|
|
249
|
-
: funding === "entry" && key === "url"
|
|
250
|
+
? "funding"
|
|
251
|
+
: (funding === "funding" || funding === "entry") && key === "url"
|
|
250
252
|
? "url"
|
|
251
253
|
: undefined);
|
|
252
254
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type RuntimePlatform, type FinalizedGraph } from "../resolve/resolver.ts";
|
|
2
|
+
import type { WorkspaceGraph } from "./workspace-graph.ts";
|
|
3
|
+
export declare function selectPlatformGraph(graph: FinalizedGraph, optionalRoots: ReadonlySet<string>, platform?: RuntimePlatform): FinalizedGraph;
|
|
4
|
+
export declare function selectWorkspacePlatform(graph: WorkspaceGraph, platform?: RuntimePlatform): WorkspaceGraph;
|
|
5
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/install/platform.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAuG3D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,QAAQ,kBAAoB,GAC3B,cAAc,CAqBhB;AACD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,cAAc,EACrB,QAAQ,kBAAoB,GAC3B,cAAc,CAsBhB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** Portable selections stay in the lock; only a compatible closure is realized. */
|
|
2
|
+
import { satisfies } from "semver";
|
|
3
|
+
import { ZyrkError } from "../errors.js";
|
|
4
|
+
import { currentPlatform, } from "../resolve/resolver.js";
|
|
5
|
+
import { lockMismatch } from "./lock.js";
|
|
6
|
+
function compatible(node, platform) {
|
|
7
|
+
return ([
|
|
8
|
+
[node.platform?.os, platform.os],
|
|
9
|
+
[node.platform?.cpu, platform.cpu],
|
|
10
|
+
[node.platform?.libc, platform.libc],
|
|
11
|
+
].every(([list, actual]) => !list?.length ||
|
|
12
|
+
(!!actual &&
|
|
13
|
+
!list.includes(`!${actual}`) &&
|
|
14
|
+
(!list.some((v) => !v.startsWith("!")) ||
|
|
15
|
+
list.includes(actual) ||
|
|
16
|
+
list.includes("any")))) &&
|
|
17
|
+
(!node.engines?.node || satisfies(process.versions.node, node.engines.node)));
|
|
18
|
+
}
|
|
19
|
+
function optional(node, edge) {
|
|
20
|
+
return (edge.kind === "optional" ||
|
|
21
|
+
(edge.kind === "peer" &&
|
|
22
|
+
(node.optionalPeers?.includes(edge.name) === true ||
|
|
23
|
+
node.peerBindings?.some((p) => p.name === edge.name && p.optional) ===
|
|
24
|
+
true)));
|
|
25
|
+
}
|
|
26
|
+
function select(nodes, roots, platform) {
|
|
27
|
+
const byKey = new Map(nodes.map((n) => [n.key, n]));
|
|
28
|
+
const viable = new Set(nodes.filter((n) => compatible(n, platform)).map((n) => n.key));
|
|
29
|
+
// Propagate required incompatibility back to the nearest optional boundary.
|
|
30
|
+
let changed = true;
|
|
31
|
+
while (changed) {
|
|
32
|
+
changed = false;
|
|
33
|
+
for (const node of nodes)
|
|
34
|
+
if (viable.has(node.key) &&
|
|
35
|
+
node.edges.some((e) => !optional(node, e) && !viable.has(e.target))) {
|
|
36
|
+
viable.delete(node.key);
|
|
37
|
+
changed = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const active = new Set();
|
|
41
|
+
const omissions = [];
|
|
42
|
+
const visit = (name, target, isOptional, parent) => {
|
|
43
|
+
if (!byKey.has(target))
|
|
44
|
+
throw lockMismatch("missing platform selection");
|
|
45
|
+
if (!viable.has(target)) {
|
|
46
|
+
if (isOptional) {
|
|
47
|
+
omissions.push({ name, parent, reason: "platform" });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
throw new ZyrkError("ZYRK_PLATFORM_UNSUPPORTED", `Cannot install required dependency ${name} on the selected platform or Node.js runtime.`, {
|
|
51
|
+
remedy: "Select a compatible package version, platform, or Node.js runtime.",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (active.has(target))
|
|
55
|
+
return;
|
|
56
|
+
active.add(target);
|
|
57
|
+
const node = byKey.get(target);
|
|
58
|
+
for (const edge of node.edges)
|
|
59
|
+
visit(edge.name, edge.target, optional(node, edge), node.key);
|
|
60
|
+
};
|
|
61
|
+
for (const root of roots)
|
|
62
|
+
visit(root.name, root.target, root.optional === true, "<root>");
|
|
63
|
+
return { active, viable, omissions };
|
|
64
|
+
}
|
|
65
|
+
export function selectPlatformGraph(graph, optionalRoots, platform = currentPlatform()) {
|
|
66
|
+
const { active, viable, omissions } = select(graph.nodes, graph.roots.map((r) => ({ ...r, optional: optionalRoots.has(r.name) })), platform);
|
|
67
|
+
return {
|
|
68
|
+
roots: graph.roots.filter((r) => active.has(r.target)),
|
|
69
|
+
omissions,
|
|
70
|
+
nodes: graph.nodes
|
|
71
|
+
.filter((n) => active.has(n.key))
|
|
72
|
+
.map((n) => ({
|
|
73
|
+
...n,
|
|
74
|
+
edges: n.edges.filter((e) => viable.has(e.target)),
|
|
75
|
+
peerBindings: n.peerBindings.map((p) => p.target !== null && !viable.has(p.target)
|
|
76
|
+
? { ...p, target: null }
|
|
77
|
+
: p),
|
|
78
|
+
})),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export function selectWorkspacePlatform(graph, platform = currentPlatform()) {
|
|
82
|
+
const { active, viable, omissions } = select(graph.nodes, Object.entries(graph.importers).map(([name, target]) => ({ name, target })), platform);
|
|
83
|
+
return {
|
|
84
|
+
...graph,
|
|
85
|
+
omissions,
|
|
86
|
+
nodes: graph.nodes
|
|
87
|
+
.filter((n) => active.has(n.key))
|
|
88
|
+
.map((n) => ({
|
|
89
|
+
...n,
|
|
90
|
+
edges: n.edges.filter((e) => viable.has(e.target)),
|
|
91
|
+
peers: Object.fromEntries(Object.entries(n.peers).map(([name, target]) => [
|
|
92
|
+
name,
|
|
93
|
+
target !== null && !viable.has(target) ? null : target,
|
|
94
|
+
])),
|
|
95
|
+
})),
|
|
96
|
+
};
|
|
97
|
+
}
|
package/dist/install/run.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RuntimePlatform } from "../resolve/resolver.ts";
|
|
1
2
|
import { type BuildCandidate } from "./private.ts";
|
|
2
3
|
import { RegistryClient } from "../fetch/registry.ts";
|
|
3
4
|
import type { ResolverLimits } from "../resolve/resolver.ts";
|
|
@@ -11,6 +12,8 @@ export type InstallProgress = {
|
|
|
11
12
|
export type InstallOptions = {
|
|
12
13
|
onProgress?: (event: InstallProgress) => void;
|
|
13
14
|
projectDir: string;
|
|
15
|
+
/** Target selection only; Store.open still checks the actual host. */
|
|
16
|
+
platform?: RuntimePlatform;
|
|
14
17
|
store: Store;
|
|
15
18
|
registry: RegistryClient;
|
|
16
19
|
specs?: readonly string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/install/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/install/run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9D,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AAYtB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AA+B3C,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EACD,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,SAAS,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;IACF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC1C,WAAW,CAAC,EAAE;QACZ,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,CAAC;AACF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EACL,OAAO,GACP,uBAAuB,GACvB,eAAe,GACf,SAAS,GACT,cAAc,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AA4GF,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAoyBxB"}
|
package/dist/install/run.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { selectPlatformGraph } from "./platform.js";
|
|
1
2
|
import { findWorkspaceRoot } from "./workspaces.js";
|
|
2
3
|
import { assertSupportedSourcePayload } from "./source-policy.js";
|
|
3
4
|
import { prepareRepair } from "./repair.js";
|
|
@@ -23,7 +24,7 @@ import { Transaction } from "../store/txn.js";
|
|
|
23
24
|
import { readSourceManifest, sourceManifestPath } from "../store/manifests.js";
|
|
24
25
|
import { realizeGraph, selectRealizationDirs } from "../store/realize.js";
|
|
25
26
|
import { createGraphDoc, graphHash } from "../store/graph.js";
|
|
26
|
-
import { resolveRequirements,
|
|
27
|
+
import { resolveRequirements, } from "../resolve/resolver.js";
|
|
27
28
|
import { parseRequirement } from "../resolve/spec.js";
|
|
28
29
|
import { readLockfile, assertFrozenCompatible } from "../lockfile/read.js";
|
|
29
30
|
import { writeLockfile } from "../lockfile/write.js";
|
|
@@ -215,7 +216,6 @@ export async function installProject(options) {
|
|
|
215
216
|
registry: options.registry.origin,
|
|
216
217
|
registries: options.registry.scopedRegistries,
|
|
217
218
|
linker: "shared",
|
|
218
|
-
platform: currentPlatform(),
|
|
219
219
|
...(object(manifest.zyrk) &&
|
|
220
220
|
Array.isArray(manifest.zyrk.mutablePackages)
|
|
221
221
|
? { mutablePackages: manifest.zyrk.mutablePackages }
|
|
@@ -224,7 +224,7 @@ export async function installProject(options) {
|
|
|
224
224
|
}),
|
|
225
225
|
});
|
|
226
226
|
const lockPath = path.join(project, "package-lock.json");
|
|
227
|
-
const existing = (await readLockfile(lockPath))?.doc;
|
|
227
|
+
const existing = (await readLockfile(lockPath, !options.frozen && !options.offline))?.doc;
|
|
228
228
|
let resolved;
|
|
229
229
|
if (options.importNpm && (!existing || existing.zyrk))
|
|
230
230
|
throw lockMismatch("import --from npm requires an existing npm-only lockfile");
|
|
@@ -240,6 +240,8 @@ export async function installProject(options) {
|
|
|
240
240
|
let compatible = true;
|
|
241
241
|
try {
|
|
242
242
|
assertFrozenCompatible(existing, fingerprints());
|
|
243
|
+
if (existing.zyrk?.platformPolicy !== "portable-optional/1")
|
|
244
|
+
throw lockMismatch("lock predates portable platform selections; refresh intentionally");
|
|
243
245
|
}
|
|
244
246
|
catch (cause) {
|
|
245
247
|
if (options.frozen)
|
|
@@ -254,12 +256,15 @@ export async function installProject(options) {
|
|
|
254
256
|
throw lockMismatch("missing compatible lockfile");
|
|
255
257
|
if (options.offline)
|
|
256
258
|
throw error("ZYRK_OFFLINE_MISSING", "Offline installation requires an existing compatible zyrk lockfile.");
|
|
257
|
-
const prior = existing?.zyrk
|
|
259
|
+
const prior = existing?.zyrk?.platformPolicy === "portable-optional/1"
|
|
260
|
+
? lockedGraph(existing)
|
|
261
|
+
: undefined;
|
|
258
262
|
const fresh = new Set(specs.map((spec) => npa(spec).name));
|
|
259
263
|
options.onProgress?.({ phase: "resolving" });
|
|
260
264
|
resolved = await resolveRequirements({
|
|
261
265
|
overrides,
|
|
262
266
|
limits: options.resolveBudget,
|
|
267
|
+
preservePlatformVariants: true,
|
|
263
268
|
provider: {
|
|
264
269
|
origin: options.registry.origin,
|
|
265
270
|
originFor: (name) => options.registry.originFor(name),
|
|
@@ -366,49 +371,15 @@ export async function installProject(options) {
|
|
|
366
371
|
node.origin !== options.registry.originFor(node.name))
|
|
367
372
|
throw error("ZYRK_POLICY_DENIED", "Selected source has an unsupported or credential-bearing registry origin or archive URL.");
|
|
368
373
|
}
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
const n = byKey.get(key);
|
|
379
|
-
if (!n)
|
|
380
|
-
throw lockMismatch("missing selected node");
|
|
381
|
-
for (const e of n.edges)
|
|
382
|
-
visit(e.target);
|
|
383
|
-
};
|
|
384
|
-
for (const r of selectedRoots)
|
|
385
|
-
visit(r.target);
|
|
386
|
-
const activeNodes = resolved.nodes.filter((n) => activeKeys.has(n.key));
|
|
387
|
-
for (const n of activeNodes) {
|
|
388
|
-
for (const [list, current] of [
|
|
389
|
-
[n.platform.os, process.platform],
|
|
390
|
-
[n.platform.cpu, process.arch],
|
|
391
|
-
]) {
|
|
392
|
-
if (list &&
|
|
393
|
-
(list.includes(`!${current}`) ||
|
|
394
|
-
(list.some((x) => !x.startsWith("!")) &&
|
|
395
|
-
!list.includes(current) &&
|
|
396
|
-
!list.includes("any"))))
|
|
397
|
-
throw new ZyrkError("ZYRK_PLATFORM_UNSUPPORTED", `Cannot install ${n.name}@${n.version} on the selected platform.`, { remedy: "Select a package version supporting this OS and CPU." });
|
|
398
|
-
}
|
|
399
|
-
if (n.platform.libc?.length) {
|
|
400
|
-
const libc = currentPlatform().libc;
|
|
401
|
-
if (!libc ||
|
|
402
|
-
n.platform.libc.includes(`!${libc}`) ||
|
|
403
|
-
(n.platform.libc.some((v) => !v.startsWith("!")) &&
|
|
404
|
-
!n.platform.libc.includes(libc)))
|
|
405
|
-
throw new ZyrkError("ZYRK_PLATFORM_UNSUPPORTED", `Cannot install ${n.name}@${n.version} with this libc.`, { remedy: "Select a compatible platform or package version." });
|
|
406
|
-
}
|
|
407
|
-
if (n.engines?.node && !satisfies(process.versions.node, n.engines.node))
|
|
408
|
-
throw new ZyrkError("ZYRK_PLATFORM_UNSUPPORTED", `Cannot install ${n.name}@${n.version} on this Node.js version.`, {
|
|
409
|
-
remedy: "Use a Node.js version satisfying the package's engines.node range.",
|
|
410
|
-
});
|
|
411
|
-
}
|
|
374
|
+
const activeResolution = selectPlatformGraph({
|
|
375
|
+
...resolved,
|
|
376
|
+
roots: resolved.roots.filter((r) => !options.omitDev ||
|
|
377
|
+
manifest.dependencies?.[r.name] !== undefined ||
|
|
378
|
+
manifest.optionalDependencies?.[r.name] !== undefined),
|
|
379
|
+
}, new Set(Object.keys(manifest.optionalDependencies ?? {})), options.platform);
|
|
380
|
+
const selectedRoots = activeResolution.roots;
|
|
381
|
+
const activeNodes = activeResolution.nodes;
|
|
382
|
+
const byKey = new Map(activeNodes.map((n) => [n.key, n]));
|
|
412
383
|
barrier = await acquireLock(path.join(options.store.paths.locksDir, "liveness.lock"), { name: "store liveness" });
|
|
413
384
|
txn = await Transaction.begin(options.store, "install");
|
|
414
385
|
const candidateLock = path.join(txn.dir, "package-lock.json");
|
|
@@ -444,7 +415,7 @@ export async function installProject(options) {
|
|
|
444
415
|
name: "package.json",
|
|
445
416
|
contents: `${JSON.stringify(manifest, null, 2)}\n`,
|
|
446
417
|
});
|
|
447
|
-
const warnings = (
|
|
418
|
+
const warnings = (activeResolution.omissions ?? []).map((item) => `${item.name}: omitted optional dependency incompatible with the selected platform.`);
|
|
448
419
|
for (const stage of ["preinstall", "install", "postinstall"])
|
|
449
420
|
if (manifest.scripts?.[stage])
|
|
450
421
|
warnings.push(`Root ${stage} hook was not run; invoke it explicitly after installation.`);
|
|
@@ -50,6 +50,7 @@ declare function resolveWorkspaceGraphPass(project: WorkspaceProject, provider:
|
|
|
50
50
|
previous?: WorkspaceGraph;
|
|
51
51
|
fresh?: ReadonlySet<string>;
|
|
52
52
|
platform?: RuntimePlatform;
|
|
53
|
+
preservePlatformVariants?: boolean;
|
|
53
54
|
maxNodes?: number;
|
|
54
55
|
maxDepth?: number;
|
|
55
56
|
deadlineMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-graph.d.ts","sourceRoot":"","sources":["../../src/install/workspace-graph.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workspace-graph.d.ts","sourceRoot":"","sources":["../../src/install/workspace-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeEngineConstraints } from "../util/engines.js";
|
|
1
2
|
/** Multi-importer resolution. Live nodes are never registry sources or CAS inputs. */
|
|
2
3
|
import { maxSatisfying, satisfies, valid } from "semver";
|
|
3
4
|
import { expectedIntegrityFromDist, } from "../fetch/registry.js";
|
|
@@ -67,6 +68,11 @@ async function resolveWorkspaceGraphPass(project, provider, options = {}, overri
|
|
|
67
68
|
]).finally(() => clearTimeout(timer));
|
|
68
69
|
};
|
|
69
70
|
const compatible = (entry) => {
|
|
71
|
+
const engines = entry.engines === undefined
|
|
72
|
+
? undefined
|
|
73
|
+
: normalizeEngineConstraints(entry.engines, () => fail("invalid npm engine constraint"));
|
|
74
|
+
if (options.preservePlatformVariants)
|
|
75
|
+
return;
|
|
70
76
|
for (const [list, actual] of [
|
|
71
77
|
[entry.os, platform.os],
|
|
72
78
|
[entry.cpu, platform.cpu],
|
|
@@ -79,8 +85,7 @@ async function resolveWorkspaceGraphPass(project, provider, options = {}, overri
|
|
|
79
85
|
!list.includes(actual) &&
|
|
80
86
|
!list.includes("any"))))
|
|
81
87
|
throw new PlatformMismatch();
|
|
82
|
-
if (
|
|
83
|
-
!satisfies(process.versions.node, entry.engines.node))
|
|
88
|
+
if (engines?.node && !satisfies(process.versions.node, engines.node))
|
|
84
89
|
throw new PlatformMismatch();
|
|
85
90
|
};
|
|
86
91
|
const build = async (parent, name, spec, kind, ancestry, explicitLocal) => {
|
|
@@ -189,7 +194,11 @@ async function resolveWorkspaceGraphPass(project, provider, options = {}, overri
|
|
|
189
194
|
...(entry.cpu ? { cpu: entry.cpu } : {}),
|
|
190
195
|
...(entry.libc ? { libc: entry.libc } : {}),
|
|
191
196
|
},
|
|
192
|
-
...(entry.engines
|
|
197
|
+
...(entry.engines === undefined
|
|
198
|
+
? {}
|
|
199
|
+
: {
|
|
200
|
+
engines: normalizeEngineConstraints(entry.engines, () => fail("invalid npm engine constraint")),
|
|
201
|
+
}),
|
|
193
202
|
edges: [],
|
|
194
203
|
peers: {},
|
|
195
204
|
optionalPeers: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-install.d.ts","sourceRoot":"","sources":["../../src/install/workspace-install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workspace-install.d.ts","sourceRoot":"","sources":["../../src/install/workspace-install.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAuH9D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAkrBxB"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { selectWorkspacePlatform } from "./platform.js";
|
|
1
2
|
/** Multi-importer live workspace installation with one publication journal. */
|
|
2
3
|
import { chmod, copyFile, lstat, mkdir, readFile, realpath, rename, rm, symlink, } from "node:fs/promises";
|
|
3
4
|
import { constants } from "node:fs";
|
|
4
5
|
import * as path from "node:path";
|
|
5
6
|
import { discoverWorkspaces, findWorkspaceRoot, assertNoLiveSourceBuilds, } from "./workspaces.js";
|
|
6
|
-
import { resolveWorkspaceGraph, workspaceRegistryOccurrences, workspaceContextId,
|
|
7
|
+
import { resolveWorkspaceGraph, workspaceRegistryOccurrences, workspaceContextId, } from "./workspace-graph.js";
|
|
7
8
|
import { workspaceOverrides } from "./workspace-overrides.js";
|
|
8
9
|
import { importNpmWorkspaceLock } from "./import-npm-workspace.js";
|
|
9
10
|
import { readWorkspaceLock, workspaceLockDoc } from "./workspace-lock.js";
|
|
@@ -24,7 +25,6 @@ import { randomId } from "../util/ids.js";
|
|
|
24
25
|
import { sha512Hex } from "../util/hash.js";
|
|
25
26
|
import { canonicalJson } from "../util/json.js";
|
|
26
27
|
import { configFingerprint, scriptPolicyFingerprint, } from "../lockfile/fingerprints.js";
|
|
27
|
-
import { currentPlatform } from "../resolve/resolver.js";
|
|
28
28
|
import { installProjection, installMetadata } from "../project/projection.js";
|
|
29
29
|
import { prepareWorkspaceMutation } from "./workspace-mutation.js";
|
|
30
30
|
import { loadProjectPatches, applyProjectPatches } from "../commands/patch.js";
|
|
@@ -135,7 +135,6 @@ export async function installWorkspaceProject(options) {
|
|
|
135
135
|
registry: options.registry.origin,
|
|
136
136
|
registries: options.registry.scopedRegistries,
|
|
137
137
|
linker: "shared",
|
|
138
|
-
platform: currentPlatform(),
|
|
139
138
|
...(mutable !== undefined
|
|
140
139
|
? { mutablePackages: mutable }
|
|
141
140
|
: {}),
|
|
@@ -147,7 +146,7 @@ export async function installWorkspaceProject(options) {
|
|
|
147
146
|
: undefined;
|
|
148
147
|
let existing = options.importNpm
|
|
149
148
|
? null
|
|
150
|
-
: await readWorkspaceLock(root, project, (name) => options.registry.originFor(name)), graph = imported;
|
|
149
|
+
: await readWorkspaceLock(root, project, (name) => options.registry.originFor(name), !options.frozen && !options.offline), graph = imported;
|
|
151
150
|
if (existing) {
|
|
152
151
|
const ext = existing.doc.zyrk;
|
|
153
152
|
if (!mutation.changed &&
|
|
@@ -172,9 +171,9 @@ export async function installWorkspaceProject(options) {
|
|
|
172
171
|
...(existing ? { previous: existing.graph } : {}),
|
|
173
172
|
fresh: mutation.fresh,
|
|
174
173
|
...options.resolveBudget,
|
|
174
|
+
preservePlatformVariants: true,
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
-
assertWorkspacePlatform(graph);
|
|
178
177
|
mutation.finish(graph);
|
|
179
178
|
fp.manifest = project.manifestFingerprint;
|
|
180
179
|
const manifestChanges = project.importers
|
|
@@ -190,6 +189,7 @@ export async function installWorkspaceProject(options) {
|
|
|
190
189
|
: workspaceLockDoc(project, graph, fp), lockText = options.frozen
|
|
191
190
|
? await readFile(path.join(root, "package-lock.json"), "utf8")
|
|
192
191
|
: JSON.stringify(doc, null, 2) + "\n";
|
|
192
|
+
graph = selectWorkspacePlatform(graph, options.platform);
|
|
193
193
|
const warnings = graph.omissions.map((o) => `${o.name}: omitted incompatible optional workspace dependency.`);
|
|
194
194
|
for (const importer of project.importers)
|
|
195
195
|
for (const stage of ["preinstall", "install", "postinstall"])
|
|
@@ -9,7 +9,7 @@ export type WorkspaceFingerprints = {
|
|
|
9
9
|
export declare function safeImporter(id: unknown): id is string;
|
|
10
10
|
export declare function workspaceLockDoc(project: WorkspaceProject, graph: WorkspaceGraph, fp: WorkspaceFingerprints): NpmLockDoc;
|
|
11
11
|
export declare function validateWorkspaceLockDoc(doc: unknown): WorkspaceGraph;
|
|
12
|
-
export declare function readWorkspaceLock(root: string, project?: WorkspaceProject, registryOrigin?: string | ((name: string) => string)): Promise<{
|
|
12
|
+
export declare function readWorkspaceLock(root: string, project?: WorkspaceProject, registryOrigin?: string | ((name: string) => string), allowPlatformRefresh?: boolean): Promise<{
|
|
13
13
|
doc: NpmLockDoc;
|
|
14
14
|
graph: WorkspaceGraph;
|
|
15
15
|
} | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-lock.d.ts","sourceRoot":"","sources":["../../src/install/workspace-lock.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AASvD,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,wBAAgB,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,MAAM,CAqBtD;AACD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,cAAc,EACrB,EAAE,EAAE,qBAAqB,GACxB,UAAU,
|
|
1
|
+
{"version":3,"file":"workspace-lock.d.ts","sourceRoot":"","sources":["../../src/install/workspace-lock.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AASvD,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,wBAAgB,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,MAAM,CAqBtD;AACD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,cAAc,EACrB,EAAE,EAAE,qBAAqB,GACxB,UAAU,CA0CZ;AACD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAmTrE;AACD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,gBAAgB,EAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,EACpD,oBAAoB,UAAQ,GAC3B,OAAO,CAAC;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GAAG,IAAI,CAAC,CAmD5D"}
|
|
@@ -54,6 +54,7 @@ export function workspaceLockDoc(project, graph, fp) {
|
|
|
54
54
|
zyrk: {
|
|
55
55
|
version: 2,
|
|
56
56
|
resolver: ZYRK_RESOLVER_POLICY,
|
|
57
|
+
platformPolicy: "portable-optional/1",
|
|
57
58
|
contextCanonicalization: CONTEXT_CANONICALIZATION_VERSION,
|
|
58
59
|
...fp,
|
|
59
60
|
nodes: {},
|
|
@@ -71,6 +72,7 @@ export function validateWorkspaceLockDoc(doc) {
|
|
|
71
72
|
if (Object.keys(e).some((k) => ![
|
|
72
73
|
"version",
|
|
73
74
|
"resolver",
|
|
75
|
+
"platformPolicy",
|
|
74
76
|
"contextCanonicalization",
|
|
75
77
|
"manifest",
|
|
76
78
|
"scripts",
|
|
@@ -85,6 +87,7 @@ export function validateWorkspaceLockDoc(doc) {
|
|
|
85
87
|
Object.keys(e.roots).length !== 0 ||
|
|
86
88
|
e.version !== 2 ||
|
|
87
89
|
e.resolver !== ZYRK_RESOLVER_POLICY ||
|
|
90
|
+
e.platformPolicy !== "portable-optional/1" ||
|
|
88
91
|
e.contextCanonicalization !== CONTEXT_CANONICALIZATION_VERSION ||
|
|
89
92
|
typeof e.manifest !== "string" ||
|
|
90
93
|
!/^[a-f0-9]{128}$/.test(e.manifest) ||
|
|
@@ -249,6 +252,7 @@ export function validateWorkspaceLockDoc(doc) {
|
|
|
249
252
|
zyrk: {
|
|
250
253
|
version: 1,
|
|
251
254
|
resolver: ZYRK_RESOLVER_POLICY,
|
|
255
|
+
platformPolicy: "portable-optional/1",
|
|
252
256
|
contextCanonicalization: CONTEXT_CANONICALIZATION_VERSION,
|
|
253
257
|
manifest: "sha512-" + "A".repeat(86) + "==",
|
|
254
258
|
scripts: "sha512-" + "A".repeat(86) + "==",
|
|
@@ -300,7 +304,7 @@ export function validateWorkspaceLockDoc(doc) {
|
|
|
300
304
|
}
|
|
301
305
|
return g;
|
|
302
306
|
}
|
|
303
|
-
export async function readWorkspaceLock(root, project, registryOrigin) {
|
|
307
|
+
export async function readWorkspaceLock(root, project, registryOrigin, allowPlatformRefresh = false) {
|
|
304
308
|
let text;
|
|
305
309
|
try {
|
|
306
310
|
text = await readFile(path.join(root, "package-lock.json"), "utf8");
|
|
@@ -317,6 +321,12 @@ export async function readWorkspaceLock(root, project, registryOrigin) {
|
|
|
317
321
|
catch {
|
|
318
322
|
throw lockMismatch("workspace lock is not valid JSON");
|
|
319
323
|
}
|
|
324
|
+
if (allowPlatformRefresh &&
|
|
325
|
+
object(doc) &&
|
|
326
|
+
object(doc.zyrk) &&
|
|
327
|
+
doc.zyrk.version === 2 &&
|
|
328
|
+
doc.zyrk.platformPolicy === undefined)
|
|
329
|
+
return null;
|
|
320
330
|
const graph = validateWorkspaceLockDoc(doc);
|
|
321
331
|
if (project) {
|
|
322
332
|
const expected = new Map(project.importers.map((i) => [i.id, i]));
|
|
@@ -72,7 +72,6 @@ export function configFingerprint(config) {
|
|
|
72
72
|
: {}),
|
|
73
73
|
linker: config.linker,
|
|
74
74
|
...(config.patches === undefined ? {} : { patches: config.patches }),
|
|
75
|
-
...(config.platform === undefined ? {} : { platform: config.platform }),
|
|
76
75
|
...(config.mutablePackages === undefined
|
|
77
76
|
? {}
|
|
78
77
|
: { mutablePackages: [...config.mutablePackages].sort() }),
|
package/dist/lockfile/read.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type ReadLockResult = {
|
|
|
10
10
|
path: string;
|
|
11
11
|
doc: NpmLockDoc;
|
|
12
12
|
};
|
|
13
|
-
export declare function readLockfile(lockPath: string): Promise<ReadLockResult | null>;
|
|
13
|
+
export declare function readLockfile(lockPath: string, allowPlatformRefresh?: boolean): Promise<ReadLockResult | null>;
|
|
14
14
|
export declare function validateLockDoc(doc: unknown, label: string): NpmLockDoc;
|
|
15
15
|
export type FrozenFingerprints = {
|
|
16
16
|
manifest: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/lockfile/read.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,UAAU,CAAC;CACjB,CAAC;AAEF,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/lockfile/read.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,UAAU,CAAC;CACjB,CAAC;AAEF,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,oBAAoB,UAAQ,GAC3B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAmChC;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CA2DvE;AA4CD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,kBAAkB,GAC3B,IAAI,CAmCN"}
|
package/dist/lockfile/read.js
CHANGED
|
@@ -11,7 +11,7 @@ import { readFile } from "node:fs/promises";
|
|
|
11
11
|
import { ZyrkError } from "../errors.js";
|
|
12
12
|
import { isErrno, pathExists } from "../util/fsx.js";
|
|
13
13
|
import { ZYRK_LOCK_EXTENSION_VERSION, } from "./types.js";
|
|
14
|
-
export async function readLockfile(lockPath) {
|
|
14
|
+
export async function readLockfile(lockPath, allowPlatformRefresh = false) {
|
|
15
15
|
if (!(await pathExists(lockPath)))
|
|
16
16
|
return null;
|
|
17
17
|
let raw;
|
|
@@ -34,6 +34,16 @@ export async function readLockfile(lockPath) {
|
|
|
34
34
|
cause: error,
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
+
if (allowPlatformRefresh && typeof parsed === "object" && parsed !== null) {
|
|
38
|
+
const extension = parsed.zyrk;
|
|
39
|
+
if (extension?.version === 1 && extension.platformPolicy === undefined) {
|
|
40
|
+
// Validate old metadata without treating a platform-pruned graph as portable.
|
|
41
|
+
const checked = structuredClone(parsed);
|
|
42
|
+
checked.zyrk.platformPolicy = "portable-optional/1";
|
|
43
|
+
validateLockDoc(checked, lockPath);
|
|
44
|
+
return { path: lockPath, doc: parsed };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
37
47
|
return { path: lockPath, doc: validateLockDoc(parsed, lockPath) };
|
|
38
48
|
}
|
|
39
49
|
export function validateLockDoc(doc, label) {
|
package/dist/lockfile/types.d.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* manifest, policy, or configuration drift.
|
|
16
16
|
*/
|
|
17
17
|
export declare const ZYRK_LOCK_EXTENSION_VERSION = 1;
|
|
18
|
+
export declare const ZYRK_PLATFORM_POLICY = "portable-optional/1";
|
|
18
19
|
/** npm package metadata, interpreted during exact-selection import. */
|
|
19
20
|
export type NpmPackageEntry = Record<string, unknown>;
|
|
20
21
|
export type NpmLockDoc = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lockfile/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,2BAA2B,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lockfile/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAE1D,uEAAuE;AACvE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC;IACxD,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACrC,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,uBAAuB,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACpC,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,oBAAoB,mBAAmB,CAAC"}
|
package/dist/lockfile/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/lockfile/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,mBAAmB,CAAC;IAChC,YAAY,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACzB,CAAC;AAEF,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/lockfile/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,mBAAmB,CAAC;IAChC,YAAY,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACzB,CAAC;AAEF,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAqOrB"}
|
package/dist/lockfile/write.js
CHANGED
|
@@ -172,6 +172,7 @@ export async function writeLockfile(options) {
|
|
|
172
172
|
const extension = {
|
|
173
173
|
version: ZYRK_LOCK_EXTENSION_VERSION,
|
|
174
174
|
resolver: ZYRK_RESOLVER_POLICY,
|
|
175
|
+
platformPolicy: "portable-optional/1",
|
|
175
176
|
contextCanonicalization: CONTEXT_CANONICALIZATION_VERSION,
|
|
176
177
|
manifest: options.fingerprints.manifest,
|
|
177
178
|
scripts: options.fingerprints.scripts,
|
|
@@ -1,24 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registry-backed dependency resolver (SPEC 9).
|
|
3
|
-
*
|
|
4
|
-
* Turns requirement strings into an immutable resolved graph: exact name,
|
|
5
|
-
* version, origin-qualified source identity, dependency edges, and peer
|
|
6
|
-
* bindings. No package code runs here; no project files are touched.
|
|
7
|
-
*
|
|
8
|
-
* Scope of this slice: registry versions, ranges, tags, scoped names, and
|
|
9
|
-
* npm aliases; prod and optional groups; required and optional peers with
|
|
10
|
-
* explicit-consumer-context bindings; cycles; bundled subtrees (skipped,
|
|
11
|
-
* never exposed). Dev groups need full packuments and arrive later, as do
|
|
12
|
-
* overrides and workspace relationships. Platform omissions are reported
|
|
13
|
-
* explicitly, and resource limits bound graph construction. Remote
|
|
14
|
-
* tarballs, Git, and local sources fail explicitly (SPEC 9.2).
|
|
15
|
-
*
|
|
16
|
-
* Peer contexts (SPEC 9.3-9.4): one verified source may back several
|
|
17
|
-
* dependency contexts. Occurrences that declare peers are instantiated per
|
|
18
|
-
* requesting parent and keyed by a fingerprint of their resolved peer
|
|
19
|
-
* closure, so identical bindings share one occurrence while differing
|
|
20
|
-
* bindings stay distinct. Peerless occurrences share by name@version.
|
|
21
|
-
*/
|
|
22
1
|
import { type Packument } from "../fetch/registry.ts";
|
|
23
2
|
import { type OverridePolicy } from "./overrides.ts";
|
|
24
3
|
export type MetadataProvider = {
|
|
@@ -70,6 +49,7 @@ export type ResolveOptions = {
|
|
|
70
49
|
overrides?: OverridePolicy;
|
|
71
50
|
limits?: Partial<ResolverLimits>;
|
|
72
51
|
platform?: RuntimePlatform;
|
|
52
|
+
preservePlatformVariants?: boolean;
|
|
73
53
|
};
|
|
74
54
|
export type RuntimePlatform = {
|
|
75
55
|
os: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resolve/resolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resolve/resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/resolve/resolver.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeEngineConstraints } from "../util/engines.js";
|
|
1
2
|
/**
|
|
2
3
|
* Registry-backed dependency resolver (SPEC 9).
|
|
3
4
|
*
|
|
@@ -75,6 +76,7 @@ class ResolverState {
|
|
|
75
76
|
occurrences = [];
|
|
76
77
|
limits;
|
|
77
78
|
platform;
|
|
79
|
+
preservePlatformVariants;
|
|
78
80
|
omissions = [];
|
|
79
81
|
expires;
|
|
80
82
|
peerExpansions = 0;
|
|
@@ -93,6 +95,7 @@ class ResolverState {
|
|
|
93
95
|
if (!Number.isSafeInteger(value) || value <= 0)
|
|
94
96
|
throw budgetError("invalid resolver limits");
|
|
95
97
|
this.platform = options.platform ?? currentPlatform();
|
|
98
|
+
this.preservePlatformVariants = options.preservePlatformVariants === true;
|
|
96
99
|
this.expires = Date.now() + this.limits.deadlineMs;
|
|
97
100
|
}
|
|
98
101
|
checkBudget(depth = 0, adding = false) {
|
|
@@ -104,6 +107,8 @@ class ResolverState {
|
|
|
104
107
|
throw budgetError("resolved node limit exceeded");
|
|
105
108
|
}
|
|
106
109
|
checkPlatform(name, entry) {
|
|
110
|
+
if (this.preservePlatformVariants)
|
|
111
|
+
return;
|
|
107
112
|
for (const [constraints, actual] of [
|
|
108
113
|
[entry.os, this.platform.os],
|
|
109
114
|
[entry.cpu, this.platform.cpu],
|
|
@@ -582,6 +587,13 @@ function assertMergeable(a, b, keys, origin) {
|
|
|
582
587
|
}
|
|
583
588
|
}
|
|
584
589
|
function toResolved(occ, key, keys, origin) {
|
|
590
|
+
const engines = occ.entry.engines === undefined
|
|
591
|
+
? undefined
|
|
592
|
+
: normalizeEngineConstraints(occ.entry.engines, () => {
|
|
593
|
+
throw new ZyrkError("ZYRK_RESOLUTION_FAILED", `Cannot resolve ${occ.name}: invalid engine constraints.`, {
|
|
594
|
+
remedy: "Select a package version with valid npm engine metadata.",
|
|
595
|
+
});
|
|
596
|
+
});
|
|
585
597
|
const edgesByName = new Map();
|
|
586
598
|
for (const link of occ.children) {
|
|
587
599
|
const target = keys.get(link.child);
|
|
@@ -630,7 +642,7 @@ function toResolved(occ, key, keys, origin) {
|
|
|
630
642
|
...(occ.entry.cpu === undefined ? {} : { cpu: occ.entry.cpu }),
|
|
631
643
|
...(occ.entry.libc === undefined ? {} : { libc: occ.entry.libc }),
|
|
632
644
|
},
|
|
633
|
-
...(
|
|
645
|
+
...(engines === undefined ? {} : { engines }),
|
|
634
646
|
};
|
|
635
647
|
}
|
|
636
648
|
function sourceIdForOccurrence(occ, origin) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engines.d.ts","sourceRoot":"","sources":["../../src/util/engines.ts"],"names":[],"mappings":"AAGA,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,KAAK,GACnB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBxB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Normalize npm's historical engine arrays without weakening modern map checks. */
|
|
2
|
+
import { validRange } from "semver";
|
|
3
|
+
export function normalizeEngineConstraints(value, invalid) {
|
|
4
|
+
if (Array.isArray(value)) {
|
|
5
|
+
const engines = {};
|
|
6
|
+
for (const item of value) {
|
|
7
|
+
const match = typeof item === "string"
|
|
8
|
+
? /^([a-z][a-z0-9._-]*)\s+(.+)$/.exec(item)
|
|
9
|
+
: null;
|
|
10
|
+
if (!match ||
|
|
11
|
+
Object.hasOwn(engines, match[1]) ||
|
|
12
|
+
validRange(match[2]) === null)
|
|
13
|
+
return invalid();
|
|
14
|
+
engines[match[1]] = match[2];
|
|
15
|
+
}
|
|
16
|
+
return engines;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value !== "object" ||
|
|
19
|
+
value === null ||
|
|
20
|
+
Object.values(value).some((item) => typeof item !== "string"))
|
|
21
|
+
return invalid();
|
|
22
|
+
return value;
|
|
23
|
+
}
|