zyrk 0.6.6 → 0.7.1
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 +96 -24
- package/VERSION +1 -1
- package/bin/zyrk.js +1 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +90 -2
- package/dist/commands/dependencies.d.ts +1 -0
- package/dist/commands/dependencies.d.ts.map +1 -1
- package/dist/commands/dependencies.js +3 -0
- package/dist/fetch/registry.d.ts +8 -0
- package/dist/fetch/registry.d.ts.map +1 -1
- package/dist/fetch/registry.js +37 -3
- package/dist/install/budgets.d.ts +5 -0
- package/dist/install/budgets.d.ts.map +1 -1
- package/dist/install/budgets.js +11 -4
- package/dist/install/platform.d.ts +4 -0
- package/dist/install/platform.d.ts.map +1 -1
- package/dist/install/platform.js +11 -0
- package/dist/install/private.d.ts +9 -0
- package/dist/install/private.d.ts.map +1 -1
- package/dist/install/private.js +71 -14
- package/dist/install/registry.d.ts.map +1 -1
- package/dist/install/registry.js +2 -0
- package/dist/install/run.d.ts +1 -0
- package/dist/install/run.d.ts.map +1 -1
- package/dist/install/run.js +41 -10
- package/dist/install/workspace-install.d.ts.map +1 -1
- package/dist/install/workspace-install.js +35 -7
- package/dist/lockfile/write.d.ts.map +1 -1
- package/dist/lockfile/write.js +16 -0
- package/dist/resolve/resolver.d.ts +2 -1
- package/dist/resolve/resolver.d.ts.map +1 -1
- package/dist/resolve/resolver.js +33 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,6 +27,14 @@ the shared store, exact dependency context, mutation rules, and cleanup contract
|
|
|
27
27
|
central to its design. Storage savings, speed, and framework compatibility will
|
|
28
28
|
be reported only after reproducible measurements and compatibility tests.
|
|
29
29
|
|
|
30
|
+
### The name and the idea
|
|
31
|
+
|
|
32
|
+
The project began as **snpm**, short for “space-efficient npm.” That name was
|
|
33
|
+
already in use, so it became **nexu**; npm's package-name similarity policy
|
|
34
|
+
then blocked publishing that name, and the project became **zyrk**. The names
|
|
35
|
+
changed, while the goal stayed the same: make shared package storage practical,
|
|
36
|
+
careful, and useful in everyday Node.js development.
|
|
37
|
+
|
|
30
38
|
## Try the current CLI
|
|
31
39
|
|
|
32
40
|
Install from npm:
|
|
@@ -46,11 +54,17 @@ From a checkout:
|
|
|
46
54
|
```bash
|
|
47
55
|
git clone https://github.com/kingjethro999/zyrk.git zyrk
|
|
48
56
|
cd zyrk
|
|
49
|
-
npm
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
npm install --global zyrk@0.6.6
|
|
58
|
+
zyrk install --frozen-lockfile
|
|
59
|
+
zyrk --help
|
|
60
|
+
zyrk --version
|
|
52
61
|
```
|
|
53
62
|
|
|
63
|
+
The global npm install bootstraps the `zyrk` executable. Project dependencies
|
|
64
|
+
are installed by zyrk itself. On a fresh checkout, use the published bootstrap
|
|
65
|
+
version first because the source checkout's own development dependencies are
|
|
66
|
+
needed to run its local CLI.
|
|
67
|
+
|
|
54
68
|
### One-line install (shell)
|
|
55
69
|
|
|
56
70
|
Linux / macOS:
|
|
@@ -90,8 +104,12 @@ Offline installs use locked verified sources and fail if an input is missing.
|
|
|
90
104
|
Manifest, lock, and projection changes are journaled for process-crash recovery;
|
|
91
105
|
a failed resolution, verification, or build-policy check keeps the prior graph.
|
|
92
106
|
|
|
93
|
-
Dependency install
|
|
94
|
-
|
|
107
|
+
Dependency `preinstall`, `install`, and `postinstall` scripts (plus implicit
|
|
108
|
+
`binding.gyp` builds) are supported. In an interactive terminal, `zyrk install`
|
|
109
|
+
shows the exact candidates and lets you select which scripts to run. Press Enter
|
|
110
|
+
to skip all pending scripts and continue with an intentionally unbuilt install.
|
|
111
|
+
Headless installs also skip unapproved scripts and report that readiness state.
|
|
112
|
+
Review candidates separately with:
|
|
95
113
|
|
|
96
114
|
```bash
|
|
97
115
|
zyrk approve-builds # inspect exact sources and commands; executes no package code
|
|
@@ -101,8 +119,12 @@ zyrk rebuild --offline # rebuild the complete approved locked graph
|
|
|
101
119
|
```
|
|
102
120
|
|
|
103
121
|
Approvals are local to the exact graph, sources, patch contents, and script
|
|
104
|
-
policy.
|
|
105
|
-
|
|
122
|
+
policy. Interactive selections are written to the checked-in
|
|
123
|
+
`zyrk-workspace.json` file with exact package source identities, so collaborators
|
|
124
|
+
can reuse the review alongside the lockfile. Manual `zyrk approve-builds
|
|
125
|
+
<package>` approvals are recorded there too. Mandatory user denies override
|
|
126
|
+
project approvals. Approved scripts run with your account's permissions;
|
|
127
|
+
permission is not a sandbox. Packages that need
|
|
106
128
|
writes use a complete private dependency generation under `.zyrk-local/`, with
|
|
107
129
|
independent writable files and dependency links confined to that generation.
|
|
108
130
|
Build failure keeps the previous project graph active. `--ignore-scripts`
|
|
@@ -111,6 +133,24 @@ hooks never run automatically. A project can request runtime writable packages
|
|
|
111
133
|
with `"zyrk": { "mutablePackages": ["package-name"] }`; this also uses a complete
|
|
112
134
|
private graph.
|
|
113
135
|
|
|
136
|
+
`zyrk-workspace.json` is portable review state, not a machine-specific store
|
|
137
|
+
manifest. It records each approved package name, version, and exact source ID;
|
|
138
|
+
the file can be committed with `package-lock.json` so collaborators do not have
|
|
139
|
+
to repeat the same approval for the same verified source. User-level denials
|
|
140
|
+
still take precedence.
|
|
141
|
+
|
|
142
|
+
### Run project scripts
|
|
143
|
+
|
|
144
|
+
Use `zyrk run <script>` or the package-manager shortcut `zyrk <script>`; both
|
|
145
|
+
use the same project-script policy, installed-generation checks, and local
|
|
146
|
+
binary path. Arguments after `--` are passed to the script:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
zyrk dev
|
|
150
|
+
zyrk test -- --watch
|
|
151
|
+
zyrk run build
|
|
152
|
+
```
|
|
153
|
+
|
|
114
154
|
Default registry and authentication settings are loaded from user/project
|
|
115
155
|
`.npmrc` for installation, dependency edits, `dlx`, and `create`. Environment
|
|
116
156
|
token placeholders are supported. Credentials are restricted to their configured
|
|
@@ -122,7 +162,10 @@ registry; private names never fall back to a public endpoint. Disabled TLS
|
|
|
122
162
|
verification is rejected before lookup. Git sources and non-workspace local sources remain unsupported;
|
|
123
163
|
they fail explicitly. Optional dependencies incompatible with the selected platform
|
|
124
164
|
are omitted; missing packages, integrity failures, and other optional failures
|
|
125
|
-
remain errors.
|
|
165
|
+
remain errors. Platform-specific optional packages that do not match this machine
|
|
166
|
+
are summarized once after installation; these are normal variants for packages
|
|
167
|
+
supporting multiple operating systems and CPUs. Locks retain exact
|
|
168
|
+
platform-qualified optional variants; each machine
|
|
126
169
|
selects its compatible local closure without rewriting the lock or recording store
|
|
127
170
|
paths. Older platform-pruned locks need an intentional non-frozen refresh; incomplete
|
|
128
171
|
npm locks must be freshly resolved before portable adoption. macOS, Windows, and
|
|
@@ -359,24 +402,34 @@ own options and configuration.
|
|
|
359
402
|
## Develop and contribute
|
|
360
403
|
|
|
361
404
|
```bash
|
|
362
|
-
npm
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
405
|
+
npm install --global zyrk@0.6.6 # bootstrap the CLI, once per machine
|
|
406
|
+
zyrk install --frozen-lockfile
|
|
407
|
+
zyrk run setup:hooks
|
|
408
|
+
zyrk run typecheck
|
|
409
|
+
zyrk run test
|
|
410
|
+
zyrk run check
|
|
411
|
+
zyrk run format:check
|
|
412
|
+
zyrk run format
|
|
369
413
|
```
|
|
370
414
|
|
|
415
|
+
Linux and macOS development, CI, and release verification use zyrk to install
|
|
416
|
+
the repository's dependencies. The Windows contract job continues to use npm
|
|
417
|
+
while native Windows filesystem and link behavior is being validated. npm is
|
|
418
|
+
also used to publish the package; that is a registry operation, not a project
|
|
419
|
+
dependency install. Vercel deployments should set the install command to
|
|
420
|
+
the commands in [web/vercel.json](web/vercel.json) and set the Vercel project
|
|
421
|
+
root directory to `web/`. The included site uses zyrk for project dependencies
|
|
422
|
+
after npm bootstraps the CLI.
|
|
423
|
+
|
|
371
424
|
The commit hook runs the full check gate, increments the version in
|
|
372
425
|
`package.json`, `package-lock.json`, and `VERSION`, and creates a matching version
|
|
373
426
|
tag after the commit. Keep changes focused and never bypass the hooks.
|
|
374
427
|
|
|
375
|
-
CI checks pushed commits and pull requests. The
|
|
376
|
-
[npm publishing action](.github/workflows/npm-publish.yml)
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
publish
|
|
428
|
+
CI checks pushed commits and pull requests. The
|
|
429
|
+
[npm publishing action](.github/workflows/npm-publish.yml) runs when the commit
|
|
430
|
+
hook's version tag is pushed, verifies formatting, typecheck, build, tests, and
|
|
431
|
+
the tag/version match, then publishes that exact commit. A manual workflow
|
|
432
|
+
dispatch can publish a prior version tag for release backfills. Dependabot and a scheduled advisory check supplement CI; an
|
|
380
433
|
unavailable advisory service fails separately from a clean result.
|
|
381
434
|
|
|
382
435
|
The contributor guide is [AGENTS.md](AGENTS.md). Bug reports and reproducible
|
|
@@ -412,10 +465,29 @@ lists each unique package/version linked after the project transaction commits.
|
|
|
412
465
|
Source counts differ from dependency contexts when peers split a package.
|
|
413
466
|
`--json` disables progress.
|
|
414
467
|
|
|
415
|
-
Install resolution has a five-minute deadline
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
468
|
+
Install resolution has a five-minute deadline, registry requests (including
|
|
469
|
+
archive downloads) have a fifteen-minute deadline, a complete fetch operation
|
|
470
|
+
has a fifteen-minute deadline, and each archive extraction has a two-minute
|
|
471
|
+
deadline. On a slow or unreliable connection, increase the request and complete
|
|
472
|
+
fetch deadlines together. For example, this gives a single request up to 30
|
|
473
|
+
minutes and the entire fetch phase up to 45 minutes:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
ZYRK_REQUEST_TIMEOUT_MS=1800000 ZYRK_FETCH_TIMEOUT_MS=2700000 zyrk install
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
To keep the settings for future commands in the current shell, use
|
|
480
|
+
`export ZYRK_REQUEST_TIMEOUT_MS=1800000` and
|
|
481
|
+
`export ZYRK_FETCH_TIMEOUT_MS=2700000`. Both values are milliseconds.
|
|
482
|
+
Resolution and extraction timeouts accept `1` to `900000` (15 minutes); request
|
|
483
|
+
and whole-fetch timeouts accept `1` to `3600000` (60 minutes). For a very slow
|
|
484
|
+
connection, the largest supported combination is:
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
ZYRK_REQUEST_TIMEOUT_MS=3600000 ZYRK_FETCH_TIMEOUT_MS=3600000 zyrk install
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
These are finite deadlines; graph, archive-entry, and byte limits still apply.
|
|
419
491
|
|
|
420
492
|
Platform gates run the complete check on Ubuntu and macOS/Node 24 and a
|
|
421
493
|
Windows CLI/artifact contract suite, including paths with spaces and Unicode.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v0.
|
|
1
|
+
v0.7.1
|
package/bin/zyrk.js
CHANGED
package/dist/cli/main.d.ts
CHANGED
package/dist/cli/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAe,SAAS,EAAe,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,CAAC;AACrB,OAAO,EAAoB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAM3C,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhF,eAAO,MAAM,uBAAuB,IAAI,CAAC;AA6DzC,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA0BhD;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA6EF;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,GACnD,SAAS,CAgDX;AAmBD,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC1B,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC1C,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;CACxC,CAAC;AAuDF,gFAAgF;AAChF,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA2fpE"}
|
package/dist/cli/main.js
CHANGED
|
@@ -12,6 +12,8 @@ import { sanitizeDiagnostic, redactSecrets } from "../log.js";
|
|
|
12
12
|
import { installProject } from "../install/run.js";
|
|
13
13
|
import { installRegistry } from "../install/registry.js";
|
|
14
14
|
import { readFileSync } from "node:fs";
|
|
15
|
+
import { readFile } from "node:fs/promises";
|
|
16
|
+
import { createInterface } from "node:readline/promises";
|
|
15
17
|
import * as path from "node:path";
|
|
16
18
|
import { fileURLToPath } from "node:url";
|
|
17
19
|
import { runCreate, starterSpecFor } from "../dlx/create.js";
|
|
@@ -22,7 +24,7 @@ import { runStoreCommand } from "../commands/store.js";
|
|
|
22
24
|
import { exitCodeFor, ZyrkError, toZyrkError } from "../errors.js";
|
|
23
25
|
export { ZyrkError };
|
|
24
26
|
import { DEFAULT_REGISTRY, RegistryClient } from "../fetch/registry.js";
|
|
25
|
-
import { resolveStoreRoot } from "../config/paths.js";
|
|
27
|
+
import { findProjectBoundary, resolveStoreRoot } from "../config/paths.js";
|
|
26
28
|
import { Store } from "../store/layout.js";
|
|
27
29
|
import { delegateToNpm, delegatedHelpLines, isDelegatedCommand, } from "./npm-delegate.js";
|
|
28
30
|
import { isGlobalInstallRequest, parseArgs } from "./parse.js";
|
|
@@ -89,6 +91,7 @@ export function helpText(version) {
|
|
|
89
91
|
`zyrk v${version} — one verified store per user, shared across projects through links.`,
|
|
90
92
|
"",
|
|
91
93
|
"Usage: zyrk <command> [args] [--json]",
|
|
94
|
+
" zyrk <script> [args] (shortcut for zyrk run <script> [args])",
|
|
92
95
|
"",
|
|
93
96
|
"Dependency commands:",
|
|
94
97
|
];
|
|
@@ -100,7 +103,7 @@ export function helpText(version) {
|
|
|
100
103
|
}
|
|
101
104
|
lines.push("", "Registry publishing and account commands (via your npm):");
|
|
102
105
|
lines.push(...delegatedHelpLines());
|
|
103
|
-
lines.push("", "Install timeouts: ZYRK_RESOLVE_TIMEOUT_MS and ZYRK_EXTRACT_TIMEOUT_MS (1..900000 ms).", "zyrk never installs packages globally and never runs npm to do it.", "Need a global package? Run npm directly: npm install --global <package-spec>");
|
|
106
|
+
lines.push("", "Install timeouts: ZYRK_RESOLVE_TIMEOUT_MS and ZYRK_EXTRACT_TIMEOUT_MS (1..900000 ms); ZYRK_REQUEST_TIMEOUT_MS (1..3600000 ms); ZYRK_FETCH_TIMEOUT_MS (1..3600000 ms).", "zyrk never installs packages globally and never runs npm to do it.", "Need a global package? Run npm directly: npm install --global <package-spec>");
|
|
104
107
|
return `${lines.join("\n")}\n`;
|
|
105
108
|
}
|
|
106
109
|
function ok(stdout, parsed) {
|
|
@@ -212,6 +215,39 @@ function readCliVersion() {
|
|
|
212
215
|
return "unknown";
|
|
213
216
|
}
|
|
214
217
|
}
|
|
218
|
+
async function promptForBuildApproval(builds, input, output) {
|
|
219
|
+
output.write("\nDependency lifecycle scripts need approval. Review these exact package sources:\n");
|
|
220
|
+
builds.forEach((build, index) => {
|
|
221
|
+
const stages = build.stages
|
|
222
|
+
.map((stage) => `${stage.name}: ${redactSecrets(stage.command)
|
|
223
|
+
.replace(/[\x00-\x1f\x7f-\x9f]/g, "")
|
|
224
|
+
.slice(0, 180)}`)
|
|
225
|
+
.join("; ");
|
|
226
|
+
output.write(` ${index + 1}. ${build.name}@${build.version} (${build.sourceId}) — ${stages}\n`);
|
|
227
|
+
});
|
|
228
|
+
output.write("Enter numbers separated by commas to approve selected sources, `all` to approve all listed sources, or press Enter to skip their scripts and continue unbuilt.\n");
|
|
229
|
+
const prompt = createInterface({
|
|
230
|
+
input,
|
|
231
|
+
output: output,
|
|
232
|
+
terminal: true,
|
|
233
|
+
});
|
|
234
|
+
try {
|
|
235
|
+
const answer = (await prompt.question("Approve builds> ")).trim();
|
|
236
|
+
if (!answer)
|
|
237
|
+
return [];
|
|
238
|
+
if (answer.toLowerCase() === "all")
|
|
239
|
+
return ["*"];
|
|
240
|
+
const numbers = answer.split(/[ ,]+/).map((value) => Number(value));
|
|
241
|
+
if (numbers.some((number) => !Number.isInteger(number) || number < 1 || number > builds.length))
|
|
242
|
+
throw new ZyrkError("ZYRK_USAGE", "Build selection contains an invalid candidate number.", {
|
|
243
|
+
remedy: `Select numbers from 1 to ${builds.length}, enter all, or press Enter to skip scripts.`,
|
|
244
|
+
});
|
|
245
|
+
return [...new Set(numbers)].map((number) => builds[number - 1].sourceId);
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
prompt.close();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
215
251
|
/** Parse, dispatch, delegate, or run a tool, and emit. The only impure seam. */
|
|
216
252
|
export async function runCli(options) {
|
|
217
253
|
const parsed = parseArgs(options.argv);
|
|
@@ -464,6 +500,11 @@ export async function runCli(options) {
|
|
|
464
500
|
env: options.env,
|
|
465
501
|
specs,
|
|
466
502
|
projectDir: cwd,
|
|
503
|
+
...(options.stdin?.isTTY && options.stderr.isTTY && !parsed.json
|
|
504
|
+
? {
|
|
505
|
+
requestBuildApproval: (builds) => promptForBuildApproval(builds, options.stdin, options.stderr),
|
|
506
|
+
}
|
|
507
|
+
: {}),
|
|
467
508
|
...tools,
|
|
468
509
|
});
|
|
469
510
|
progress.close();
|
|
@@ -520,6 +561,11 @@ export async function runCli(options) {
|
|
|
520
561
|
projectDir: options.cwd ?? process.cwd(),
|
|
521
562
|
store: tools.store,
|
|
522
563
|
registry: tools.registry,
|
|
564
|
+
...(options.stdin?.isTTY && options.stderr.isTTY && !parsed.json
|
|
565
|
+
? {
|
|
566
|
+
requestBuildApproval: (builds) => promptForBuildApproval(builds, options.stdin, options.stderr),
|
|
567
|
+
}
|
|
568
|
+
: {}),
|
|
523
569
|
});
|
|
524
570
|
progress.close();
|
|
525
571
|
if (parsed.json) {
|
|
@@ -602,6 +648,48 @@ export async function runCli(options) {
|
|
|
602
648
|
return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
|
|
603
649
|
}
|
|
604
650
|
}
|
|
651
|
+
// Package scripts are accepted as ergonomic aliases for `zyrk run <name>`.
|
|
652
|
+
// Route through the same project runner so policy, generation leases,
|
|
653
|
+
// local-bin PATH and lifecycle environment stay identical.
|
|
654
|
+
if (!parsed.help &&
|
|
655
|
+
!parsed.version &&
|
|
656
|
+
parsed.command !== undefined &&
|
|
657
|
+
!KNOWN_COMMANDS.has(parsed.command) &&
|
|
658
|
+
parsed.argsBeforeCommand.length === 0) {
|
|
659
|
+
const cwd = options.cwd ?? process.cwd();
|
|
660
|
+
const boundary = await findProjectBoundary(cwd);
|
|
661
|
+
if (boundary) {
|
|
662
|
+
let declared = false;
|
|
663
|
+
try {
|
|
664
|
+
const manifest = JSON.parse(await readFile(path.join(boundary, "package.json"), "utf8"));
|
|
665
|
+
if (manifest.scripts !== null &&
|
|
666
|
+
typeof manifest.scripts === "object" &&
|
|
667
|
+
!Array.isArray(manifest.scripts) &&
|
|
668
|
+
typeof manifest.scripts[parsed.command] === "string")
|
|
669
|
+
declared = true;
|
|
670
|
+
}
|
|
671
|
+
catch {
|
|
672
|
+
// Preserve the normal unknown-command diagnostic when no valid
|
|
673
|
+
// project script can be identified.
|
|
674
|
+
}
|
|
675
|
+
if (declared) {
|
|
676
|
+
try {
|
|
677
|
+
return await runProjectCommand({
|
|
678
|
+
command: "run",
|
|
679
|
+
args: [parsed.command, ...parsed.commandArgs],
|
|
680
|
+
cwd,
|
|
681
|
+
env: options.env,
|
|
682
|
+
stdout: options.stdout,
|
|
683
|
+
stderr: options.stderr,
|
|
684
|
+
json: parsed.json,
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
catch (error) {
|
|
688
|
+
return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
605
693
|
return emit(dispatch(parsed, { version, env: options.env }));
|
|
606
694
|
}
|
|
607
695
|
async function defaultTools(env, version, cwd = process.cwd()) {
|
|
@@ -10,5 +10,6 @@ export declare function runDependencyCommand(options: {
|
|
|
10
10
|
registry: RegistryClient;
|
|
11
11
|
env?: NodeJS.ProcessEnv;
|
|
12
12
|
onProgress?: InstallOptions["onProgress"];
|
|
13
|
+
requestBuildApproval?: InstallOptions["requestBuildApproval"];
|
|
13
14
|
}): Promise<InstallResult>;
|
|
14
15
|
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/commands/dependencies.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAavE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,OAAO,EAAE,iBAAiB,CAAC;IAC3B,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/commands/dependencies.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAavE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,OAAO,EAAE,iBAAiB,CAAC;IAC3B,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;IAC1C,oBAAoB,CAAC,EAAE,cAAc,CAAC,sBAAsB,CAAC,CAAC;CAC/D,GAAG,OAAO,CAAC,aAAa,CAAC,CA+HzB"}
|
|
@@ -16,6 +16,9 @@ export async function runDependencyCommand(options) {
|
|
|
16
16
|
registry: options.registry,
|
|
17
17
|
...(options.env ? { env: options.env } : {}),
|
|
18
18
|
...(options.onProgress ? { onProgress: options.onProgress } : {}),
|
|
19
|
+
...(options.requestBuildApproval
|
|
20
|
+
? { requestBuildApproval: options.requestBuildApproval }
|
|
21
|
+
: {}),
|
|
19
22
|
};
|
|
20
23
|
const names = [];
|
|
21
24
|
let from;
|
package/dist/fetch/registry.d.ts
CHANGED
|
@@ -13,6 +13,10 @@ import type { Logger } from "../log.ts";
|
|
|
13
13
|
import { type HashedBytes } from "../util/integrity.ts";
|
|
14
14
|
/** 512 MiB: large for an npm package, small enough to bound mishaps. */
|
|
15
15
|
export declare const DEFAULT_MAX_TARBALL_BYTES: number;
|
|
16
|
+
/** Bounds the complete metadata closure while allowing large framework graphs. */
|
|
17
|
+
export declare const DEFAULT_MAX_TOTAL_METADATA_BYTES: number;
|
|
18
|
+
/** Fifteen minutes per registry operation, including archive transfer. */
|
|
19
|
+
export declare const DEFAULT_REQUEST_DEADLINE_MS = 900000;
|
|
16
20
|
/** Default registry for tool environments (SPEC 13.1). */
|
|
17
21
|
export declare const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
|
|
18
22
|
export interface PackumentDist {
|
|
@@ -92,6 +96,10 @@ export declare class RegistryClient {
|
|
|
92
96
|
packument(name: string, options?: {
|
|
93
97
|
signal?: AbortSignal;
|
|
94
98
|
}): Promise<Packument>;
|
|
99
|
+
/** Fetch one exact version without transferring every release in a packument. */
|
|
100
|
+
versionManifest(name: string, version: string, options?: {
|
|
101
|
+
signal?: AbortSignal;
|
|
102
|
+
}): Promise<PackumentVersion>;
|
|
95
103
|
/** Registry advisory request; private names may never follow an external redirect. */
|
|
96
104
|
auditAdvisories(packages: Readonly<Record<string, readonly string[]>>, options?: {
|
|
97
105
|
signal?: AbortSignal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/fetch/registry.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/fetch/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/fetch/registry.js
CHANGED
|
@@ -17,6 +17,10 @@ import { assertIntegrityOk, canonicalStrongSri, IntegrityHasher, base64FromHex,
|
|
|
17
17
|
const transport = createRequire(import.meta.url)("make-fetch-happen");
|
|
18
18
|
/** 512 MiB: large for an npm package, small enough to bound mishaps. */
|
|
19
19
|
export const DEFAULT_MAX_TARBALL_BYTES = 512 * 1024 * 1024;
|
|
20
|
+
/** Bounds the complete metadata closure while allowing large framework graphs. */
|
|
21
|
+
export const DEFAULT_MAX_TOTAL_METADATA_BYTES = 256 * 1024 * 1024;
|
|
22
|
+
/** Fifteen minutes per registry operation, including archive transfer. */
|
|
23
|
+
export const DEFAULT_REQUEST_DEADLINE_MS = 900_000;
|
|
20
24
|
/** Default registry for tool environments (SPEC 13.1). */
|
|
21
25
|
export const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
|
|
22
26
|
/** npm's abbreviated packument media type, used for installs. */
|
|
@@ -66,9 +70,9 @@ export class RegistryClient {
|
|
|
66
70
|
(scope.pathname.startsWith(boundary.pathname) ||
|
|
67
71
|
boundary.pathname.startsWith(scope.pathname)));
|
|
68
72
|
this.#maxMetadataBytes = positiveLimit(options.maxMetadataBytes ?? 32 * 1024 * 1024, "maxMetadataBytes");
|
|
69
|
-
this.#maxTotalMetadataBytes = positiveLimit(options.maxTotalMetadataBytes ??
|
|
73
|
+
this.#maxTotalMetadataBytes = positiveLimit(options.maxTotalMetadataBytes ?? DEFAULT_MAX_TOTAL_METADATA_BYTES, "maxTotalMetadataBytes");
|
|
70
74
|
this.#maxMetadataVersions = positiveLimit(options.maxMetadataVersions ?? 100_000, "maxMetadataVersions");
|
|
71
|
-
this.#requestDeadlineMs = positiveLimit(options.requestDeadlineMs ??
|
|
75
|
+
this.#requestDeadlineMs = positiveLimit(options.requestDeadlineMs ?? DEFAULT_REQUEST_DEADLINE_MS, "requestDeadlineMs");
|
|
72
76
|
positiveLimit(this.#maxTarballBytes, "maxTarballBytes");
|
|
73
77
|
this.#signal = options.signal;
|
|
74
78
|
const { scopedRegistries, ...baseOptions } = options;
|
|
@@ -143,6 +147,33 @@ export class RegistryClient {
|
|
|
143
147
|
}
|
|
144
148
|
return validatePackument(raw, name, this.#origin, this.#maxMetadataVersions);
|
|
145
149
|
}
|
|
150
|
+
/** Fetch one exact version without transferring every release in a packument. */
|
|
151
|
+
async versionManifest(name, version, options = {}) {
|
|
152
|
+
const selected = this.forPackage(name);
|
|
153
|
+
if (selected !== this)
|
|
154
|
+
return selected.versionManifest(name, version, options);
|
|
155
|
+
const url = `${this.#registry}${escapePackageName(name)}/${encodeURIComponent(version)}`;
|
|
156
|
+
this.#logger?.debug("fetching exact version metadata", {
|
|
157
|
+
name,
|
|
158
|
+
version,
|
|
159
|
+
url,
|
|
160
|
+
});
|
|
161
|
+
let raw;
|
|
162
|
+
try {
|
|
163
|
+
raw = await this.#withRequest(url, `${INSTALL_V1_ACCEPT}, application/json`, (response) => this.#readMetadata(response), options.signal);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
throw mapFetchError(error, `fetch metadata for ${name}@${version}`);
|
|
167
|
+
}
|
|
168
|
+
const validated = validatePackument({ name, versions: { [version]: raw } }, name, this.#origin, 1);
|
|
169
|
+
const entry = validated.versions[version];
|
|
170
|
+
if (entry === undefined)
|
|
171
|
+
throw new ZyrkError("ZYRK_RESOLUTION_FAILED", `registry has no version ${version} of ${name}`, {
|
|
172
|
+
detail: { name, version },
|
|
173
|
+
remedy: "check the requested version exists in the configured registry",
|
|
174
|
+
});
|
|
175
|
+
return entry;
|
|
176
|
+
}
|
|
146
177
|
/** Registry advisory request; private names may never follow an external redirect. */
|
|
147
178
|
async auditAdvisories(packages, options = {}) {
|
|
148
179
|
for (const [name, versions] of Object.entries(packages)) {
|
|
@@ -414,7 +445,10 @@ export class RegistryClient {
|
|
|
414
445
|
throw resourceLimit("redirect count", 10, "registry redirect configuration");
|
|
415
446
|
}
|
|
416
447
|
catch (error) {
|
|
417
|
-
|
|
448
|
+
// A bounded body consumer can stop while the decoder still has source
|
|
449
|
+
// bytes arriving. Abort the transport before closing the exposed stream
|
|
450
|
+
// so compressed responses cannot write into a closed decompressor.
|
|
451
|
+
cancel();
|
|
418
452
|
if (timedOut || signals.some((source) => source.aborted))
|
|
419
453
|
throw resourceLimit("request deadline or cancellation", this.#requestDeadlineMs, "requestDeadlineMs");
|
|
420
454
|
throw error;
|
|
@@ -3,5 +3,10 @@ import type { ExtractionLimits } from "../extract/tarball.ts";
|
|
|
3
3
|
export declare function installBudgets(env: NodeJS.ProcessEnv): {
|
|
4
4
|
resolveBudget: Partial<ResolverLimits>;
|
|
5
5
|
extractBudget: Partial<ExtractionLimits>;
|
|
6
|
+
fetchBudget: {
|
|
7
|
+
deadlineMs: number;
|
|
8
|
+
};
|
|
6
9
|
};
|
|
10
|
+
/** Bound slow registry transfers while allowing large framework archives. */
|
|
11
|
+
export declare function registryRequestDeadline(env: NodeJS.ProcessEnv): number;
|
|
7
12
|
//# sourceMappingURL=budgets.d.ts.map
|
|
@@ -1 +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;
|
|
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;AAyB9D,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;IACzC,WAAW,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC,CAYA;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAEtE"}
|
package/dist/install/budgets.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/** Public, bounded install timeout configuration. Node and byte limits stay intact. */
|
|
2
2
|
import { ZyrkError } from "../errors.js";
|
|
3
|
-
function timeout(env, key, fallback) {
|
|
3
|
+
function timeout(env, key, fallback, maximum = 900000) {
|
|
4
4
|
const raw = env[key];
|
|
5
5
|
if (raw === undefined)
|
|
6
6
|
return fallback;
|
|
7
7
|
if (!/^[0-9]+$/.test(raw) ||
|
|
8
8
|
!Number.isSafeInteger(Number(raw)) ||
|
|
9
9
|
Number(raw) < 1 ||
|
|
10
|
-
Number(raw) >
|
|
11
|
-
throw new ZyrkError("ZYRK_POLICY_DENIED", `Cannot configure install: ${key} must be an integer from 1 to
|
|
12
|
-
remedy: `Set ${key} to a timeout in milliseconds from 1 to
|
|
10
|
+
Number(raw) > maximum)
|
|
11
|
+
throw new ZyrkError("ZYRK_POLICY_DENIED", `Cannot configure install: ${key} must be an integer from 1 to ${maximum}.`, {
|
|
12
|
+
remedy: `Set ${key} to a timeout in milliseconds from 1 to ${maximum}, or unset it to use the default.`,
|
|
13
13
|
});
|
|
14
14
|
return Number(raw);
|
|
15
15
|
}
|
|
@@ -21,5 +21,12 @@ export function installBudgets(env) {
|
|
|
21
21
|
extractBudget: {
|
|
22
22
|
maxDurationMs: timeout(env, "ZYRK_EXTRACT_TIMEOUT_MS", 120000),
|
|
23
23
|
},
|
|
24
|
+
fetchBudget: {
|
|
25
|
+
deadlineMs: timeout(env, "ZYRK_FETCH_TIMEOUT_MS", 900000, 3600000),
|
|
26
|
+
},
|
|
24
27
|
};
|
|
25
28
|
}
|
|
29
|
+
/** Bound slow registry transfers while allowing large framework archives. */
|
|
30
|
+
export function registryRequestDeadline(env) {
|
|
31
|
+
return timeout(env, "ZYRK_REQUEST_TIMEOUT_MS", 900000, 3600000);
|
|
32
|
+
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { type RuntimePlatform, type FinalizedGraph } from "../resolve/resolver.ts";
|
|
2
2
|
import type { WorkspaceGraph } from "./workspace-graph.ts";
|
|
3
|
+
/** Summarize expected platform filtering without emitting one warning per variant. */
|
|
4
|
+
export declare function platformOmissionSummary(omissions: readonly {
|
|
5
|
+
name: string;
|
|
6
|
+
}[]): string | undefined;
|
|
3
7
|
export declare function selectPlatformGraph(graph: FinalizedGraph, optionalRoots: ReadonlySet<string>, platform?: RuntimePlatform): FinalizedGraph;
|
|
4
8
|
export declare function selectWorkspacePlatform(graph: WorkspaceGraph, platform?: RuntimePlatform, omitDev?: boolean): WorkspaceGraph;
|
|
5
9
|
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/install/platform.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/install/platform.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,sFAAsF;AACtF,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACrC,MAAM,GAAG,SAAS,CAQpB;AAsGD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,QAAQ,kBAAoB,GAC3B,cAAc,CAqBhB;AACD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,cAAc,EACrB,QAAQ,kBAAoB,EAC5B,OAAO,UAAQ,GACd,cAAc,CA+BhB"}
|
package/dist/install/platform.js
CHANGED
|
@@ -3,6 +3,17 @@ import { satisfies } from "semver";
|
|
|
3
3
|
import { ZyrkError } from "../errors.js";
|
|
4
4
|
import { currentPlatform, } from "../resolve/resolver.js";
|
|
5
5
|
import { lockMismatch } from "./lock.js";
|
|
6
|
+
/** Summarize expected platform filtering without emitting one warning per variant. */
|
|
7
|
+
export function platformOmissionSummary(omissions) {
|
|
8
|
+
if (omissions.length === 0)
|
|
9
|
+
return undefined;
|
|
10
|
+
const packages = new Set(omissions.map((item) => item.name));
|
|
11
|
+
const entries = omissions.length;
|
|
12
|
+
const variants = packages.size;
|
|
13
|
+
const entryLabel = `${entries} platform-specific optional ${entries === 1 ? "dependency" : "dependencies"}`;
|
|
14
|
+
const packageLabel = `${variants} ${variants === 1 ? "package variant" : "package variants"}`;
|
|
15
|
+
return `Skipped ${entryLabel} across ${packageLabel}; this is expected when selecting dependencies for the current platform.`;
|
|
16
|
+
}
|
|
6
17
|
function compatible(node, platform) {
|
|
7
18
|
return ([
|
|
8
19
|
[node.platform?.os, platform.os],
|
|
@@ -12,6 +12,7 @@ export type BuildCandidate = {
|
|
|
12
12
|
command: string;
|
|
13
13
|
}>;
|
|
14
14
|
};
|
|
15
|
+
export declare const WORKSPACE_POLICY_FILE = "zyrk-workspace.json";
|
|
15
16
|
export declare function candidates(nodes: readonly ResolvedOccurrence[], dirs: ReadonlyMap<string, string>): Promise<BuildCandidate[]>;
|
|
16
17
|
export declare function candidateDigest(graph: GraphDoc, builds: readonly BuildCandidate[], policy: unknown, patches: string): string;
|
|
17
18
|
export declare function approveCandidate(options: {
|
|
@@ -21,7 +22,15 @@ export declare function approveCandidate(options: {
|
|
|
21
22
|
selected: readonly string[];
|
|
22
23
|
env?: NodeJS.ProcessEnv;
|
|
23
24
|
policy?: unknown;
|
|
25
|
+
portable?: boolean;
|
|
24
26
|
}): Promise<void>;
|
|
27
|
+
export declare function approvedCandidates(options: {
|
|
28
|
+
project: string;
|
|
29
|
+
env: NodeJS.ProcessEnv;
|
|
30
|
+
digest: string;
|
|
31
|
+
builds: readonly BuildCandidate[];
|
|
32
|
+
policy: unknown;
|
|
33
|
+
}): Promise<BuildCandidate[]>;
|
|
25
34
|
export declare function assertApproved(options: {
|
|
26
35
|
project: string;
|
|
27
36
|
env: NodeJS.ProcessEnv;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/install/private.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAOjE,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD,CAAC;
|
|
1
|
+
{"version":3,"file":"private.d.ts","sourceRoot":"","sources":["../../src/install/private.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAOjE,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD,CAAC;AACF,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAe3D,wBAAsB,UAAU,CAC9B,KAAK,EAAE,SAAS,kBAAkB,EAAE,EACpC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,OAAO,CAAC,cAAc,EAAE,CAAC,CA8C3B;AAyBD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,MAAM,GACd,MAAM,CASR;AACD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAClC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB;AA0ED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAgC5B;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhB;AACD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,QAAQ,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,aAAa,CAAC,CAmGzB;AAID,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAClC,QAAQ,EAAE,aAAa,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsFhB"}
|
package/dist/install/private.js
CHANGED
|
@@ -13,6 +13,7 @@ import { canonicalJson } from "../util/json.js";
|
|
|
13
13
|
import { isErrno, pathExists, writeFileAtomic } from "../util/fsx.js";
|
|
14
14
|
import { superviseChild } from "../util/proc.js";
|
|
15
15
|
import { redactSecrets } from "../log.js";
|
|
16
|
+
export const WORKSPACE_POLICY_FILE = "zyrk-workspace.json";
|
|
16
17
|
function fail(message) {
|
|
17
18
|
throw new ZyrkError("ZYRK_SCRIPT_BLOCKED", message, {
|
|
18
19
|
remedy: "Review the exact candidate with zyrk approve-builds, then explicitly approve its package names. Mandatory denials cannot be overridden.",
|
|
@@ -93,16 +94,62 @@ export async function approveCandidate(options) {
|
|
|
93
94
|
const selected = new Set(options.selected);
|
|
94
95
|
const all = selected.has("*");
|
|
95
96
|
for (const name of selected)
|
|
96
|
-
if (name !== "*" &&
|
|
97
|
+
if (name !== "*" &&
|
|
98
|
+
!options.builds.some((b) => b.name === name || b.sourceId === name))
|
|
97
99
|
fail("An approval selector does not match a reviewed build candidate.");
|
|
98
100
|
await writeFileAtomic(path.join(options.project, ".zyrk-local", "approvals.json"), JSON.stringify({
|
|
99
101
|
schemaVersion: 1,
|
|
100
102
|
candidate: options.digest,
|
|
101
103
|
sources: options.builds
|
|
102
|
-
.filter((b) => all || selected.has(b.name))
|
|
104
|
+
.filter((b) => all || selected.has(b.name) || selected.has(b.sourceId))
|
|
103
105
|
.map((b) => b.sourceId)
|
|
104
106
|
.sort(),
|
|
105
107
|
}), { mode: 0o600 });
|
|
108
|
+
if (options.portable) {
|
|
109
|
+
const selectedBuilds = options.builds.filter((build) => all || selected.has(build.name) || selected.has(build.sourceId));
|
|
110
|
+
await writePortableApprovals(options.project, selectedBuilds);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function readPortableApprovals(project) {
|
|
114
|
+
const file = path.join(project, WORKSPACE_POLICY_FILE);
|
|
115
|
+
let raw;
|
|
116
|
+
try {
|
|
117
|
+
const stat = await lstat(file);
|
|
118
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
119
|
+
fail("The workspace build-approval file must be a regular file.");
|
|
120
|
+
raw = JSON.parse(await readFile(file, "utf8"));
|
|
121
|
+
}
|
|
122
|
+
catch (cause) {
|
|
123
|
+
if (cause instanceof ZyrkError)
|
|
124
|
+
throw cause;
|
|
125
|
+
if (isErrno(cause, "ENOENT"))
|
|
126
|
+
return [];
|
|
127
|
+
fail("The workspace build-approval file is unreadable or malformed.");
|
|
128
|
+
}
|
|
129
|
+
if (!object(raw) ||
|
|
130
|
+
raw.schemaVersion !== 1 ||
|
|
131
|
+
!Array.isArray(raw.approvedBuilds) ||
|
|
132
|
+
raw.approvedBuilds.some((item) => !object(item) ||
|
|
133
|
+
typeof item.name !== "string" ||
|
|
134
|
+
typeof item.version !== "string" ||
|
|
135
|
+
typeof item.sourceId !== "string" ||
|
|
136
|
+
!/^src1_[a-f0-9]{40}$/.test(item.sourceId)))
|
|
137
|
+
fail("The workspace build-approval file has an unsupported format.");
|
|
138
|
+
return raw.approvedBuilds;
|
|
139
|
+
}
|
|
140
|
+
async function writePortableApprovals(project, selected) {
|
|
141
|
+
const current = await readPortableApprovals(project);
|
|
142
|
+
const bySource = new Map(current.map((item) => [item.sourceId, item]));
|
|
143
|
+
for (const build of selected)
|
|
144
|
+
bySource.set(build.sourceId, {
|
|
145
|
+
name: build.name,
|
|
146
|
+
version: build.version,
|
|
147
|
+
sourceId: build.sourceId,
|
|
148
|
+
});
|
|
149
|
+
await writeFileAtomic(path.join(project, WORKSPACE_POLICY_FILE), `${JSON.stringify({
|
|
150
|
+
schemaVersion: 1,
|
|
151
|
+
approvedBuilds: [...bySource.values()].sort((a, b) => a.name.localeCompare(b.name)),
|
|
152
|
+
}, null, 2)}\n`, { mode: 0o644 });
|
|
106
153
|
}
|
|
107
154
|
async function readUserPolicy(env) {
|
|
108
155
|
let user = {};
|
|
@@ -117,9 +164,9 @@ async function readUserPolicy(env) {
|
|
|
117
164
|
fail("Mandatory user build policy is malformed.");
|
|
118
165
|
return user;
|
|
119
166
|
}
|
|
120
|
-
export async function
|
|
167
|
+
export async function approvedCandidates(options) {
|
|
121
168
|
if (!options.builds.length)
|
|
122
|
-
return;
|
|
169
|
+
return [];
|
|
123
170
|
const user = await readUserPolicy(options.env);
|
|
124
171
|
let local;
|
|
125
172
|
try {
|
|
@@ -133,19 +180,29 @@ export async function assertApproved(options) {
|
|
|
133
180
|
throw cause;
|
|
134
181
|
local = undefined;
|
|
135
182
|
}
|
|
136
|
-
|
|
183
|
+
const portable = await readPortableApprovals(options.project);
|
|
184
|
+
return options.builds.filter((build) => {
|
|
137
185
|
if (denied(user.scripts, build) || denied(options.policy, build))
|
|
138
|
-
|
|
139
|
-
const
|
|
186
|
+
return false;
|
|
187
|
+
const manifestAllowed = object(options.policy) &&
|
|
140
188
|
Array.isArray(options.policy.allow) &&
|
|
141
189
|
options.policy.allow.includes(build.sourceId);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
190
|
+
const workspaceAllowed = portable.some((approval) => approval.sourceId === build.sourceId);
|
|
191
|
+
const localAllowed = object(local) &&
|
|
192
|
+
local.schemaVersion === 1 &&
|
|
193
|
+
local.candidate === options.digest &&
|
|
194
|
+
Array.isArray(local.sources) &&
|
|
195
|
+
local.sources.includes(build.sourceId);
|
|
196
|
+
return manifestAllowed || workspaceAllowed || localAllowed;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
export async function assertApproved(options) {
|
|
200
|
+
const approved = await approvedCandidates(options);
|
|
201
|
+
if (approved.length !== options.builds.length) {
|
|
202
|
+
const pending = options.builds.find((build) => !approved.some((item) => item.sourceId === build.sourceId));
|
|
203
|
+
fail(pending
|
|
204
|
+
? `Build of ${pending.name}@${pending.version} has not been approved for this exact source.`
|
|
205
|
+
: "Not every dependency build candidate is approved.");
|
|
149
206
|
}
|
|
150
207
|
}
|
|
151
208
|
export async function materializePrivate(options) {
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/install/registry.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAoB,MAAM,sBAAsB,CAAC;AAMxE,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"}
|
package/dist/install/registry.js
CHANGED
|
@@ -8,6 +8,7 @@ import { RegistryClient, DEFAULT_REGISTRY } from "../fetch/registry.js";
|
|
|
8
8
|
import { isErrno } from "../util/fsx.js";
|
|
9
9
|
import { findProjectBoundary } from "../config/paths.js";
|
|
10
10
|
import { cleanUrl } from "./lock.js";
|
|
11
|
+
import { registryRequestDeadline } from "./budgets.js";
|
|
11
12
|
export async function installRegistry(options) {
|
|
12
13
|
let registry = DEFAULT_REGISTRY;
|
|
13
14
|
const auth = {};
|
|
@@ -97,6 +98,7 @@ export async function installRegistry(options) {
|
|
|
97
98
|
return new RegistryClient({
|
|
98
99
|
registry,
|
|
99
100
|
scopedRegistries,
|
|
101
|
+
requestDeadlineMs: registryRequestDeadline(options.env),
|
|
100
102
|
userAgent: `zyrk/${options.version}`,
|
|
101
103
|
fetchOptions: auth,
|
|
102
104
|
});
|
package/dist/install/run.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export type InstallOptions = {
|
|
|
43
43
|
env?: NodeJS.ProcessEnv;
|
|
44
44
|
reviewBuilds?: boolean;
|
|
45
45
|
approveBuilds?: readonly string[];
|
|
46
|
+
requestBuildApproval?: (builds: readonly BuildCandidate[]) => Promise<readonly string[]>;
|
|
46
47
|
rebuild?: boolean;
|
|
47
48
|
repair?: boolean;
|
|
48
49
|
resolveBudget?: Partial<ResolverLimits>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/install/run.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/install/run.ts"],"names":[],"mappings":"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"}
|
package/dist/install/run.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { sourceProgress, reportLinked } from "./progress.js";
|
|
2
|
-
import { selectPlatformGraph } from "./platform.js";
|
|
2
|
+
import { platformOmissionSummary, selectPlatformGraph } from "./platform.js";
|
|
3
3
|
import { findWorkspaceRoot } from "./workspaces.js";
|
|
4
4
|
import { assertSupportedSourcePayload } from "./source-policy.js";
|
|
5
5
|
import { prepareRepair } from "./repair.js";
|
|
6
6
|
import { createFetchOperation } from "../fetch/package.js";
|
|
7
|
-
import { candidates, candidateDigest, approveCandidate,
|
|
7
|
+
import { candidates, candidateDigest, approveCandidate, approvedCandidates, materializePrivate, buildPrivate, } from "./private.js";
|
|
8
8
|
import { loadProjectPatches, applyProjectPatches } from "../commands/patch.js";
|
|
9
9
|
import { registerGeneration } from "./metadata.js";
|
|
10
10
|
import { randomId } from "../util/ids.js";
|
|
@@ -102,6 +102,7 @@ export async function installProject(options) {
|
|
|
102
102
|
...options,
|
|
103
103
|
resolveBudget: { ...budgets.resolveBudget, ...options.resolveBudget },
|
|
104
104
|
extractBudget: { ...budgets.extractBudget, ...options.extractBudget },
|
|
105
|
+
fetchBudget: { ...budgets.fetchBudget, ...options.fetchBudget },
|
|
105
106
|
};
|
|
106
107
|
if (await findWorkspaceRoot(options.projectDir)) {
|
|
107
108
|
const { installWorkspaceProject } = await import("./workspace-install.js");
|
|
@@ -272,6 +273,9 @@ export async function installProject(options) {
|
|
|
272
273
|
packument: (name) => options.registry.packument(name, {
|
|
273
274
|
signal: operation.operation.signal,
|
|
274
275
|
}),
|
|
276
|
+
versionManifest: (name, version) => options.registry.versionManifest(name, version, {
|
|
277
|
+
signal: operation.operation.signal,
|
|
278
|
+
}),
|
|
275
279
|
},
|
|
276
280
|
requirements: Object.entries(allDeps)
|
|
277
281
|
.map(([name, spec]) => {
|
|
@@ -416,7 +420,10 @@ export async function installProject(options) {
|
|
|
416
420
|
name: "package.json",
|
|
417
421
|
contents: `${JSON.stringify(manifest, null, 2)}\n`,
|
|
418
422
|
});
|
|
419
|
-
const warnings =
|
|
423
|
+
const warnings = [];
|
|
424
|
+
const omissionSummary = platformOmissionSummary(activeResolution.omissions ?? []);
|
|
425
|
+
if (omissionSummary)
|
|
426
|
+
warnings.push(omissionSummary);
|
|
420
427
|
for (const stage of ["preinstall", "install", "postinstall"])
|
|
421
428
|
if (manifest.scripts?.[stage])
|
|
422
429
|
warnings.push(`Root ${stage} hook was not run; invoke it explicitly after installation.`);
|
|
@@ -549,6 +556,7 @@ export async function installProject(options) {
|
|
|
549
556
|
selected: options.approveBuilds,
|
|
550
557
|
env: options.env ?? process.env,
|
|
551
558
|
policy: scriptPolicy(manifest),
|
|
559
|
+
portable: true,
|
|
552
560
|
});
|
|
553
561
|
return {
|
|
554
562
|
readiness: "build-review",
|
|
@@ -559,15 +567,37 @@ export async function installProject(options) {
|
|
|
559
567
|
builds,
|
|
560
568
|
};
|
|
561
569
|
}
|
|
562
|
-
|
|
570
|
+
let approvedBuilds = [];
|
|
563
571
|
if (builds.length && !options.ignoreScripts) {
|
|
564
|
-
|
|
572
|
+
const approvalOptions = {
|
|
565
573
|
project,
|
|
566
574
|
env: options.env ?? process.env,
|
|
567
575
|
digest: reviewedDigest,
|
|
568
576
|
builds,
|
|
569
577
|
policy: scriptPolicy(manifest),
|
|
570
|
-
}
|
|
578
|
+
};
|
|
579
|
+
approvedBuilds = await approvedCandidates(approvalOptions);
|
|
580
|
+
if (approvedBuilds.length < builds.length &&
|
|
581
|
+
options.requestBuildApproval) {
|
|
582
|
+
const pending = builds.filter((build) => !approvedBuilds.some((item) => item.sourceId === build.sourceId));
|
|
583
|
+
const selected = await options.requestBuildApproval(pending);
|
|
584
|
+
if (selected.length) {
|
|
585
|
+
await approveCandidate({
|
|
586
|
+
project,
|
|
587
|
+
digest: reviewedDigest,
|
|
588
|
+
builds: pending,
|
|
589
|
+
selected,
|
|
590
|
+
env: options.env ?? process.env,
|
|
591
|
+
policy: scriptPolicy(manifest),
|
|
592
|
+
portable: true,
|
|
593
|
+
});
|
|
594
|
+
approvedBuilds = await approvedCandidates(approvalOptions);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const unbuilt = builds.length > 0 &&
|
|
599
|
+
(options.ignoreScripts === true || approvedBuilds.length < builds.length);
|
|
600
|
+
if (approvedBuilds.length && !options.ignoreScripts) {
|
|
571
601
|
if (!privateGraph) {
|
|
572
602
|
realized = await materializePrivate({
|
|
573
603
|
project,
|
|
@@ -582,7 +612,7 @@ export async function installProject(options) {
|
|
|
582
612
|
project,
|
|
583
613
|
generationId,
|
|
584
614
|
nodes: activeNodes,
|
|
585
|
-
builds,
|
|
615
|
+
builds: approvedBuilds,
|
|
586
616
|
realized,
|
|
587
617
|
env: options.env ?? process.env,
|
|
588
618
|
});
|
|
@@ -606,9 +636,10 @@ export async function installProject(options) {
|
|
|
606
636
|
privateGraph = true;
|
|
607
637
|
}
|
|
608
638
|
}
|
|
609
|
-
if (unbuilt)
|
|
610
|
-
|
|
611
|
-
|
|
639
|
+
if (unbuilt) {
|
|
640
|
+
const skipped = builds.length - approvedBuilds.length;
|
|
641
|
+
warnings.push(`${skipped} dependency build ${skipped === 1 ? "script was" : "scripts were"} skipped because approval was not granted; readiness is intentionally unbuilt. Run zyrk approve-builds to review and approve sources.`);
|
|
642
|
+
}
|
|
612
643
|
if (privateGraph)
|
|
613
644
|
warnings.push("Using a complete project-private dependency graph; build/runtime writes do not change shared source.");
|
|
614
645
|
const entries = selectedRoots.map((r) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-install.d.ts","sourceRoot":"","sources":["../../src/install/workspace-install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workspace-install.d.ts","sourceRoot":"","sources":["../../src/install/workspace-install.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAuH9D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAqtBxB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sourceProgress, reportLinked } from "./progress.js";
|
|
2
|
-
import { selectWorkspacePlatform } from "./platform.js";
|
|
2
|
+
import { platformOmissionSummary, selectWorkspacePlatform, } from "./platform.js";
|
|
3
3
|
/** Multi-importer live workspace installation with one publication journal. */
|
|
4
4
|
import { chmod, copyFile, lstat, mkdir, readFile, realpath, rename, rm, symlink, } from "node:fs/promises";
|
|
5
5
|
import { constants } from "node:fs";
|
|
@@ -32,7 +32,7 @@ import { loadProjectPatches, applyProjectPatches } from "../commands/patch.js";
|
|
|
32
32
|
import { prepareRepair } from "./repair.js";
|
|
33
33
|
import { assertSupportedSourcePayload } from "./source-policy.js";
|
|
34
34
|
import { registerGeneration } from "./metadata.js";
|
|
35
|
-
import { candidates, candidateDigest, approveCandidate,
|
|
35
|
+
import { candidates, candidateDigest, approveCandidate, approvedCandidates, buildPrivate, } from "./private.js";
|
|
36
36
|
const object = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
37
37
|
const unsupported = (message) => {
|
|
38
38
|
throw new ZyrkError("ZYRK_NOT_IMPLEMENTED", message, {
|
|
@@ -191,7 +191,10 @@ export async function installWorkspaceProject(options) {
|
|
|
191
191
|
? await readFile(path.join(root, "package-lock.json"), "utf8")
|
|
192
192
|
: JSON.stringify(doc, null, 2) + "\n";
|
|
193
193
|
graph = selectWorkspacePlatform(graph, options.platform, options.omitDev);
|
|
194
|
-
const warnings =
|
|
194
|
+
const warnings = [];
|
|
195
|
+
const omissionSummary = platformOmissionSummary(graph.omissions);
|
|
196
|
+
if (omissionSummary)
|
|
197
|
+
warnings.push(omissionSummary);
|
|
195
198
|
for (const importer of project.importers)
|
|
196
199
|
for (const stage of ["preinstall", "install", "postinstall"])
|
|
197
200
|
if (importer.manifest.scripts?.[stage])
|
|
@@ -441,6 +444,7 @@ export async function installWorkspaceProject(options) {
|
|
|
441
444
|
selected: options.approveBuilds,
|
|
442
445
|
env: options.env ?? process.env,
|
|
443
446
|
policy,
|
|
447
|
+
portable: true,
|
|
444
448
|
});
|
|
445
449
|
return {
|
|
446
450
|
readiness: "build-review",
|
|
@@ -451,14 +455,38 @@ export async function installWorkspaceProject(options) {
|
|
|
451
455
|
builds,
|
|
452
456
|
};
|
|
453
457
|
}
|
|
458
|
+
let approvedBuilds = [];
|
|
454
459
|
if (builds.length && !options.ignoreScripts) {
|
|
455
|
-
|
|
460
|
+
const approvalOptions = {
|
|
456
461
|
project: root,
|
|
457
462
|
env: options.env ?? process.env,
|
|
458
463
|
digest,
|
|
459
464
|
builds,
|
|
460
465
|
policy,
|
|
461
|
-
}
|
|
466
|
+
};
|
|
467
|
+
approvedBuilds = await approvedCandidates(approvalOptions);
|
|
468
|
+
if (approvedBuilds.length < builds.length &&
|
|
469
|
+
options.requestBuildApproval) {
|
|
470
|
+
const pending = builds.filter((build) => !approvedBuilds.some((item) => item.sourceId === build.sourceId));
|
|
471
|
+
const selected = await options.requestBuildApproval(pending);
|
|
472
|
+
if (selected.length) {
|
|
473
|
+
await approveCandidate({
|
|
474
|
+
project: root,
|
|
475
|
+
digest,
|
|
476
|
+
builds: pending,
|
|
477
|
+
selected,
|
|
478
|
+
env: options.env ?? process.env,
|
|
479
|
+
policy,
|
|
480
|
+
portable: true,
|
|
481
|
+
});
|
|
482
|
+
approvedBuilds = await approvedCandidates(approvalOptions);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
const skippedBuilds = builds.length - approvedBuilds.length;
|
|
487
|
+
if (skippedBuilds > 0)
|
|
488
|
+
warnings.push(`${skippedBuilds} dependency build ${skippedBuilds === 1 ? "script was" : "scripts were"} skipped because approval was not granted; readiness is intentionally unbuilt. Run zyrk approve-builds to review and approve sources.`);
|
|
489
|
+
if (approvedBuilds.length && !options.ignoreScripts) {
|
|
462
490
|
// Approved writes need a coherent fully private registry closure.
|
|
463
491
|
await allocatePrivate(new Set(nodes.map((n) => n.key)));
|
|
464
492
|
options.onProgress?.({ phase: "building" });
|
|
@@ -466,12 +494,12 @@ export async function installWorkspaceProject(options) {
|
|
|
466
494
|
project: root,
|
|
467
495
|
generationId,
|
|
468
496
|
nodes,
|
|
469
|
-
builds,
|
|
497
|
+
builds: approvedBuilds,
|
|
470
498
|
realized,
|
|
471
499
|
env: options.env ?? process.env,
|
|
472
500
|
});
|
|
473
501
|
}
|
|
474
|
-
const readiness = builds.length && options.ignoreScripts
|
|
502
|
+
const readiness = builds.length && (options.ignoreScripts || skippedBuilds > 0)
|
|
475
503
|
? "intentionally-unbuilt"
|
|
476
504
|
: "ready";
|
|
477
505
|
registration = await registerGeneration({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/lockfile/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,mBAAmB,CAAC;IAChC,YAAY,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACzB,CAAC;AAEF,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/lockfile/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,mBAAmB,CAAC;IAChC,YAAY,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACzB,CAAC;AAEF,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAqPrB"}
|
package/dist/lockfile/write.js
CHANGED
|
@@ -94,7 +94,23 @@ export async function writeLockfile(options) {
|
|
|
94
94
|
: `npm:${target.name}@${target.version}`;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
+
const npmMetadata = {};
|
|
98
|
+
const existingEntry = existingPackages[location];
|
|
99
|
+
if (existingEntry !== undefined) {
|
|
100
|
+
for (const field of [
|
|
101
|
+
"license",
|
|
102
|
+
"funding",
|
|
103
|
+
"deprecated",
|
|
104
|
+
"hasInstallScript",
|
|
105
|
+
"inBundle",
|
|
106
|
+
]) {
|
|
107
|
+
if (Object.hasOwn(existingEntry, field)) {
|
|
108
|
+
npmMetadata[field] = existingEntry[field];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
97
112
|
packages[location] = {
|
|
113
|
+
...npmMetadata,
|
|
98
114
|
name: node.name,
|
|
99
115
|
version: node.version,
|
|
100
116
|
resolved: node.tarballUrl,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { type Packument } from "../fetch/registry.ts";
|
|
1
|
+
import { type Packument, type PackumentVersion } from "../fetch/registry.ts";
|
|
2
2
|
import { type OverridePolicy } from "./overrides.ts";
|
|
3
3
|
export type MetadataProvider = {
|
|
4
4
|
readonly origin: string;
|
|
5
5
|
originFor?(name: string): string;
|
|
6
6
|
packument(name: string): Promise<Packument>;
|
|
7
|
+
versionManifest?(name: string, version: string): Promise<PackumentVersion>;
|
|
7
8
|
};
|
|
8
9
|
export type EdgeKind = "prod" | "optional" | "peer";
|
|
9
10
|
export type ResolvedEdge = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resolve/resolver.ts"],"names":[],"mappings":"AAyBA,OAAO,EAEL,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resolve/resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/resolve/resolver.js
CHANGED
|
@@ -70,6 +70,7 @@ class ResolverState {
|
|
|
70
70
|
provider;
|
|
71
71
|
overrides;
|
|
72
72
|
packuments = new Map();
|
|
73
|
+
versionManifests = new Map();
|
|
73
74
|
peerless = new Map();
|
|
74
75
|
peerBearing = new Map();
|
|
75
76
|
freshPeers = new Map();
|
|
@@ -142,6 +143,23 @@ class ResolverState {
|
|
|
142
143
|
this.packuments.set(name, pending);
|
|
143
144
|
return pending;
|
|
144
145
|
}
|
|
146
|
+
versionManifestOf(name, version) {
|
|
147
|
+
const key = `${name}\0${version}`;
|
|
148
|
+
const cached = this.versionManifests.get(key);
|
|
149
|
+
if (cached !== undefined)
|
|
150
|
+
return cached;
|
|
151
|
+
this.checkBudget();
|
|
152
|
+
let timer;
|
|
153
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
154
|
+
timer = setTimeout(() => reject(budgetError("resolution deadline exceeded")), Math.max(1, this.expires - Date.now()));
|
|
155
|
+
});
|
|
156
|
+
const pending = Promise.race([
|
|
157
|
+
this.provider.versionManifest(name, version),
|
|
158
|
+
deadline,
|
|
159
|
+
]).finally(() => clearTimeout(timer));
|
|
160
|
+
this.versionManifests.set(key, pending);
|
|
161
|
+
return pending;
|
|
162
|
+
}
|
|
145
163
|
/**
|
|
146
164
|
* Build (or reuse) the occurrence for one dependency edge. Peerless
|
|
147
165
|
* packages share one occurrence per name@version; packages declaring
|
|
@@ -442,6 +460,21 @@ class ResolverState {
|
|
|
442
460
|
// Version selection
|
|
443
461
|
// ---------------------------------------------------------------------------
|
|
444
462
|
async function selectVersion(state, req) {
|
|
463
|
+
if (req.targetKind === "exact" && state.provider.versionManifest) {
|
|
464
|
+
try {
|
|
465
|
+
return {
|
|
466
|
+
version: req.targetSpec,
|
|
467
|
+
entry: await state.versionManifestOf(req.realName, req.targetSpec),
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
// Registries and older test adapters may expose only packuments. Keep
|
|
472
|
+
// the optimization opportunistic when the exact endpoint is absent.
|
|
473
|
+
if (!(error instanceof ZyrkError) || error.detail?.status !== 404) {
|
|
474
|
+
throw error;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
445
478
|
const packument = await state.packumentOf(req.realName);
|
|
446
479
|
const fail = (message, remedy) => new ZyrkError("ZYRK_RESOLUTION_FAILED", message, {
|
|
447
480
|
detail: { name: req.realName, spec: req.targetSpec },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zyrk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
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",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"version:bump": "node scripts/bump-version.js",
|
|
21
21
|
"setup:hooks": "git config core.hooksPath .githooks",
|
|
22
22
|
"build": "tsc -p tsconfig.build.json",
|
|
23
|
-
"prepublishOnly": "
|
|
23
|
+
"prepublishOnly": "node bin/zyrk.js run build"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"make-fetch-happen": "16.0.1",
|