zyrk 0.5.3 → 0.5.4

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 CHANGED
@@ -367,3 +367,8 @@ recorded in the manifest fingerprint; frozen installs reject policy drift.
367
367
  preparation, resolution, verified source counts, realization, approved builds,
368
368
  and project linking on stderr. Interactive terminals show an activity spinner;
369
369
  redirected output contains plain phase messages. `--json` disables progress.
370
+
371
+ Install resolution has a five-minute deadline; each archive extraction has a
372
+ two-minute deadline. Set `ZYRK_RESOLVE_TIMEOUT_MS` or `ZYRK_EXTRACT_TIMEOUT_MS`
373
+ to an integer from `1` to `900000` milliseconds to adjust these timeouts.
374
+ Graph, archive-entry, and byte limits still apply.
package/VERSION CHANGED
@@ -1 +1 @@
1
- v0.5.3
1
+ v0.5.4
@@ -0,0 +1,7 @@
1
+ import type { ResolverLimits } from "../resolve/resolver.ts";
2
+ import type { ExtractionLimits } from "../extract/tarball.ts";
3
+ export declare function installBudgets(env: NodeJS.ProcessEnv): {
4
+ resolveBudget: Partial<ResolverLimits>;
5
+ extractBudget: Partial<ExtractionLimits>;
6
+ };
7
+ //# sourceMappingURL=budgets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budgets.d.ts","sourceRoot":"","sources":["../../src/install/budgets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAwB9D,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG;IACtD,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACvC,aAAa,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC1C,CASA"}
@@ -0,0 +1,25 @@
1
+ /** Public, bounded install timeout configuration. Node and byte limits stay intact. */
2
+ import { ZyrkError } from "../errors.js";
3
+ function timeout(env, key, fallback) {
4
+ const raw = env[key];
5
+ if (raw === undefined)
6
+ return fallback;
7
+ if (!/^[0-9]+$/.test(raw) ||
8
+ !Number.isSafeInteger(Number(raw)) ||
9
+ Number(raw) < 1 ||
10
+ Number(raw) > 900000)
11
+ throw new ZyrkError("ZYRK_POLICY_DENIED", `Cannot configure install: ${key} must be an integer from 1 to 900000.`, {
12
+ remedy: `Set ${key} to a timeout in milliseconds from 1 to 900000, or unset it to use the default.`,
13
+ });
14
+ return Number(raw);
15
+ }
16
+ export function installBudgets(env) {
17
+ return {
18
+ resolveBudget: {
19
+ deadlineMs: timeout(env, "ZYRK_RESOLVE_TIMEOUT_MS", 300000),
20
+ },
21
+ extractBudget: {
22
+ maxDurationMs: timeout(env, "ZYRK_EXTRACT_TIMEOUT_MS", 120000),
23
+ },
24
+ };
25
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"import-npm.d.ts","sourceRoot":"","sources":["../../src/install/import-npm.ts"],"names":[],"mappings":"AAAA,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,CAqLhB"}
1
+ {"version":3,"file":"import-npm.d.ts","sourceRoot":"","sources":["../../src/install/import-npm.ts"],"names":[],"mappings":"AAAA,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,CAyMhB"}
@@ -2,7 +2,7 @@
2
2
  import { createRootOverrides, } from "../resolve/overrides.js";
3
3
  import { validateLockDoc } from "../lockfile/read.js";
4
4
  import { canonicalStrongSri } from "../util/integrity.js";
5
- import { valid, satisfies } from "semver";
5
+ import { valid, validRange, satisfies } from "semver";
6
6
  import { parseRequirement } from "../resolve/spec.js";
7
7
  import { sourceIdOf, sha512Hex } from "../util/hash.js";
8
8
  import { cleanUrl, lockMismatch, packageName } from "./lock.js";
@@ -76,12 +76,28 @@ export function importNpmLock(doc, requirements, origin, overrides = createRootO
76
76
  peerBindings: [],
77
77
  };
78
78
  if (entry.engines !== undefined) {
79
- if (typeof entry.engines !== "object" ||
80
- entry.engines === null ||
81
- Array.isArray(entry.engines) ||
82
- Object.values(entry.engines).some((value) => typeof value !== "string"))
83
- throw lockMismatch("invalid npm engine constraint");
84
- node.engines = entry.engines;
79
+ if (Array.isArray(entry.engines)) {
80
+ // Old npm manifests used ["node >= 0.2.0"] instead of an engine map.
81
+ const engines = {};
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
+ }
85
101
  }
