zyrk 0.5.0 → 0.5.2
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 +10 -2
- package/VERSION +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +7 -11
- package/dist/commands/maintenance.d.ts.map +1 -1
- package/dist/commands/maintenance.js +22 -2
- package/dist/fetch/package.d.ts.map +1 -1
- package/dist/fetch/package.js +2 -1
- package/dist/fetch/registry.d.ts +5 -0
- package/dist/fetch/registry.d.ts.map +1 -1
- package/dist/fetch/registry.js +84 -10
- package/dist/install/import-npm-workspace.d.ts +2 -1
- package/dist/install/import-npm-workspace.d.ts.map +1 -1
- package/dist/install/import-npm-workspace.js +34 -12
- package/dist/install/import-npm.d.ts +3 -1
- package/dist/install/import-npm.d.ts.map +1 -1
- package/dist/install/import-npm.js +14 -9
- package/dist/install/registry-policy.d.ts +9 -0
- package/dist/install/registry-policy.d.ts.map +1 -0
- package/dist/install/registry-policy.js +30 -0
- package/dist/install/registry.d.ts.map +1 -1
- package/dist/install/registry.js +18 -13
- package/dist/install/run.d.ts.map +1 -1
- package/dist/install/run.js +22 -5
- package/dist/install/workspace-graph.d.ts +7 -1
- package/dist/install/workspace-graph.d.ts.map +1 -1
- package/dist/install/workspace-graph.js +53 -9
- package/dist/install/workspace-install.d.ts.map +1 -1
- package/dist/install/workspace-install.js +16 -6
- 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 +5 -1
- package/dist/install/workspace-mutation.d.ts.map +1 -1
- package/dist/install/workspace-mutation.js +4 -1
- package/dist/install/workspace-overrides.d.ts +11 -0
- package/dist/install/workspace-overrides.d.ts.map +1 -0
- package/dist/install/workspace-overrides.js +67 -0
- package/dist/install/workspaces.d.ts.map +1 -1
- package/dist/install/workspaces.js +4 -1
- package/dist/lockfile/fingerprints.d.ts +1 -0
- package/dist/lockfile/fingerprints.d.ts.map +1 -1
- package/dist/lockfile/fingerprints.js +16 -1
- package/dist/resolve/overrides.d.ts +19 -0
- package/dist/resolve/overrides.d.ts.map +1 -0
- package/dist/resolve/overrides.js +142 -0
- package/dist/resolve/resolver.d.ts +3 -0
- package/dist/resolve/resolver.d.ts.map +1 -1
- package/dist/resolve/resolver.js +62 -18
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Credential-free routing captured with the exact installed generation. */
|
|
2
|
+
import { cleanUrl, lockMismatch } from "./lock.js";
|
|
3
|
+
export function installedRegistryConfig(state, nodes) {
|
|
4
|
+
const object = (x) => !!x && typeof x === "object" && !Array.isArray(x);
|
|
5
|
+
const raw = state.registryConfig;
|
|
6
|
+
if (raw === undefined) {
|
|
7
|
+
const origins = new Set(nodes.map((n) => n.origin));
|
|
8
|
+
if (origins.size !== 1)
|
|
9
|
+
throw lockMismatch("legacy installed state has no exact registry routing");
|
|
10
|
+
return { registry: [...origins][0] };
|
|
11
|
+
}
|
|
12
|
+
if (!object(raw) ||
|
|
13
|
+
Object.keys(raw).some((k) => !["registry", "registries"].includes(k)) ||
|
|
14
|
+
typeof raw.registry !== "string" ||
|
|
15
|
+
!cleanUrl(raw.registry) ||
|
|
16
|
+
!object(raw.registries) ||
|
|
17
|
+
Object.entries(raw.registries).some(([scope, url]) => !/^@[a-z0-9][a-z0-9._-]*$/.test(scope) ||
|
|
18
|
+
typeof url !== "string" ||
|
|
19
|
+
!cleanUrl(url)))
|
|
20
|
+
throw lockMismatch("installed registry routing is malformed");
|
|
21
|
+
const registries = raw.registries;
|
|
22
|
+
for (const node of nodes) {
|
|
23
|
+
const expected = node.name.startsWith("@")
|
|
24
|
+
? (registries[node.name.slice(0, node.name.indexOf("/"))] ?? raw.registry)
|
|
25
|
+
: raw.registry;
|
|
26
|
+
if (node.origin !== expected)
|
|
27
|
+
throw lockMismatch("installed registry routing disagrees with selected sources");
|
|
28
|
+
}
|
|
29
|
+
return { registry: raw.registry, registries };
|
|
30
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/install/registry.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAoB,MAAM,sBAAsB,CAAC;AAKxE,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/install/registry.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAoB,MAAM,sBAAsB,CAAC;AAKxE,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuI1B"}
|
package/dist/install/registry.js
CHANGED
|
@@ -11,6 +11,7 @@ import { cleanUrl } from "./lock.js";
|
|
|
11
11
|
export async function installRegistry(options) {
|
|
12
12
|
let registry = DEFAULT_REGISTRY;
|
|
13
13
|
const auth = {};
|
|
14
|
+
const scopedRegistries = {};
|
|
14
15
|
const home = options.env.HOME ?? os.homedir();
|
|
15
16
|
const project = (await findWorkspaceRoot(options.cwd)) ??
|
|
16
17
|
(await findProjectBoundary(options.cwd)) ??
|
|
@@ -64,9 +65,7 @@ export async function installRegistry(options) {
|
|
|
64
65
|
if (key === "registry")
|
|
65
66
|
registry = value;
|
|
66
67
|
if (/^@.+:registry$/.test(key))
|
|
67
|
-
|
|
68
|
-
remedy: "Use npm for mixed-registry projects; zyrk will not silently fetch a private scope from a public registry.",
|
|
69
|
-
});
|
|
68
|
+
scopedRegistries[key.slice(0, -9)] = value;
|
|
70
69
|
if (key === "strict-ssl" && value === "false")
|
|
71
70
|
throw new ZyrkError("ZYRK_POLICY_DENIED", "Disabling registry TLS verification is not supported.", {
|
|
72
71
|
remedy: "Configure a trusted HTTPS registry with valid TLS certificates.",
|
|
@@ -80,18 +79,24 @@ export async function installRegistry(options) {
|
|
|
80
79
|
options.env.npm_config_registry ??
|
|
81
80
|
options.env.NPM_CONFIG_REGISTRY ??
|
|
82
81
|
registry;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
82
|
+
const validate = (registry) => {
|
|
83
|
+
if (!cleanUrl(registry))
|
|
84
|
+
throw new ZyrkError("ZYRK_POLICY_DENIED", "Registry URL must be HTTP(S) without credentials, query parameters, or fragments.", {
|
|
85
|
+
remedy: "Use a credential-free registry URL and configure URL-scoped credentials separately in .npmrc.",
|
|
86
|
+
});
|
|
87
|
+
const url = new URL(registry);
|
|
88
|
+
if (url.protocol !== "https:" &&
|
|
89
|
+
!["127.0.0.1", "localhost", "[::1]"].includes(url.hostname))
|
|
90
|
+
throw new ZyrkError("ZYRK_POLICY_DENIED", "Remote registries require HTTPS.", {
|
|
91
|
+
remedy: "Select an HTTPS registry; HTTP is limited to loopback development registries.",
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
validate(registry);
|
|
95
|
+
for (const selected of Object.values(scopedRegistries))
|
|
96
|
+
validate(selected);
|
|
93
97
|
return new RegistryClient({
|
|
94
98
|
registry,
|
|
99
|
+
scopedRegistries,
|
|
95
100
|
userAgent: `zyrk/${options.version}`,
|
|
96
101
|
fetchOptions: auth,
|
|
97
102
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/install/run.ts"],"names":[],"mappings":"AAIA,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/install/run.ts"],"names":[],"mappings":"AAIA,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AAYtB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAgC3C,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,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,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,CAyyBxB"}
|
package/dist/install/run.js
CHANGED
|
@@ -6,6 +6,7 @@ import { candidates, candidateDigest, approveCandidate, assertApproved, material
|
|
|
6
6
|
import { loadProjectPatches, applyProjectPatches } from "../commands/patch.js";
|
|
7
7
|
import { registerGeneration } from "./metadata.js";
|
|
8
8
|
import { randomId } from "../util/ids.js";
|
|
9
|
+
import { createRootOverrides } from "../resolve/overrides.js";
|
|
9
10
|
import { importNpmLock } from "./import-npm.js";
|
|
10
11
|
/** Native project install: resolve -> verify -> realize -> journaled publication. */
|
|
11
12
|
import { readFile, realpath, lstat, mkdir, rm } from "node:fs/promises";
|
|
@@ -65,10 +66,9 @@ async function readManifest(project) {
|
|
|
65
66
|
throw error("ZYRK_MANIFEST_INVALID", `Project ${group} must contain valid package names and string specifiers.`);
|
|
66
67
|
}
|
|
67
68
|
if (doc.workspaces !== undefined ||
|
|
68
|
-
doc.overrides !== undefined ||
|
|
69
69
|
doc.bundledDependencies !== undefined ||
|
|
70
70
|
doc.bundleDependencies !== undefined)
|
|
71
|
-
throw error("ZYRK_NOT_IMPLEMENTED", "Project workspaces
|
|
71
|
+
throw error("ZYRK_NOT_IMPLEMENTED", "Project workspaces and bundled dependencies are not supported by install yet.");
|
|
72
72
|
if (doc.zyrk !== undefined &&
|
|
73
73
|
(!object(doc.zyrk) ||
|
|
74
74
|
Object.keys(doc.zyrk).some((key) => !["scripts", "audit", "patches", "mutablePackages"].includes(key)) ||
|
|
@@ -98,6 +98,13 @@ export async function installProject(options) {
|
|
|
98
98
|
return installWorkspaceProject(options);
|
|
99
99
|
}
|
|
100
100
|
const project = await realpath(options.projectDir);
|
|
101
|
+
const preliminaryManifest = (await readManifest(project)).doc;
|
|
102
|
+
const preliminaryOverrides = createRootOverrides(preliminaryManifest);
|
|
103
|
+
if (options.importNpm) {
|
|
104
|
+
const preliminaryLock = (await readLockfile(path.join(project, "package-lock.json")))?.doc;
|
|
105
|
+
if (preliminaryLock && !preliminaryLock.zyrk)
|
|
106
|
+
importNpmLock(preliminaryLock, requirements(preliminaryManifest), (name) => options.registry.originFor(name), preliminaryOverrides);
|
|
107
|
+
}
|
|
101
108
|
// A local control-directory link would redirect locks and recovery writes.
|
|
102
109
|
const local = path.join(project, PROJECT_STATE_DIR);
|
|
103
110
|
try {
|
|
@@ -189,6 +196,7 @@ export async function installProject(options) {
|
|
|
189
196
|
if (other !== group && manifest[other])
|
|
190
197
|
delete manifest[other][parsed.name];
|
|
191
198
|
}
|
|
199
|
+
const overrides = createRootOverrides(manifest);
|
|
192
200
|
const allDeps = requirements(manifest);
|
|
193
201
|
for (const [name, spec] of Object.entries(allDeps))
|
|
194
202
|
parseRequirement(name, spec);
|
|
@@ -197,6 +205,7 @@ export async function installProject(options) {
|
|
|
197
205
|
scripts: scriptPolicyFingerprint(scriptPolicy(manifest)),
|
|
198
206
|
config: configFingerprint({
|
|
199
207
|
registry: options.registry.origin,
|
|
208
|
+
registries: options.registry.scopedRegistries,
|
|
200
209
|
linker: "shared",
|
|
201
210
|
platform: currentPlatform(),
|
|
202
211
|
...(object(manifest.zyrk) &&
|
|
@@ -214,7 +223,7 @@ export async function installProject(options) {
|
|
|
214
223
|
if (existing && !existing.zyrk) {
|
|
215
224
|
if (options.frozen || options.offline || specs.length)
|
|
216
225
|
throw lockMismatch("npm-only lockfile requires a non-frozen adoption install before adding packages");
|
|
217
|
-
resolved = importNpmLock(existing, allDeps, options.registry.
|
|
226
|
+
resolved = importNpmLock(existing, allDeps, (name) => options.registry.originFor(name), overrides);
|
|
218
227
|
}
|
|
219
228
|
if (existing?.zyrk &&
|
|
220
229
|
specs.length === 0 &&
|
|
@@ -240,8 +249,10 @@ export async function installProject(options) {
|
|
|
240
249
|
const prior = existing?.zyrk ? lockedGraph(existing) : undefined;
|
|
241
250
|
const fresh = new Set(specs.map((spec) => npa(spec).name));
|
|
242
251
|
resolved = await resolveRequirements({
|
|
252
|
+
overrides,
|
|
243
253
|
provider: {
|
|
244
254
|
origin: options.registry.origin,
|
|
255
|
+
originFor: (name) => options.registry.originFor(name),
|
|
245
256
|
packument: (name) => options.registry.packument(name, {
|
|
246
257
|
signal: operation.operation.signal,
|
|
247
258
|
}),
|
|
@@ -342,7 +353,7 @@ export async function installProject(options) {
|
|
|
342
353
|
if (!packageName(node.name) ||
|
|
343
354
|
!cleanUrl(node.origin) ||
|
|
344
355
|
!cleanUrl(node.tarballUrl) ||
|
|
345
|
-
node.origin !== options.registry.
|
|
356
|
+
node.origin !== options.registry.originFor(node.name))
|
|
346
357
|
throw error("ZYRK_POLICY_DENIED", "Selected source has an unsupported or credential-bearing registry origin or archive URL.");
|
|
347
358
|
}
|
|
348
359
|
const selectedRoots = resolved.roots.filter((r) => !options.omitDev ||
|
|
@@ -458,7 +469,9 @@ export async function installProject(options) {
|
|
|
458
469
|
if (options.offline)
|
|
459
470
|
throw error("ZYRK_OFFLINE_MISSING", `Verified source for ${node.name}@${node.version} is missing from the store.`);
|
|
460
471
|
const tarball = path.join(txn.dir, `${node.sourceId}.tgz`);
|
|
461
|
-
const download = await options.registry
|
|
472
|
+
const download = await options.registry
|
|
473
|
+
.forPackage(node.name)
|
|
474
|
+
.downloadTarball({
|
|
462
475
|
signal: operation.operation.signal,
|
|
463
476
|
onBytes: operation.operation.consumeArchiveBytes,
|
|
464
477
|
url: node.tarballUrl,
|
|
@@ -680,6 +693,10 @@ export async function installProject(options) {
|
|
|
680
693
|
instances: registration.instances,
|
|
681
694
|
activeContexts: registration.contexts,
|
|
682
695
|
lockDigest: sha512Hex(canonicalJson(doc)),
|
|
696
|
+
registryConfig: {
|
|
697
|
+
registry: options.registry.origin,
|
|
698
|
+
registries: options.registry.scopedRegistries,
|
|
699
|
+
},
|
|
683
700
|
graphDigest: digest,
|
|
684
701
|
platform: process.platform,
|
|
685
702
|
arch: process.arch,
|
|
@@ -46,17 +46,23 @@ export type WorkspaceGraph = {
|
|
|
46
46
|
reason: "platform";
|
|
47
47
|
}>;
|
|
48
48
|
};
|
|
49
|
-
|
|
49
|
+
declare function resolveWorkspaceGraphPass(project: WorkspaceProject, provider: MetadataProvider, options?: {
|
|
50
50
|
previous?: WorkspaceGraph;
|
|
51
51
|
fresh?: ReadonlySet<string>;
|
|
52
52
|
platform?: RuntimePlatform;
|
|
53
53
|
maxNodes?: number;
|
|
54
54
|
maxDepth?: number;
|
|
55
55
|
deadlineMs?: number;
|
|
56
|
+
}, overrideState?: {
|
|
57
|
+
policy: import("../resolve/overrides.ts").OverridePolicy;
|
|
58
|
+
contexts: Map<string, import("../resolve/overrides.ts").OverrideContext>;
|
|
56
59
|
}): Promise<WorkspaceGraph>;
|
|
60
|
+
/** Retry pure planning when a registry edge narrows a live importer's scope. */
|
|
61
|
+
export declare function resolveWorkspaceGraph(project: WorkspaceProject, provider: MetadataProvider, options?: Parameters<typeof resolveWorkspaceGraphPass>[2]): Promise<WorkspaceGraph>;
|
|
57
62
|
export declare function workspaceRegistryOccurrences(graph: WorkspaceGraph): ResolvedOccurrence[];
|
|
58
63
|
/** Rooted semantic context including live source identity; occurrence keys never split equal peers. */
|
|
59
64
|
export declare function workspaceContextId(graph: WorkspaceGraph, rootKey: string, projectId: string): string;
|
|
60
65
|
/** Recheck locked platform/runtime requirements as strictly as fresh resolution. */
|
|
61
66
|
export declare function assertWorkspacePlatform(graph: WorkspaceGraph): void;
|
|
67
|
+
export {};
|
|
62
68
|
//# sourceMappingURL=workspace-graph.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-graph.d.ts","sourceRoot":"","sources":["../../src/install/workspace-graph.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EAChB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace-graph.d.ts","sourceRoot":"","sources":["../../src/install/workspace-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { maxSatisfying, satisfies, valid } from "semver";
|
|
3
3
|
import { expectedIntegrityFromDist, } from "../fetch/registry.js";
|
|
4
4
|
import { currentPlatform } from "../resolve/resolver.js";
|
|
5
|
+
import { workspaceOverrides, refineWorkspaceOverride, WorkspaceOverrideRestart, } from "./workspace-overrides.js";
|
|
5
6
|
import { parseRequirement } from "../resolve/spec.js";
|
|
6
7
|
import { sourceIdOf, sha512Hex } from "../util/hash.js";
|
|
7
8
|
import { ZyrkError } from "../errors.js";
|
|
@@ -14,7 +15,9 @@ const fail = (reason) => {
|
|
|
14
15
|
};
|
|
15
16
|
class PlatformMismatch extends Error {
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
+
async function resolveWorkspaceGraphPass(project, provider, options = {}, overrideState = workspaceOverrides(project)) {
|
|
19
|
+
const overrides = overrideState.policy;
|
|
20
|
+
const overrideContexts = new Map(overrideState.contexts);
|
|
18
21
|
const graph = { nodes: [], importers: {}, omissions: [] };
|
|
19
22
|
const byKey = new Map(), manifests = new Map(), chains = new Map();
|
|
20
23
|
const metadata = new Map();
|
|
@@ -83,6 +86,10 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
83
86
|
const build = async (parent, name, spec, kind, ancestry, explicitLocal) => {
|
|
84
87
|
check(ancestry.length);
|
|
85
88
|
try {
|
|
89
|
+
const overridden = overrides.select(overrideContexts.get(parent.key), name, spec);
|
|
90
|
+
if (overridden.spec !== spec)
|
|
91
|
+
explicitLocal = undefined;
|
|
92
|
+
spec = overridden.spec;
|
|
86
93
|
let local = explicitLocal === undefined
|
|
87
94
|
? undefined
|
|
88
95
|
: project.importers.find((item) => item.id === explicitLocal);
|
|
@@ -106,8 +113,11 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
106
113
|
local = candidate;
|
|
107
114
|
}
|
|
108
115
|
}
|
|
109
|
-
if (local)
|
|
110
|
-
|
|
116
|
+
if (local) {
|
|
117
|
+
const key = graph.importers[local.id];
|
|
118
|
+
refineWorkspaceOverride(overrideState.contexts, key, overridden.context);
|
|
119
|
+
return key;
|
|
120
|
+
}
|
|
111
121
|
if (!requirement)
|
|
112
122
|
throw lockMismatch("missing workspace requirement");
|
|
113
123
|
const doc = await packument(requirement.realName);
|
|
@@ -145,13 +155,15 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
145
155
|
.map((key) => byKey.get(key))
|
|
146
156
|
.find((node) => node?.kind === "registry" &&
|
|
147
157
|
node.name === requirement.realName &&
|
|
148
|
-
node.version === version
|
|
158
|
+
node.version === version &&
|
|
159
|
+
overrideContexts.get(node.key)?.id === overridden.context.id);
|
|
149
160
|
if (ancestor)
|
|
150
161
|
return ancestor.key;
|
|
151
162
|
const key = `${requirement.realName}@${version}#${sha512Hex(parent.key + "\0" + name).slice(0, 16)}`;
|
|
152
163
|
if (byKey.has(key))
|
|
153
164
|
return key;
|
|
154
|
-
|
|
165
|
+
const origin = provider.originFor?.(requirement.realName) ?? provider.origin;
|
|
166
|
+
if (!cleanUrl(origin) || !cleanUrl(entry.dist.tarball))
|
|
155
167
|
fail("unsafe registry source metadata");
|
|
156
168
|
const bin = typeof entry.bin === "string"
|
|
157
169
|
? { [requirement.realName.split("/").at(-1)]: entry.bin }
|
|
@@ -165,10 +177,10 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
165
177
|
sourceType: "registry",
|
|
166
178
|
name: requirement.realName,
|
|
167
179
|
version,
|
|
168
|
-
origin
|
|
180
|
+
origin,
|
|
169
181
|
integrity,
|
|
170
182
|
}),
|
|
171
|
-
origin
|
|
183
|
+
origin,
|
|
172
184
|
integrity,
|
|
173
185
|
tarballUrl: entry.dist.tarball,
|
|
174
186
|
bin,
|
|
@@ -183,6 +195,7 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
183
195
|
optionalPeers: [],
|
|
184
196
|
};
|
|
185
197
|
graph.nodes.push(node);
|
|
198
|
+
overrideContexts.set(key, overridden.context);
|
|
186
199
|
byKey.set(key, node);
|
|
187
200
|
manifests.set(key, entry);
|
|
188
201
|
chains.set(key, [...ancestry, parent.key]);
|
|
@@ -234,7 +247,8 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
234
247
|
for (const node of graph.nodes) {
|
|
235
248
|
check();
|
|
236
249
|
const manifest = manifests.get(node.key);
|
|
237
|
-
for (const [name,
|
|
250
|
+
for (const [name, rawRange] of Object.entries(manifest.peerDependencies ?? {}).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {
|
|
251
|
+
const range = overrides.select(overrideContexts.get(node.key), name, rawRange).spec;
|
|
238
252
|
const optional = manifest.peerDependenciesMeta?.[name]?.optional === true;
|
|
239
253
|
if (optional && !node.optionalPeers.includes(name))
|
|
240
254
|
node.optionalPeers.push(name);
|
|
@@ -256,7 +270,7 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
256
270
|
const selected = byKey.get(target);
|
|
257
271
|
const requested = range.startsWith("workspace:")
|
|
258
272
|
? range.slice(10)
|
|
259
|
-
: range;
|
|
273
|
+
: parseRequirement(name, range).targetSpec;
|
|
260
274
|
if (!["*", "^", "~"].includes(requested) &&
|
|
261
275
|
!satisfies(selected.version, requested))
|
|
262
276
|
throw new ZyrkError("ZYRK_PEER_CONFLICT", `Workspace peer ${name} required by ${node.name} conflicts with its consumer.`, { remedy: "Align the consumer and package peer requirements." });
|
|
@@ -293,6 +307,36 @@ export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
|
293
307
|
}
|
|
294
308
|
return fail("peer binding iteration limit exceeded");
|
|
295
309
|
}
|
|
310
|
+
/** Retry pure planning when a registry edge narrows a live importer's scope. */
|
|
311
|
+
export async function resolveWorkspaceGraph(project, provider, options = {}) {
|
|
312
|
+
const state = workspaceOverrides(project), expires = Date.now() + (options.deadlineMs ?? 30000);
|
|
313
|
+
const packuments = new Map();
|
|
314
|
+
const cached = {
|
|
315
|
+
...provider,
|
|
316
|
+
origin: provider.origin,
|
|
317
|
+
...(provider.originFor
|
|
318
|
+
? { originFor: (name) => provider.originFor(name) }
|
|
319
|
+
: {}),
|
|
320
|
+
packument: (name) => {
|
|
321
|
+
let pending = packuments.get(name);
|
|
322
|
+
if (!pending) {
|
|
323
|
+
pending = provider.packument(name);
|
|
324
|
+
packuments.set(name, pending);
|
|
325
|
+
}
|
|
326
|
+
return pending;
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
for (let round = 0; round < 128 && Date.now() < expires; round++) {
|
|
330
|
+
try {
|
|
331
|
+
return await resolveWorkspaceGraphPass(project, cached, { ...options, deadlineMs: Math.max(1, expires - Date.now()) }, state);
|
|
332
|
+
}
|
|
333
|
+
catch (cause) {
|
|
334
|
+
if (!(cause instanceof WorkspaceOverrideRestart))
|
|
335
|
+
throw cause;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
throw lockMismatch("workspace override planning resource limit exceeded");
|
|
339
|
+
}
|
|
296
340
|
export function workspaceRegistryOccurrences(graph) {
|
|
297
341
|
return graph.nodes
|
|
298
342
|
.filter((node) => node.kind === "registry")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-install.d.ts","sourceRoot":"","sources":["../../src/install/workspace-install.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAyH9D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"workspace-install.d.ts","sourceRoot":"","sources":["../../src/install/workspace-install.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAyH9D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA6pBxB"}
|
|
@@ -4,6 +4,7 @@ import { constants } from "node:fs";
|
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { discoverWorkspaces, findWorkspaceRoot, assertNoLiveSourceBuilds, } from "./workspaces.js";
|
|
6
6
|
import { resolveWorkspaceGraph, workspaceRegistryOccurrences, workspaceContextId, assertWorkspacePlatform, } from "./workspace-graph.js";
|
|
7
|
+
import { workspaceOverrides } from "./workspace-overrides.js";
|
|
7
8
|
import { importNpmWorkspaceLock } from "./import-npm-workspace.js";
|
|
8
9
|
import { readWorkspaceLock, workspaceLockDoc } from "./workspace-lock.js";
|
|
9
10
|
import { publishWorkspaceProjection, recoverWorkspaceProjection, workspaceProjectionPaths, } from "./workspace-transaction.js";
|
|
@@ -61,7 +62,7 @@ async function readNpmWorkspaceImport(root, project, options) {
|
|
|
61
62
|
catch {
|
|
62
63
|
throw lockMismatch("npm workspace adoption needs an existing readable JSON lock");
|
|
63
64
|
}
|
|
64
|
-
const graph = importNpmWorkspaceLock(npmDoc, project, options.registry.
|
|
65
|
+
const graph = importNpmWorkspaceLock(npmDoc, project, (name) => options.registry.originFor(name));
|
|
65
66
|
// Prove the complete graph and ordinary npm projection are representable
|
|
66
67
|
// before any project state is created. Actual policy fingerprints are added
|
|
67
68
|
// under the install lock after policy validation.
|
|
@@ -70,6 +71,7 @@ async function readNpmWorkspaceImport(root, project, options) {
|
|
|
70
71
|
scripts: scriptPolicyFingerprint(undefined),
|
|
71
72
|
config: configFingerprint({
|
|
72
73
|
registry: options.registry.origin,
|
|
74
|
+
registries: options.registry.scopedRegistries,
|
|
73
75
|
linker: "shared",
|
|
74
76
|
}),
|
|
75
77
|
});
|
|
@@ -79,6 +81,7 @@ export async function installWorkspaceProject(options) {
|
|
|
79
81
|
const root = await findWorkspaceRoot(options.projectDir);
|
|
80
82
|
if (!root)
|
|
81
83
|
throw lockMismatch("no authoritative workspace root");
|
|
84
|
+
workspaceOverrides(await discoverWorkspaces(root));
|
|
82
85
|
// Refuse untranslatable locks before creating control directories or
|
|
83
86
|
// recovering a previous generation. Revalidate under the project lock below.
|
|
84
87
|
if (options.importNpm)
|
|
@@ -98,10 +101,9 @@ export async function installWorkspaceProject(options) {
|
|
|
98
101
|
await readFile(path.join(i.directory, "package.json"), "utf8"),
|
|
99
102
|
])));
|
|
100
103
|
const mutation = await prepareWorkspaceMutation(project, options);
|
|
101
|
-
if (manifest.
|
|
102
|
-
manifest.bundledDependencies !== undefined ||
|
|
104
|
+
if (manifest.bundledDependencies !== undefined ||
|
|
103
105
|
manifest.bundleDependencies !== undefined)
|
|
104
|
-
unsupported("Workspace
|
|
106
|
+
unsupported("Workspace bundled root dependencies are unsupported.");
|
|
105
107
|
const policy = object(manifest.zyrk) ? manifest.zyrk.scripts : undefined;
|
|
106
108
|
if (manifest.zyrk !== undefined &&
|
|
107
109
|
(!object(manifest.zyrk) ||
|
|
@@ -131,6 +133,7 @@ export async function installWorkspaceProject(options) {
|
|
|
131
133
|
scripts: scriptPolicyFingerprint(policy),
|
|
132
134
|
config: configFingerprint({
|
|
133
135
|
registry: options.registry.origin,
|
|
136
|
+
registries: options.registry.scopedRegistries,
|
|
134
137
|
linker: "shared",
|
|
135
138
|
platform: currentPlatform(),
|
|
136
139
|
...(mutable !== undefined
|
|
@@ -144,7 +147,7 @@ export async function installWorkspaceProject(options) {
|
|
|
144
147
|
: undefined;
|
|
145
148
|
let existing = options.importNpm
|
|
146
149
|
? null
|
|
147
|
-
: await readWorkspaceLock(root, project, options.registry.
|
|
150
|
+
: await readWorkspaceLock(root, project, (name) => options.registry.originFor(name)), graph = imported;
|
|
148
151
|
if (existing) {
|
|
149
152
|
const ext = existing.doc.zyrk;
|
|
150
153
|
if (!mutation.changed &&
|
|
@@ -160,6 +163,7 @@ export async function installWorkspaceProject(options) {
|
|
|
160
163
|
throw lockMismatch("offline/frozen workspace install needs a compatible lock");
|
|
161
164
|
graph = await resolveWorkspaceGraph(project, {
|
|
162
165
|
origin: options.registry.origin,
|
|
166
|
+
originFor: (name) => options.registry.originFor(name),
|
|
163
167
|
packument: (name) => options.registry.packument(name, {
|
|
164
168
|
signal: operation.operation.signal,
|
|
165
169
|
}),
|
|
@@ -264,7 +268,9 @@ export async function installWorkspaceProject(options) {
|
|
|
264
268
|
throw new ZyrkError("ZYRK_OFFLINE_MISSING", `Verified workspace dependency ${node.name}@${node.version} is missing.`, {
|
|
265
269
|
remedy: "Fetch the exact locked sources online before retrying offline.",
|
|
266
270
|
});
|
|
267
|
-
const archive = path.join(txn.dir, `${node.sourceId}.tgz`), download = await options.registry
|
|
271
|
+
const archive = path.join(txn.dir, `${node.sourceId}.tgz`), download = await options.registry
|
|
272
|
+
.forPackage(node.name)
|
|
273
|
+
.downloadTarball({
|
|
268
274
|
url: node.tarballUrl,
|
|
269
275
|
expectedIntegrity: node.integrity,
|
|
270
276
|
destPath: archive,
|
|
@@ -508,6 +514,10 @@ export async function installWorkspaceProject(options) {
|
|
|
508
514
|
instances: registration.instances,
|
|
509
515
|
activeContexts: registration.contexts,
|
|
510
516
|
lockDigest: sha512Hex(canonicalJson(doc)),
|
|
517
|
+
registryConfig: {
|
|
518
|
+
registry: options.registry.origin,
|
|
519
|
+
registries: options.registry.scopedRegistries,
|
|
520
|
+
},
|
|
511
521
|
graphDigest: graphHash(sourceGraph),
|
|
512
522
|
platform: process.platform,
|
|
513
523
|
arch: process.arch,
|
|
@@ -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): Promise<{
|
|
12
|
+
export declare function readWorkspaceLock(root: string, project?: WorkspaceProject, registryOrigin?: string | ((name: string) => string)): 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,CAyCZ;AACD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAgTrE;AACD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,gBAAgB,EAC1B,cAAc,CAAC,EAAE,MAAM,
|
|
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,CAyCZ;AACD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAgTrE;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,GACnD,OAAO,CAAC;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GAAG,IAAI,CAAC,CA2C5D"}
|
|
@@ -333,7 +333,11 @@ export async function readWorkspaceLock(root, project, registryOrigin) {
|
|
|
333
333
|
throw lockMismatch("workspace importer is missing");
|
|
334
334
|
}
|
|
335
335
|
if (registryOrigin &&
|
|
336
|
-
graph.nodes.some((n) => n.kind === "registry" &&
|
|
336
|
+
graph.nodes.some((n) => n.kind === "registry" &&
|
|
337
|
+
n.origin !==
|
|
338
|
+
(typeof registryOrigin === "string"
|
|
339
|
+
? registryOrigin
|
|
340
|
+
: registryOrigin(n.name))))
|
|
337
341
|
throw lockMismatch("workspace registry origin differs");
|
|
338
342
|
return { doc: doc, graph };
|
|
339
343
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-mutation.d.ts","sourceRoot":"","sources":["../../src/install/workspace-mutation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAiB3D,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"workspace-mutation.d.ts","sourceRoot":"","sources":["../../src/install/workspace-mutation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAiB3D,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAc3E;AACD,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC;IACT,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACpC,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC,CA8ID"}
|
|
@@ -18,7 +18,10 @@ export function refreshWorkspaceFingerprint(project) {
|
|
|
18
18
|
member.id,
|
|
19
19
|
member.manifest.name ?? null,
|
|
20
20
|
member.manifest.version ?? null,
|
|
21
|
-
manifestFingerprint(
|
|
21
|
+
manifestFingerprint({
|
|
22
|
+
...member.manifest,
|
|
23
|
+
overrides: member.id === "." ? member.manifest.overrides : undefined,
|
|
24
|
+
}),
|
|
22
25
|
])));
|
|
23
26
|
}
|
|
24
27
|
export async function prepareWorkspaceMutation(project, options) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type OverrideContext } from "../resolve/overrides.ts";
|
|
2
|
+
import { type WorkspaceProject } from "./workspaces.ts";
|
|
3
|
+
export declare function workspaceOverrides(project: WorkspaceProject): {
|
|
4
|
+
policy: import("../resolve/overrides.ts").OverridePolicy;
|
|
5
|
+
contexts: Map<string, OverrideContext>;
|
|
6
|
+
};
|
|
7
|
+
/** Internal signal: restart pure planning before any fetch/publication mutation. */
|
|
8
|
+
export declare class WorkspaceOverrideRestart extends Error {
|
|
9
|
+
}
|
|
10
|
+
export declare function refineWorkspaceOverride(contexts: Map<string, OverrideContext>, key: string, incoming: OverrideContext): void;
|
|
11
|
+
//# sourceMappingURL=workspace-overrides.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-overrides.d.ts","sourceRoot":"","sources":["../../src/install/workspace-overrides.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,iBAAiB,CAAC;AAWzB,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB;;;EAuD3D;AACD,oFAAoF;AACpF,qBAAa,wBAAyB,SAAQ,KAAK;CAAG;AACtD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACtC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,eAAe,GACxB,IAAI,CASN"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** Live importers have one dependency graph; compatible scopes may narrow it. */
|
|
2
|
+
import { satisfies } from "semver";
|
|
3
|
+
import { createRootOverrides, } from "../resolve/overrides.js";
|
|
4
|
+
import { parseRequirement } from "../resolve/spec.js";
|
|
5
|
+
import { planWorkspaceDependencies, } from "./workspaces.js";
|
|
6
|
+
import { lockMismatch } from "./lock.js";
|
|
7
|
+
function ancestor(outer, inner) {
|
|
8
|
+
for (let current = inner; current; current = current.parent)
|
|
9
|
+
if (current === outer)
|
|
10
|
+
return true;
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
export function workspaceOverrides(project) {
|
|
14
|
+
const policy = createRootOverrides(project.importers.find((i) => i.id === ".").manifest);
|
|
15
|
+
const contexts = new Map();
|
|
16
|
+
const plans = planWorkspaceDependencies(project);
|
|
17
|
+
for (const importer of project.importers)
|
|
18
|
+
contexts.set(`workspace:${importer.id}`, importer.id === "."
|
|
19
|
+
? policy.root
|
|
20
|
+
: policy.select(policy.root, importer.manifest.name, importer.manifest.version).context);
|
|
21
|
+
for (let round = 0; round <= 128; round++) {
|
|
22
|
+
let changed = false;
|
|
23
|
+
for (const plan of plans) {
|
|
24
|
+
const parent = contexts.get(`workspace:${plan.importer.id}`);
|
|
25
|
+
for (const edge of plan.dependencies) {
|
|
26
|
+
const selected = policy.select(parent, edge.name, edge.spec);
|
|
27
|
+
const localId = edge.selection.kind === "local" ? edge.selection.importer : undefined;
|
|
28
|
+
let local = project.importers.find((i) => i.id === localId);
|
|
29
|
+
if (selected.spec !== edge.spec) {
|
|
30
|
+
const requirement = parseRequirement(edge.name, selected.spec);
|
|
31
|
+
local = project.importers.find((i) => i.id !== "." &&
|
|
32
|
+
i.manifest.name === requirement.realName &&
|
|
33
|
+
requirement.kind !== "alias" &&
|
|
34
|
+
requirement.targetKind !== "tag" &&
|
|
35
|
+
satisfies(i.manifest.version, requirement.targetSpec));
|
|
36
|
+
}
|
|
37
|
+
if (!local)
|
|
38
|
+
continue;
|
|
39
|
+
const key = `workspace:${local.id}`, current = contexts.get(key);
|
|
40
|
+
if (ancestor(current, selected.context)) {
|
|
41
|
+
if (current !== selected.context) {
|
|
42
|
+
contexts.set(key, selected.context);
|
|
43
|
+
changed = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (!ancestor(selected.context, current)) {
|
|
47
|
+
throw lockMismatch("one live workspace cannot represent incompatible scoped override contexts");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!changed)
|
|
52
|
+
return { policy, contexts };
|
|
53
|
+
}
|
|
54
|
+
throw lockMismatch("workspace override propagation resource limit exceeded");
|
|
55
|
+
}
|
|
56
|
+
/** Internal signal: restart pure planning before any fetch/publication mutation. */
|
|
57
|
+
export class WorkspaceOverrideRestart extends Error {
|
|
58
|
+
}
|
|
59
|
+
export function refineWorkspaceOverride(contexts, key, incoming) {
|
|
60
|
+
const current = contexts.get(key);
|
|
61
|
+
if (current === incoming || ancestor(incoming, current))
|
|
62
|
+
return;
|
|
63
|
+
if (!ancestor(current, incoming))
|
|
64
|
+
throw lockMismatch("one live workspace cannot represent incompatible scoped override contexts");
|
|
65
|
+
contexts.set(key, incoming);
|
|
66
|
+
throw new WorkspaceOverrideRestart();
|
|
67
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/install/workspaces.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4EAA4E;IAC5E,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,0EAA0E;IAC1E,MAAM,EAAE;QAAE,IAAI,EAAE,gBAAgB,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9E,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AA2GF,kFAAkF;AAClF,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7D,OAAO,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/install/workspaces.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4EAA4E;IAC5E,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,0EAA0E;IAC1E,MAAM,EAAE;QAAE,IAAI,EAAE,gBAAgB,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9E,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AA2GF,kFAAkF;AAClF,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7D,OAAO,CAAC,gBAAgB,CAAC,CAgG3B;AACD,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;IAC3C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,EACL;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACnC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,WAAW,EAAE,iBAAiB,CAAA;KAAE,CAAC;CAC1D,CAAC;AACF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,YAAY,EAAE,mBAAmB,EAAE,CAAC;CACrC,CAAC;AACF,8FAA8F;AAC9F,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,gBAAgB,GACxB,qBAAqB,EAAE,CAmFzB;AACD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,iBAAiB,EAAE,CAerB;AACD,0FAA0F;AAC1F,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAChD,MAAM,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAC9C,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,GAAG,IAAI,CA+BP;AAED,sFAAsF;AACtF,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,qBAAqB,EAAE,GACrC,MAAM,EAAE,CAoCV;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiC3E"}
|
|
@@ -164,7 +164,10 @@ export async function discoverWorkspaces(rootDirectory, options = {}) {
|
|
|
164
164
|
member.id,
|
|
165
165
|
member.manifest.name ?? null,
|
|
166
166
|
member.manifest.version ?? null,
|
|
167
|
-
manifestFingerprint(
|
|
167
|
+
manifestFingerprint({
|
|
168
|
+
...member.manifest,
|
|
169
|
+
overrides: member.id === "." ? member.manifest.overrides : undefined,
|
|
170
|
+
}),
|
|
168
171
|
]))),
|
|
169
172
|
};
|
|
170
173
|
}
|