@zitadel/cli 0.1.0-alpha.8 → 1.0.0-alpha.20

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 (66) hide show
  1. package/README.md +250 -62
  2. package/SKILLS.md +227 -38
  3. package/dist/branding-cygSBPkV.mjs +79 -0
  4. package/dist/branding-cygSBPkV.mjs.map +1 -0
  5. package/dist/claim-state-DlfD6Res.mjs +66 -0
  6. package/dist/claim-state-DlfD6Res.mjs.map +1 -0
  7. package/dist/commands/apply.mjs +27 -8
  8. package/dist/commands/apply.mjs.map +1 -1
  9. package/dist/commands/branding/eject.mjs +104 -0
  10. package/dist/commands/branding/eject.mjs.map +1 -0
  11. package/dist/commands/claim.mjs +402 -0
  12. package/dist/commands/claim.mjs.map +1 -0
  13. package/dist/commands/doctor.mjs +687 -55
  14. package/dist/commands/doctor.mjs.map +1 -1
  15. package/dist/commands/eject.mjs +18 -6
  16. package/dist/commands/eject.mjs.map +1 -1
  17. package/dist/commands/logs.mjs +2 -2
  18. package/dist/commands/plan.mjs +19 -6
  19. package/dist/commands/plan.mjs.map +1 -1
  20. package/dist/commands/reset.mjs +12 -4
  21. package/dist/commands/reset.mjs.map +1 -1
  22. package/dist/commands/schemas/list.mjs +146 -0
  23. package/dist/commands/schemas/list.mjs.map +1 -0
  24. package/dist/commands/setup.mjs +642 -287
  25. package/dist/commands/setup.mjs.map +1 -1
  26. package/dist/commands/start.mjs +73 -6
  27. package/dist/commands/start.mjs.map +1 -1
  28. package/dist/commands/status.mjs +52 -13
  29. package/dist/commands/status.mjs.map +1 -1
  30. package/dist/commands/stop.mjs +59 -6
  31. package/dist/commands/stop.mjs.map +1 -1
  32. package/dist/designs-Ckz18Dpo.mjs +38 -0
  33. package/dist/designs-Ckz18Dpo.mjs.map +1 -0
  34. package/dist/{docker-BA78SdC2.mjs → docker-DcRGTOJa.mjs} +61 -11
  35. package/dist/docker-DcRGTOJa.mjs.map +1 -0
  36. package/dist/environment-rjRVkJjW.mjs +17 -0
  37. package/dist/environment-rjRVkJjW.mjs.map +1 -0
  38. package/dist/journey-guidance-BGrOX_gT.mjs +40 -0
  39. package/dist/journey-guidance-BGrOX_gT.mjs.map +1 -0
  40. package/dist/oclif-CanO3zdt.mjs +1769 -0
  41. package/dist/oclif-CanO3zdt.mjs.map +1 -0
  42. package/dist/{orca-CfKDQRop.mjs → orca-BzQIQqzt.mjs} +1663 -303
  43. package/dist/orca-BzQIQqzt.mjs.map +1 -0
  44. package/dist/package-manager-DFdLcDx1.mjs +194 -0
  45. package/dist/package-manager-DFdLcDx1.mjs.map +1 -0
  46. package/dist/ports-BM20XIZb.mjs +116 -0
  47. package/dist/ports-BM20XIZb.mjs.map +1 -0
  48. package/dist/processes-DKHPkU8O.mjs +120 -0
  49. package/dist/processes-DKHPkU8O.mjs.map +1 -0
  50. package/dist/{project-CKAHtHML.mjs → project-CHhot85s.mjs} +57 -4
  51. package/dist/project-CHhot85s.mjs.map +1 -0
  52. package/dist/sync-BBlACKzT.mjs +1633 -0
  53. package/dist/sync-BBlACKzT.mjs.map +1 -0
  54. package/dist/user-schema-DTuOsdKE.mjs +91 -0
  55. package/dist/user-schema-DTuOsdKE.mjs.map +1 -0
  56. package/oclif.manifest.json +412 -5
  57. package/package.json +10 -5
  58. package/dist/docker-BA78SdC2.mjs.map +0 -1
  59. package/dist/docker-guidance-BvfpmsDj.mjs +0 -21
  60. package/dist/docker-guidance-BvfpmsDj.mjs.map +0 -1
  61. package/dist/oclif-VkCTGIEk.mjs +0 -818
  62. package/dist/oclif-VkCTGIEk.mjs.map +0 -1
  63. package/dist/orca-CfKDQRop.mjs.map +0 -1
  64. package/dist/project-CKAHtHML.mjs.map +0 -1
  65. package/dist/sync-B5lqgQO3.mjs +0 -733
  66. package/dist/sync-B5lqgQO3.mjs.map +0 -1