86
102
  if (typeof entry.bin === "object" &&
87
103
  entry.bin !== null &&
@@ -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,CA6M3D;AAED,kFAAkF;AAClF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAK,GAAG,IAAI,CAmC3E"}
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,CA6M3D;AAUD,kFAAkF;AAClF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAK,GAAG,IAAI,CAM3E"}
@@ -201,10 +201,20 @@ export function lockedGraph(doc) {
201
201
  }
202
202
  return { nodes, roots };
203
203
  }
204
+ // npm publishes this canonical GitHub sponsorship link in funding metadata.
205
+ // Keep source/archive URL validation query-free, and allow no other query here.
206
+ function githubFundingUrl(value) {
207
+ return /^https:\/\/github\.com\/[A-Za-z0-9_-]+\/[A-Za-z0-9_.-]+\?sponsor=1$/.test(value);
208
+ }
204
209
  /** Preserved metadata is subject to the same portability boundary as new data. */
205
210
  export function assertPortableLockMetadata(value, field = "") {
211
+ visitPortableLockMetadata(value, field, field === "funding" ? "entry" : undefined);
212
+ }
213
+ function visitPortableLockMetadata(value, field, funding) {
206
214
  if (typeof value === "string") {
207
- if (/^(?:https?:|file:|git\+|ssh:)/i.test(value) && !cleanUrl(value))
215
+ if (/^(?:https?:|file:|git\+|ssh:)/i.test(value) &&
216
+ !cleanUrl(value) &&
217
+ !(funding && githubFundingUrl(value)))
208
218
  throw lockMismatch("portable metadata contains an unsafe URL");
209
219
  if (value.startsWith("/") || /^[A-Za-z]:[\\/]/.test(value))
210
220
  throw lockMismatch("portable metadata contains a local path");
@@ -212,7 +222,7 @@ export function assertPortableLockMetadata(value, field = "") {
212
222
  }
213
223
  if (Array.isArray(value)) {
214
224
  for (const item of value)
215
- assertPortableLockMetadata(item, field);
225
+ visitPortableLockMetadata(item, field, funding === "entry" ? "entry" : undefined);
216
226
  return;
217
227
  }
218
228
  if (value && typeof value === "object")
@@ -234,6 +244,10 @@ export function assertPortableLockMetadata(value, field = "") {
234
244
  ".",
235
245
  ].includes(field))
236
246
  throw lockMismatch("portable metadata contains a credential field");
237
- assertPortableLockMetadata(item, key);
247
+ visitPortableLockMetadata(item, key, key === "funding"
248
+ ? "entry"
249
+ : funding === "entry" && key === "url"
250
+ ? "url"
251
+ : undefined);
238
252
  }
239
253
  }
@@ -1,5 +1,7 @@
1
1
  import { type BuildCandidate } from "./private.ts";
2
2
  import { RegistryClient } from "../fetch/registry.ts";
3
+ import type { ResolverLimits } from "../resolve/resolver.ts";
4
+ import type { ExtractionLimits } from "../extract/tarball.ts";
3
5
  import { Store } from "../store/layout.ts";
