zyrk 0.3.8 → 0.4.8

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 (218) hide show
  1. package/README.md +143 -34
  2. package/SECURITY.md +42 -0
  3. package/VERSION +1 -1
  4. package/bin/zyrk.js +9 -1
  5. package/dist/cli/main.d.ts +40 -0
  6. package/dist/cli/main.d.ts.map +1 -0
  7. package/dist/cli/main.js +605 -0
  8. package/dist/cli/npm-delegate.d.ts +38 -0
  9. package/dist/cli/npm-delegate.d.ts.map +1 -0
  10. package/{src/cli/npm-delegate.ts → dist/cli/npm-delegate.js} +21 -55
  11. package/dist/cli/parse.d.ts +40 -0
  12. package/dist/cli/parse.d.ts.map +1 -0
  13. package/dist/cli/parse.js +78 -0
  14. package/dist/commands/dependencies.d.ts +13 -0
  15. package/dist/commands/dependencies.d.ts.map +1 -0
  16. package/dist/commands/dependencies.js +119 -0
  17. package/dist/commands/deploy.d.ts +15 -0
  18. package/dist/commands/deploy.d.ts.map +1 -0
  19. package/dist/commands/deploy.js +761 -0
  20. package/dist/commands/maintenance.d.ts +28 -0
  21. package/dist/commands/maintenance.d.ts.map +1 -0
  22. package/dist/commands/maintenance.js +225 -0
  23. package/dist/commands/patch.d.ts +39 -0
  24. package/dist/commands/patch.d.ts.map +1 -0
  25. package/dist/commands/patch.js +353 -0
  26. package/dist/commands/project.d.ts +17 -0
  27. package/dist/commands/project.d.ts.map +1 -0
  28. package/dist/commands/project.js +519 -0
  29. package/dist/commands/store.d.ts +10 -0
  30. package/dist/commands/store.d.ts.map +1 -0
  31. package/dist/commands/store.js +610 -0
  32. package/dist/config/paths.d.ts +37 -0
  33. package/dist/config/paths.d.ts.map +1 -0
  34. package/dist/config/paths.js +66 -0
  35. package/dist/dlx/create.d.ts +23 -0
  36. package/dist/dlx/create.d.ts.map +1 -0
  37. package/dist/dlx/create.js +59 -0
  38. package/dist/dlx/run.d.ts +53 -0
  39. package/dist/dlx/run.d.ts.map +1 -0
  40. package/dist/dlx/run.js +395 -0
  41. package/dist/errors.d.ts +68 -0
  42. package/dist/errors.d.ts.map +1 -0
  43. package/dist/errors.js +116 -0
  44. package/dist/extract/tarball.d.ts +86 -0
  45. package/dist/extract/tarball.d.ts.map +1 -0
  46. package/dist/extract/tarball.js +727 -0
  47. package/dist/fetch/all.d.ts +54 -0
  48. package/dist/fetch/all.d.ts.map +1 -0
  49. package/dist/fetch/all.js +168 -0
  50. package/dist/fetch/package.d.ts +65 -0
  51. package/dist/fetch/package.d.ts.map +1 -0
  52. package/dist/fetch/package.js +197 -0
  53. package/dist/fetch/registry.d.ts +125 -0
  54. package/dist/fetch/registry.d.ts.map +1 -0
  55. package/dist/fetch/registry.js +674 -0
  56. package/dist/install/import-npm.d.ts +4 -0
  57. package/dist/install/import-npm.d.ts.map +1 -0
  58. package/dist/install/import-npm.js +156 -0
  59. package/dist/install/lock.d.ts +10 -0
  60. package/dist/install/lock.d.ts.map +1 -0
  61. package/dist/install/lock.js +239 -0
  62. package/dist/install/metadata.d.ts +25 -0
  63. package/dist/install/metadata.d.ts.map +1 -0
  64. package/dist/install/metadata.js +92 -0
  65. package/dist/install/private.d.ts +46 -0
  66. package/dist/install/private.d.ts.map +1 -0
  67. package/dist/install/private.js +304 -0
  68. package/dist/install/registry.d.ts +8 -0
  69. package/dist/install/registry.d.ts.map +1 -0
  70. package/dist/install/registry.js +98 -0
  71. package/dist/install/repair.d.ts +22 -0
  72. package/dist/install/repair.d.ts.map +1 -0
  73. package/dist/install/repair.js +115 -0
  74. package/dist/install/run.d.ts +45 -0
  75. package/dist/install/run.d.ts.map +1 -0
  76. package/dist/install/run.js +716 -0
  77. package/dist/install/source-policy.d.ts +11 -0
  78. package/dist/install/source-policy.d.ts.map +1 -0
  79. package/dist/install/source-policy.js +8 -0
  80. package/dist/install/workspace-graph.d.ts +62 -0
  81. package/dist/install/workspace-graph.d.ts.map +1 -0
  82. package/dist/install/workspace-graph.js +365 -0
  83. package/dist/install/workspace-install.d.ts +3 -0
  84. package/dist/install/workspace-install.d.ts.map +1 -0
  85. package/dist/install/workspace-install.js +527 -0
  86. package/dist/install/workspace-lock.d.ts +16 -0
  87. package/dist/install/workspace-lock.d.ts.map +1 -0
  88. package/dist/install/workspace-lock.js +428 -0
  89. package/dist/install/workspace-mutation.d.ts +10 -0
  90. package/dist/install/workspace-mutation.d.ts.map +1 -0
  91. package/dist/install/workspace-mutation.js +154 -0
  92. package/dist/install/workspace-transaction.d.ts +26 -0
  93. package/dist/install/workspace-transaction.d.ts.map +1 -0
  94. package/dist/install/workspace-transaction.js +191 -0
  95. package/dist/install/workspaces.d.ts +66 -0
  96. package/dist/install/workspaces.d.ts.map +1 -0
  97. package/dist/install/workspaces.js +343 -0
  98. package/dist/lockfile/fingerprints.d.ts +45 -0
  99. package/dist/lockfile/fingerprints.d.ts.map +1 -0
  100. package/dist/lockfile/fingerprints.js +65 -0
  101. package/dist/lockfile/read.d.ts +27 -0
  102. package/dist/lockfile/read.d.ts.map +1 -0
  103. package/dist/lockfile/read.js +136 -0
  104. package/dist/lockfile/types.d.ts +77 -0
  105. package/dist/lockfile/types.d.ts.map +1 -0
  106. package/dist/lockfile/types.js +18 -0
  107. package/dist/lockfile/write.d.ts +36 -0
  108. package/dist/lockfile/write.d.ts.map +1 -0
  109. package/dist/lockfile/write.js +211 -0
  110. package/dist/log.d.ts +24 -0
  111. package/dist/log.d.ts.map +1 -0
  112. package/dist/log.js +126 -0
  113. package/dist/project/projection.d.ts +50 -0
  114. package/dist/project/projection.d.ts.map +1 -0
  115. package/dist/project/projection.js +292 -0
  116. package/dist/resolve/resolver.d.ts +99 -0
  117. package/dist/resolve/resolver.d.ts.map +1 -0
  118. package/dist/resolve/resolver.js +669 -0
  119. package/dist/resolve/spec.d.ts +26 -0
  120. package/dist/resolve/spec.d.ts.map +1 -0
  121. package/dist/resolve/spec.js +87 -0
  122. package/dist/store/db.d.ts +49 -0
  123. package/dist/store/db.d.ts.map +1 -0
  124. package/{src/store/db.ts → dist/store/db.js} +106 -206
  125. package/dist/store/graph.d.ts +60 -0
  126. package/dist/store/graph.d.ts.map +1 -0
  127. package/dist/store/graph.js +115 -0
  128. package/dist/store/layout.d.ts +71 -0
  129. package/dist/store/layout.d.ts.map +1 -0
  130. package/dist/store/layout.js +282 -0
  131. package/dist/store/manifests.d.ts +78 -0
  132. package/dist/store/manifests.d.ts.map +1 -0
  133. package/dist/store/manifests.js +238 -0
  134. package/dist/store/objects.d.ts +59 -0
  135. package/dist/store/objects.d.ts.map +1 -0
  136. package/dist/store/objects.js +194 -0
  137. package/dist/store/realize.d.ts +44 -0
  138. package/dist/store/realize.d.ts.map +1 -0
  139. package/dist/store/realize.js +302 -0
  140. package/dist/store/source.d.ts +42 -0
  141. package/dist/store/source.d.ts.map +1 -0
  142. package/dist/store/source.js +169 -0
  143. package/dist/store/txn.d.ts +37 -0
  144. package/dist/store/txn.d.ts.map +1 -0
  145. package/dist/store/txn.js +97 -0
  146. package/dist/store/verify.d.ts +41 -0
  147. package/dist/store/verify.d.ts.map +1 -0
  148. package/dist/store/verify.js +405 -0
  149. package/dist/util/fsx.d.ts +54 -0
  150. package/dist/util/fsx.d.ts.map +1 -0
  151. package/dist/util/fsx.js +259 -0
  152. package/dist/util/hash.d.ts +48 -0
  153. package/dist/util/hash.d.ts.map +1 -0
  154. package/dist/util/hash.js +80 -0
  155. package/dist/util/ids.d.ts +19 -0
  156. package/dist/util/ids.d.ts.map +1 -0
  157. package/dist/util/ids.js +38 -0
  158. package/dist/util/integrity.d.ts +107 -0
  159. package/dist/util/integrity.d.ts.map +1 -0
  160. package/dist/util/integrity.js +227 -0
  161. package/dist/util/json.d.ts +14 -0
  162. package/dist/util/json.d.ts.map +1 -0
  163. package/dist/util/json.js +78 -0
  164. package/dist/util/locks.d.ts +40 -0
  165. package/dist/util/locks.d.ts.map +1 -0
  166. package/dist/util/locks.js +219 -0
  167. package/dist/util/proc.d.ts +53 -0
  168. package/dist/util/proc.d.ts.map +1 -0
  169. package/dist/util/proc.js +189 -0
  170. package/dist/version.d.ts +27 -0
  171. package/dist/version.d.ts.map +1 -0
  172. package/{src/version.ts → dist/version.js} +0 -8
  173. package/package.json +9 -4
  174. package/src/cli/main.ts +0 -602
  175. package/src/cli/parse.ts +0 -106
  176. package/src/commands/dependencies.ts +0 -154
  177. package/src/commands/deploy.ts +0 -777
  178. package/src/commands/maintenance.ts +0 -260
  179. package/src/commands/patch.ts +0 -408
  180. package/src/commands/project.ts +0 -598
  181. package/src/commands/store.ts +0 -689
  182. package/src/config/paths.ts +0 -119
  183. package/src/dlx/create.ts +0 -69
  184. package/src/dlx/run.ts +0 -389
  185. package/src/errors.ts +0 -142
  186. package/src/extract/tarball.ts +0 -868
  187. package/src/fetch/all.ts +0 -206
  188. package/src/fetch/package.ts +0 -181
  189. package/src/fetch/registry.ts +0 -615
  190. package/src/install/import-npm.ts +0 -177
  191. package/src/install/lock.ts +0 -176
  192. package/src/install/metadata.ts +0 -122
  193. package/src/install/registry.ts +0 -88
  194. package/src/install/run.ts +0 -760
  195. package/src/lockfile/fingerprints.ts +0 -74
  196. package/src/lockfile/read.ts +0 -198
  197. package/src/lockfile/types.ts +0 -75
  198. package/src/lockfile/write.ts +0 -257
  199. package/src/log.ts +0 -100
  200. package/src/project/projection.ts +0 -390
  201. package/src/resolve/resolver.ts +0 -757
  202. package/src/resolve/spec.ts +0 -131
  203. package/src/store/graph.ts +0 -175
  204. package/src/store/layout.ts +0 -431
  205. package/src/store/manifests.ts +0 -347
  206. package/src/store/objects.ts +0 -229
  207. package/src/store/realize.ts +0 -322
  208. package/src/store/source.ts +0 -249
  209. package/src/store/txn.ts +0 -118
  210. package/src/store/verify.ts +0 -433
  211. package/src/types/vendor.d.ts +0 -120
  212. package/src/util/fsx.ts +0 -289
  213. package/src/util/hash.ts +0 -117
  214. package/src/util/ids.ts +0 -42
  215. package/src/util/integrity.ts +0 -269
  216. package/src/util/json.ts +0 -89
  217. package/src/util/locks.ts +0 -266
  218. package/src/util/proc.ts +0 -108