@@ -0,0 +1,194 @@
1
+ import { S as isObject } from "./oclif-CanO3zdt.mjs";
2
+ import { i as updateScaffold, n as readState } from "./user-schema-DTuOsdKE.mjs";
3
+ import { readFile, stat } from "node:fs/promises";
4
+ import { isAbsolute, join, relative, sep } from "node:path";
5
+ import { createHash } from "node:crypto";
6
+ import { spawn } from "node:child_process";
7
+ //#region src/lib/scaffold-manifest.ts
8
+ /**
9
+ * Content hash of one scaffolded file as recorded in the scaffold manifest.
10
+ * Deliberately hashes the raw text (not a parsed structure): the manifest
11
+ * answers "are these still the bytes setup wrote?", nothing more. The sync
12
+ * loop's hashers work on JSON objects and serve a different contract.
13
+ */
14
+ function hashScaffoldFile(contents) {
15
+ return createHash("sha256").update(contents).digest("hex");
16
+ }
17
+ /**
18
+ * Read the scaffold manifest from `.zitadel/state.json`, or `undefined` when
19
+ * the file, the section, its `files` record, or any file entry is missing or
20
+ * malformed (each entry needs a string `hash` and a known `class`).
21
+ * `undefined` sends the doctor managed-files check into its template-derived
22
+ * fallback mode, so a corrupt or future-shaped manifest degrades rather than
23
+ * breaks.
24
+ */
25
+ async function readScaffoldManifest(cwd) {
26
+ try {
27
+ const scaffold = (await readState(cwd)).scaffold;
28
+ if (!isObject(scaffold)) return;
29
+ if (!isObject(scaffold.files)) return;
30
+ for (const entry of Object.values(scaffold.files)) {
31
+ if (!isObject(entry)) return;
32
+ if (typeof entry.hash !== "string") return;
33
+ if (entry.class !== "infrastructure" && entry.class !== "presentation") return;
34
+ }
35
+ if (scaffold.posture !== void 0 && scaffold.posture !== "page" && scaffold.posture !== "widget") return;
36
+ return scaffold;
37
+ } catch {
38
+ return;
39
+ }
40
+ }
41
+ /**
42
+ * Record which managed app files `zitadel setup` actually wrote (or found
43
+ * already matching), keyed by project-root-relative posix path with the
44
+ * content hash and ownership class. Only marked files that the scaffold run
45
+ * touched are recorded — a conditional file whose op never ran (e.g. the
46
+ * framework home page on a pre-existing app) is simply absent, which is what
47
+ * lets `doctor` later distinguish "CLI wrote this and it vanished" from "the
48
+ * CLI never owned this".
49
+ */
50
+ async function writeScaffoldManifest(options) {
51
+ const { cwd, actions, written, scaffoldedFramework, devPort, posture } = options;
52
+ const touched = new Set(written.map((path) => relativePosix(cwd, path)));
53
+ const files = {};
54
+ for (const path of actions.markedFiles) {
55
+ const key = relativePosix(cwd, path);
56
+ if (!touched.has(key)) continue;
57
+ let contents;
58
+ try {
59
+ contents = await readFile(join(cwd, key), "utf8");
60
+ } catch {
61
+ continue;
62
+ }
63
+ files[key] = {
64
+ hash: hashScaffoldFile(contents),
65
+ class: actions.fileClasses?.[path] ?? "presentation"
66
+ };
67
+ }
68
+ await updateScaffold(cwd, {
69
+ files,
70
+ ...scaffoldedFramework ? { scaffolded_framework: true } : {},
71
+ ...typeof devPort === "number" ? { dev_port: devPort } : {},
72
+ ...posture === void 0 ? {} : { posture }
73
+ });
74
+ }
75
+ /** Normalizes an absolute or relative path to a cwd-relative posix key. */
76
+ function relativePosix(cwd, path) {
77
+ return (isAbsolute(path) ? relative(cwd, path) : path).split(sep).join("/");
78
+ }
79
+ //#endregion
80
+ //#region src/lib/package-manager.ts
81
+ async function detectPackageManager(cwd) {
82
+ const declared = await packageManagerFromManifest(cwd);
83
+ if (declared) return declared;
84
+ if (await exists(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
85
+ if (await exists(join(cwd, "yarn.lock"))) return "yarn";
86
+ if (await exists(join(cwd, "bun.lock"))) return "bun";
87
+ if (await exists(join(cwd, "bun.lockb"))) return "bun";
88
+ if (await exists(join(cwd, "package-lock.json"))) return "npm";
89
+ return "npm";
90
+ }
91
+ function installCommandFor(packageManager) {
92
+ return command(packageManager, ["install"]);
93
+ }
94
+ /**
95
+ * Adds (or re-pins) the given `name@version` specs at exactly those versions.
96
+ * Every manager saves a caret range by default, which would silently turn an
97
+ * exact pin into a float — the exact-save flag keeps the written specifier
98
+ * identical to the requested version.
99
+ */
100
+ function addExactCommandFor(packageManager, packages) {
101
+ switch (packageManager) {
102
+ case "npm": return command("npm", [
103
+ "install",
104
+ "--save-exact",
105
+ ...packages
106
+ ]);
107
+ case "pnpm": return command("pnpm", [
108
+ "add",
109
+ "--save-exact",
110
+ ...packages
111
+ ]);
112
+ case "yarn": return command("yarn", [
113
+ "add",
114
+ "--exact",
115
+ ...packages
116
+ ]);
117
+ case "bun": return command("bun", [
118
+ "add",
119
+ "--exact",
120
+ ...packages
121
+ ]);
122
+ }
123
+ }
124
+ function devCommandFor(packageManager) {
125
+ switch (packageManager) {
126
+ case "npm": return command("npm", ["run", "dev"]);
127
+ case "pnpm": return command("pnpm", ["dev"]);
128
+ case "yarn": return command("yarn", ["dev"]);
129
+ case "bun": return command("bun", ["run", "dev"]);
130
+ }
131
+ }
132
+ async function runPackageCommand(packageCommand, options) {
133
+ await new Promise((resolve, reject) => {
134
+ const child = spawn(packageCommand.command, packageCommand.args, {
135
+ cwd: options.cwd,
136
+ env: options.env ?? process.env,
137
+ stdio: options.redirectStdoutToStderr ? [
138
+ "ignore",
139
+ "pipe",
140
+ "pipe"
141
+ ] : "inherit"
142
+ });
143
+ if (options.redirectStdoutToStderr) {
144
+ child.stdout?.on("data", (chunk) => process.stderr.write(chunk));
145
+ child.stderr?.on("data", (chunk) => process.stderr.write(chunk));
146
+ }
147
+ child.on("error", reject);
148
+ child.on("close", (code, signal) => {
149
+ if (code === 0) {
150
+ resolve();
151
+ return;
152
+ }
153
+ const detail = signal ? `signal ${signal}` : `exit ${String(code ?? 1)}`;
154
+ const error = /* @__PURE__ */ new Error(`${packageCommand.display} failed with ${detail}`);
155
+ Object.assign(error, {
156
+ code: code ?? 1,
157
+ signal
158
+ });
159
+ reject(error);
160
+ });
161
+ });
162
+ }
163
+ function command(packageManager, args) {
164
+ return {
165
+ command: packageManager,
166
+ args,
167
+ display: [packageManager, ...args].join(" ")
168
+ };
169
+ }
170
+ async function packageManagerFromManifest(cwd) {
171
+ try {
172
+ const raw = await readFile(join(cwd, "package.json"), "utf8");
173
+ const parsed = JSON.parse(raw);
174
+ return typeof parsed.packageManager === "string" ? packageManagerFromString(parsed.packageManager) : void 0;
175
+ } catch {
176
+ return;
177
+ }
178
+ }
179
+ function packageManagerFromString(value) {
180
+ const name = value.split("@")[0];
181
+ return name === "npm" || name === "pnpm" || name === "yarn" || name === "bun" ? name : void 0;
182
+ }
183
+ async function exists(path) {
184
+ try {
185
+ await stat(path);
186
+ return true;
187
+ } catch {
188
+ return false;
189
+ }
190
+ }
191
+ //#endregion
192
+ export { runPackageCommand as a, writeScaffoldManifest as c, installCommandFor as i, detectPackageManager as n, hashScaffoldFile as o, devCommandFor as r, readScaffoldManifest as s, addExactCommandFor as t };
193
+
194
+ //# sourceMappingURL=package-manager-DFdLcDx1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manager-DFdLcDx1.mjs","names":[],"sources":["../src/lib/scaffold-manifest.ts","../src/lib/package-manager.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { join, isAbsolute, relative, sep } from \"node:path\";\n\nimport { isObject } from \"./json\";\nimport type { EjectActions } from \"./orca/patchers/types\";\nimport { readState, updateScaffold } from \"./sync/state\";\nimport type { ScaffoldManifest, ScaffoldPosture } from \"./sync/types\";\n\n/**\n * Content hash of one scaffolded file as recorded in the scaffold manifest.\n * Deliberately hashes the raw text (not a parsed structure): the manifest\n * answers \"are these still the bytes setup wrote?\", nothing more. The sync\n * loop's hashers work on JSON objects and serve a different contract.\n */\nexport function hashScaffoldFile(contents: string): string {\n return createHash(\"sha256\").update(contents).digest(\"hex\");\n}\n\n/**\n * Read the scaffold manifest from `.zitadel/state.json`, or `undefined` when\n * the file, the section, its `files` record, or any file entry is missing or\n * malformed (each entry needs a string `hash` and a known `class`).\n * `undefined` sends the doctor managed-files check into its template-derived\n * fallback mode, so a corrupt or future-shaped manifest degrades rather than\n * breaks.\n */\nexport async function readScaffoldManifest(cwd: string): Promise<ScaffoldManifest | undefined> {\n try {\n const state = await readState(cwd);\n const scaffold = state.scaffold;\n // isObject rejects arrays too — `typeof [] === \"object\"`, and an array\n // `files` would otherwise enter manifest mode as \"0 tracked\".\n if (!isObject(scaffold)) {\n return undefined;\n }\n if (!isObject(scaffold.files)) {\n return undefined;\n }\n for (const entry of Object.values(scaffold.files)) {\n if (!isObject(entry)) {\n return undefined;\n }\n if (typeof entry.hash !== \"string\") {\n return undefined;\n }\n if (entry.class !== \"infrastructure\" && entry.class !== \"presentation\") {\n return undefined;\n }\n }\n // A posture value this CLI does not know is a future-shaped manifest —\n // degrade like any other malformed section rather than restoring a\n // posture the templates cannot render.\n if (\n scaffold.posture !== undefined &&\n scaffold.posture !== \"page\" &&\n scaffold.posture !== \"widget\"\n ) {\n return undefined;\n }\n return scaffold as unknown as ScaffoldManifest;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Record which managed app files `zitadel setup` actually wrote (or found\n * already matching), keyed by project-root-relative posix path with the\n * content hash and ownership class. Only marked files that the scaffold run\n * touched are recorded — a conditional file whose op never ran (e.g. the\n * framework home page on a pre-existing app) is simply absent, which is what\n * lets `doctor` later distinguish \"CLI wrote this and it vanished\" from \"the\n * CLI never owned this\".\n */\nexport async function writeScaffoldManifest(options: {\n cwd: string;\n actions: EjectActions;\n /** Paths the scaffold reported written or skipped-as-identical. */\n written: ReadonlyArray<string>;\n scaffoldedFramework?: boolean;\n devPort?: number;\n posture?: ScaffoldPosture;\n}): Promise<void> {\n const { cwd, actions, written, scaffoldedFramework, devPort, posture } = options;\n const touched = new Set(written.map((path) => relativePosix(cwd, path)));\n const files: ScaffoldManifest[\"files\"] = {};\n for (const path of actions.markedFiles) {\n const key = relativePosix(cwd, path);\n if (!touched.has(key)) {\n continue;\n }\n let contents: string;\n try {\n contents = await readFile(join(cwd, key), \"utf8\");\n } catch {\n continue;\n }\n files[key] = {\n hash: hashScaffoldFile(contents),\n class: actions.fileClasses?.[path] ?? \"presentation\",\n };\n }\n await updateScaffold(cwd, {\n files,\n ...(scaffoldedFramework ? { scaffolded_framework: true } : {}),\n ...(typeof devPort === \"number\" ? { dev_port: devPort } : {}),\n ...(posture === undefined ? {} : { posture }),\n });\n}\n\n/** Normalizes an absolute or relative path to a cwd-relative posix key. */\nfunction relativePosix(cwd: string, path: string): string {\n const rel = isAbsolute(path) ? relative(cwd, path) : path;\n return rel.split(sep).join(\"/\");\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport type PackageCommand = {\n command: PackageManager;\n args: string[];\n display: string;\n};\n\nexport async function detectPackageManager(cwd: string): Promise<PackageManager> {\n const declared = await packageManagerFromManifest(cwd);\n if (declared) {\n return declared;\n }\n if (await exists(join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (await exists(join(cwd, \"yarn.lock\"))) return \"yarn\";\n if (await exists(join(cwd, \"bun.lock\"))) return \"bun\";\n if (await exists(join(cwd, \"bun.lockb\"))) return \"bun\";\n if (await exists(join(cwd, \"package-lock.json\"))) return \"npm\";\n return \"npm\";\n}\n\nexport function installCommandFor(packageManager: PackageManager): PackageCommand {\n return command(packageManager, [\"install\"]);\n}\n\n/**\n * Adds (or re-pins) the given `name@version` specs at exactly those versions.\n * Every manager saves a caret range by default, which would silently turn an\n * exact pin into a float — the exact-save flag keeps the written specifier\n * identical to the requested version.\n */\nexport function addExactCommandFor(\n packageManager: PackageManager,\n packages: ReadonlyArray<string>,\n): PackageCommand {\n switch (packageManager) {\n case \"npm\":\n return command(\"npm\", [\"install\", \"--save-exact\", ...packages]);\n case \"pnpm\":\n return command(\"pnpm\", [\"add\", \"--save-exact\", ...packages]);\n case \"yarn\":\n return command(\"yarn\", [\"add\", \"--exact\", ...packages]);\n case \"bun\":\n return command(\"bun\", [\"add\", \"--exact\", ...packages]);\n }\n}\n\nexport function devCommandFor(packageManager: PackageManager): PackageCommand {\n switch (packageManager) {\n case \"npm\":\n return command(\"npm\", [\"run\", \"dev\"]);\n case \"pnpm\":\n return command(\"pnpm\", [\"dev\"]);\n case \"yarn\":\n return command(\"yarn\", [\"dev\"]);\n case \"bun\":\n return command(\"bun\", [\"run\", \"dev\"]);\n }\n}\n\nexport async function runPackageCommand(\n packageCommand: PackageCommand,\n options: {\n cwd: string;\n env?: NodeJS.ProcessEnv;\n redirectStdoutToStderr?: boolean;\n },\n): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(packageCommand.command, packageCommand.args, {\n cwd: options.cwd,\n env: options.env ?? process.env,\n stdio: options.redirectStdoutToStderr ? [\"ignore\", \"pipe\", \"pipe\"] : \"inherit\",\n });\n\n if (options.redirectStdoutToStderr) {\n child.stdout?.on(\"data\", (chunk) => process.stderr.write(chunk));\n child.stderr?.on(\"data\", (chunk) => process.stderr.write(chunk));\n }\n\n child.on(\"error\", reject);\n child.on(\"close\", (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n const detail = signal ? `signal ${signal}` : `exit ${String(code ?? 1)}`;\n const error = new Error(`${packageCommand.display} failed with ${detail}`);\n Object.assign(error, { code: code ?? 1, signal });\n reject(error);\n });\n });\n}\n\nfunction command(packageManager: PackageManager, args: string[]): PackageCommand {\n return {\n command: packageManager,\n args,\n display: [packageManager, ...args].join(\" \"),\n };\n}\n\nasync function packageManagerFromManifest(cwd: string): Promise<PackageManager | undefined> {\n try {\n const raw = await readFile(join(cwd, \"package.json\"), \"utf8\");\n const parsed = JSON.parse(raw) as { packageManager?: unknown };\n return typeof parsed.packageManager === \"string\"\n ? packageManagerFromString(parsed.packageManager)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction packageManagerFromString(value: string): PackageManager | undefined {\n const name = value.split(\"@\")[0];\n return name === \"npm\" || name === \"pnpm\" || name === \"yarn\" || name === \"bun\" ? name : undefined;\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ import { j as publicCliCommand } from "./oclif-CanO3zdt.mjs";
2
+ import { execFile } from "node:child_process";
3
+ //#region src/lib/local-server/docker-guidance.ts
4
+ function dockerUnavailableMessage(error) {
5
+ const detail = error instanceof Error ? error.message : String(error);
6
+ return `Docker is not reachable${detail.trim() ? ` (${detail.trim()})` : ""}; managed local runtime commands need Docker, but remote or cloud setup can continue with --server <url>.`;
7
+ }
8
+ function dockerRuntimeGuidance(retryCommand, cliVersion) {
9
+ return {
10
+ hint: "Docker is required only for the managed local runtime (`zitadel start` and `--server local`). Start Docker, then retry; or target a remote server with `--server <url>`.",
11
+ nextActions: [
12
+ "Start Docker Desktop, Docker Engine, or a Docker-compatible runtime such as Colima.",
13
+ `Run \`docker version\`, then rerun \`${publicCliCommand(retryCommand, cliVersion)}\`.`,
14
+ "If you are not using the managed local runtime, run setup with `--server <url>` instead."
15
+ ],
16
+ nextCommands: ["docker version", publicCliCommand(retryCommand, cliVersion)]
17
+ };
18
+ }
19
+ //#endregion
20
+ //#region src/lib/prober/ports.ts
21
+ /**
22
+ * Enumerate TCP LISTEN sockets on loopback/wildcard interfaces (`127.0.0.1`,
23
+ * `::1`, or the wildcard `*`) with enough metadata for CLI diagnostics.
24
+ * Spawns `lsof -iTCP -sTCP:LISTEN -P -n -F pcn` and parses its
25
+ * machine-readable output.
26
+ *
27
+ * Never throws. Returns `[]` whenever lsof is unavailable (e.g. Windows,
28
+ * unusual PATH), the spawn errors, exits non-zero, or the call exceeds
29
+ * `timeoutMs` (default 1000ms). The caller treats an empty list the same as
30
+ * "no visible listeners."
31
+ */
32
+ async function listListeningTcpListeners(opts) {
33
+ const timeoutMs = opts?.timeoutMs ?? 1e3;
34
+ try {
35
+ return parseLsofListeners(await runLsof(timeoutMs));
36
+ } catch {
37
+ return [];
38
+ }
39
+ }
40
+ async function listenersForPort(port, opts) {
41
+ return (await listListeningTcpListeners(opts)).filter((listener) => listener.port === port);
42
+ }
43
+ /**
44
+ * Spawn `lsof` with the canned argv and resolve to its stdout. Hand-rolled
45
+ * rather than `util.promisify(execFile)` because the latter resolves with a
46
+ * `{stdout, stderr}` object via its custom-promisify symbol — a heavier shape
47
+ * to mock and worse to read at the call site, where we only ever want stdout.
48
+ */
49
+ function runLsof(timeoutMs) {
50
+ return new Promise((resolve, reject) => {
51
+ execFile("lsof", [
52
+ "-iTCP",
53
+ "-sTCP:LISTEN",
54
+ "-P",
55
+ "-n",
56
+ "-F",
57
+ "pcn"
58
+ ], {
59
+ timeout: timeoutMs,
60
+ encoding: "utf8"
61
+ }, (err, stdout) => {
62
+ if (err) {
63
+ reject(err);
64
+ return;
65
+ }
66
+ resolve(stdout);
67
+ });
68
+ });
69
+ }
70
+ /**
71
+ * Parse the pid (`p`), command (`c`), and name/address (`n`) records emitted by
72
+ * `lsof -F pcn`. Address records end in `:<port>` (e.g. `n*:8080`,
73
+ * `n127.0.0.1:3000`, `n[::1]:5050`). Only loopback/wildcard hosts are kept;
74
+ * external interface bindings are ignored.
75
+ */
76
+ function parseLsofListeners(stdout) {
77
+ const listeners = [];
78
+ let pid;
79
+ let command;
80
+ for (const line of stdout.split(/\r?\n/)) {
81
+ if (line.startsWith("p")) {
82
+ const parsed = Number.parseInt(line.slice(1), 10);
83
+ pid = Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
84
+ command = void 0;
85
+ continue;
86
+ }
87
+ if (line.startsWith("c")) {
88
+ command = line.slice(1) || void 0;
89
+ continue;
90
+ }
91
+ if (!line.startsWith("n")) continue;
92
+ const address = line.slice(1);
93
+ const colon = address.lastIndexOf(":");
94
+ if (colon < 0) continue;
95
+ const host = address.slice(0, colon);
96
+ const portStr = address.slice(colon + 1);
97
+ if (!isLoopback(host)) continue;
98
+ const port = Number.parseInt(portStr, 10);
99
+ if (Number.isFinite(port) && port > 0 && port < 65536) listeners.push({
100
+ address,
101
+ command,
102
+ host,
103
+ pid,
104
+ port
105
+ });
106
+ }
107
+ return listeners.sort((a, b) => a.port - b.port || (a.pid ?? 0) - (b.pid ?? 0));
108
+ }
109
+ /** Recognised loopback host strings as emitted by `lsof -F n`. */
110
+ function isLoopback(host) {
111
+ return host === "*" || host === "127.0.0.1" || host === "[::1]" || host === "::1";
112
+ }
113
+ //#endregion
114
+ export { dockerRuntimeGuidance as n, dockerUnavailableMessage as r, listenersForPort as t };
115
+
116
+ //# sourceMappingURL=ports-BM20XIZb.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports-BM20XIZb.mjs","names":[],"sources":["../src/lib/local-server/docker-guidance.ts","../src/lib/prober/ports.ts"],"sourcesContent":["import { publicCliCommand } from \"../public-cli\";\n\nexport type DockerRuntimeGuidance = {\n hint: string;\n nextActions: string[];\n nextCommands: string[];\n};\n\nexport function dockerUnavailableMessage(error: unknown): string {\n const detail = error instanceof Error ? error.message : String(error);\n const suffix = detail.trim() ? ` (${detail.trim()})` : \"\";\n return `Docker is not reachable${suffix}; managed local runtime commands need Docker, but remote or cloud setup can continue with --server <url>.`;\n}\n\nexport function dockerRuntimeGuidance(\n retryCommand: \"doctor\" | \"start\",\n cliVersion: string,\n): DockerRuntimeGuidance {\n return {\n hint:\n \"Docker is required only for the managed local runtime (`zitadel start` and `--server local`). Start Docker, then retry; or target a remote server with `--server <url>`.\",\n nextActions: [\n \"Start Docker Desktop, Docker Engine, or a Docker-compatible runtime such as Colima.\",\n `Run \\`docker version\\`, then rerun \\`${publicCliCommand(retryCommand, cliVersion)}\\`.`,\n \"If you are not using the managed local runtime, run setup with `--server <url>` instead.\",\n ],\n nextCommands: [\"docker version\", publicCliCommand(retryCommand, cliVersion)],\n };\n}\n","import { execFile } from \"node:child_process\";\n\nexport type TcpListener = Readonly<{\n address: string;\n command?: string;\n host: string;\n pid?: number;\n port: number;\n}>;\n\n/**\n * Enumerate TCP LISTEN sockets on loopback/wildcard interfaces (`127.0.0.1`,\n * `::1`, or the wildcard `*`) with enough metadata for CLI diagnostics.\n * Spawns `lsof -iTCP -sTCP:LISTEN -P -n -F pcn` and parses its\n * machine-readable output.\n *\n * Never throws. Returns `[]` whenever lsof is unavailable (e.g. Windows,\n * unusual PATH), the spawn errors, exits non-zero, or the call exceeds\n * `timeoutMs` (default 1000ms). The caller treats an empty list the same as\n * \"no visible listeners.\"\n */\nexport async function listListeningTcpListeners(opts?: {\n readonly timeoutMs?: number;\n}): Promise<ReadonlyArray<TcpListener>> {\n const timeoutMs = opts?.timeoutMs ?? 1000;\n try {\n const stdout = await runLsof(timeoutMs);\n return parseLsofListeners(stdout);\n } catch {\n return [];\n }\n}\n\nexport async function listenersForPort(\n port: number,\n opts?: { readonly timeoutMs?: number },\n): Promise<ReadonlyArray<TcpListener>> {\n return (await listListeningTcpListeners(opts)).filter((listener) => listener.port === port);\n}\n\n/**\n * Spawn `lsof` with the canned argv and resolve to its stdout. Hand-rolled\n * rather than `util.promisify(execFile)` because the latter resolves with a\n * `{stdout, stderr}` object via its custom-promisify symbol — a heavier shape\n * to mock and worse to read at the call site, where we only ever want stdout.\n */\nfunction runLsof(timeoutMs: number): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n execFile(\n \"lsof\",\n [\"-iTCP\", \"-sTCP:LISTEN\", \"-P\", \"-n\", \"-F\", \"pcn\"],\n { timeout: timeoutMs, encoding: \"utf8\" },\n (err, stdout) => {\n if (err) {\n reject(err);\n return;\n }\n resolve(stdout);\n },\n );\n });\n}\n\n/**\n * Parse the pid (`p`), command (`c`), and name/address (`n`) records emitted by\n * `lsof -F pcn`. Address records end in `:<port>` (e.g. `n*:8080`,\n * `n127.0.0.1:3000`, `n[::1]:5050`). Only loopback/wildcard hosts are kept;\n * external interface bindings are ignored.\n */\nfunction parseLsofListeners(stdout: string): ReadonlyArray<TcpListener> {\n const listeners: TcpListener[] = [];\n let pid: number | undefined;\n let command: string | undefined;\n for (const line of stdout.split(/\\r?\\n/)) {\n if (line.startsWith(\"p\")) {\n const parsed = Number.parseInt(line.slice(1), 10);\n pid = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n command = undefined;\n continue;\n }\n if (line.startsWith(\"c\")) {\n command = line.slice(1) || undefined;\n continue;\n }\n if (!line.startsWith(\"n\")) {\n continue;\n }\n const address = line.slice(1);\n const colon = address.lastIndexOf(\":\");\n if (colon < 0) {\n continue;\n }\n const host = address.slice(0, colon);\n const portStr = address.slice(colon + 1);\n if (!isLoopback(host)) {\n continue;\n }\n const port = Number.parseInt(portStr, 10);\n if (Number.isFinite(port) && port > 0 && port < 65536) {\n listeners.push({ address, command, host, pid, port });\n }\n }\n return listeners.sort((a, b) => a.port - b.port || (a.pid ?? 0) - (b.pid ?? 0));\n}\n\n/** Recognised loopback host strings as emitted by `lsof -F n`. */\nfunction isLoopback(host: string): boolean {\n return host === \"*\" || host === \"127.0.0.1\" || host === \"[::1]\" || host === \"::1\";\n}\n"],"mappings":";;;AAQA,SAAgB,yBAAyB,OAAwB;CAC/D,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAErE,QAAO,0BADQ,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,CAAC,KAAK,GACf;;AAG1C,SAAgB,sBACd,cACA,YACuB;AACvB,QAAO;EACL,MACE;EACF,aAAa;GACX;GACA,wCAAwC,iBAAiB,cAAc,WAAW,CAAC;GACnF;GACD;EACD,cAAc,CAAC,kBAAkB,iBAAiB,cAAc,WAAW,CAAC;EAC7E;;;;;;;;;;;;;;;ACNH,eAAsB,0BAA0B,MAER;CACtC,MAAM,YAAY,MAAM,aAAa;AACrC,KAAI;AAEF,SAAO,mBAAmB,MADL,QAAQ,UAAU,CACN;SAC3B;AACN,SAAO,EAAE;;;AAIb,eAAsB,iBACpB,MACA,MACqC;AACrC,SAAQ,MAAM,0BAA0B,KAAK,EAAE,QAAQ,aAAa,SAAS,SAAS,KAAK;;;;;;;;AAS7F,SAAS,QAAQ,WAAoC;AACnD,QAAO,IAAI,SAAiB,SAAS,WAAW;AAC9C,WACE,QACA;GAAC;GAAS;GAAgB;GAAM;GAAM;GAAM;GAAM,EAClD;GAAE,SAAS;GAAW,UAAU;GAAQ,GACvC,KAAK,WAAW;AACf,OAAI,KAAK;AACP,WAAO,IAAI;AACX;;AAEF,WAAQ,OAAO;IAElB;GACD;;;;;;;;AASJ,SAAS,mBAAmB,QAA4C;CACtE,MAAM,YAA2B,EAAE;CACnC,IAAI;CACJ,IAAI;AACJ,MAAK,MAAM,QAAQ,OAAO,MAAM,QAAQ,EAAE;AACxC,MAAI,KAAK,WAAW,IAAI,EAAE;GACxB,MAAM,SAAS,OAAO,SAAS,KAAK,MAAM,EAAE,EAAE,GAAG;AACjD,SAAM,OAAO,SAAS,OAAO,IAAI,SAAS,IAAI,SAAS,KAAA;AACvD,aAAU,KAAA;AACV;;AAEF,MAAI,KAAK,WAAW,IAAI,EAAE;AACxB,aAAU,KAAK,MAAM,EAAE,IAAI,KAAA;AAC3B;;AAEF,MAAI,CAAC,KAAK,WAAW,IAAI,CACvB;EAEF,MAAM,UAAU,KAAK,MAAM,EAAE;EAC7B,MAAM,QAAQ,QAAQ,YAAY,IAAI;AACtC,MAAI,QAAQ,EACV;EAEF,MAAM,OAAO,QAAQ,MAAM,GAAG,MAAM;EACpC,MAAM,UAAU,QAAQ,MAAM,QAAQ,EAAE;AACxC,MAAI,CAAC,WAAW,KAAK,CACnB;EAEF,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AACzC,MAAI,OAAO,SAAS,KAAK,IAAI,OAAO,KAAK,OAAO,MAC9C,WAAU,KAAK;GAAE;GAAS;GAAS;GAAM;GAAK;GAAM,CAAC;;AAGzD,QAAO,UAAU,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,MAAM,EAAE,OAAO,GAAG;;;AAIjF,SAAS,WAAW,MAAuB;AACzC,QAAO,SAAS,OAAO,SAAS,eAAe,SAAS,WAAW,SAAS"}
@@ -0,0 +1,120 @@
1
+ import { basename } from "node:path";
2
+ import { execFile } from "node:child_process";
3
+ //#region src/lib/local-server/processes.ts
4
+ async function discoverManagedRuntimeProcesses(opts) {
5
+ if (process.platform === "win32") return {
6
+ supported: false,
7
+ processes: [],
8
+ error: "process sweep is not available on Windows"
9
+ };
10
+ let rows;
11
+ try {
12
+ rows = parsePsRows(await runPs(["axo", "pid=,ppid=,command="], opts?.timeoutMs ?? 1e3));
13
+ } catch (error) {
14
+ return {
15
+ supported: false,
16
+ processes: [],
17
+ error: errorMessage(error)
18
+ };
19
+ }
20
+ const candidates = rows.filter((row) => isRuntimeCandidate(row.command));
21
+ return {
22
+ supported: true,
23
+ processes: uniqueByPid((await Promise.all(candidates.map(async (row) => ({
24
+ ...row,
25
+ command: await hydrateCommand(row.pid, row.command, opts?.timeoutMs ?? 1e3)
26
+ })))).map(toManagedRuntimeProcess).filter((candidate) => candidate !== void 0))
27
+ };
28
+ }
29
+ function runPs(args, timeoutMs) {
30
+ return new Promise((resolve, reject) => {
31
+ execFile("ps", args, {
32
+ timeout: timeoutMs,
33
+ encoding: "utf8"
34
+ }, (err, stdout) => {
35
+ if (err) {
36
+ reject(err);
37
+ return;
38
+ }
39
+ resolve(stdout);
40
+ });
41
+ });
42
+ }
43
+ async function hydrateCommand(pid, fallback, timeoutMs) {
44
+ try {
45
+ return (await runPs([
46
+ "eww",
47
+ "-p",
48
+ String(pid),
49
+ "-o",
50
+ "command="
51
+ ], timeoutMs)).trim() || fallback;
52
+ } catch {
53
+ return fallback;
54
+ }
55
+ }
56
+ function parsePsRows(stdout) {
57
+ const rows = [];
58
+ for (const line of stdout.split(/\r?\n/)) {
59
+ const trimmed = line.trim();
60
+ if (!trimmed) continue;
61
+ const match = trimmed.match(/^(\d+)\s+(\d+)\s+(.+)$/);
62
+ if (!match) continue;
63
+ rows.push({
64
+ pid: Number(match[1]),
65
+ ppid: Number(match[2]),
66
+ command: match[3] ?? ""
67
+ });
68
+ }
69
+ return rows;
70
+ }
71
+ function toManagedRuntimeProcess(row) {
72
+ const dataDir = extractDataDir(row.command);
73
+ const wrapper = isServerWrapper(row.command);
74
+ const binary = isServerBinary(row.command);
75
+ if (!wrapper && !binary) return;
76
+ if (!wrapper && !isCliLocalDataDir(dataDir)) return;
77
+ return {
78
+ pid: row.pid,
79
+ ppid: row.ppid,
80
+ command: stripEnvironmentNoise(row.command),
81
+ kind: wrapper ? "server-wrapper" : "server-binary",
82
+ ...dataDir ? { data_dir: dataDir } : {}
83
+ };
84
+ }
85
+ function isRuntimeCandidate(command) {
86
+ return isServerWrapper(command) || isServerBinary(command) || command.includes("NEXTGEN_SERVER_DATA_DIR=") || basename(command.split(/\s+/)[0] ?? "") === "nextgen";
87
+ }
88
+ function isServerWrapper(command) {
89
+ return command.includes("zitadel-server.js");
90
+ }
91
+ function isServerBinary(command) {
92
+ if (/@zitadel\/server-[^/\s]+\/bin\/nextgen(?:\.exe)?(?:\s|$)/.test(command)) return true;
93
+ return isCliLocalDataDir(extractDataDir(command)) && commandTokens(command).some((token) => basename(token) === "nextgen");
94
+ }
95
+ function extractDataDir(command) {
96
+ const value = command.match(/NEXTGEN_SERVER_DATA_DIR=("[^"]+"|'[^']+'|[^\s]+)/)?.[1];
97
+ if (!value) return;
98
+ return value.replace(/^["']|["']$/g, "");
99
+ }
100
+ function isCliLocalDataDir(path) {
101
+ return Boolean(path && /(?:^|\/)\.zitadel\/local\/nextgen-data\/?$/.test(path));
102
+ }
103
+ function stripEnvironmentNoise(command) {
104
+ return command.replace(/(^|\s)[A-Z_][A-Z0-9_]*=(?:"[^"]+"|'[^']+'|[^\s]+)/g, " ").replace(/\s{2,}/g, " ").trim();
105
+ }
106
+ function commandTokens(command) {
107
+ return command.split(/\s+/).filter((token) => !/^[A-Z_][A-Z0-9_]*=/.test(token));
108
+ }
109
+ function uniqueByPid(processes) {
110
+ const byPid = /* @__PURE__ */ new Map();
111
+ for (const processInfo of processes) byPid.set(processInfo.pid, processInfo);
112
+ return [...byPid.values()].sort((a, b) => a.pid - b.pid);
113
+ }
114
+ function errorMessage(error) {
115
+ return error instanceof Error ? error.message : String(error);
116
+ }
117
+ //#endregion
118
+ export { discoverManagedRuntimeProcesses as t };
119
+
120
+ //# sourceMappingURL=processes-DKHPkU8O.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processes-DKHPkU8O.mjs","names":[],"sources":["../src/lib/local-server/processes.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { basename } from \"node:path\";\n\nexport type ManagedRuntimeProcess = Readonly<{\n command: string;\n data_dir?: string;\n kind: \"server-binary\" | \"server-wrapper\";\n pid: number;\n ppid?: number;\n}>;\n\nexport type ManagedRuntimeDiscovery = Readonly<{\n error?: string;\n processes: ReadonlyArray<ManagedRuntimeProcess>;\n supported: boolean;\n}>;\n\ntype ProcessRow = Readonly<{\n command: string;\n pid: number;\n ppid?: number;\n}>;\n\nexport async function discoverManagedRuntimeProcesses(opts?: {\n readonly timeoutMs?: number;\n}): Promise<ManagedRuntimeDiscovery> {\n if (process.platform === \"win32\") {\n return { supported: false, processes: [], error: \"process sweep is not available on Windows\" };\n }\n\n let rows: ReadonlyArray<ProcessRow>;\n try {\n rows = parsePsRows(await runPs([\"axo\", \"pid=,ppid=,command=\"], opts?.timeoutMs ?? 1000));\n } catch (error) {\n return { supported: false, processes: [], error: errorMessage(error) };\n }\n\n const candidates = rows.filter((row) => isRuntimeCandidate(row.command));\n const hydrated = await Promise.all(\n candidates.map(async (row) => ({\n ...row,\n command: await hydrateCommand(row.pid, row.command, opts?.timeoutMs ?? 1000),\n })),\n );\n const processes = hydrated\n .map(toManagedRuntimeProcess)\n .filter((candidate): candidate is ManagedRuntimeProcess => candidate !== undefined);\n return { supported: true, processes: uniqueByPid(processes) };\n}\n\nfunction runPs(args: string[], timeoutMs: number): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n execFile(\"ps\", args, { timeout: timeoutMs, encoding: \"utf8\" }, (err, stdout) => {\n if (err) {\n reject(err);\n return;\n }\n resolve(stdout);\n });\n });\n}\n\nasync function hydrateCommand(pid: number, fallback: string, timeoutMs: number): Promise<string> {\n try {\n const hydrated = await runPs([\"eww\", \"-p\", String(pid), \"-o\", \"command=\"], timeoutMs);\n return hydrated.trim() || fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction parsePsRows(stdout: string): ReadonlyArray<ProcessRow> {\n const rows: ProcessRow[] = [];\n for (const line of stdout.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) {\n continue;\n }\n const match = trimmed.match(/^(\\d+)\\s+(\\d+)\\s+(.+)$/);\n if (!match) {\n continue;\n }\n rows.push({\n pid: Number(match[1]),\n ppid: Number(match[2]),\n command: match[3] ?? \"\",\n });\n }\n return rows;\n}\n\nfunction toManagedRuntimeProcess(row: ProcessRow): ManagedRuntimeProcess | undefined {\n const dataDir = extractDataDir(row.command);\n const wrapper = isServerWrapper(row.command);\n const binary = isServerBinary(row.command);\n if (!wrapper && !binary) {\n return undefined;\n }\n if (!wrapper && !isCliLocalDataDir(dataDir)) {\n return undefined;\n }\n return {\n pid: row.pid,\n ppid: row.ppid,\n command: stripEnvironmentNoise(row.command),\n kind: wrapper ? \"server-wrapper\" : \"server-binary\",\n ...(dataDir ? { data_dir: dataDir } : {}),\n };\n}\n\nfunction isRuntimeCandidate(command: string): boolean {\n return (\n isServerWrapper(command) ||\n isServerBinary(command) ||\n command.includes(\"NEXTGEN_SERVER_DATA_DIR=\") ||\n basename(command.split(/\\s+/)[0] ?? \"\") === \"nextgen\"\n );\n}\n\nfunction isServerWrapper(command: string): boolean {\n return command.includes(\"zitadel-server.js\");\n}\n\nfunction isServerBinary(command: string): boolean {\n if (/@zitadel\\/server-[^/\\s]+\\/bin\\/nextgen(?:\\.exe)?(?:\\s|$)/.test(command)) {\n return true;\n }\n return (\n isCliLocalDataDir(extractDataDir(command)) &&\n commandTokens(command).some((token) => basename(token) === \"nextgen\")\n );\n}\n\nfunction extractDataDir(command: string): string | undefined {\n const match = command.match(/NEXTGEN_SERVER_DATA_DIR=(\"[^\"]+\"|'[^']+'|[^\\s]+)/);\n const value = match?.[1];\n if (!value) {\n return undefined;\n }\n return value.replace(/^[\"']|[\"']$/g, \"\");\n}\n\nfunction isCliLocalDataDir(path: string | undefined): boolean {\n return Boolean(path && /(?:^|\\/)\\.zitadel\\/local\\/nextgen-data\\/?$/.test(path));\n}\n\nfunction stripEnvironmentNoise(command: string): string {\n return command\n .replace(/(^|\\s)[A-Z_][A-Z0-9_]*=(?:\"[^\"]+\"|'[^']+'|[^\\s]+)/g, \" \")\n .replace(/\\s{2,}/g, \" \")\n .trim();\n}\n\nfunction commandTokens(command: string): string[] {\n return command.split(/\\s+/).filter((token) => !/^[A-Z_][A-Z0-9_]*=/.test(token));\n}\n\nfunction uniqueByPid(\n processes: ReadonlyArray<ManagedRuntimeProcess>,\n): ReadonlyArray<ManagedRuntimeProcess> {\n const byPid = new Map<number, ManagedRuntimeProcess>();\n for (const processInfo of processes) {\n byPid.set(processInfo.pid, processInfo);\n }\n return [...byPid.values()].sort((a, b) => a.pid - b.pid);\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { D as ZitadelError, T as parseJsonObject, w as isObject } from "./oclif-VkCTGIEk.mjs";
1
+ import { C as parseJsonObject, E as ZitadelError, S as isObject, T as stableStringify, n as DEFAULT_SERVER } from "./oclif-CanO3zdt.mjs";
2
+ import { chmod, readFile, rename, stat, writeFile } from "node:fs/promises";
2
3
  import { join } from "node:path";
3
- import { readFile, stat } from "node:fs/promises";
4
4
  //#region src/lib/project.ts
5
5
  /**
6
6
  * Reports whether `cwd` has already been initialized, i.e. a committed
@@ -62,6 +62,25 @@ async function readZitadelSecret(cwd) {
62
62
  }
63
63
  }
64
64
  /**
65
+ * Writes `.zitadel/secret` back after a command mutated it (today only
66
+ * `zitadel claim`, which records `claimed_at` and `team_id`).
67
+ *
68
+ * Atomic by construction: the bytes land in a sibling temp file that is
69
+ * `chmod`ed and then `rename`d over the target, so a crash mid-write can never
70
+ * leave a truncated or world-readable credentials file — the same
71
+ * temp-then-rename the file-writer uses for managed files. Serialised with
72
+ * {@link stableStringify} at mode `0600` to match exactly how setup's patcher
73
+ * first wrote it, so a claim does not churn the file's formatting or loosen
74
+ * the permissions `doctor` asserts.
75
+ */
76
+ async function writeZitadelSecret(cwd, secret) {
77
+ const path = join(cwd, ".zitadel/secret");
78
+ const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
79
+ await writeFile(tmp, `${stableStringify(secret)}\n`, { mode: 384 });
80
+ await chmod(tmp, 384).catch(() => void 0);
81
+ await rename(tmp, path);
82
+ }
83
+ /**
65
84
  * Reads the configured renderer id from a parsed `zitadel.json`, normalising the
66
85
  * legacy `default` alias to `react` and falling back to `react` when unset. The
67
86
  * value is validated downstream by `getRenderer`, so callers need not re-check.
@@ -71,6 +90,40 @@ function readRendererId(config) {
71
90
  const value = branding && typeof branding.renderer === "string" ? branding.renderer : "react";
72
91
  return value === "default" ? "react" : value;
73
92
  }
93
+ /**
94
+ * Reads the recorded sign-in preset from a parsed `zitadel.json`, if present.
95
+ * Setup persists it (see the patcher's `projectConfig`); absent means
96
+ * password-first per the setup default.
97
+ */
98
+ function readPreset(config) {
99
+ return typeof config.preset === "string" ? config.preset : void 0;
100
+ }
101
+ /**
102
+ * Reads the recorded use case from a parsed `zitadel.json`, if present.
103
+ * Guidance-only, like the field itself — behavior lives in the generated
104
+ * schema/flow files.
105
+ */
106
+ function readUseCase(config) {
107
+ return typeof config.useCase === "string" ? config.useCase : void 0;
108
+ }
109
+ /**
110
+ * Reads the top-level `server` origin from a parsed `zitadel.json`, falling
111
+ * back to {@link DEFAULT_SERVER} when the key is absent.
112
+ *
113
+ * Top-level only, unlike `resolveServer`, which prefers the selected
114
+ * environment's `server` before falling back here. That is the point: an
115
+ * environment override says where one invocation should talk, not where the
116
+ * project lives. No practical difference today, since setup always writes a
117
+ * concrete top-level `server`.
118
+ *
119
+ * This is the server the project actually lives on, which is not always the one
120
+ * a command is talking to: `doctor` pins its own source to the local runtime URL
121
+ * and `status --server local` overrides it. Anything reasoning about the
122
+ * project itself (rather than about this invocation) has to read it from here.
123
+ */
124
+ function readProjectServer(config) {
125
+ return typeof config.server === "string" ? config.server : DEFAULT_SERVER;
126
+ }
74
127
  /** Reads `environments.development.issuer` from a parsed `zitadel.json`, if present. */
75
128
  function readDevelopmentIssuer(config) {
76
129
  if (isObject(config.environments) && isObject(config.environments.development)) {
@@ -82,6 +135,6 @@ function isNotFound(error) {
82
135
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
83
136
  }
84
137
  //#endregion
85
- export { readZitadelConfig as a, readRendererId as i, hasZitadelSecret as n, readZitadelSecret as o, readDevelopmentIssuer as r, hasZitadelConfig as t };
138
+ export { readProjectServer as a, readZitadelConfig as c, readPreset as i, readZitadelSecret as l, hasZitadelSecret as n, readRendererId as o, readDevelopmentIssuer as r, readUseCase as s, hasZitadelConfig as t, writeZitadelSecret as u };
86
139
 
87
- //# sourceMappingURL=project-CKAHtHML.mjs.map
140
+ //# sourceMappingURL=project-CHhot85s.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-CHhot85s.mjs","names":[],"sources":["../src/lib/project.ts"],"sourcesContent":["import { chmod, readFile, rename, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ZitadelError } from \"./errors\";\nimport { isObject, parseJsonObject, stableStringify } from \"./json\";\nimport { DEFAULT_SERVER } from \"./server\";\n\n/**\n * Reports whether `cwd` has already been initialized, i.e. a committed\n * `zitadel.json` exists. Used to decide whether setup should run or skip.\n */\nexport async function hasZitadelConfig(cwd: string): Promise<boolean> {\n return exists(join(cwd, \"zitadel.json\"));\n}\n\n/**\n * Reports whether local secret material (`.zitadel/secret`) is present. Gates\n * commands that need credentials, and signals that secrets were already pulled.\n */\nexport async function hasZitadelSecret(cwd: string): Promise<boolean> {\n return exists(join(cwd, \".zitadel/secret\"));\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch (error) {\n if (isNotFound(error)) {\n return false;\n }\n throw error;\n }\n}\n\n/**\n * Shape of the project secret persisted at `.zitadel/secret`. Holds the\n * project identity plus the credentials used to talk to the platform in\n * preview and production. Validated structurally by {@link readZitadelSecret}.\n */\nexport type ZitadelSecret = {\n project_id: string;\n project_secret: string;\n preview_secret: string;\n preview_origins: string[];\n created_at: string;\n /**\n * When the project was attached to an owning team, recorded by\n * `zitadel claim`. Absent until then. The durable record lives on the\n * platform (the team's project grant); this is a local cache so commands can\n * answer \"is this already attached?\" without a round trip.\n */\n claimed_at?: string;\n /** The team that owns the project, recorded alongside {@link claimed_at}. */\n team_id?: string;\n};\n\n/**\n * Reads and parses `zitadel.json` into a plain object. Translates a missing\n * file into an actionable `E_VALIDATION` error pointing at `zitadel setup`;\n * other errors (e.g. malformed JSON) propagate unchanged.\n */\nexport async function readZitadelConfig(cwd: string): Promise<Record<string, unknown>> {\n try {\n return parseJsonObject(await readFile(join(cwd, \"zitadel.json\"), \"utf8\"), \"zitadel.json\");\n } catch (error) {\n if (isNotFound(error)) {\n throw new ZitadelError(\"E_VALIDATION\", \"zitadel.json was not found\", {\n hint: \"Run `zitadel setup` first.\",\n nextCommands: [\"zitadel setup\"],\n });\n }\n throw error;\n }\n}\n\n/**\n * Reads, parses, and structurally validates `.zitadel/secret`, returning it\n * as a {@link ZitadelSecret}. A missing file becomes an actionable\n * `E_VALIDATION` error pointing at `zitadel setup` / `zitadel doctor --fix`;\n * a present-but-incomplete file throws so callers never proceed with partial\n * credentials.\n */\nexport async function readZitadelSecret(cwd: string): Promise<ZitadelSecret> {\n try {\n const secret = parseJsonObject(\n await readFile(join(cwd, \".zitadel/secret\"), \"utf8\"),\n \".zitadel/secret\",\n );\n if (\n typeof secret.project_id !== \"string\" ||\n typeof secret.project_secret !== \"string\" ||\n typeof secret.preview_secret !== \"string\" ||\n !Array.isArray(secret.preview_origins)\n ) {\n throw new Error(\".zitadel/secret is missing required fields\");\n }\n return secret as ZitadelSecret;\n } catch (error) {\n if (isNotFound(error)) {\n throw new ZitadelError(\"E_VALIDATION\", \".zitadel/secret was not found\", {\n hint: \"Run `zitadel setup` first, or restore the project secret with `zitadel doctor --fix`.\",\n nextCommands: [\"zitadel setup\", \"zitadel doctor --fix\"],\n });\n }\n throw error;\n }\n}\n\n/**\n * Writes `.zitadel/secret` back after a command mutated it (today only\n * `zitadel claim`, which records `claimed_at` and `team_id`).\n *\n * Atomic by construction: the bytes land in a sibling temp file that is\n * `chmod`ed and then `rename`d over the target, so a crash mid-write can never\n * leave a truncated or world-readable credentials file — the same\n * temp-then-rename the file-writer uses for managed files. Serialised with\n * {@link stableStringify} at mode `0600` to match exactly how setup's patcher\n * first wrote it, so a claim does not churn the file's formatting or loosen\n * the permissions `doctor` asserts.\n */\nexport async function writeZitadelSecret(cwd: string, secret: ZitadelSecret): Promise<void> {\n const path = join(cwd, \".zitadel/secret\");\n const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;\n await writeFile(tmp, `${stableStringify(secret)}\\n`, { mode: 0o600 });\n // `writeFile`'s mode is masked by the process umask, so re-assert it.\n await chmod(tmp, 0o600).catch(() => undefined);\n await rename(tmp, path);\n}\n\n/**\n * Reads the configured renderer id from a parsed `zitadel.json`, normalising the\n * legacy `default` alias to `react` and falling back to `react` when unset. The\n * value is validated downstream by `getRenderer`, so callers need not re-check.\n */\nexport function readRendererId(config: Record<string, unknown>): string {\n const branding = isObject(config.branding) ? config.branding : undefined;\n const value = branding && typeof branding.renderer === \"string\" ? branding.renderer : \"react\";\n return value === \"default\" ? \"react\" : value;\n}\n\n/**\n * Reads the recorded sign-in preset from a parsed `zitadel.json`, if present.\n * Setup persists it (see the patcher's `projectConfig`); absent means\n * password-first per the setup default.\n */\nexport function readPreset(config: Record<string, unknown>): string | undefined {\n return typeof config.preset === \"string\" ? config.preset : undefined;\n}\n\n/**\n * Reads the recorded use case from a parsed `zitadel.json`, if present.\n * Guidance-only, like the field itself — behavior lives in the generated\n * schema/flow files.\n */\nexport function readUseCase(config: Record<string, unknown>): string | undefined {\n return typeof config.useCase === \"string\" ? config.useCase : undefined;\n}\n\n/**\n * Reads the top-level `server` origin from a parsed `zitadel.json`, falling\n * back to {@link DEFAULT_SERVER} when the key is absent.\n *\n * Top-level only, unlike `resolveServer`, which prefers the selected\n * environment's `server` before falling back here. That is the point: an\n * environment override says where one invocation should talk, not where the\n * project lives. No practical difference today, since setup always writes a\n * concrete top-level `server`.\n *\n * This is the server the project actually lives on, which is not always the one\n * a command is talking to: `doctor` pins its own source to the local runtime URL\n * and `status --server local` overrides it. Anything reasoning about the\n * project itself (rather than about this invocation) has to read it from here.\n */\nexport function readProjectServer(config: Record<string, unknown>): string {\n return typeof config.server === \"string\" ? config.server : DEFAULT_SERVER;\n}\n\n/** Reads `environments.development.issuer` from a parsed `zitadel.json`, if present. */\nexport function readDevelopmentIssuer(config: Record<string, unknown>): string | undefined {\n if (isObject(config.environments) && isObject(config.environments.development)) {\n const issuer = config.environments.development.issuer;\n return typeof issuer === \"string\" ? issuer : undefined;\n }\n return undefined;\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: string }).code === \"ENOENT\"\n );\n}\n"],"mappings":";;;;;;;;AAWA,eAAsB,iBAAiB,KAA+B;AACpE,QAAO,OAAO,KAAK,KAAK,eAAe,CAAC;;;;;;AAO1C,eAAsB,iBAAiB,KAA+B;AACpE,QAAO,OAAO,KAAK,KAAK,kBAAkB,CAAC;;AAG7C,eAAe,OAAO,MAAgC;AACpD,KAAI;AACF,QAAM,KAAK,KAAK;AAChB,SAAO;UACA,OAAO;AACd,MAAI,WAAW,MAAM,CACnB,QAAO;AAET,QAAM;;;;;;;;AA+BV,eAAsB,kBAAkB,KAA+C;AACrF,KAAI;AACF,SAAO,gBAAgB,MAAM,SAAS,KAAK,KAAK,eAAe,EAAE,OAAO,EAAE,eAAe;UAClF,OAAO;AACd,MAAI,WAAW,MAAM,CACnB,OAAM,IAAI,aAAa,gBAAgB,8BAA8B;GACnE,MAAM;GACN,cAAc,CAAC,gBAAgB;GAChC,CAAC;AAEJ,QAAM;;;;;;;;;;AAWV,eAAsB,kBAAkB,KAAqC;AAC3E,KAAI;EACF,MAAM,SAAS,gBACb,MAAM,SAAS,KAAK,KAAK,kBAAkB,EAAE,OAAO,EACpD,kBACD;AACD,MACE,OAAO,OAAO,eAAe,YAC7B,OAAO,OAAO,mBAAmB,YACjC,OAAO,OAAO,mBAAmB,YACjC,CAAC,MAAM,QAAQ,OAAO,gBAAgB,CAEtC,OAAM,IAAI,MAAM,6CAA6C;AAE/D,SAAO;UACA,OAAO;AACd,MAAI,WAAW,MAAM,CACnB,OAAM,IAAI,aAAa,gBAAgB,iCAAiC;GACtE,MAAM;GACN,cAAc,CAAC,iBAAiB,uBAAuB;GACxD,CAAC;AAEJ,QAAM;;;;;;;;;;;;;;;AAgBV,eAAsB,mBAAmB,KAAa,QAAsC;CAC1F,MAAM,OAAO,KAAK,KAAK,kBAAkB;CACzC,MAAM,MAAM,GAAG,KAAK,OAAO,QAAQ,IAAI,GAAG,KAAK,KAAK;AACpD,OAAM,UAAU,KAAK,GAAG,gBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,KAAO,CAAC;AAErE,OAAM,MAAM,KAAK,IAAM,CAAC,YAAY,KAAA,EAAU;AAC9C,OAAM,OAAO,KAAK,KAAK;;;;;;;AAQzB,SAAgB,eAAe,QAAyC;CACtE,MAAM,WAAW,SAAS,OAAO,SAAS,GAAG,OAAO,WAAW,KAAA;CAC/D,MAAM,QAAQ,YAAY,OAAO,SAAS,aAAa,WAAW,SAAS,WAAW;AACtF,QAAO,UAAU,YAAY,UAAU;;;;;;;AAQzC,SAAgB,WAAW,QAAqD;AAC9E,QAAO,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS,KAAA;;;;;;;AAQ7D,SAAgB,YAAY,QAAqD;AAC/E,QAAO,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU,KAAA;;;;;;;;;;;;;;;;;AAkB/D,SAAgB,kBAAkB,QAAyC;AACzE,QAAO,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;;;AAI7D,SAAgB,sBAAsB,QAAqD;AACzF,KAAI,SAAS,OAAO,aAAa,IAAI,SAAS,OAAO,aAAa,YAAY,EAAE;EAC9E,MAAM,SAAS,OAAO,aAAa,YAAY;AAC/C,SAAO,OAAO,WAAW,WAAW,SAAS,KAAA;;;AAKjD,SAAS,WAAW,OAAyB;AAC3C,QACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAA4B,SAAS"}