zyrk 0.3.7 → 0.3.9

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 (189) hide show
  1. package/VERSION +1 -1
  2. package/bin/zyrk.js +1 -1
  3. package/dist/cli/main.d.ts +54 -0
  4. package/dist/cli/main.d.ts.map +1 -0
  5. package/dist/cli/main.js +473 -0
  6. package/dist/cli/npm-delegate.d.ts +38 -0
  7. package/dist/cli/npm-delegate.d.ts.map +1 -0
  8. package/{src/cli/npm-delegate.ts → dist/cli/npm-delegate.js} +26 -55
  9. package/dist/cli/parse.d.ts +40 -0
  10. package/dist/cli/parse.d.ts.map +1 -0
  11. package/dist/cli/parse.js +78 -0
  12. package/dist/commands/dependencies.d.ts +12 -0
  13. package/dist/commands/dependencies.d.ts.map +1 -0
  14. package/dist/commands/dependencies.js +118 -0
  15. package/dist/commands/deploy.d.ts +15 -0
  16. package/dist/commands/deploy.d.ts.map +1 -0
  17. package/dist/commands/deploy.js +506 -0
  18. package/dist/commands/maintenance.d.ts +27 -0
  19. package/dist/commands/maintenance.d.ts.map +1 -0
  20. package/dist/commands/maintenance.js +198 -0
  21. package/dist/commands/patch.d.ts +38 -0
  22. package/dist/commands/patch.d.ts.map +1 -0
  23. package/dist/commands/patch.js +336 -0
  24. package/dist/commands/project.d.ts +15 -0
  25. package/dist/commands/project.d.ts.map +1 -0
  26. package/dist/commands/project.js +396 -0
  27. package/dist/commands/store.d.ts +10 -0
  28. package/dist/commands/store.d.ts.map +1 -0
  29. package/dist/commands/store.js +551 -0
  30. package/dist/config/paths.d.ts +37 -0
  31. package/dist/config/paths.d.ts.map +1 -0
  32. package/dist/config/paths.js +66 -0
  33. package/dist/dlx/create.d.ts +23 -0
  34. package/dist/dlx/create.d.ts.map +1 -0
  35. package/dist/dlx/create.js +59 -0
  36. package/dist/dlx/run.d.ts +54 -0
  37. package/dist/dlx/run.d.ts.map +1 -0
  38. package/dist/dlx/run.js +274 -0
  39. package/dist/errors.d.ts +68 -0
  40. package/dist/errors.d.ts.map +1 -0
  41. package/dist/errors.js +111 -0
  42. package/dist/extract/tarball.d.ts +82 -0
  43. package/dist/extract/tarball.d.ts.map +1 -0
  44. package/dist/extract/tarball.js +645 -0
  45. package/dist/fetch/all.d.ts +48 -0
  46. package/dist/fetch/all.d.ts.map +1 -0
  47. package/dist/fetch/all.js +127 -0
  48. package/dist/fetch/package.d.ts +45 -0
  49. package/dist/fetch/package.d.ts.map +1 -0
  50. package/dist/fetch/package.js +124 -0
  51. package/dist/fetch/registry.d.ts +109 -0
  52. package/dist/fetch/registry.d.ts.map +1 -0
  53. package/dist/fetch/registry.js +418 -0
  54. package/dist/install/import-npm.d.ts +4 -0
  55. package/dist/install/import-npm.d.ts.map +1 -0
  56. package/dist/install/import-npm.js +147 -0
  57. package/dist/install/lock.d.ts +8 -0
  58. package/dist/install/lock.d.ts.map +1 -0
  59. package/dist/install/lock.js +146 -0
  60. package/dist/install/metadata.d.ts +19 -0
  61. package/dist/install/metadata.d.ts.map +1 -0
  62. package/dist/install/metadata.js +79 -0
  63. package/dist/install/registry.d.ts +8 -0
  64. package/dist/install/registry.d.ts.map +1 -0
  65. package/dist/install/registry.js +59 -0
  66. package/dist/install/run.d.ts +32 -0
  67. package/dist/install/run.d.ts.map +1 -0
  68. package/dist/install/run.js +545 -0
  69. package/dist/lockfile/fingerprints.d.ts +35 -0
  70. package/dist/lockfile/fingerprints.d.ts.map +1 -0
  71. package/dist/lockfile/fingerprints.js +56 -0
  72. package/dist/lockfile/read.d.ts +27 -0
  73. package/dist/lockfile/read.d.ts.map +1 -0
  74. package/dist/lockfile/read.js +126 -0
  75. package/dist/lockfile/types.d.ts +74 -0
  76. package/dist/lockfile/types.d.ts.map +1 -0
  77. package/dist/lockfile/types.js +17 -0
  78. package/dist/lockfile/write.d.ts +39 -0
  79. package/dist/lockfile/write.d.ts.map +1 -0
  80. package/dist/lockfile/write.js +180 -0
  81. package/dist/log.d.ts +21 -0
  82. package/dist/log.d.ts.map +1 -0
  83. package/dist/log.js +79 -0
  84. package/dist/project/projection.d.ts +50 -0
  85. package/dist/project/projection.d.ts.map +1 -0
  86. package/dist/project/projection.js +276 -0
  87. package/dist/resolve/resolver.d.ts +75 -0
  88. package/dist/resolve/resolver.d.ts.map +1 -0
  89. package/dist/resolve/resolver.js +533 -0
  90. package/dist/resolve/spec.d.ts +26 -0
  91. package/dist/resolve/spec.d.ts.map +1 -0
  92. package/dist/resolve/spec.js +87 -0
  93. package/dist/store/db.d.ts +49 -0
  94. package/dist/store/db.d.ts.map +1 -0
  95. package/{src/store/db.ts → dist/store/db.js} +106 -206
  96. package/dist/store/graph.d.ts +60 -0
  97. package/dist/store/graph.d.ts.map +1 -0
  98. package/dist/store/graph.js +115 -0
  99. package/dist/store/layout.d.ts +71 -0
  100. package/dist/store/layout.d.ts.map +1 -0
  101. package/dist/store/layout.js +282 -0
  102. package/dist/store/manifests.d.ts +78 -0
  103. package/dist/store/manifests.d.ts.map +1 -0
  104. package/dist/store/manifests.js +238 -0
  105. package/dist/store/objects.d.ts +56 -0
  106. package/dist/store/objects.d.ts.map +1 -0
  107. package/dist/store/objects.js +157 -0
  108. package/dist/store/realize.d.ts +38 -0
  109. package/dist/store/realize.d.ts.map +1 -0
  110. package/dist/store/realize.js +227 -0
  111. package/dist/store/source.d.ts +42 -0
  112. package/dist/store/source.d.ts.map +1 -0
  113. package/dist/store/source.js +169 -0
  114. package/dist/store/txn.d.ts +37 -0
  115. package/dist/store/txn.d.ts.map +1 -0
  116. package/dist/store/txn.js +97 -0
  117. package/dist/store/verify.d.ts +40 -0
  118. package/dist/store/verify.d.ts.map +1 -0
  119. package/dist/store/verify.js +396 -0
  120. package/dist/util/fsx.d.ts +54 -0
  121. package/dist/util/fsx.d.ts.map +1 -0
  122. package/dist/util/fsx.js +259 -0
  123. package/dist/util/hash.d.ts +48 -0
  124. package/dist/util/hash.d.ts.map +1 -0
  125. package/dist/util/hash.js +80 -0
  126. package/dist/util/ids.d.ts +19 -0
  127. package/dist/util/ids.d.ts.map +1 -0
  128. package/dist/util/ids.js +38 -0
  129. package/dist/util/integrity.d.ts +97 -0
  130. package/dist/util/integrity.d.ts.map +1 -0
  131. package/dist/util/integrity.js +192 -0
  132. package/dist/util/json.d.ts +14 -0
  133. package/dist/util/json.d.ts.map +1 -0
  134. package/dist/util/json.js +78 -0
  135. package/dist/util/locks.d.ts +40 -0
  136. package/dist/util/locks.d.ts.map +1 -0
  137. package/dist/util/locks.js +186 -0
  138. package/dist/util/proc.d.ts +32 -0
  139. package/dist/util/proc.d.ts.map +1 -0
  140. package/dist/util/proc.js +84 -0
  141. package/dist/version.d.ts +27 -0
  142. package/dist/version.d.ts.map +1 -0
  143. package/{src/version.ts → dist/version.js} +0 -8
  144. package/package.json +5 -3
  145. package/src/cli/main.ts +0 -468
  146. package/src/cli/parse.ts +0 -106
  147. package/src/commands/dependencies.ts +0 -154
  148. package/src/commands/deploy.ts +0 -777
  149. package/src/commands/maintenance.ts +0 -260
  150. package/src/commands/patch.ts +0 -408
  151. package/src/commands/project.ts +0 -598
  152. package/src/commands/store.ts +0 -689
  153. package/src/config/paths.ts +0 -119
  154. package/src/dlx/create.ts +0 -69
  155. package/src/dlx/run.ts +0 -389
  156. package/src/errors.ts +0 -142
  157. package/src/extract/tarball.ts +0 -868
  158. package/src/fetch/all.ts +0 -206
  159. package/src/fetch/package.ts +0 -181
  160. package/src/fetch/registry.ts +0 -615
  161. package/src/install/import-npm.ts +0 -177
  162. package/src/install/lock.ts +0 -176
  163. package/src/install/metadata.ts +0 -122
  164. package/src/install/registry.ts +0 -88
  165. package/src/install/run.ts +0 -760
  166. package/src/lockfile/fingerprints.ts +0 -74
  167. package/src/lockfile/read.ts +0 -198
  168. package/src/lockfile/types.ts +0 -75
  169. package/src/lockfile/write.ts +0 -257
  170. package/src/log.ts +0 -100
  171. package/src/project/projection.ts +0 -390
  172. package/src/resolve/resolver.ts +0 -757
  173. package/src/resolve/spec.ts +0 -131
  174. package/src/store/graph.ts +0 -175
  175. package/src/store/layout.ts +0 -431
  176. package/src/store/manifests.ts +0 -347
  177. package/src/store/objects.ts +0 -229
  178. package/src/store/realize.ts +0 -322
  179. package/src/store/source.ts +0 -249
  180. package/src/store/txn.ts +0 -118
  181. package/src/store/verify.ts +0 -433
  182. package/src/types/vendor.d.ts +0 -120
  183. package/src/util/fsx.ts +0 -289
  184. package/src/util/hash.ts +0 -117
  185. package/src/util/ids.ts +0 -42
  186. package/src/util/integrity.ts +0 -269
  187. package/src/util/json.ts +0 -89
  188. package/src/util/locks.ts +0 -266
  189. package/src/util/proc.ts +0 -108