4
6
  export type InstallProgress = {
5
7
  phase: "planning" | "resolving" | "fetching" | "realizing" | "building" | "linking";
@@ -32,6 +34,8 @@ export type InstallOptions = {
32
34
  approveBuilds?: readonly string[];
33
35
  rebuild?: boolean;
34
36
  repair?: boolean;
37
+ resolveBudget?: Partial<ResolverLimits>;
38
+ extractBudget?: Partial<ExtractionLimits>;
35
39
  fetchBudget?: {
36
40
  maxArchiveBytes?: number;
37
41
  maxExpandedBytes?: number;
@@ -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;AAYtB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAgC3C,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,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,CA8zBxB"}
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;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;AAgC3C,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,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,CAs0BxB"}
@@ -15,6 +15,7 @@ import npa from "npm-package-arg";
15
15
  import { satisfies } from "semver";
16
16
  import { ZyrkError } from "../errors.js";
17
17
  import { RegistryClient } from "../fetch/registry.js";
18
+ import { installBudgets } from "./budgets.js";
18
19
  import { extractTarball } from "../extract/tarball.js";
19
20
  import { commitExtractedSource } from "../store/source.js";
20
21
  import { Store } from "../store/layout.js";
@@ -94,6 +95,12 @@ function scriptPolicy(manifest) {
94
95
  }
95
96
  export async function installProject(options) {
96
97
  options.onProgress?.({ phase: "planning" });
98
+ const budgets = installBudgets(options.env ?? process.env);
99
+ options = {
100
+ ...options,
101
+ resolveBudget: { ...budgets.resolveBudget, ...options.resolveBudget },
102
+ extractBudget: { ...budgets.extractBudget, ...options.extractBudget },
103
+ };
97
104
  if (await findWorkspaceRoot(options.projectDir)) {
98
105
  const { installWorkspaceProject } = await import("./workspace-install.js");
99
106
  return installWorkspaceProject(options);
@@ -252,6 +259,7 @@ export async function installProject(options) {
252
259
  options.onProgress?.({ phase: "resolving" });
253
260
  resolved = await resolveRequirements({
254
261
  overrides,
262
+ limits: options.resolveBudget,
255
263
  provider: {
256
264
  origin: options.registry.origin,
257
265
  originFor: (name) => options.registry.originFor(name),
@@ -493,6 +501,7 @@ export async function installProject(options) {
493
501
  label: `${node.name}@${node.version}`,
494
502
  });
495
503
  const extracted = await extractTarball({
504
+ limits: options.extractBudget,
496
505
  signal: operation.operation.signal,
497
506
  onExpandedBytes: operation.operation.consumeExpandedBytes,
498
507
  tarballPath: tarball,
@@ -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,CA6qBxB"}
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,CA+qBxB"}
@@ -171,6 +171,7 @@ export async function installWorkspaceProject(options) {
171
171
  }, {
172
172
  ...(existing ? { previous: existing.graph } : {}),
173
173
  fresh: mutation.fresh,
174
+ ...options.resolveBudget,
174
175
  });
175
176
  }
176
177
  assertWorkspacePlatform(graph);
@@ -287,6 +288,7 @@ export async function installWorkspaceProject(options) {
287
288
  onBytes: operation.operation.consumeArchiveBytes,
288
289
  });
289
290
  const extraction = await extractTarball({
291
+ limits: options.extractBudget,
290
292
  tarballPath: archive,
291
293
  destDir: path.join(txn.dir, node.sourceId),
292
294
  signal: operation.operation.signal,
@@ -1 +1 @@
1
- {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/resolve/spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAElE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,eAAe,CAAC;IACtB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;CACvC,CAAC;AAcF;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,iBAAiB,CAqFnB"}
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/resolve/spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAElE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,eAAe,CAAC;IACtB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;CACvC,CAAC;AAcF;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,iBAAiB,CA6FnB"}
@@ -7,6 +7,7 @@
7
7
  * explicitly — they are never handed to a tool that might run scripts.
8
8
  */
9
9
  import npa from "npm-package-arg";
10
+ import { SemVer } from "semver";
10
11
  import { ZyrkError } from "../errors.js";
11
12
  function unsupported(what, spec) {
12
13
  return new ZyrkError("ZYRK_RESOLUTION_FAILED", `unsupported dependency protocol in "${spec}" (${what})`, {
@@ -46,7 +47,13 @@ export function parseRequirement(edgeName, spec) {
46
47
  edgeName,
47
48
  realName: parsed.name,
48
49
  kind: "exact",
49
- targetSpec: parsed.fetchSpec,
50
+ // npm accepts = and v prefixes for exact versions. SemVer.format()
51
+ // omits build metadata, so append it explicitly for registry lookup.
52
+ targetSpec: (() => {
53
+ const version = new SemVer(parsed.fetchSpec.replace(/^[=v\s]+/, ""));
54
+ return (version.version +
55
+ (version.build.length ? `+${version.build.join(".")}` : ""));
56
+ })(),
50
57
  targetKind: "exact",
51
58
  };
52
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zyrk",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Storage-efficient Node package manager: one verified store per user, shared across projects through links.",
5
5
  "license": "MIT",
6
6
  "type": "module",