@@ -0,0 +1,605 @@
1
+ import { runMaintenanceCommand } from "../commands/maintenance.js";
2
+ import { runDeployCommand } from "../commands/deploy.js";
3
+ import { runPatchCommand } from "../commands/patch.js";
4
+ import { sanitizeDiagnostic, redactSecrets } from "../log.js";
5
+ /** zyrk command dispatch (SPEC 15).
6
+ * Native handlers share validated graph and registry adapters; delegated registry
7
+ * operations preserve npm arguments. Global install rejection precedes effects.
8
+ * Unsupported command modes fail explicitly in their handler.
9
+ */
10
+ import { installProject } from "../install/run.js";
11
+ import { installRegistry } from "../install/registry.js";
12
+ import { readFileSync } from "node:fs";
13
+ import * as path from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ import { runCreate } from "../dlx/create.js";
16
+ import { runDlx } from "../dlx/run.js";
17
+ import { runDependencyCommand, } from "../commands/dependencies.js";
18
+ import { runProjectCommand, } from "../commands/project.js";
19
+ import { runStoreCommand } from "../commands/store.js";
20
+ import { exitCodeFor, ZyrkError, toZyrkError } from "../errors.js";
21
+ export { ZyrkError };
22
+ import { DEFAULT_REGISTRY, RegistryClient } from "../fetch/registry.js";
23
+ import { resolveStoreRoot } from "../config/paths.js";
24
+ import { Store } from "../store/layout.js";
25
+ import { delegateToNpm, delegatedHelpLines, isDelegatedCommand, } from "./npm-delegate.js";
26
+ import { isGlobalInstallRequest, parseArgs } from "./parse.js";
27
+ export const CLI_JSON_SCHEMA_VERSION = 1;
28
+ /** Spec-defined dependency commands (SPEC 15.1-15.2, fetch, docker). */
29
+ const NATIVE_COMMANDS = [
30
+ ["install, i", "Install the locked or newly resolved graph."],
31
+ ["fetch", "Fetch and verify a locked source closure."],
32
+ ["add", "Add dependencies transactionally."],
33
+ ["remove", "Remove direct dependencies and refresh the closure."],
34
+ ["update", "Update within allowed ranges."],
35
+ ["run", "Run a project script with local binary paths."],
36
+ ["exec", "Run an installed executable (never fetches)."],
37
+ ["dlx", "Explicitly fetch and run a temporary tool environment."],
38
+ ["create", "Scaffold from a create-* starter package."],
39
+ ["list, why", "Show the installed graph / why a dependency is selected."],
40
+ ["doctor", "Diagnose filesystem, links, policy, install-state issues."],
41
+ ["approve-builds, rebuild", "Review script permissions / rebuild."],
42
+ ["audit", "Report vulnerabilities under the configured privacy policy."],
43
+ ["patch, patch-commit", "Create a private edit area / emit a patch."],
44
+ ["store", "Inspect, verify, collect, and retain the store."],
45
+ ["projects", "List registrations / drop a retention root."],
46
+ ["repair", "Reconstruct the project from verified locked inputs."],
47
+ ["import", "Convert supported npm lock information."],
48
+ ["deploy", "Create self-contained production output."],
49
+ ["docker", "Generate, build, and start the Docker setup."],
50
+ ];
51
+ const KNOWN_COMMANDS = new Set();
52
+ for (const [names] of NATIVE_COMMANDS) {
53
+ for (const name of names.split(", "))
54
+ KNOWN_COMMANDS.add(name);
55
+ }
56
+ /** Commands with a real implementation behind runCli. */
57
+ const IMPLEMENTED_COMMANDS = new Set([
58
+ "dlx",
59
+ "create",
60
+ "install",
61
+ "i",
62
+ "add",
63
+ "remove",
64
+ "update",
65
+ "import",
66
+ "run",
67
+ "exec",
68
+ "list",
69
+ "why",
70
+ "doctor",
71
+ "repair",
72
+ "store",
73
+ "projects",
74
+ "fetch",
75
+ "audit",
76
+ "approve-builds",
77
+ "rebuild",
78
+ "patch",
79
+ "patch-commit",
80
+ "deploy",
81
+ "docker",
82
+ ]);
83
+ export function helpText(version) {
84
+ const lines = [
85
+ `zyrk v${version} — one verified store per user, shared across projects through links.`,
86
+ "",
87
+ "Usage: zyrk <command> [args] [--json]",
88
+ "",
89
+ "Dependency commands:",
90
+ ];
91
+ for (const [names, description] of NATIVE_COMMANDS) {
92
+ const done = names
93
+ .split(", ")
94
+ .some((name) => IMPLEMENTED_COMMANDS.has(name));
95
+ lines.push(` ${names.padEnd(24, " ")}${description}${done ? "" : " (not implemented yet)"}`);
96
+ }
97
+ lines.push("", "Registry publishing and account commands (via your npm):");
98
+ lines.push(...delegatedHelpLines());
99
+ lines.push("", "zyrk never installs packages globally and never runs npm to do it.", "Need a global package? Run npm directly: npm install --global <package-spec>");
100
+ return `${lines.join("\n")}\n`;
101
+ }
102
+ function ok(stdout, parsed) {
103
+ if (!parsed.json)
104
+ return { exitCode: 0, stdout, stderr: "" };
105
+ return {
106
+ exitCode: 0,
107
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok" })}\n`,
108
+ stderr: "",
109
+ };
110
+ }
111
+ function fail(error, parsed, stdoutHint = "") {
112
+ const human = `zyrk: error ${error.code}: ${error.message}` +
113
+ (error.remedy === undefined ? "" : `\n${error.remedy}`);
114
+ if (!parsed.json) {
115
+ return {
116
+ exitCode: exitCodeFor(error),
117
+ stdout: stdoutHint,
118
+ stderr: `${human}\n`,
119
+ };
120
+ }
121
+ const body = {
122
+ schemaVersion: CLI_JSON_SCHEMA_VERSION,
123
+ status: "error",
124
+ code: error.code,
125
+ message: error.message,
126
+ };
127
+ if (error.remedy !== undefined)
128
+ body.remedy = error.remedy;
129
+ return {
130
+ exitCode: exitCodeFor(error),
131
+ stdout: `${JSON.stringify(sanitizeDiagnostic(body))}\n`,
132
+ stderr: "",
133
+ };
134
+ }
135
+ /**
136
+ * Echo a command token back safely: drop control characters, cap length,
137
+ * and strip URL userinfo so error output cannot leak credentials or forge
138
+ * terminal sequences. Full structured output redaction is S03; this covers
139
+ * the one place CLI dispatch interpolates an arbitrary token today.
140
+ */
141
+ /**
142
+ * Drop C0 control characters and DEL without regex escapes.
143
+ */
144
+ function stripControlChars(token) {
145
+ let out = "";
146
+ for (const ch of token) {
147
+ const code = ch.codePointAt(0);
148
+ if (code !== undefined && code >= 32 && code !== 127)
149
+ out += ch;
150
+ }
151
+ return out;
152
+ }
153
+ function sanitizeCommandToken(token) {
154
+ const oneLine = stripControlChars(token);
155
+ const capped = oneLine.length > 64 ? `${oneLine.slice(0, 64)}…` : oneLine;
156
+ return capped.replace(/([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)([^@/]*@)?/, "$1");
157
+ }
158
+ function globalInstallError(command) {
159
+ return new ZyrkError("ZYRK_GLOBAL_INSTALL_UNSUPPORTED", `zyrk does not install packages globally (requested: zyrk ${command} with global-install mode).`, {
160
+ detail: { command },
161
+ remedy: "Shared storage is not global installation. Run npm directly, for example: " +
162
+ "npm install --global <package-spec>. zyrk will not run npm for you.",
163
+ });
164
+ }
165
+ /**
166
+ * Pure dispatch: no filesystem, network, or subprocess effects. Returns the
167
+ * exact bytes for stdout/stderr and the process exit code.
168
+ */
169
+ export function dispatch(parsed, context) {
170
+ if (parsed.version) {
171
+ return ok(`${context.version}\n`, parsed);
172
+ }
173
+ if (parsed.help || parsed.command === undefined) {
174
+ return ok(helpText(context.version), parsed);
175
+ }
176
+ const command = parsed.command;
177
+ if (isGlobalInstallRequest(command, parsed.commandArgs, context.env)) {
178
+ return fail(globalInstallError(command), parsed);
179
+ }
180
+ if (!KNOWN_COMMANDS.has(command)) {
181
+ const shown = sanitizeCommandToken(command);
182
+ const placementHint = command.includes("://") || parsed.argsBeforeCommand.length > 0
183
+ ? " If this was an option value, use the --flag=value form or place the command first."
184
+ : "";
185
+ return fail(new ZyrkError("ZYRK_USAGE", `unknown command: ${shown}.`, {
186
+ detail: { command: shown },
187
+ remedy: `Run \`zyrk --help\` for the documented command list.${placementHint}`,
188
+ }), parsed, helpText(context.version));
189
+ }
190
+ if (!IMPLEMENTED_COMMANDS.has(command)) {
191
+ return fail(new ZyrkError("ZYRK_NOT_IMPLEMENTED", `zyrk ${command} is not implemented yet.`, {
192
+ detail: { command },
193
+ remedy: "Only documented, implemented commands are advertised; this one is on the roadmap.",
194
+ }), parsed);
195
+ }
196
+ throw new ZyrkError("ZYRK_INTERNAL", `implemented command ${command} bypassed runCli.`, {
197
+ detail: { command },
198
+ remedy: "report this unreachable dispatch failure",
199
+ });
200
+ }
201
+ function readCliVersion() {
202
+ try {
203
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
204
+ const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
205
+ return typeof pkg.version === "string" ? pkg.version : "unknown";
206
+ }
207
+ catch {
208
+ return "unknown";
209
+ }
210
+ }
211
+ /** Parse, dispatch, delegate, or run a tool, and emit. The only impure seam. */
212
+ export async function runCli(options) {
213
+ const parsed = parseArgs(options.argv);
214
+ const version = (options.readVersion ?? readCliVersion)();
215
+ const emit = (result) => {
216
+ if (result.stdout !== "")
217
+ options.stdout.write(result.stdout);
218
+ if (result.stderr !== "")
219
+ options.stderr.write(result.stderr);
220
+ return result.exitCode;
221
+ };
222
+ if (!parsed.help &&
223
+ !parsed.version &&
224
+ parsed.command &&
225
+ isGlobalInstallRequest(parsed.command, parsed.commandArgs, options.env))
226
+ return emit(fail(globalInstallError(parsed.command), parsed));
227
+ // Delegation bypasses dispatch: zyrk interprets no command arguments
228
+ // itself, adds no JSON envelope, and forwards every non-zyrk token
229
+ // verbatim — before the command as well as after it. A leading
230
+ // protective flag such as `--dry-run` belongs to npm; dropping it would
231
+ // silently change what runs (S05). The only tokens zyrk consumes are its
232
+ // own `--json`/`--help`/`--version`, and `--json` is passed on so npm
233
+ // still sees exactly what it was given.
234
+ if (!parsed.help &&
235
+ !parsed.version &&
236
+ parsed.command !== undefined &&
237
+ isDelegatedCommand(parsed.command)) {
238
+ try {
239
+ const forwarded = [...parsed.argsBeforeCommand];
240
+ if (parsed.json && !parsed.argsAfterCommand.includes("--json")) {
241
+ forwarded.push("--json");
242
+ }
243
+ forwarded.push(...parsed.argsAfterCommand);
244
+ return await delegateToNpm({
245
+ command: parsed.command,
246
+ args: forwarded,
247
+ env: options.env,
248
+ stderr: options.stderr,
249
+ });
250
+ }
251
+ catch (error) {
252
+ return emit(fail(toZyrkError(error, "zyrk failed while delegating to npm."), parsed));
253
+ }
254
+ }
255
+ if (!parsed.help &&
256
+ !parsed.version &&
257
+ parsed.command &&
258
+ [
259
+ "fetch",
260
+ "audit",
261
+ "approve-builds",
262
+ "rebuild",
263
+ "repair",
264
+ "patch",
265
+ "patch-commit",
266
+ "deploy",
267
+ "docker",
268
+ ].includes(parsed.command)) {
269
+ try {
270
+ const command = parsed.command, cwd = options.cwd ?? process.cwd();
271
+ if (command === "deploy" || command === "docker")
272
+ return await runDeployCommand({
273
+ command,
274
+ args: parsed.commandArgs,
275
+ cwd,
276
+ env: options.env,
277
+ stdout: options.stdout,
278
+ stderr: options.stderr,
279
+ json: parsed.json,
280
+ });
281
+ const tools = options.tools
282
+ ? await options.tools()
283
+ : await defaultTools(options.env, version, cwd);
284
+ let result;
285
+ if (command === "patch" || command === "patch-commit")
286
+ result = await runPatchCommand({
287
+ command,
288
+ args: parsed.commandArgs,
289
+ cwd,
290
+ store: tools.store,
291
+ });
292
+ else if (command === "approve-builds") {
293
+ if (parsed.commandArgs.some((v) => v.startsWith("-") && v !== "--all"))
294
+ throw new ZyrkError("ZYRK_USAGE", "Unsupported build approval option.", {
295
+ remedy: "Use approve-builds to review; approve-builds <name...> or --all explicitly trusts reviewed source code.",
296
+ });
297
+ const selected = parsed.commandArgs.includes("--all")
298
+ ? ["*"]
299
+ : parsed.commandArgs;
300
+ result = await installProject({
301
+ ...tools,
302
+ projectDir: cwd,
303
+ env: options.env,
304
+ reviewBuilds: true,
305
+ ...(selected.length ? { approveBuilds: selected } : {}),
306
+ });
307
+ }
308
+ else if (command === "rebuild") {
309
+ if (parsed.commandArgs.some((v) => v !== "--offline"))
310
+ throw new ZyrkError("ZYRK_USAGE", "Rebuild operates on the complete approved project graph.", { remedy: "Use zyrk rebuild [--offline]; review approvals first." });
311
+ result = await installProject({
312
+ ...tools,
313
+ projectDir: cwd,
314
+ env: options.env,
315
+ frozen: true,
316
+ rebuild: true,
317
+ offline: parsed.commandArgs.includes("--offline"),
318
+ });
319
+ }
320
+ else if (command === "repair") {
321
+ if (parsed.commandArgs.some((arg) => arg !== "--offline"))
322
+ throw new ZyrkError("ZYRK_USAGE", "Repair accepts only --offline.", {
323
+ remedy: "Use zyrk repair to rebuild verified instances selected by the lock.",
324
+ });
325
+ result = await installProject({
326
+ ...tools,
327
+ projectDir: cwd,
328
+ env: options.env,
329
+ frozen: true,
330
+ repair: true,
331
+ offline: parsed.commandArgs.includes("--offline"),
332
+ });
333
+ }
334
+ else
335
+ result = await runMaintenanceCommand({
336
+ command: command,
337
+ env: options.env,
338
+ args: parsed.commandArgs,
339
+ projectDir: cwd,
340
+ ...tools,
341
+ });
342
+ const payload = (command === "audit" ? sanitizeDiagnostic(result) : result);
343
+ if (Array.isArray(payload.builds))
344
+ payload.builds = sanitizeDiagnostic(payload.builds);
345
+ const exitCode = payload.status === "unavailable" || payload.thresholdExceeded === true
346
+ ? 1
347
+ : 0;
348
+ if (parsed.json)
349
+ return emit({
350
+ exitCode,
351
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, ...payload, status: payload.status ?? "ok" })}\n`,
352
+ stderr: "",
353
+ });
354
+ if (command === "approve-builds") {
355
+ const builds = (payload.builds ?? []);
356
+ return emit({
357
+ exitCode,
358
+ stdout: builds.length
359
+ ? builds
360
+ .map((b) => `${b.name}@${b.version} ${b.sourceId}\n${b.stages.map((s) => ` ${s.name}: ${redactSecrets(s.command)}`).join("\n")}`)
361
+ .join("\n") +
362
+ "\nReview runs no package code. Approval trusts these exact candidate sources.\n"
363
+ : "No dependency builds require approval.\n",
364
+ stderr: "",
365
+ });
366
+ }
367
+ return emit({
368
+ exitCode,
369
+ stdout: `${JSON.stringify(payload)}\n`,
370
+ stderr: "",
371
+ });
372
+ }
373
+ catch (error) {
374
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
375
+ }
376
+ }
377
+ if (!parsed.help &&
378
+ !parsed.version &&
379
+ (parsed.command === "install" || parsed.command === "i")) {
380
+ if (isGlobalInstallRequest(parsed.command, parsed.commandArgs, options.env))
381
+ return emit(fail(globalInstallError(parsed.command), parsed));
382
+ try {
383
+ if (parsed.commandArgs.includes("--help") ||
384
+ parsed.commandArgs.includes("-h")) {
385
+ return emit(ok("Usage: zyrk install [package[@version] ...] [-D] [--save-exact] [--frozen-lockfile] [--offline] [--ignore-scripts] [--lockfile-only] [--omit=dev] [--registry=https://registry.npmjs.org/] [--json]\n", parsed));
386
+ }
387
+ const specs = [];
388
+ const flags = {};
389
+ let registryUrl;
390
+ for (const token of parsed.commandArgs) {
391
+ if (token === "--frozen-lockfile")
392
+ flags.frozen = true;
393
+ else if (token === "--offline")
394
+ flags.offline = true;
395
+ else if (token === "--ignore-scripts")
396
+ flags.ignoreScripts = true;
397
+ else if (token === "--lockfile-only")
398
+ flags.lockfileOnly = true;
399
+ else if (token === "--omit=dev" || token === "--production")
400
+ flags.omitDev = true;
401
+ else if (token === "-D" || token === "--save-dev")
402
+ flags.saveDev = true;
403
+ else if (token === "-E" || token === "--save-exact")
404
+ flags.saveExact = true;
405
+ else if (token === "--no-global" || token === "--global=false")
406
+ continue;
407
+ else if (token.startsWith("--registry="))
408
+ registryUrl = token.slice("--registry=".length);
409
+ else if (token.startsWith("-"))
410
+ throw new ZyrkError("ZYRK_USAGE", "Unsupported install option.", {
411
+ remedy: "Run zyrk install --help for supported options; use --registry=URL for a custom registry.",
412
+ });
413
+ else
414
+ specs.push(token);
415
+ }
416
+ const cwd = options.cwd ?? process.cwd();
417
+ const tools = options.tools
418
+ ? await options.tools()
419
+ : {
420
+ registry: await installRegistry({
421
+ cwd,
422
+ env: options.env,
423
+ version,
424
+ ...(registryUrl === undefined ? {} : { registry: registryUrl }),
425
+ }),
426
+ store: await Store.open({
427
+ root: resolveStoreRoot({ env: options.env }).root,
428
+ create: true,
429
+ }),
430
+ };
431
+ const result = await installProject({
432
+ ...flags,
433
+ env: options.env,
434
+ specs,
435
+ projectDir: cwd,
436
+ ...tools,
437
+ });
438
+ if (parsed.json)
439
+ return emit({
440
+ exitCode: 0,
441
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok", ...result })}\n`,
442
+ stderr: "",
443
+ });
444
+ const summary = result.readiness === "lockfile-only"
445
+ ? "Lockfile written; dependencies were not installed."
446
+ : `Installed ${result.packages} packages using shared storage (${result.reused} realizations reused); ${result.readiness}.`;
447
+ return emit({
448
+ exitCode: 0,
449
+ stdout: `${summary}\n`,
450
+ stderr: result.warnings.map((w) => `zyrk: ${w}\n`).join(""),
451
+ });
452
+ }
453
+ catch (error) {
454
+ return emit(fail(toZyrkError(error, "zyrk install failed."), parsed));
455
+ }
456
+ }
457
+ if (!parsed.help &&
458
+ !parsed.version &&
459
+ (parsed.command === "dlx" || parsed.command === "create")) {
460
+ try {
461
+ return await runToolCommand(parsed.command, parsed, options, version);
462
+ }
463
+ catch (error) {
464
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
465
+ }
466
+ }
467
+ // Dependency commands: add, remove, update, import
468
+ if (!parsed.help &&
469
+ !parsed.version &&
470
+ (parsed.command === "add" ||
471
+ parsed.command === "remove" ||
472
+ parsed.command === "update" ||
473
+ parsed.command === "import")) {
474
+ try {
475
+ const tools = options.tools === undefined
476
+ ? await defaultTools(options.env, version, options.cwd ?? process.cwd())
477
+ : await options.tools();
478
+ const result = await runDependencyCommand({
479
+ command: parsed.command,
480
+ env: options.env,
481
+ args: parsed.commandArgs,
482
+ projectDir: options.cwd ?? process.cwd(),
483
+ store: tools.store,
484
+ registry: tools.registry,
485
+ });
486
+ if (parsed.json) {
487
+ return emit({
488
+ exitCode: 0,
489
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok", ...result })}\n`,
490
+ stderr: "",
491
+ });
492
+ }
493
+ return emit({
494
+ exitCode: 0,
495
+ stdout: `Dependency command ${parsed.command} completed.\n`,
496
+ stderr: "",
497
+ });
498
+ }
499
+ catch (error) {
500
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
501
+ }
502
+ }
503
+ // Project commands: run, exec, list, why, doctor, repair
504
+ if (!parsed.help &&
505
+ !parsed.version &&
506
+ (parsed.command === "run" ||
507
+ parsed.command === "exec" ||
508
+ parsed.command === "list" ||
509
+ parsed.command === "why" ||
510
+ parsed.command === "doctor" ||
511
+ parsed.command === "repair")) {
512
+ try {
513
+ return await runProjectCommand({
514
+ command: parsed.command,
515
+ args: parsed.commandArgs,
516
+ cwd: options.cwd ?? process.cwd(),
517
+ env: options.env,
518
+ stdout: options.stdout,
519
+ stderr: options.stderr,
520
+ json: parsed.json,
521
+ });
522
+ }
523
+ catch (error) {
524
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
525
+ }
526
+ }
527
+ // Store and projects commands: store path/status/verify/gc/pin/unpin, projects list/forget
528
+ if (!parsed.help &&
529
+ !parsed.version &&
530
+ (parsed.command === "store" || parsed.command === "projects")) {
531
+ try {
532
+ const store = options.tools === undefined
533
+ ? await Store.open({
534
+ root: resolveStoreRoot({ env: options.env }).root,
535
+ create: false,
536
+ })
537
+ : (await options.tools()).store;
538
+ const result = await runStoreCommand({
539
+ command: parsed.command,
540
+ args: parsed.commandArgs,
541
+ store,
542
+ cwd: options.cwd ?? process.cwd(),
543
+ json: parsed.json,
544
+ });
545
+ if (parsed.json) {
546
+ return emit({
547
+ exitCode: 0,
548
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok", ...result })}\n`,
549
+ stderr: "",
550
+ });
551
+ }
552
+ return emit({
553
+ exitCode: 0,
554
+ stdout: `${JSON.stringify(result)}\n`,
555
+ stderr: "",
556
+ });
557
+ }
558
+ catch (error) {
559
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
560
+ }
561
+ }
562
+ return emit(dispatch(parsed, { version, env: options.env }));
563
+ }
564
+ async function defaultTools(env, version, cwd = process.cwd()) {
565
+ const registry = await installRegistry({ cwd, env, version });
566
+ const store = await Store.open({
567
+ root: resolveStoreRoot({ env }).root,
568
+ create: true,
569
+ });
570
+ return { store, registry };
571
+ }
572
+ async function runToolCommand(command, parsed, options, version) {
573
+ if (parsed.json) {
574
+ throw new ZyrkError("ZYRK_USAGE", `zyrk ${command} does not support --json; the tool owns stdout.`, {
575
+ detail: { command },
576
+ remedy: `run zyrk ${command} without --json.`,
577
+ });
578
+ }
579
+ const tail = parsed.commandArgs;
580
+ const first = tail[0];
581
+ if (first === undefined) {
582
+ throw new ZyrkError("ZYRK_USAGE", command === "dlx"
583
+ ? "zyrk dlx needs a tool specifier."
584
+ : "zyrk create needs an initializer name.", {
585
+ detail: { command },
586
+ remedy: command === "dlx"
587
+ ? "use zyrk dlx <package>[@version] [args...]."
588
+ : "use zyrk create <name>[@version] [args...].",
589
+ });
590
+ }
591
+ const tools = options.tools === undefined
592
+ ? await defaultTools(options.env, version, options.cwd ?? process.cwd())
593
+ : await options.tools();
594
+ const base = {
595
+ store: tools.store,
596
+ registry: tools.registry,
597
+ args: tail.slice(1),
598
+ cwd: options.cwd ?? process.cwd(),
599
+ env: options.env,
600
+ };
601
+ if (command === "dlx") {
602
+ return (await runDlx({ ...base, spec: first })).exitCode;
603
+ }
604
+ return (await runCreate({ ...base, input: first })).exitCode;
605
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Explicit delegation of registry write-side and account commands to the
3
+ * user's own npm CLI (D-3, founder direction).
4
+ *
5
+ * zyrk does not reimplement publishing or registry authentication: it
6
+ * verifies nothing about the arguments, forwards them verbatim to `npm`,
7
+ * and propagates the child exit code or signal unchanged. The environment
8
+ * passes through untouched — zyrk injects no credentials, tokens, or ZYRK_*
9
+ * variables, and npm authenticates exactly as when run directly. stdio is
10
+ * inherited so interactive flows (`login`) and scripts parsing stdout
11
+ * (`pack --json`) behave identically. A one-line disclosure goes to stderr
12
+ * so npm's stdout stays clean.
13
+ *
14
+ * Delegation never touches the zyrk store, lockfile, or projection, never
15
+ * runs package code itself, and never selects versions: those commands
16
+ * operate outside zyrk's dependency management. Global installs are never
17
+ * delegated (F-018); see parse.ts.
18
+ */
19
+ export declare const DELEGATED_COMMAND_NAMES: ReadonlySet<string>;
20
+ export declare function isDelegatedCommand(command: string): boolean;
21
+ export declare function delegatedHelpLines(): string[];
22
+ export type DelegateOptions = {
23
+ command: string;
24
+ /** Raw tokens after the command, verbatim (may include --json, --, -g). */
25
+ args: readonly string[];
26
+ env: NodeJS.ProcessEnv;
27
+ stderr: {
28
+ write(chunk: string): unknown;
29
+ };
30
+ };
31
+ /**
32
+ * Exec `npm <command> <args...>` with inherited stdio. Resolves with the
33
+ * child exit code, or 128 plus the signal number when signaled (the shell
34
+ * convention), so callers observe the same termination. Rejects with
35
+ * ZYRK_NPM_UNAVAILABLE when npm cannot be launched.
36
+ */
37
+ export declare function delegateToNpm(options: DelegateOptions): Promise<number>;
38
+ //# sourceMappingURL=npm-delegate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-delegate.d.ts","sourceRoot":"","sources":["../../src/cli/npm-delegate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAsBH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAEvD,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAK7C;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC3C,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB7E"}