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.
Files changed (49) hide show
  1. package/README.md +10 -2
  2. package/VERSION +1 -1
  3. package/dist/commands/deploy.d.ts.map +1 -1
  4. package/dist/commands/deploy.js +7 -11
  5. package/dist/commands/maintenance.d.ts.map +1 -1
  6. package/dist/commands/maintenance.js +22 -2
  7. package/dist/fetch/package.d.ts.map +1 -1
  8. package/dist/fetch/package.js +2 -1
  9. package/dist/fetch/registry.d.ts +5 -0
  10. package/dist/fetch/registry.d.ts.map +1 -1
  11. package/dist/fetch/registry.js +84 -10
  12. package/dist/install/import-npm-workspace.d.ts +2 -1
  13. package/dist/install/import-npm-workspace.d.ts.map +1 -1
  14. package/dist/install/import-npm-workspace.js +34 -12
  15. package/dist/install/import-npm.d.ts +3 -1
  16. package/dist/install/import-npm.d.ts.map +1 -1
  17. package/dist/install/import-npm.js +14 -9
  18. package/dist/install/registry-policy.d.ts +9 -0
  19. package/dist/install/registry-policy.d.ts.map +1 -0
  20. package/dist/install/registry-policy.js +30 -0
  21. package/dist/install/registry.d.ts.map +1 -1
  22. package/dist/install/registry.js +18 -13
  23. package/dist/install/run.d.ts.map +1 -1
  24. package/dist/install/run.js +22 -5
  25. package/dist/install/workspace-graph.d.ts +7 -1
  26. package/dist/install/workspace-graph.d.ts.map +1 -1
  27. package/dist/install/workspace-graph.js +53 -9
  28. package/dist/install/workspace-install.d.ts.map +1 -1
  29. package/dist/install/workspace-install.js +16 -6
  30. package/dist/install/workspace-lock.d.ts +1 -1
  31. package/dist/install/workspace-lock.d.ts.map +1 -1
  32. package/dist/install/workspace-lock.js +5 -1
  33. package/dist/install/workspace-mutation.d.ts.map +1 -1
  34. package/dist/install/workspace-mutation.js +4 -1
  35. package/dist/install/workspace-overrides.d.ts +11 -0
  36. package/dist/install/workspace-overrides.d.ts.map +1 -0
  37. package/dist/install/workspace-overrides.js +67 -0
  38. package/dist/install/workspaces.d.ts.map +1 -1
  39. package/dist/install/workspaces.js +4 -1
  40. package/dist/lockfile/fingerprints.d.ts +1 -0
  41. package/dist/lockfile/fingerprints.d.ts.map +1 -1
  42. package/dist/lockfile/fingerprints.js +16 -1
  43. package/dist/resolve/overrides.d.ts +19 -0
  44. package/dist/resolve/overrides.d.ts.map +1 -0
  45. package/dist/resolve/overrides.js +142 -0
  46. package/dist/resolve/resolver.d.ts +3 -0
  47. package/dist/resolve/resolver.d.ts.map +1 -1
  48. package/dist/resolve/resolver.js +62 -18
  49. 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,CAwI1B"}
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"}
@@ -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
- throw new ZyrkError("ZYRK_POLICY_DENIED", "Scoped registry routing is not supported by native commands yet.", {
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
- 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
- });
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;AAWtB,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;AA6GF,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA4wBxB"}
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"}
@@ -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, overrides, and bundled dependencies are not supported by install yet.");
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.origin);
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.origin)
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.downloadTarball({
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
- export declare function resolveWorkspaceGraph(project: WorkspaceProject, provider: MetadataProvider, options?: {
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":"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"}
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
- export async function resolveWorkspaceGraph(project, provider, options = {}) {
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
- return graph.importers[local.id];
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
- if (!cleanUrl(provider.origin) || !cleanUrl(entry.dist.tarball))
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: provider.origin,
180
+ origin,
169
181
  integrity,
170
182
  }),
171
- origin: provider.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, range] of Object.entries(manifest.peerDependencies ?? {}).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {
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,CAopBxB"}
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.origin);
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.overrides !== undefined ||
102
- manifest.bundledDependencies !== undefined ||
104
+ if (manifest.bundledDependencies !== undefined ||
103
105
  manifest.bundleDependencies !== undefined)
104
- unsupported("Workspace overrides and bundled root dependencies are unsupported.");
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.origin), graph = imported;
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.downloadTarball({
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,GACtB,OAAO,CAAC;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GAAG,IAAI,CAAC,CAsC5D"}
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" && n.origin !== registryOrigin))
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,CAW3E;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"}
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(member.manifest),
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,CA4F3B;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"}
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(member.manifest),
167
+ manifestFingerprint({
168
+ ...member.manifest,
169
+ overrides: member.id === "." ? member.manifest.overrides : undefined,
170
+ }),
168
171
  ]))),
169
172
  };
170
173
  }