package/VERSION CHANGED
@@ -1 +1 @@
1
- v0.3.7
1
+ v0.3.9
package/bin/zyrk.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { runCli } from "../src/cli/main.ts";
2
+ import { runCli } from "../dist/cli/main.js";
3
3
 
4
4
  process.exitCode = await runCli({
5
5
  argv: process.argv.slice(2),
@@ -0,0 +1,54 @@
1
+ /**
2
+ * zyrk command dispatch (SPEC 15).
3
+ *
4
+ * This is the roadmap skeleton, not the whole implementation: `dlx` and
5
+ * `create` run temporary tool environments; `--help`, `--version`, the
6
+ * global-install rejection, and explicit npm delegation do their jobs.
7
+ * `install` publishes a verified shared project graph. Other dependency
8
+ * commands fail with ZYRK_NOT_IMPLEMENTED rather than pretending to work;
9
+ * unknown commands fail with ZYRK_USAGE
10
+ * and the help text.
11
+ * Nothing here launches a subprocess: rejection happens before resolution,
12
+ * downloads, lifecycle execution, project/store mutation, or any child
13
+ * process (SPEC 15.3.1).
14
+ */
15
+ import { ZyrkError } from "../errors.ts";
16
+ export { ZyrkError };
17
+ import { RegistryClient } from "../fetch/registry.ts";
18
+ import { Store } from "../store/layout.ts";
19
+ import { type ParsedArgs } from "./parse.ts";
20
+ export declare const CLI_JSON_SCHEMA_VERSION = 1;
21
+ export declare function helpText(version: string): string;
22
+ export type CliOutput = {
23
+ exitCode: number;
24
+ stdout: string;
25
+ stderr: string;
26
+ };
27
+ /**
28
+ * Pure dispatch: no filesystem, network, or subprocess effects. Returns the
29
+ * exact bytes for stdout/stderr and the process exit code.
30
+ */
31
+ export declare function dispatch(parsed: ParsedArgs, context: {
32
+ version: string;
33
+ env: NodeJS.ProcessEnv;
34
+ }): CliOutput;
35
+ export type ToolEnvironment = {
36
+ store: Store;
37
+ registry: RegistryClient;
38
+ };
39
+ export type RunCliOptions = {
40
+ argv: readonly string[];
41
+ env: NodeJS.ProcessEnv;
42
+ stdout: {
43
+ write(chunk: string): unknown;
44
+ };
45
+ stderr: {
46
+ write(chunk: string): unknown;
47
+ };
48
+ readVersion?: () => string;
49
+ cwd?: string;
50
+ tools?: () => Promise<ToolEnvironment>;
51
+ };
52
+ /** Parse, dispatch, delegate, or run a tool, and emit. The only impure seam. */
53
+ export declare function runCli(options: RunCliOptions): Promise<number>;
54
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAkBH,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;AAmDzC,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwBhD;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,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC1C,MAAM,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;CACxC,CAAC;AAEF,gFAAgF;AAChF,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAqPpE"}
@@ -0,0 +1,473 @@
1
+ /**
2
+ * zyrk command dispatch (SPEC 15).
3
+ *
4
+ * This is the roadmap skeleton, not the whole implementation: `dlx` and
5
+ * `create` run temporary tool environments; `--help`, `--version`, the
6
+ * global-install rejection, and explicit npm delegation do their jobs.
7
+ * `install` publishes a verified shared project graph. Other dependency
8
+ * commands fail with ZYRK_NOT_IMPLEMENTED rather than pretending to work;
9
+ * unknown commands fail with ZYRK_USAGE
10
+ * and the help text.
11
+ * Nothing here launches a subprocess: rejection happens before resolution,
12
+ * downloads, lifecycle execution, project/store mutation, or any child
13
+ * process (SPEC 15.3.1).
14
+ */
15
+ import { installProject } from "../install/run.js";
16
+ import { installRegistry } from "../install/registry.js";
17
+ import { readFileSync } from "node:fs";
18
+ import * as path from "node:path";
19
+ import { fileURLToPath } from "node:url";
20
+ import { runCreate } from "../dlx/create.js";
21
+ import { runDlx } from "../dlx/run.js";
22
+ import { runDependencyCommand, } from "../commands/dependencies.js";
23
+ import { runProjectCommand, } from "../commands/project.js";
24
+ import { runStoreCommand } from "../commands/store.js";
25
+ import { exitCodeFor, ZyrkError, toZyrkError } from "../errors.js";
26
+ export { ZyrkError };
27
+ import { DEFAULT_REGISTRY, RegistryClient } from "../fetch/registry.js";
28
+ import { resolveStoreRoot } from "../config/paths.js";
29
+ import { Store } from "../store/layout.js";
30
+ import { delegateToNpm, delegatedHelpLines, isDelegatedCommand, } from "./npm-delegate.js";
31
+ import { isGlobalInstallRequest, parseArgs } from "./parse.js";
32
+ export const CLI_JSON_SCHEMA_VERSION = 1;
33
+ /** Spec-defined dependency commands (SPEC 15.1-15.2, fetch, docker). */
34
+ const NATIVE_COMMANDS = [
35
+ ["install, i", "Install the locked or newly resolved graph."],
36
+ ["fetch", "Fetch and verify a locked source closure."],
37
+ ["add", "Add dependencies transactionally."],
38
+ ["remove", "Remove direct dependencies and refresh the closure."],
39
+ ["update", "Update within allowed ranges."],
40
+ ["run", "Run a project script with local binary paths."],
41
+ ["exec", "Run an installed executable (never fetches)."],
42
+ ["dlx", "Explicitly fetch and run a temporary tool environment."],
43
+ ["create", "Scaffold from a create-* starter package."],
44
+ ["list, why", "Show the installed graph / why a dependency is selected."],
45
+ ["doctor", "Diagnose filesystem, links, policy, install-state issues."],
46
+ ["approve-builds, rebuild", "Review script permissions / rebuild."],
47
+ ["audit", "Report vulnerabilities under the configured privacy policy."],
48
+ ["patch, patch-commit", "Create a private edit area / emit a patch."],
49
+ ["store", "Inspect, verify, collect, and retain the store."],
50
+ ["projects", "List registrations / drop a retention root."],
51
+ ["repair", "Reconstruct the project from verified locked inputs."],
52
+ ["import", "Convert supported npm lock information."],
53
+ ["deploy", "Create self-contained production output."],
54
+ ["docker", "Generate, build, and start the Docker setup."],
55
+ ];
56
+ const KNOWN_COMMANDS = new Set();
57
+ for (const [names] of NATIVE_COMMANDS) {
58
+ for (const name of names.split(", "))
59
+ KNOWN_COMMANDS.add(name);
60
+ }
61
+ /** Commands with a real implementation behind runCli. */
62
+ const IMPLEMENTED_COMMANDS = new Set([
63
+ "dlx",
64
+ "create",
65
+ "install",
66
+ "i",
67
+ "add",
68
+ "remove",
69
+ "update",
70
+ "import",
71
+ "run",
72
+ "exec",
73
+ "list",
74
+ "why",
75
+ "doctor",
76
+ "repair",
77
+ "store",
78
+ "projects",
79
+ ]);
80
+ export function helpText(version) {
81
+ const lines = [
82
+ `zyrk v${version} — one verified store per user, shared across projects through links.`,
83
+ "",
84
+ "Usage: zyrk <command> [args] [--json]",
85
+ "",
86
+ "Dependency commands:",
87
+ ];
88
+ for (const [names, description] of NATIVE_COMMANDS) {
89
+ const done = names
90
+ .split(", ")
91
+ .some((name) => IMPLEMENTED_COMMANDS.has(name));
92
+ lines.push(` ${names.padEnd(24, " ")}${description}${done ? "" : " (not implemented yet)"}`);
93
+ }
94
+ lines.push("", "Registry publishing and account commands (via your npm):");
95
+ lines.push(...delegatedHelpLines());
96
+ 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>");
97
+ return `${lines.join("\n")}\n`;
98
+ }
99
+ function ok(stdout, parsed) {
100
+ if (!parsed.json)
101
+ return { exitCode: 0, stdout, stderr: "" };
102
+ return {
103
+ exitCode: 0,
104
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok" })}\n`,
105
+ stderr: "",
106
+ };
107
+ }
108
+ function fail(error, parsed, stdoutHint = "") {
109
+ const human = `zyrk: error ${error.code}: ${error.message}` +
110
+ (error.remedy === undefined ? "" : `\n${error.remedy}`);
111
+ if (!parsed.json) {
112
+ return {
113
+ exitCode: exitCodeFor(error),
114
+ stdout: stdoutHint,
115
+ stderr: `${human}\n`,
116
+ };
117
+ }
118
+ const body = {
119
+ schemaVersion: CLI_JSON_SCHEMA_VERSION,
120
+ status: "error",
121
+ code: error.code,
122
+ message: error.message,
123
+ };
124
+ if (error.remedy !== undefined)
125
+ body.remedy = error.remedy;
126
+ return {
127
+ exitCode: exitCodeFor(error),
128
+ stdout: `${JSON.stringify(body)}\n`,
129
+ stderr: "",
130
+ };
131
+ }
132
+ /**
133
+ * Echo a command token back safely: drop control characters, cap length,
134
+ * and strip URL userinfo so error output cannot leak credentials or forge
135
+ * terminal sequences. Full structured output redaction is S03; this covers
136
+ * the one place CLI dispatch interpolates an arbitrary token today.
137
+ */
138
+ /**
139
+ * Drop C0 control characters and DEL without regex escapes.
140
+ */
141
+ function stripControlChars(token) {
142
+ let out = "";
143
+ for (const ch of token) {
144
+ const code = ch.codePointAt(0);
145
+ if (code !== undefined && code >= 32 && code !== 127)
146
+ out += ch;
147
+ }
148
+ return out;
149
+ }
150
+ function sanitizeCommandToken(token) {
151
+ const oneLine = stripControlChars(token);
152
+ const capped = oneLine.length > 64 ? `${oneLine.slice(0, 64)}…` : oneLine;
153
+ return capped.replace(/([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)([^@/]*@)?/, "$1");
154
+ }
155
+ function globalInstallError(command) {
156
+ return new ZyrkError("ZYRK_GLOBAL_INSTALL_UNSUPPORTED", `zyrk does not install packages globally (requested: zyrk ${command} with global-install mode).`, {
157
+ detail: { command },
158
+ remedy: "Shared storage is not global installation. Run npm directly, for example: " +
159
+ "npm install --global <package-spec>. zyrk will not run npm for you.",
160
+ });
161
+ }
162
+ /**
163
+ * Pure dispatch: no filesystem, network, or subprocess effects. Returns the
164
+ * exact bytes for stdout/stderr and the process exit code.
165
+ */
166
+ export function dispatch(parsed, context) {
167
+ if (parsed.version) {
168
+ return ok(`${context.version}\n`, parsed);
169
+ }
170
+ if (parsed.help || parsed.command === undefined) {
171
+ return ok(helpText(context.version), parsed);
172
+ }
173
+ const command = parsed.command;
174
+ if (isGlobalInstallRequest(command, parsed.commandArgs, context.env)) {
175
+ return fail(globalInstallError(command), parsed);
176
+ }
177
+ if (!KNOWN_COMMANDS.has(command)) {
178
+ const shown = sanitizeCommandToken(command);
179
+ const placementHint = command.includes("://") || parsed.argsBeforeCommand.length > 0
180
+ ? " If this was an option value, use the --flag=value form or place the command first."
181
+ : "";
182
+ return fail(new ZyrkError("ZYRK_USAGE", `unknown command: ${shown}.`, {
183
+ detail: { command: shown },
184
+ remedy: `Run \`zyrk --help\` for the documented command list.${placementHint}`,
185
+ }), parsed, helpText(context.version));
186
+ }
187
+ if (!IMPLEMENTED_COMMANDS.has(command)) {
188
+ return fail(new ZyrkError("ZYRK_NOT_IMPLEMENTED", `zyrk ${command} is not implemented yet.`, {
189
+ detail: { command },
190
+ remedy: "Only documented, implemented commands are advertised; this one is on the roadmap.",
191
+ }), parsed);
192
+ }
193
+ throw new ZyrkError("ZYRK_INTERNAL", `implemented command ${command} bypassed runCli.`, {
194
+ detail: { command },
195
+ remedy: "report this unreachable dispatch failure",
196
+ });
197
+ }
198
+ function readCliVersion() {
199
+ try {
200
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
201
+ const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
202
+ return typeof pkg.version === "string" ? pkg.version : "unknown";
203
+ }
204
+ catch {
205
+ return "unknown";
206
+ }
207
+ }
208
+ /** Parse, dispatch, delegate, or run a tool, and emit. The only impure seam. */
209
+ export async function runCli(options) {
210
+ const parsed = parseArgs(options.argv);
211
+ const version = (options.readVersion ?? readCliVersion)();
212
+ const emit = (result) => {
213
+ if (result.stdout !== "")
214
+ options.stdout.write(result.stdout);
215
+ if (result.stderr !== "")
216
+ options.stderr.write(result.stderr);
217
+ return result.exitCode;
218
+ };
219
+ // Delegation bypasses dispatch: zyrk interprets no command arguments
220
+ // itself, adds no JSON envelope, and forwards every non-zyrk token
221
+ // verbatim — before the command as well as after it. A leading
222
+ // protective flag such as `--dry-run` belongs to npm; dropping it would
223
+ // silently change what runs (S05). The only tokens zyrk consumes are its
224
+ // own `--json`/`--help`/`--version`, and `--json` is passed on so npm
225
+ // still sees exactly what it was given.
226
+ if (!parsed.help &&
227
+ !parsed.version &&
228
+ parsed.command !== undefined &&
229
+ isDelegatedCommand(parsed.command)) {
230
+ try {
231
+ const forwarded = [...parsed.argsBeforeCommand];
232
+ if (parsed.json && !parsed.argsAfterCommand.includes("--json")) {
233
+ forwarded.push("--json");
234
+ }
235
+ forwarded.push(...parsed.argsAfterCommand);
236
+ return await delegateToNpm({
237
+ command: parsed.command,
238
+ args: forwarded,
239
+ env: options.env,
240
+ stderr: options.stderr,
241
+ });
242
+ }
243
+ catch (error) {
244
+ return emit(fail(toZyrkError(error, "zyrk failed while delegating to npm."), parsed));
245
+ }
246
+ }
247
+ if (!parsed.help &&
248
+ !parsed.version &&
249
+ (parsed.command === "install" || parsed.command === "i")) {
250
+ if (isGlobalInstallRequest(parsed.command, parsed.commandArgs, options.env))
251
+ return emit(fail(globalInstallError(parsed.command), parsed));
252
+ try {
253
+ if (parsed.commandArgs.includes("--help") ||
254
+ parsed.commandArgs.includes("-h")) {
255
+ 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));
256
+ }
257
+ const specs = [];
258
+ const flags = {};
259
+ let registryUrl;
260
+ for (const token of parsed.commandArgs) {
261
+ if (token === "--frozen-lockfile")
262
+ flags.frozen = true;
263
+ else if (token === "--offline")
264
+ flags.offline = true;
265
+ else if (token === "--ignore-scripts")
266
+ flags.ignoreScripts = true;
267
+ else if (token === "--lockfile-only")
268
+ flags.lockfileOnly = true;
269
+ else if (token === "--omit=dev" || token === "--production")
270
+ flags.omitDev = true;
271
+ else if (token === "-D" || token === "--save-dev")
272
+ flags.saveDev = true;
273
+ else if (token === "-E" || token === "--save-exact")
274
+ flags.saveExact = true;
275
+ else if (token === "--no-global" || token === "--global=false")
276
+ continue;
277
+ else if (token.startsWith("--registry="))
278
+ registryUrl = token.slice("--registry=".length);
279
+ else if (token.startsWith("-"))
280
+ throw new ZyrkError("ZYRK_USAGE", "Unsupported install option.", {
281
+ remedy: "Run zyrk install --help for supported options; use --registry=URL for a custom registry.",
282
+ });
283
+ else
284
+ specs.push(token);
285
+ }
286
+ const cwd = options.cwd ?? process.cwd();
287
+ const tools = options.tools
288
+ ? await options.tools()
289
+ : {
290
+ registry: await installRegistry({
291
+ cwd,
292
+ env: options.env,
293
+ version,
294
+ ...(registryUrl === undefined ? {} : { registry: registryUrl }),
295
+ }),
296
+ store: await Store.open({
297
+ root: resolveStoreRoot({ env: options.env }).root,
298
+ create: true,
299
+ }),
300
+ };
301
+ const result = await installProject({
302
+ ...flags,
303
+ specs,
304
+ projectDir: cwd,
305
+ ...tools,
306
+ });
307
+ if (parsed.json)
308
+ return emit({
309
+ exitCode: 0,
310
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok", ...result })}\n`,
311
+ stderr: "",
312
+ });
313
+ const summary = result.readiness === "lockfile-only"
314
+ ? "Lockfile written; dependencies were not installed."
315
+ : `Installed ${result.packages} packages using shared storage (${result.reused} realizations reused); ${result.readiness}.`;
316
+ return emit({
317
+ exitCode: 0,
318
+ stdout: `${summary}\n`,
319
+ stderr: result.warnings.map((w) => `zyrk: ${w}\n`).join(""),
320
+ });
321
+ }
322
+ catch (error) {
323
+ return emit(fail(toZyrkError(error, "zyrk install failed."), parsed));
324
+ }
325
+ }
326
+ if (!parsed.help &&
327
+ !parsed.version &&
328
+ (parsed.command === "dlx" || parsed.command === "create")) {
329
+ try {
330
+ return await runToolCommand(parsed.command, parsed, options, version);
331
+ }
332
+ catch (error) {
333
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
334
+ }
335
+ }
336
+ // Dependency commands: add, remove, update, import
337
+ if (!parsed.help &&
338
+ !parsed.version &&
339
+ (parsed.command === "add" ||
340
+ parsed.command === "remove" ||
341
+ parsed.command === "update" ||
342
+ parsed.command === "import")) {
343
+ try {
344
+ const tools = options.tools === undefined
345
+ ? await defaultTools(options.env, version)
346
+ : await options.tools();
347
+ const result = await runDependencyCommand({
348
+ command: parsed.command,
349
+ args: parsed.commandArgs,
350
+ projectDir: options.cwd ?? process.cwd(),
351
+ store: tools.store,
352
+ registry: tools.registry,
353
+ });
354
+ if (parsed.json) {
355
+ return emit({
356
+ exitCode: 0,
357
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok", ...result })}\n`,
358
+ stderr: "",
359
+ });
360
+ }
361
+ return emit({
362
+ exitCode: 0,
363
+ stdout: `Dependency command ${parsed.command} completed.\n`,
364
+ stderr: "",
365
+ });
366
+ }
367
+ catch (error) {
368
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
369
+ }
370
+ }
371
+ // Project commands: run, exec, list, why, doctor, repair
372
+ if (!parsed.help &&
373
+ !parsed.version &&
374
+ (parsed.command === "run" ||
375
+ parsed.command === "exec" ||
376
+ parsed.command === "list" ||
377
+ parsed.command === "why" ||
378
+ parsed.command === "doctor" ||
379
+ parsed.command === "repair")) {
380
+ try {
381
+ return await runProjectCommand({
382
+ command: parsed.command,
383
+ args: parsed.commandArgs,
384
+ cwd: options.cwd ?? process.cwd(),
385
+ env: options.env,
386
+ stdout: options.stdout,
387
+ stderr: options.stderr,
388
+ json: parsed.json,
389
+ });
390
+ }
391
+ catch (error) {
392
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
393
+ }
394
+ }
395
+ // Store and projects commands: store path/status/verify/gc/pin/unpin, projects list/forget
396
+ if (!parsed.help &&
397
+ !parsed.version &&
398
+ (parsed.command === "store" || parsed.command === "projects")) {
399
+ try {
400
+ const tools = options.tools === undefined
401
+ ? await defaultTools(options.env, version)
402
+ : await options.tools();
403
+ const result = await runStoreCommand({
404
+ command: parsed.command,
405
+ args: parsed.commandArgs,
406
+ store: tools.store,
407
+ cwd: options.cwd ?? process.cwd(),
408
+ json: parsed.json,
409
+ });
410
+ if (parsed.json) {
411
+ return emit({
412
+ exitCode: 0,
413
+ stdout: `${JSON.stringify({ schemaVersion: CLI_JSON_SCHEMA_VERSION, status: "ok", ...result })}\n`,
414
+ stderr: "",
415
+ });
416
+ }
417
+ return emit({
418
+ exitCode: 0,
419
+ stdout: `${JSON.stringify(result)}\n`,
420
+ stderr: "",
421
+ });
422
+ }
423
+ catch (error) {
424
+ return emit(fail(toZyrkError(error, `zyrk ${parsed.command} failed.`), parsed));
425
+ }
426
+ }
427
+ return emit(dispatch(parsed, { version, env: options.env }));
428
+ }
429
+ async function defaultTools(env, version) {
430
+ const store = await Store.open({
431
+ root: resolveStoreRoot({ env }).root,
432
+ create: true,
433
+ });
434
+ const registry = new RegistryClient({
435
+ registry: DEFAULT_REGISTRY,
436
+ userAgent: `zyrk/${version}`,
437
+ });
438
+ return { store, registry };
439
+ }
440
+ async function runToolCommand(command, parsed, options, version) {
441
+ if (parsed.json) {
442
+ throw new ZyrkError("ZYRK_USAGE", `zyrk ${command} does not support --json; the tool owns stdout.`, {
443
+ detail: { command },
444
+ remedy: `run zyrk ${command} without --json.`,
445
+ });
446
+ }
447
+ const tail = parsed.commandArgs;
448
+ const first = tail[0];
449
+ if (first === undefined) {
450
+ throw new ZyrkError("ZYRK_USAGE", command === "dlx"
451
+ ? "zyrk dlx needs a tool specifier."
452
+ : "zyrk create needs an initializer name.", {
453
+ detail: { command },
454
+ remedy: command === "dlx"
455
+ ? "use zyrk dlx <package>[@version] [args...]."
456
+ : "use zyrk create <name>[@version] [args...].",
457
+ });
458
+ }
459
+ const tools = options.tools === undefined
460
+ ? await defaultTools(options.env, version)
461
+ : await options.tools();
462
+ const base = {
463
+ store: tools.store,
464
+ registry: tools.registry,
465
+ args: tail.slice(1),
466
+ cwd: options.cwd ?? process.cwd(),
467
+ env: options.env,
468
+ };
469
+ if (command === "dlx") {
470
+ return (await runDlx({ ...base, spec: first })).exitCode;
471
+ }
472
+ return (await runCreate({ ...base, input: first })).exitCode;
473
+ }
@@ -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;AAuBH,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,CA2B7E"}