@zitadel/cli 0.1.0-alpha.1 → 0.1.0-alpha.2

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 (33) hide show
  1. package/README.md +44 -29
  2. package/SKILLS.md +30 -13
  3. package/dist/commands/apply.mjs +4 -4
  4. package/dist/commands/doctor.mjs +54 -30
  5. package/dist/commands/doctor.mjs.map +1 -1
  6. package/dist/commands/eject.mjs +4 -4
  7. package/dist/commands/logs.mjs +3 -3
  8. package/dist/commands/logs.mjs.map +1 -1
  9. package/dist/commands/plan.mjs +4 -4
  10. package/dist/commands/reset.mjs +5 -6
  11. package/dist/commands/reset.mjs.map +1 -1
  12. package/dist/commands/setup.mjs +187 -23
  13. package/dist/commands/setup.mjs.map +1 -1
  14. package/dist/commands/start.mjs +13 -17
  15. package/dist/commands/start.mjs.map +1 -1
  16. package/dist/commands/status.mjs +15 -9
  17. package/dist/commands/status.mjs.map +1 -1
  18. package/dist/commands/stop.mjs +4 -5
  19. package/dist/commands/stop.mjs.map +1 -1
  20. package/dist/{docker-C0aVpJqm.mjs → docker-DrOBycgG.mjs} +6 -5
  21. package/dist/docker-DrOBycgG.mjs.map +1 -0
  22. package/dist/{oclif-DSPO9Sck.mjs → oclif-CqkWBQ7i.mjs} +89 -33
  23. package/dist/oclif-CqkWBQ7i.mjs.map +1 -0
  24. package/dist/{orca-DOxshV9n.mjs → orca-S1tVnngd.mjs} +38 -12
  25. package/dist/{orca-DOxshV9n.mjs.map → orca-S1tVnngd.mjs.map} +1 -1
  26. package/dist/{project-Dwb9WVAT.mjs → project-B6YfSaZw.mjs} +3 -3
  27. package/dist/{project-Dwb9WVAT.mjs.map → project-B6YfSaZw.mjs.map} +1 -1
  28. package/dist/{sync-DmtTYNmq.mjs → sync-DN4oNLVH.mjs} +3 -3
  29. package/dist/{sync-DmtTYNmq.mjs.map → sync-DN4oNLVH.mjs.map} +1 -1
  30. package/oclif.manifest.json +7 -1
  31. package/package.json +3 -3
  32. package/dist/docker-C0aVpJqm.mjs.map +0 -1
  33. package/dist/oclif-DSPO9Sck.mjs.map +0 -1
package/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  Scaffolds Zitadel auth (login, register, profile, middleware) into a Next.js app.
4
4
 
5
5
  ```sh
6
- npx @zitadel/cli@latest start
7
- npx @zitadel/cli@latest setup --framework next --server local
6
+ npx @zitadel/cli@alpha start
7
+ npx @zitadel/cli@alpha setup --framework next --server local
8
8
  ```
9
9
 
10
10
  > **Beta.** This is the **next-generation Zitadel**, a ground-up rewrite of the platform. It is distinct from the established Zitadel at [github.com/zitadel/zitadel](https://github.com/zitadel/zitadel). APIs and CLI flags will change.
@@ -20,21 +20,33 @@ npx @zitadel/cli@latest setup --framework next --server local
20
20
  ```sh
21
21
  npx create-next-app@latest my-app
22
22
  cd my-app
23
- npx @zitadel/cli@latest doctor
24
- npx @zitadel/cli@latest start
25
- npx @zitadel/cli@latest setup --framework next --server local
26
- npm install
23
+ npx @zitadel/cli@alpha doctor
24
+ npx @zitadel/cli@alpha start
25
+ npx @zitadel/cli@alpha setup --framework next --server local
27
26
  npm run dev
28
27
  ```
29
28
 
30
29
  `start` runs a Docker-backed local Zitadel server and stores runtime data
31
- under `.zitadel/local/`. It uses `ghcr.io/zitadel/nextgen:latest` unless
32
- overridden with `--image` or `ZITADEL_LOCAL_IMAGE`. `setup --server local`
33
- creates a project on that local server, scaffolds `app/login`, `app/register`, and
34
- `middleware.ts`, and writes `.env.local` and `.zitadel/`. The project's default
35
- user schema and login flow are provisioned server-side at creation time, so the
36
- CLI does not scaffold or upload them. Open `http://localhost:3000/login` to see
37
- the login page.
30
+ under `.zitadel/local/`. Alpha CLI versions use the matching
31
+ `ghcr.io/zitadel/nextgen:<cli-version>` image by default; local/dev builds fall
32
+ back to `ghcr.io/zitadel/nextgen:latest`. Override with `--image` or
33
+ `ZITADEL_LOCAL_IMAGE` for advanced debugging.
34
+ `setup --server local` creates a project on that local server, scaffolds
35
+ `app/login`, `app/register`, and `middleware.ts`, writes `.env.local` and
36
+ `.zitadel/`, and installs dependencies with the detected package manager. Pass
37
+ `--skip-install` to install them yourself. The project's default user schema
38
+ and login flow are provisioned server-side at creation time, so the CLI does
39
+ not scaffold or upload them. Open `http://localhost:3000/login` to see the
40
+ login page.
41
+
42
+ For a reproducible tester report, use the exact alpha train from the GitHub
43
+ Release:
44
+
45
+ ```sh
46
+ npx @zitadel/cli@0.1.0-alpha.N doctor
47
+ npx @zitadel/cli@0.1.0-alpha.N start
48
+ npx @zitadel/cli@0.1.0-alpha.N setup --framework next --server local
49
+ ```
38
50
 
39
51
  The default project flow supports password registration/login, passkey
40
52
  registration/login, and optional passkey setup after password registration.
@@ -54,21 +66,22 @@ passkey can sign in with either credential.
54
66
  <summary>Full command reference</summary>
55
67
 
56
68
  <!-- commands -->
57
- * [`zitadel autocomplete [SHELL]`](#zitadel-autocomplete-shell)
58
- * [`zitadel commands`](#zitadel-commands)
59
- * [`zitadel doctor`](#zitadel-doctor)
60
- * [`zitadel eject`](#zitadel-eject)
61
- * [`zitadel help [COMMAND]`](#zitadel-help-command)
62
- * [`zitadel logs`](#zitadel-logs)
63
- * [`zitadel reset`](#zitadel-reset)
64
- * [`zitadel search`](#zitadel-search)
65
- * [`zitadel setup`](#zitadel-setup)
66
- * [`zitadel start`](#zitadel-start)
67
- * [`zitadel status`](#zitadel-status)
68
- * [`zitadel stop`](#zitadel-stop)
69
- * [`zitadel uninstall`](#zitadel-uninstall)
70
- * [`zitadel version`](#zitadel-version)
71
- * [`zitadel which`](#zitadel-which)
69
+
70
+ - [`zitadel autocomplete [SHELL]`](#zitadel-autocomplete-shell)
71
+ - [`zitadel commands`](#zitadel-commands)
72
+ - [`zitadel doctor`](#zitadel-doctor)
73
+ - [`zitadel eject`](#zitadel-eject)
74
+ - [`zitadel help [COMMAND]`](#zitadel-help-command)
75
+ - [`zitadel logs`](#zitadel-logs)
76
+ - [`zitadel reset`](#zitadel-reset)
77
+ - [`zitadel search`](#zitadel-search)
78
+ - [`zitadel setup`](#zitadel-setup)
79
+ - [`zitadel start`](#zitadel-start)
80
+ - [`zitadel status`](#zitadel-status)
81
+ - [`zitadel stop`](#zitadel-stop)
82
+ - [`zitadel uninstall`](#zitadel-uninstall)
83
+ - [`zitadel version`](#zitadel-version)
84
+ - [`zitadel which`](#zitadel-which)
72
85
 
73
86
  ## `zitadel autocomplete [SHELL]`
74
87
 
@@ -279,7 +292,7 @@ Create a Zitadel project and scaffold local auth.
279
292
  ```
280
293
  USAGE
281
294
  $ zitadel setup [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
282
- [--framework next] [--renderer react|web-component]
295
+ [--framework next] [--renderer react|web-component] [--skip-install]
283
296
 
284
297
  FLAGS
285
298
  -c, --cwd=<value> Project directory to operate on.
@@ -292,6 +305,7 @@ FLAGS
292
305
  <options: next>
293
306
  --renderer=<option> Renderer (default: react).
294
307
  <options: react|web-component>
308
+ --skip-install Do not install dependencies after setup updates package.json.
295
309
  --verbose Verbose logging.
296
310
 
297
311
  GLOBAL FLAGS
@@ -459,6 +473,7 @@ EXAMPLES
459
473
  ```
460
474
 
461
475
  _See code: [@oclif/plugin-which](https://github.com/oclif/plugin-which/blob/3.2.55/src/commands/which.ts)_
476
+
462
477
  <!-- commandsstop -->
463
478
 
464
479
  </details>
package/SKILLS.md CHANGED
@@ -24,7 +24,7 @@ parse the result rather than scraping human output.
24
24
  metadata) or run `zitadel <command> --help` for the full per-command flag list.
25
25
 
26
26
  ```sh
27
- npx @zitadel/cli@latest <command> --non-interactive --json
27
+ npx @zitadel/cli@alpha <command> --non-interactive --json
28
28
  ```
29
29
 
30
30
  ## Reading the envelope
@@ -39,7 +39,7 @@ Each invocation prints one JSON object:
39
39
  `message`.
40
40
  - `next_commands`: the suggested follow-ups. Prefer these over free-text hints.
41
41
  - `E_LOCAL_SERVER_NOT_RUNNING`: start the local Docker runtime with
42
- `zitadel start`, then retry with `--server local`.
42
+ `npx @zitadel/cli@alpha start`, then retry with `--server local`.
43
43
 
44
44
  Exit codes mirror the error class (3 = validation, 4 = network, 5 = conflict,
45
45
  1 = auth, 2 = not-implemented). An unknown command is handled by the CLI's help
@@ -53,9 +53,10 @@ layer, not the envelope.
53
53
  scaffolds nor uploads them. Flags: `--framework`, `--renderer`.
54
54
  - `plan` — validate config and preview the sync diff without mutating anything.
55
55
  - `apply` — validate and upload repo config to the platform.
56
- - `doctor` — verify local Docker runtime prerequisites and, once `zitadel.json`
57
- exists, generated app files and local state; `--fix` re-applies missing
58
- managed files.
56
+ - `doctor` — verify generated app files and local state once `zitadel.json`
57
+ exists. Local Docker runtime prerequisites are advisory warnings unless an
58
+ existing managed runtime is unhealthy; `--fix` re-applies missing managed
59
+ files.
59
60
  - `status` — summarize the local Docker runtime and project state.
60
61
  - `eject` (alias `uninstall`) — remove managed files and local Zitadel state;
61
62
  requires `--force` when non-interactive.
@@ -67,20 +68,36 @@ layer, not the envelope.
67
68
  - `reset` — stop/remove the managed container and delete local runtime data;
68
69
  requires `--force` when non-interactive.
69
70
 
71
+ Alpha releases are lockstep trains. `npx @zitadel/cli@alpha start` runs the
72
+ latest tested alpha server image, and
73
+ `npx @zitadel/cli@0.1.0-alpha.N start` runs
74
+ `ghcr.io/zitadel/nextgen:0.1.0-alpha.N`. `zitadel start --image <ref>` remains
75
+ the explicit image override for debugging.
76
+
70
77
  ## Golden path
71
78
 
72
79
  ```sh
73
- npx @zitadel/cli@latest doctor --non-interactive --json
74
- npx @zitadel/cli@latest start --non-interactive --json
75
- npx @zitadel/cli@latest setup --framework next --server local --non-interactive --json
76
- npx @zitadel/cli@latest doctor --non-interactive --json
77
- npx @zitadel/cli@latest plan --non-interactive --json
78
- npx @zitadel/cli@latest apply --non-interactive --json
80
+ npx @zitadel/cli@alpha doctor --non-interactive --json
81
+ npx @zitadel/cli@alpha start --non-interactive --json
82
+ npx @zitadel/cli@alpha setup --framework next --server local --non-interactive --json
83
+ npx @zitadel/cli@alpha doctor --non-interactive --json
84
+ npx @zitadel/cli@alpha plan --non-interactive --json
85
+ npx @zitadel/cli@alpha apply --non-interactive --json
86
+ ```
87
+
88
+ Exact alpha train invocation:
89
+
90
+ ```sh
91
+ npx @zitadel/cli@0.1.0-alpha.N doctor --non-interactive --json
92
+ npx @zitadel/cli@0.1.0-alpha.N start --non-interactive --json
93
+ npx @zitadel/cli@0.1.0-alpha.N setup --framework next --server local --non-interactive --json
79
94
  ```
80
95
 
81
96
  Repo config is authoritative: edit `zitadel.json` or files under `.zitadel/`,
82
97
  then re-run `plan` and `apply`. Managed files carry a marker comment; `eject`
83
98
  removes only files that still carry it, preserving anything the user replaced.
84
99
  For app-local development, `--server local` resolves through
85
- `.zitadel/local/runtime.json` and requires a healthy `zitadel start`
86
- runtime.
100
+ `.zitadel/local/runtime.json` and requires a healthy `npx @zitadel/cli@alpha start`
101
+ runtime. `setup` installs dependencies with the detected package manager by
102
+ default; pass `--skip-install` when the agent or host workflow will install
103
+ dependencies separately.
@@ -1,9 +1,9 @@
1
- import { t as BaseCommand } from "../oclif-DSPO9Sck.mjs";
2
- import { o as readZitadelSecret } from "../project-Dwb9WVAT.mjs";
3
- import { a as makeSyncers, i as runSyncLoop, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-DmtTYNmq.mjs";
1
+ import { t as BaseCommand } from "../oclif-CqkWBQ7i.mjs";
2
+ import { o as readZitadelSecret } from "../project-B6YfSaZw.mjs";
3
+ import { a as makeSyncers, i as runSyncLoop, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-DN4oNLVH.mjs";
4
4
  import { Flags } from "@oclif/core";
5
- import { consola as consola$1 } from "consola";
6
5
  import { createZitadelClient } from "@zitadel/api/client";
6
+ import { consola as consola$1 } from "consola";
7
7
  //#region src/commands/apply.ts
8
8
  /**
9
9
  * `zitadel apply` — validate and upload repo config to the platform.
@@ -1,11 +1,11 @@
1
- import { S as isObject, T as ZitadelError, _ as readRuntimeMetadata, g as localServerUrl, h as localRuntimePaths, l as assertWritableDirectory, p as isPortAvailable, s as DEFAULT_LOCAL_SERVER_PORT, t as BaseCommand, u as checkLocalServerHealth } from "../oclif-DSPO9Sck.mjs";
2
- import { r as issuerFromPort, t as createOrca } from "../orca-DOxshV9n.mjs";
3
- import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-Dwb9WVAT.mjs";
4
- import { o as imageAvailable, r as dockerAvailable } from "../docker-C0aVpJqm.mjs";
1
+ import { C as isObject, E as ZitadelError, a as DEFAULT_LOCAL_SERVER_PORT, c as checkLocalServerHealth, f as isPortAvailable, g as readRuntimeMetadata, h as localServerUrl, l as defaultLocalServerImageForCliVersion, m as localRuntimePaths, s as assertWritableDirectory, t as BaseCommand, x as publicCliCommand } from "../oclif-CqkWBQ7i.mjs";
2
+ import { r as issuerFromPort, t as createOrca } from "../orca-S1tVnngd.mjs";
3
+ import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-B6YfSaZw.mjs";
4
+ import { o as imageAvailable, r as dockerAvailable } from "../docker-DrOBycgG.mjs";
5
5
  import { Flags } from "@oclif/core";
6
6
  import consola from "consola";
7
- import { chmod, readFile, stat, writeFile } from "node:fs/promises";
8
7
  import { join } from "node:path";
8
+ import { chmod, readFile, stat, writeFile } from "node:fs/promises";
9
9
  import "@zitadel/api/generated/endpoints/zitadelNextGen.zod";
10
10
  //#region src/commands/doctor/checks/types.ts
11
11
  /**
@@ -284,7 +284,7 @@ var Doctor = class Doctor extends BaseCommand {
284
284
  source: localServerUrl(port)
285
285
  });
286
286
  const { cwd, dryRun } = this.meta;
287
- const image = flags.image ?? this.meta.env.ZITADEL_LOCAL_IMAGE ?? "ghcr.io/zitadel/nextgen:latest";
287
+ const image = flags.image ?? this.meta.env.ZITADEL_LOCAL_IMAGE ?? defaultLocalServerImageForCliVersion(this.meta.cliVersion);
288
288
  const runtimeChecks = await runLocalRuntimeChecks(cwd, image, port);
289
289
  const hasConfig = await hasZitadelConfig(cwd);
290
290
  const ctx = {
@@ -307,8 +307,9 @@ var Doctor = class Doctor extends BaseCommand {
307
307
  const projectChecks = hasConfig ? await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx))) : [];
308
308
  const checks = [...runtimeChecks, ...projectChecks];
309
309
  const failed = checks.filter((check) => check.status === "fail");
310
+ const warnings = checks.filter((check) => check.status === "warn");
310
311
  const data = {
311
- title: failed.length === 0 ? "Zitadel doctor passed." : "Zitadel doctor found issues.",
312
+ title: failed.length > 0 ? "Zitadel doctor found issues." : warnings.length > 0 ? "Zitadel doctor passed with warnings." : "Zitadel doctor passed.",
312
313
  ok: failed.length === 0,
313
314
  image,
314
315
  port,
@@ -316,7 +317,7 @@ var Doctor = class Doctor extends BaseCommand {
316
317
  checks
317
318
  };
318
319
  if (failed.length > 0) {
319
- const advice = failureAdvice(failed, image, port);
320
+ const advice = failureAdvice(failed, image, port, this.meta.cliVersion);
320
321
  throw new ZitadelError("E_VALIDATION", "Zitadel doctor found issues", {
321
322
  hint: advice.hint,
322
323
  nextCommands: advice.nextCommands,
@@ -325,65 +326,80 @@ var Doctor = class Doctor extends BaseCommand {
325
326
  }
326
327
  return this.emit({
327
328
  status: "ok",
328
- data
329
+ data,
330
+ warnings: warnings.map((warning) => `${warning.name}: ${warning.message}`)
329
331
  });
330
332
  }
331
333
  };
332
- function failureAdvice(failed, image, port) {
334
+ function failureAdvice(failed, image, port, cliVersion) {
333
335
  const failedNames = new Set(failed.map((check) => check.name));
334
336
  if (failedNames.has("docker-cli")) return {
335
337
  hint: "Docker is required for `zitadel start`, but the Docker daemon is not reachable. Install or start Docker, then rerun `zitadel doctor`.",
336
- nextCommands: ["docker version", "zitadel doctor"]
338
+ nextCommands: ["docker version", publicCliCommand("doctor", cliVersion)]
337
339
  };
338
340
  if (failedNames.has("image")) return {
339
341
  hint: "The local Zitadel image is not available. Check Docker registry access, build it locally, or pass --image / ZITADEL_LOCAL_IMAGE.",
340
- nextCommands: [`docker pull ${image}`, "zitadel doctor"]
342
+ nextCommands: [`docker pull ${image}`, publicCliCommand("doctor", cliVersion)]
341
343
  };
342
344
  if (failedNames.has("state-dir")) return {
343
345
  hint: "The local Zitadel state directory is not writable. Fix directory permissions, then rerun `zitadel doctor`.",
344
- nextCommands: ["zitadel doctor"]
346
+ nextCommands: [publicCliCommand("doctor", cliVersion)]
345
347
  };
346
348
  if (failedNames.has("port")) {
347
349
  const fallbackPort = port === 8080 ? port + 1 : DEFAULT_LOCAL_SERVER_PORT;
348
350
  return {
349
351
  hint: `Port ${String(port)} is already in use. Stop the process using it, or choose another port for local Zitadel.`,
350
- nextCommands: [`zitadel doctor --port ${String(fallbackPort)}`]
352
+ nextCommands: [publicCliCommand(`doctor --port ${String(fallbackPort)}`, cliVersion)]
351
353
  };
352
354
  }
353
355
  if (failedNames.has("runtime")) return {
354
356
  hint: "Existing local runtime metadata was found, but the local Zitadel server is not healthy. Start it again or reset stale local data.",
355
- nextCommands: ["zitadel start", "zitadel reset --force"]
357
+ nextCommands: [publicCliCommand("start", cliVersion), publicCliCommand("reset --force", cliVersion)]
356
358
  };
357
359
  if (failed.some((check) => !LOCAL_RUNTIME_CHECK_NAMES.has(check.name))) return {
358
- hint: "Run `npx @zitadel/cli@alpha doctor --fix` to re-apply missing managed files.",
359
- nextCommands: ["zitadel doctor --fix"]
360
+ hint: `Run \`${publicCliCommand("doctor --fix", cliVersion)}\` to re-apply missing managed files.`,
361
+ nextCommands: [publicCliCommand("doctor --fix", cliVersion)]
360
362
  };
361
363
  return {
362
364
  hint: "Fix the reported checks, then rerun `zitadel doctor`.",
363
- nextCommands: ["zitadel doctor"]
365
+ nextCommands: [publicCliCommand("doctor", cliVersion)]
364
366
  };
365
367
  }
366
368
  async function runLocalRuntimeChecks(cwd, image, port) {
367
369
  const runtime = await readRuntimeMetadata(cwd);
370
+ const docker = await check("docker-cli", "Docker is reachable", async () => {
371
+ let result;
372
+ try {
373
+ result = await dockerAvailable();
374
+ } catch (error) {
375
+ throw new Error(dockerUnavailableMessage(error), { cause: error });
376
+ }
377
+ if (result.status !== 0) throw new Error(dockerUnavailableMessage(result.stderr || "docker version failed"));
378
+ return `Docker engine ${result.stdout.trim() || "available"}`;
379
+ }, "warn");
368
380
  return [
369
- await check("docker-cli", "Docker is reachable", async () => {
370
- const result = await dockerAvailable();
371
- if (result.status !== 0) throw new Error(result.stderr || "docker version failed");
372
- return `Docker engine ${result.stdout.trim() || "available"}`;
373
- }),
374
- await check("image", `Image ${image} is available`, async () => {
375
- return await imageAvailable(image) === "local" ? `Image ${image} is available locally` : `Image ${image} is available from the registry`;
376
- }),
381
+ docker,
382
+ docker.status === "pass" ? await check("image", `Image ${image} is available`, async () => {
383
+ try {
384
+ return await imageAvailable(image) === "local" ? `Image ${image} is available locally` : `Image ${image} is available from the registry`;
385
+ } catch (error) {
386
+ throw new Error(imageUnavailableMessage(image, error), { cause: error });
387
+ }
388
+ }, "warn") : {
389
+ name: "image",
390
+ status: "warn",
391
+ message: "Skipped image check because Docker is not reachable."
392
+ },
377
393
  await check("state-dir", "Local state directory is writable", async () => {
378
394
  const paths = localRuntimePaths(cwd);
379
395
  await assertWritableDirectory(paths.dataDir);
380
396
  return `${paths.dataDir} is writable`;
381
- }),
397
+ }, "warn"),
382
398
  await check("port", `Port ${String(port)} is available`, async () => {
383
399
  if (runtime && await checkLocalServerHealth(runtime.server_url)) return `${runtime.server_url} is already healthy`;
384
400
  if (!await isPortAvailable(port)) throw new Error(`Port ${String(port)} is already in use`);
385
401
  return `Port ${String(port)} is available`;
386
- }),
402
+ }, "warn"),
387
403
  await check("runtime", "Existing local runtime is healthy", async () => {
388
404
  if (!runtime) return "No existing runtime metadata";
389
405
  if (!await checkLocalServerHealth(runtime.server_url)) throw new Error(`${runtime.server_url} did not respond to /healthz`);
@@ -391,7 +407,7 @@ async function runLocalRuntimeChecks(cwd, image, port) {
391
407
  })
392
408
  ];
393
409
  }
394
- async function check(name, fallback, run) {
410
+ async function check(name, fallback, run, failureStatus = "fail") {
395
411
  try {
396
412
  return {
397
413
  name,
@@ -401,11 +417,19 @@ async function check(name, fallback, run) {
401
417
  } catch (error) {
402
418
  return {
403
419
  name,
404
- status: "fail",
420
+ status: failureStatus,
405
421
  message: error instanceof Error ? error.message : fallback
406
422
  };
407
423
  }
408
424
  }
425
+ function dockerUnavailableMessage(error) {
426
+ const detail = error instanceof Error ? error.message : String(error);
427
+ return `Docker is not reachable${detail.trim() ? ` (${detail.trim()})` : ""}; \`zitadel start\` needs Docker, but cloud setup can continue.`;
428
+ }
429
+ function imageUnavailableMessage(image, error) {
430
+ const detail = error instanceof Error ? error.message : String(error);
431
+ return `Image ${image} is not available to Docker${detail.trim() ? ` (${detail.trim()})` : ""}; \`zitadel start\` may need a pull or a different image.`;
432
+ }
409
433
  //#endregion
410
434
  export { Doctor as default };
411
435
 
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.mjs","names":[],"sources":["../../src/commands/doctor/checks/types.ts","../../src/commands/doctor/checks/config.ts","../../src/commands/doctor/checks/secret.ts","../../src/commands/doctor/checks/secret-permissions.ts","../../src/commands/doctor/checks/gitignore.ts","../../src/commands/doctor/checks/env-example.ts","../../src/commands/doctor/checks/framework.ts","../../src/commands/doctor/patch-context.ts","../../src/commands/doctor/checks/dependency.ts","../../src/commands/doctor/checks/project-match.ts","../../src/commands/doctor/checks/index.ts","../../src/commands/doctor/index.ts"],"sourcesContent":["import type { Orca } from \"../../../lib/orca\";\n\n/** Pass/fail outcome of a single {@link SanityCheck}. */\nexport type CheckOutcome = {\n name: string;\n status: \"pass\" | \"fail\";\n message: string;\n path?: string;\n};\n\n/** Everything a check needs to inspect or repair a project. */\nexport type CheckContext = {\n readonly cwd: string;\n readonly orca: Orca;\n readonly cliVersion: string;\n /** When true, {@link SanityCheck.fix} must preview without writing. */\n readonly dryRun: boolean;\n};\n\n/**\n * One diagnostic the `doctor` command runs. Each concrete check is a small\n * standalone class that both verifies its concern ({@link run}) and knows how\n * to repair it ({@link fix}); the command executes every registered check,\n * aggregates the {@link CheckOutcome}s, and (under `--fix`) repairs the ones\n * that failed.\n */\nexport interface SanityCheck {\n /** Stable identifier surfaced in logs and the JSON envelope. */\n readonly name: string;\n run(ctx: CheckContext): Promise<CheckOutcome>;\n /** Repair what this check verifies. A no-op when there is no safe auto-fix. */\n fix(ctx: CheckContext): Promise<void>;\n}\n\n/**\n * Base class for checks: subclasses declare `name`, `path`, and a success\n * `summary`, and implement the single {@link verify} method that throws on\n * failure. {@link run} wraps it so a thrown error becomes a `fail` outcome\n * carrying the error message, and success becomes a `pass` with `summary`.\n *\n * {@link fix} defaults to a no-op: checks whose failure has no safe automatic\n * remedy (a missing secret, an invalid user schema) simply do not override it.\n */\nexport abstract class AbstractSanityCheck implements SanityCheck {\n abstract readonly name: string;\n abstract readonly path: string;\n protected abstract readonly summary: string;\n\n /** Throw to signal failure; the thrown message is surfaced to the user. */\n protected abstract verify(ctx: CheckContext): Promise<void>;\n\n async run(ctx: CheckContext): Promise<CheckOutcome> {\n try {\n await this.verify(ctx);\n return { name: this.name, status: \"pass\", message: this.summary, path: this.path };\n } catch (error) {\n return {\n name: this.name,\n status: \"fail\",\n message: error instanceof Error ? error.message : String(error),\n path: this.path,\n };\n }\n }\n\n async fix(_ctx: CheckContext): Promise<void> {\n return;\n }\n}\n","import { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `zitadel.json` exists and parses. */\nexport class ConfigCheck extends AbstractSanityCheck {\n readonly name = \"config\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"zitadel.json parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelConfig(ctx.cwd);\n }\n}\n","import { readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` exists and parses. */\nexport class SecretCheck extends AbstractSanityCheck {\n readonly name = \"secret\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelSecret(ctx.cwd);\n }\n}\n","import { chmod, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` is locked down to `0600`, and re-locks it on fix. */\nexport class SecretPermissionsCheck extends AbstractSanityCheck {\n readonly name = \"secret-permissions\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret has 0600 permissions\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const mode = (await stat(join(ctx.cwd, \".zitadel/secret\"))).mode & 0o777;\n if (mode !== 0o600) {\n throw new Error(`expected 0600, got ${mode.toString(8)}`);\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n if (ctx.dryRun) {\n return;\n }\n await chmod(join(ctx.cwd, \".zitadel/secret\"), 0o600);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The entries `.gitignore` must carry to keep secrets and env files untracked. */\nconst REQUIRED_ENTRIES = [\".zitadel/secret\", \".env*\", \"!.env.example\"];\n\n/** Verifies `.gitignore` excludes the local secret and env files; appends any missing. */\nexport class GitignoreCheck extends AbstractSanityCheck {\n readonly name = \"gitignore\";\n readonly path = \".gitignore\";\n protected readonly summary = \".gitignore protects local secret/env files\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const lines = (await readFile(join(ctx.cwd, \".gitignore\"), \"utf8\")).split(/\\r?\\n/g);\n for (const entry of REQUIRED_ENTRIES) {\n if (!lines.includes(entry)) {\n throw new Error(`missing ${entry}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".gitignore\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const lines = existing.split(/\\r?\\n/g);\n const missing = REQUIRED_ENTRIES.filter((entry) => !lines.includes(entry));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.join(\"\\n\")}\\n`);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The keys `.env.example` must document for a Zitadel-managed project. */\nconst REQUIRED_KEYS = [\"ZITADEL_PROJECT_ID\", \"ZITADEL_ENVIRONMENT\", \"ZITADEL_ISSUER\"];\n\n/** Verifies `.env.example` documents the required Zitadel keys; appends any missing. */\nexport class EnvExampleCheck extends AbstractSanityCheck {\n readonly name = \"env-example\";\n readonly path = \".env.example\";\n protected readonly summary = \".env.example references required keys\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const contents = await readFile(join(ctx.cwd, \".env.example\"), \"utf8\");\n for (const key of REQUIRED_KEYS) {\n if (!contents.includes(`${key}=`)) {\n throw new Error(`missing ${key}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".env.example\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const missing = REQUIRED_KEYS.filter((key) => !existing.includes(`${key}=`));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.map((key) => `${key}=`).join(\"\\n\")}\\n`);\n }\n}\n","import { isObject } from \"../../../lib/json\";\nimport { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies the framework detected on disk matches the one recorded in config. */\nexport class FrameworkCheck extends AbstractSanityCheck {\n readonly name = \"framework\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"Detected framework matches recorded framework\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const detected = await ctx.orca.detect(ctx.cwd);\n const recorded = isObject(config.framework) ? config.framework.id : undefined;\n if (recorded !== detected.id) {\n throw new Error(`expected ${String(recorded)}, detected ${detected.id}`);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { issuerFromPort, type FrameworkFacts, type Orca } from \"../../lib/orca\";\nimport type { PatchContext } from \"../../lib/orca/patchers/types\";\nimport { readDevelopmentIssuer, readRendererId, readZitadelConfig, readZitadelSecret } from \"../../lib/project\";\n\n/**\n * Reconstructs a {@link PatchContext} from the on-disk project (config, secret)\n * plus fresh framework detection, so a patcher repair can rebuild its plan.\n * Used by the dependency check's `fix`, which reclaims the framework-specific\n * SDK package via `patcher.repair`. The user schema and flow definition are\n * server-owned and no longer scaffolded locally, so nothing here reads them.\n */\nexport async function loadPatchContext(\n cwd: string,\n orca: Orca,\n cliVersion: string,\n): Promise<PatchContext> {\n const config = await readZitadelConfig(cwd);\n const secret = await readZitadelSecret(cwd);\n const framework = await orca.detect(cwd);\n return {\n framework,\n rendererId: readRendererId(config),\n issuer: await resolveIssuer(cwd, config, framework),\n server: typeof config.server === \"string\" ? config.server : \"\",\n cliVersion,\n project: {\n id: secret.project_id,\n projectSecret: secret.project_secret,\n previewSecret: secret.preview_secret,\n previewOrigins: secret.preview_origins,\n createdAt: secret.created_at,\n },\n };\n}\n\nasync function resolveIssuer(\n cwd: string,\n config: Record<string, unknown>,\n facts: FrameworkFacts,\n): Promise<string> {\n const fromConfig = readDevelopmentIssuer(config);\n if (fromConfig && fromConfig.length > 0) {\n return fromConfig;\n }\n const state = await readState(cwd);\n if (typeof state?.dev_port === \"number\") {\n return issuerFromPort(state.dev_port);\n }\n return facts.url;\n}\n\nasync function readState(cwd: string): Promise<{ dev_port?: number } | undefined> {\n try {\n const contents = await readFile(join(cwd, \".zitadel/state.json\"), \"utf8\");\n return JSON.parse(contents) as { dev_port?: number };\n } catch {\n return undefined;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { loadPatchContext } from \"../patch-context\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/**\n * Verifies the project still declares a Zitadel SDK dependency in\n * `package.json`. The patcher adds a scoped package (e.g.\n * `@zitadel/sdk-next`); the check is generic over the `@zitadel*`\n * scope so any framework renderer's dependency satisfies it.\n */\nexport class DependencyCheck extends AbstractSanityCheck {\n readonly name = \"dependency\";\n readonly path = \"package.json\";\n protected readonly summary = \"package.json depends on a Zitadel SDK package\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const pkg = JSON.parse(await readFile(join(ctx.cwd, \"package.json\"), \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const names = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n if (!names.some((name) => name.startsWith(\"@zitadel\"))) {\n throw new Error(\"no @zitadel* dependency found in package.json\");\n }\n }\n\n /**\n * Repairs by reclaiming the patcher's managed artifacts: rebuilds the\n * `PatchContext` from disk and calls `patcher.repair`, which re-adds the\n * SDK dependency via its `add-dep` op. The exact package name is framework\n * + renderer specific and known only to the patcher (which deliberately\n * hides its file-op plan behind the family-neutral `Patcher` interface),\n * so going through `repair` is the only sanctioned path.\n */\n override async fix(ctx: CheckContext): Promise<void> {\n const patchCtx = await loadPatchContext(ctx.cwd, ctx.orca, ctx.cliVersion);\n await ctx.orca.patcherFor(patchCtx.framework.id).repair(patchCtx, {\n cwd: ctx.cwd,\n dryRun: ctx.dryRun,\n force: true,\n });\n }\n}\n","import { readZitadelConfig, readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret`'s project_id matches `zitadel.json`'s project. */\nexport class ProjectMatchCheck extends AbstractSanityCheck {\n readonly name = \"project-match\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret project_id matches zitadel.json project\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const secret = await readZitadelSecret(ctx.cwd);\n const configProject = typeof config.project === \"string\" ? config.project : undefined;\n if (secret.project_id !== configProject) {\n throw new Error(\".zitadel/secret project_id does not match zitadel.json project\");\n }\n }\n}\n","/**\n * Public surface for the doctor sanity checks. The `doctor` command imports\n * {@link SANITY_CHECKS} and runs every entry, aggregating the outcomes. Each\n * check is a small standalone class (see its own file); add a new diagnostic\n * by writing a class and appending an instance to the registry below.\n */\nimport type { SanityCheck } from \"./types\";\nimport { ConfigCheck } from \"./config\";\nimport { SecretCheck } from \"./secret\";\nimport { SecretPermissionsCheck } from \"./secret-permissions\";\nimport { GitignoreCheck } from \"./gitignore\";\nimport { EnvExampleCheck } from \"./env-example\";\nimport { FrameworkCheck } from \"./framework\";\nimport { DependencyCheck } from \"./dependency\";\nimport { ProjectMatchCheck } from \"./project-match\";\n\nexport type { SanityCheck, CheckContext, CheckOutcome } from \"./types\";\nexport { AbstractSanityCheck } from \"./types\";\nexport { ConfigCheck } from \"./config\";\nexport { SecretCheck } from \"./secret\";\nexport { SecretPermissionsCheck } from \"./secret-permissions\";\nexport { GitignoreCheck } from \"./gitignore\";\nexport { EnvExampleCheck } from \"./env-example\";\nexport { FrameworkCheck } from \"./framework\";\nexport { SchemaCheck } from \"./schema\";\nexport { DependencyCheck } from \"./dependency\";\nexport { ProjectMatchCheck } from \"./project-match\";\n\n/** Every diagnostic the `doctor` command runs, in display order. */\nexport const SANITY_CHECKS: ReadonlyArray<SanityCheck> = [\n new ConfigCheck(),\n new SecretCheck(),\n new SecretPermissionsCheck(),\n new GitignoreCheck(),\n new EnvExampleCheck(),\n new FrameworkCheck(),\n // SchemaCheck is disabled: the user schema is now provisioned server-side\n // and no longer scaffolded into `.zitadel/schemas/user.json`, so there is\n // no local file to verify. The check is kept (imported/exported below) for\n // the future pull-based workflow that will re-introduce local resources.\n // new SchemaCheck(),\n new DependencyCheck(),\n new ProjectMatchCheck(),\n];\n","import { Flags } from \"@oclif/core\";\nimport consola from \"consola\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../../lib/oclif\";\nimport { ZitadelError } from \"../../lib/errors\";\nimport { dockerAvailable, imageAvailable } from \"../../lib/local-server/docker\";\nimport {\n DEFAULT_LOCAL_SERVER_IMAGE,\n DEFAULT_LOCAL_SERVER_PORT,\n assertWritableDirectory,\n checkLocalServerHealth,\n isPortAvailable,\n localRuntimePaths,\n localServerUrl,\n readRuntimeMetadata,\n} from \"../../lib/local-server/runtime\";\nimport { createOrca } from \"../../lib/orca\";\nimport { hasZitadelConfig } from \"../../lib/project\";\nimport { SANITY_CHECKS, type CheckContext, type CheckOutcome } from \"./checks\";\n\nconst LOCAL_RUNTIME_CHECK_NAMES = new Set([\"docker-cli\", \"image\", \"state-dir\", \"port\", \"runtime\"]);\n\n/**\n * `zitadel doctor` — verify generated files and local state.\n *\n * Runs every registered {@link SANITY_CHECKS} entry and emits the aggregate\n * result; if any check fails it throws `E_VALIDATION` carrying the full check\n * details. With `--fix`, each failing check first attempts its own repair (a\n * no-op for checks with no safe automatic remedy), then the battery re-runs.\n *\n * The `--fix` loop is best-effort: a repair that throws (e.g. a missing\n * prerequisite file the check itself would also flag) is logged at debug\n * level and skipped, not propagated — the post-fix re-verify still reports\n * whatever remains broken.\n */\nexport default class Doctor extends BaseCommand {\n static override description = \"Verify local runtime and project state.\";\n static override flags = {\n fix: Flags.boolean({ description: \"Re-apply missing managed files.\" }),\n image: Flags.string({ description: \"Container image to check.\" }),\n port: Flags.integer({ description: \"Local HTTP port.\", default: DEFAULT_LOCAL_SERVER_PORT }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Doctor);\n const port = flags.port ?? DEFAULT_LOCAL_SERVER_PORT;\n await this.toMeta(flags, { resolveServer: false, source: localServerUrl(port) });\n const { cwd, dryRun } = this.meta;\n const image = flags.image ?? this.meta.env.ZITADEL_LOCAL_IMAGE ?? DEFAULT_LOCAL_SERVER_IMAGE;\n const runtimeChecks = await runLocalRuntimeChecks(cwd, image, port);\n const hasConfig = await hasZitadelConfig(cwd);\n const ctx: CheckContext = { cwd, orca: createOrca(), cliVersion: this.meta.cliVersion, dryRun };\n\n if (hasConfig && flags.fix) {\n const before = await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)));\n for (const [index, check] of SANITY_CHECKS.entries()) {\n if (before[index]?.status !== \"fail\") {\n continue;\n }\n try {\n await check.fix(ctx);\n } catch (error) {\n consola.debug(`doctor --fix: ${check.name} repair failed`, error);\n }\n }\n }\n\n const projectChecks = hasConfig\n ? await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)))\n : [];\n const checks = [...runtimeChecks, ...projectChecks];\n const failed = checks.filter((check) => check.status === \"fail\");\n const data = {\n title: failed.length === 0 ? \"Zitadel doctor passed.\" : \"Zitadel doctor found issues.\",\n ok: failed.length === 0,\n image,\n port,\n project: {\n lifecycle: hasConfig ? \"configured\" : \"not-configured\",\n },\n checks,\n };\n\n if (failed.length > 0) {\n const advice = failureAdvice(failed, image, port);\n throw new ZitadelError(\"E_VALIDATION\", \"Zitadel doctor found issues\", {\n hint: advice.hint,\n nextCommands: advice.nextCommands,\n details: data,\n });\n }\n\n return this.emit({ status: \"ok\", data });\n }\n}\n\nfunction failureAdvice(\n failed: CheckOutcome[],\n image: string,\n port: number,\n): { hint: string; nextCommands: string[] } {\n const failedNames = new Set(failed.map((check) => check.name));\n\n if (failedNames.has(\"docker-cli\")) {\n return {\n hint:\n \"Docker is required for `zitadel start`, but the Docker daemon is not reachable. Install or start Docker, then rerun `zitadel doctor`.\",\n nextCommands: [\"docker version\", \"zitadel doctor\"],\n };\n }\n\n if (failedNames.has(\"image\")) {\n return {\n hint:\n \"The local Zitadel image is not available. Check Docker registry access, build it locally, or pass --image / ZITADEL_LOCAL_IMAGE.\",\n nextCommands: [`docker pull ${image}`, \"zitadel doctor\"],\n };\n }\n\n if (failedNames.has(\"state-dir\")) {\n return {\n hint: \"The local Zitadel state directory is not writable. Fix directory permissions, then rerun `zitadel doctor`.\",\n nextCommands: [\"zitadel doctor\"],\n };\n }\n\n if (failedNames.has(\"port\")) {\n const fallbackPort = port === DEFAULT_LOCAL_SERVER_PORT ? port + 1 : DEFAULT_LOCAL_SERVER_PORT;\n return {\n hint: `Port ${String(port)} is already in use. Stop the process using it, or choose another port for local Zitadel.`,\n nextCommands: [`zitadel doctor --port ${String(fallbackPort)}`],\n };\n }\n\n if (failedNames.has(\"runtime\")) {\n return {\n hint:\n \"Existing local runtime metadata was found, but the local Zitadel server is not healthy. Start it again or reset stale local data.\",\n nextCommands: [\"zitadel start\", \"zitadel reset --force\"],\n };\n }\n\n const hasProjectFailure = failed.some((check) => !LOCAL_RUNTIME_CHECK_NAMES.has(check.name));\n if (hasProjectFailure) {\n return {\n hint: \"Run `npx @zitadel/cli@alpha doctor --fix` to re-apply missing managed files.\",\n nextCommands: [\"zitadel doctor --fix\"],\n };\n }\n\n return {\n hint: \"Fix the reported checks, then rerun `zitadel doctor`.\",\n nextCommands: [\"zitadel doctor\"],\n };\n}\n\nasync function runLocalRuntimeChecks(\n cwd: string,\n image: string,\n port: number,\n): Promise<CheckOutcome[]> {\n const runtime = await readRuntimeMetadata(cwd);\n return [\n await check(\"docker-cli\", \"Docker is reachable\", async () => {\n const result = await dockerAvailable();\n if (result.status !== 0) {\n throw new Error(result.stderr || \"docker version failed\");\n }\n return `Docker engine ${result.stdout.trim() || \"available\"}`;\n }),\n await check(\"image\", `Image ${image} is available`, async () => {\n const source = await imageAvailable(image);\n return source === \"local\"\n ? `Image ${image} is available locally`\n : `Image ${image} is available from the registry`;\n }),\n await check(\"state-dir\", \"Local state directory is writable\", async () => {\n const paths = localRuntimePaths(cwd);\n await assertWritableDirectory(paths.dataDir);\n return `${paths.dataDir} is writable`;\n }),\n await check(\"port\", `Port ${String(port)} is available`, async () => {\n if (runtime && (await checkLocalServerHealth(runtime.server_url))) {\n return `${runtime.server_url} is already healthy`;\n }\n if (!(await isPortAvailable(port))) {\n throw new Error(`Port ${String(port)} is already in use`);\n }\n return `Port ${String(port)} is available`;\n }),\n await check(\"runtime\", \"Existing local runtime is healthy\", async () => {\n if (!runtime) {\n return \"No existing runtime metadata\";\n }\n if (!(await checkLocalServerHealth(runtime.server_url))) {\n throw new Error(`${runtime.server_url} did not respond to /healthz`);\n }\n return `${runtime.server_url} is healthy`;\n }),\n ];\n}\n\nasync function check(\n name: string,\n fallback: string,\n run: () => Promise<string>,\n): Promise<CheckOutcome> {\n try {\n return { name, status: \"pass\", message: await run() };\n } catch (error) {\n return {\n name,\n status: \"fail\",\n message: error instanceof Error ? error.message : fallback,\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"doctor.mjs","names":[],"sources":["../../src/commands/doctor/checks/types.ts","../../src/commands/doctor/checks/config.ts","../../src/commands/doctor/checks/secret.ts","../../src/commands/doctor/checks/secret-permissions.ts","../../src/commands/doctor/checks/gitignore.ts","../../src/commands/doctor/checks/env-example.ts","../../src/commands/doctor/checks/framework.ts","../../src/commands/doctor/patch-context.ts","../../src/commands/doctor/checks/dependency.ts","../../src/commands/doctor/checks/project-match.ts","../../src/commands/doctor/checks/index.ts","../../src/commands/doctor/index.ts"],"sourcesContent":["import type { Orca } from \"../../../lib/orca\";\n\n/** Pass/fail/advisory outcome of a single {@link SanityCheck}. */\nexport type CheckOutcome = {\n name: string;\n status: \"pass\" | \"warn\" | \"fail\";\n message: string;\n path?: string;\n};\n\n/** Everything a check needs to inspect or repair a project. */\nexport type CheckContext = {\n readonly cwd: string;\n readonly orca: Orca;\n readonly cliVersion: string;\n /** When true, {@link SanityCheck.fix} must preview without writing. */\n readonly dryRun: boolean;\n};\n\n/**\n * One diagnostic the `doctor` command runs. Each concrete check is a small\n * standalone class that both verifies its concern ({@link run}) and knows how\n * to repair it ({@link fix}); the command executes every registered check,\n * aggregates the {@link CheckOutcome}s, and (under `--fix`) repairs the ones\n * that failed.\n */\nexport interface SanityCheck {\n /** Stable identifier surfaced in logs and the JSON envelope. */\n readonly name: string;\n run(ctx: CheckContext): Promise<CheckOutcome>;\n /** Repair what this check verifies. A no-op when there is no safe auto-fix. */\n fix(ctx: CheckContext): Promise<void>;\n}\n\n/**\n * Base class for checks: subclasses declare `name`, `path`, and a success\n * `summary`, and implement the single {@link verify} method that throws on\n * failure. {@link run} wraps it so a thrown error becomes a `fail` outcome\n * carrying the error message, and success becomes a `pass` with `summary`.\n *\n * {@link fix} defaults to a no-op: checks whose failure has no safe automatic\n * remedy (a missing secret, an invalid user schema) simply do not override it.\n */\nexport abstract class AbstractSanityCheck implements SanityCheck {\n abstract readonly name: string;\n abstract readonly path: string;\n protected abstract readonly summary: string;\n\n /** Throw to signal failure; the thrown message is surfaced to the user. */\n protected abstract verify(ctx: CheckContext): Promise<void>;\n\n async run(ctx: CheckContext): Promise<CheckOutcome> {\n try {\n await this.verify(ctx);\n return { name: this.name, status: \"pass\", message: this.summary, path: this.path };\n } catch (error) {\n return {\n name: this.name,\n status: \"fail\",\n message: error instanceof Error ? error.message : String(error),\n path: this.path,\n };\n }\n }\n\n async fix(_ctx: CheckContext): Promise<void> {\n return;\n }\n}\n","import { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `zitadel.json` exists and parses. */\nexport class ConfigCheck extends AbstractSanityCheck {\n readonly name = \"config\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"zitadel.json parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelConfig(ctx.cwd);\n }\n}\n","import { readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` exists and parses. */\nexport class SecretCheck extends AbstractSanityCheck {\n readonly name = \"secret\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelSecret(ctx.cwd);\n }\n}\n","import { chmod, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` is locked down to `0600`, and re-locks it on fix. */\nexport class SecretPermissionsCheck extends AbstractSanityCheck {\n readonly name = \"secret-permissions\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret has 0600 permissions\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const mode = (await stat(join(ctx.cwd, \".zitadel/secret\"))).mode & 0o777;\n if (mode !== 0o600) {\n throw new Error(`expected 0600, got ${mode.toString(8)}`);\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n if (ctx.dryRun) {\n return;\n }\n await chmod(join(ctx.cwd, \".zitadel/secret\"), 0o600);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The entries `.gitignore` must carry to keep secrets and env files untracked. */\nconst REQUIRED_ENTRIES = [\".zitadel/secret\", \".env*\", \"!.env.example\"];\n\n/** Verifies `.gitignore` excludes the local secret and env files; appends any missing. */\nexport class GitignoreCheck extends AbstractSanityCheck {\n readonly name = \"gitignore\";\n readonly path = \".gitignore\";\n protected readonly summary = \".gitignore protects local secret/env files\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const lines = (await readFile(join(ctx.cwd, \".gitignore\"), \"utf8\")).split(/\\r?\\n/g);\n for (const entry of REQUIRED_ENTRIES) {\n if (!lines.includes(entry)) {\n throw new Error(`missing ${entry}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".gitignore\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const lines = existing.split(/\\r?\\n/g);\n const missing = REQUIRED_ENTRIES.filter((entry) => !lines.includes(entry));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.join(\"\\n\")}\\n`);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The keys `.env.example` must document for a Zitadel-managed project. */\nconst REQUIRED_KEYS = [\"ZITADEL_PROJECT_ID\", \"ZITADEL_ENVIRONMENT\", \"ZITADEL_ISSUER\"];\n\n/** Verifies `.env.example` documents the required Zitadel keys; appends any missing. */\nexport class EnvExampleCheck extends AbstractSanityCheck {\n readonly name = \"env-example\";\n readonly path = \".env.example\";\n protected readonly summary = \".env.example references required keys\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const contents = await readFile(join(ctx.cwd, \".env.example\"), \"utf8\");\n for (const key of REQUIRED_KEYS) {\n if (!contents.includes(`${key}=`)) {\n throw new Error(`missing ${key}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".env.example\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const missing = REQUIRED_KEYS.filter((key) => !existing.includes(`${key}=`));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.map((key) => `${key}=`).join(\"\\n\")}\\n`);\n }\n}\n","import { isObject } from \"../../../lib/json\";\nimport { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies the framework detected on disk matches the one recorded in config. */\nexport class FrameworkCheck extends AbstractSanityCheck {\n readonly name = \"framework\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"Detected framework matches recorded framework\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const detected = await ctx.orca.detect(ctx.cwd);\n const recorded = isObject(config.framework) ? config.framework.id : undefined;\n if (recorded !== detected.id) {\n throw new Error(`expected ${String(recorded)}, detected ${detected.id}`);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { issuerFromPort, type FrameworkFacts, type Orca } from \"../../lib/orca\";\nimport type { PatchContext } from \"../../lib/orca/patchers/types\";\nimport { readDevelopmentIssuer, readRendererId, readZitadelConfig, readZitadelSecret } from \"../../lib/project\";\n\n/**\n * Reconstructs a {@link PatchContext} from the on-disk project (config, secret)\n * plus fresh framework detection, so a patcher repair can rebuild its plan.\n * Used by the dependency check's `fix`, which reclaims the framework-specific\n * SDK package via `patcher.repair`. The user schema and flow definition are\n * server-owned and no longer scaffolded locally, so nothing here reads them.\n */\nexport async function loadPatchContext(\n cwd: string,\n orca: Orca,\n cliVersion: string,\n): Promise<PatchContext> {\n const config = await readZitadelConfig(cwd);\n const secret = await readZitadelSecret(cwd);\n const framework = await orca.detect(cwd);\n return {\n framework,\n rendererId: readRendererId(config),\n issuer: await resolveIssuer(cwd, config, framework),\n server: typeof config.server === \"string\" ? config.server : \"\",\n cliVersion,\n project: {\n id: secret.project_id,\n projectSecret: secret.project_secret,\n previewSecret: secret.preview_secret,\n previewOrigins: secret.preview_origins,\n createdAt: secret.created_at,\n },\n };\n}\n\nasync function resolveIssuer(\n cwd: string,\n config: Record<string, unknown>,\n facts: FrameworkFacts,\n): Promise<string> {\n const fromConfig = readDevelopmentIssuer(config);\n if (fromConfig && fromConfig.length > 0) {\n return fromConfig;\n }\n const state = await readState(cwd);\n if (typeof state?.dev_port === \"number\") {\n return issuerFromPort(state.dev_port);\n }\n return facts.url;\n}\n\nasync function readState(cwd: string): Promise<{ dev_port?: number } | undefined> {\n try {\n const contents = await readFile(join(cwd, \".zitadel/state.json\"), \"utf8\");\n return JSON.parse(contents) as { dev_port?: number };\n } catch {\n return undefined;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { loadPatchContext } from \"../patch-context\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/**\n * Verifies the project still declares a Zitadel SDK dependency in\n * `package.json`. The patcher adds a scoped package (e.g.\n * `@zitadel/sdk-next`); the check is generic over the `@zitadel*`\n * scope so any framework renderer's dependency satisfies it.\n */\nexport class DependencyCheck extends AbstractSanityCheck {\n readonly name = \"dependency\";\n readonly path = \"package.json\";\n protected readonly summary = \"package.json depends on a Zitadel SDK package\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const pkg = JSON.parse(await readFile(join(ctx.cwd, \"package.json\"), \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const names = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n if (!names.some((name) => name.startsWith(\"@zitadel\"))) {\n throw new Error(\"no @zitadel* dependency found in package.json\");\n }\n }\n\n /**\n * Repairs by reclaiming the patcher's managed artifacts: rebuilds the\n * `PatchContext` from disk and calls `patcher.repair`, which re-adds the\n * SDK dependency via its `add-dep` op. The exact package name is framework\n * + renderer specific and known only to the patcher (which deliberately\n * hides its file-op plan behind the family-neutral `Patcher` interface),\n * so going through `repair` is the only sanctioned path.\n */\n override async fix(ctx: CheckContext): Promise<void> {\n const patchCtx = await loadPatchContext(ctx.cwd, ctx.orca, ctx.cliVersion);\n await ctx.orca.patcherFor(patchCtx.framework.id).repair(patchCtx, {\n cwd: ctx.cwd,\n dryRun: ctx.dryRun,\n force: true,\n });\n }\n}\n","import { readZitadelConfig, readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret`'s project_id matches `zitadel.json`'s project. */\nexport class ProjectMatchCheck extends AbstractSanityCheck {\n readonly name = \"project-match\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret project_id matches zitadel.json project\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const secret = await readZitadelSecret(ctx.cwd);\n const configProject = typeof config.project === \"string\" ? config.project : undefined;\n if (secret.project_id !== configProject) {\n throw new Error(\".zitadel/secret project_id does not match zitadel.json project\");\n }\n }\n}\n","/**\n * Public surface for the doctor sanity checks. The `doctor` command imports\n * {@link SANITY_CHECKS} and runs every entry, aggregating the outcomes. Each\n * check is a small standalone class (see its own file); add a new diagnostic\n * by writing a class and appending an instance to the registry below.\n */\nimport type { SanityCheck } from \"./types\";\nimport { ConfigCheck } from \"./config\";\nimport { SecretCheck } from \"./secret\";\nimport { SecretPermissionsCheck } from \"./secret-permissions\";\nimport { GitignoreCheck } from \"./gitignore\";\nimport { EnvExampleCheck } from \"./env-example\";\nimport { FrameworkCheck } from \"./framework\";\nimport { DependencyCheck } from \"./dependency\";\nimport { ProjectMatchCheck } from \"./project-match\";\n\nexport type { SanityCheck, CheckContext, CheckOutcome } from \"./types\";\nexport { AbstractSanityCheck } from \"./types\";\nexport { ConfigCheck } from \"./config\";\nexport { SecretCheck } from \"./secret\";\nexport { SecretPermissionsCheck } from \"./secret-permissions\";\nexport { GitignoreCheck } from \"./gitignore\";\nexport { EnvExampleCheck } from \"./env-example\";\nexport { FrameworkCheck } from \"./framework\";\nexport { SchemaCheck } from \"./schema\";\nexport { DependencyCheck } from \"./dependency\";\nexport { ProjectMatchCheck } from \"./project-match\";\n\n/** Every diagnostic the `doctor` command runs, in display order. */\nexport const SANITY_CHECKS: ReadonlyArray<SanityCheck> = [\n new ConfigCheck(),\n new SecretCheck(),\n new SecretPermissionsCheck(),\n new GitignoreCheck(),\n new EnvExampleCheck(),\n new FrameworkCheck(),\n // SchemaCheck is disabled: the user schema is now provisioned server-side\n // and no longer scaffolded into `.zitadel/schemas/user.json`, so there is\n // no local file to verify. The check is kept (imported/exported below) for\n // the future pull-based workflow that will re-introduce local resources.\n // new SchemaCheck(),\n new DependencyCheck(),\n new ProjectMatchCheck(),\n];\n","import { Flags } from \"@oclif/core\";\nimport consola from \"consola\";\n\nimport { ZitadelError } from \"../../lib/errors\";\nimport { dockerAvailable, imageAvailable } from \"../../lib/local-server/docker\";\nimport {\n DEFAULT_LOCAL_SERVER_PORT,\n assertWritableDirectory,\n checkLocalServerHealth,\n defaultLocalServerImageForCliVersion,\n isPortAvailable,\n localRuntimePaths,\n localServerUrl,\n readRuntimeMetadata,\n} from \"../../lib/local-server/runtime\";\nimport { BaseCommand, type JsonEnvelope } from \"../../lib/oclif\";\nimport { createOrca } from \"../../lib/orca\";\nimport { hasZitadelConfig } from \"../../lib/project\";\nimport { publicCliCommand } from \"../../lib/public-cli\";\nimport { SANITY_CHECKS, type CheckContext, type CheckOutcome } from \"./checks\";\n\nconst LOCAL_RUNTIME_CHECK_NAMES = new Set([\"docker-cli\", \"image\", \"state-dir\", \"port\", \"runtime\"]);\n\n/**\n * `zitadel doctor` — verify generated files and local state.\n *\n * Runs every registered {@link SANITY_CHECKS} entry and emits the aggregate\n * result; if any check fails it throws `E_VALIDATION` carrying the full check\n * details. With `--fix`, each failing check first attempts its own repair (a\n * no-op for checks with no safe automatic remedy), then the battery re-runs.\n *\n * The `--fix` loop is best-effort: a repair that throws (e.g. a missing\n * prerequisite file the check itself would also flag) is logged at debug\n * level and skipped, not propagated — the post-fix re-verify still reports\n * whatever remains broken.\n */\nexport default class Doctor extends BaseCommand {\n static override description = \"Verify local runtime and project state.\";\n static override flags = {\n fix: Flags.boolean({ description: \"Re-apply missing managed files.\" }),\n image: Flags.string({ description: \"Container image to check.\" }),\n port: Flags.integer({ description: \"Local HTTP port.\", default: DEFAULT_LOCAL_SERVER_PORT }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Doctor);\n const port = flags.port ?? DEFAULT_LOCAL_SERVER_PORT;\n await this.toMeta(flags, { resolveServer: false, source: localServerUrl(port) });\n const { cwd, dryRun } = this.meta;\n const image =\n flags.image ??\n this.meta.env.ZITADEL_LOCAL_IMAGE ??\n defaultLocalServerImageForCliVersion(this.meta.cliVersion);\n const runtimeChecks = await runLocalRuntimeChecks(cwd, image, port);\n const hasConfig = await hasZitadelConfig(cwd);\n const ctx: CheckContext = { cwd, orca: createOrca(), cliVersion: this.meta.cliVersion, dryRun };\n\n if (hasConfig && flags.fix) {\n const before = await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)));\n for (const [index, check] of SANITY_CHECKS.entries()) {\n if (before[index]?.status !== \"fail\") {\n continue;\n }\n try {\n await check.fix(ctx);\n } catch (error) {\n consola.debug(`doctor --fix: ${check.name} repair failed`, error);\n }\n }\n }\n\n const projectChecks = hasConfig\n ? await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)))\n : [];\n const checks = [...runtimeChecks, ...projectChecks];\n const failed = checks.filter((check) => check.status === \"fail\");\n const warnings = checks.filter((check) => check.status === \"warn\");\n const data = {\n title:\n failed.length > 0\n ? \"Zitadel doctor found issues.\"\n : warnings.length > 0\n ? \"Zitadel doctor passed with warnings.\"\n : \"Zitadel doctor passed.\",\n ok: failed.length === 0,\n image,\n port,\n project: {\n lifecycle: hasConfig ? \"configured\" : \"not-configured\",\n },\n checks,\n };\n\n if (failed.length > 0) {\n const advice = failureAdvice(failed, image, port, this.meta.cliVersion);\n throw new ZitadelError(\"E_VALIDATION\", \"Zitadel doctor found issues\", {\n hint: advice.hint,\n nextCommands: advice.nextCommands,\n details: data,\n });\n }\n\n return this.emit({\n status: \"ok\",\n data,\n warnings: warnings.map((warning) => `${warning.name}: ${warning.message}`),\n });\n }\n}\n\nfunction failureAdvice(\n failed: CheckOutcome[],\n image: string,\n port: number,\n cliVersion: string,\n): { hint: string; nextCommands: string[] } {\n const failedNames = new Set(failed.map((check) => check.name));\n\n if (failedNames.has(\"docker-cli\")) {\n return {\n hint: \"Docker is required for `zitadel start`, but the Docker daemon is not reachable. Install or start Docker, then rerun `zitadel doctor`.\",\n nextCommands: [\"docker version\", publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"image\")) {\n return {\n hint: \"The local Zitadel image is not available. Check Docker registry access, build it locally, or pass --image / ZITADEL_LOCAL_IMAGE.\",\n nextCommands: [`docker pull ${image}`, publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"state-dir\")) {\n return {\n hint: \"The local Zitadel state directory is not writable. Fix directory permissions, then rerun `zitadel doctor`.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"port\")) {\n const fallbackPort = port === DEFAULT_LOCAL_SERVER_PORT ? port + 1 : DEFAULT_LOCAL_SERVER_PORT;\n return {\n hint: `Port ${String(port)} is already in use. Stop the process using it, or choose another port for local Zitadel.`,\n nextCommands: [publicCliCommand(`doctor --port ${String(fallbackPort)}`, cliVersion)],\n };\n }\n\n if (failedNames.has(\"runtime\")) {\n return {\n hint: \"Existing local runtime metadata was found, but the local Zitadel server is not healthy. Start it again or reset stale local data.\",\n nextCommands: [\n publicCliCommand(\"start\", cliVersion),\n publicCliCommand(\"reset --force\", cliVersion),\n ],\n };\n }\n\n const hasProjectFailure = failed.some((check) => !LOCAL_RUNTIME_CHECK_NAMES.has(check.name));\n if (hasProjectFailure) {\n return {\n hint: `Run \\`${publicCliCommand(\"doctor --fix\", cliVersion)}\\` to re-apply missing managed files.`,\n nextCommands: [publicCliCommand(\"doctor --fix\", cliVersion)],\n };\n }\n\n return {\n hint: \"Fix the reported checks, then rerun `zitadel doctor`.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n}\n\nasync function runLocalRuntimeChecks(\n cwd: string,\n image: string,\n port: number,\n): Promise<CheckOutcome[]> {\n const runtime = await readRuntimeMetadata(cwd);\n const docker = await check(\n \"docker-cli\",\n \"Docker is reachable\",\n async () => {\n let result: Awaited<ReturnType<typeof dockerAvailable>>;\n try {\n result = await dockerAvailable();\n } catch (error) {\n throw new Error(dockerUnavailableMessage(error), { cause: error });\n }\n if (result.status !== 0) {\n throw new Error(dockerUnavailableMessage(result.stderr || \"docker version failed\"));\n }\n return `Docker engine ${result.stdout.trim() || \"available\"}`;\n },\n \"warn\",\n );\n\n const imageCheck =\n docker.status === \"pass\"\n ? await check(\n \"image\",\n `Image ${image} is available`,\n async () => {\n try {\n const source = await imageAvailable(image);\n return source === \"local\"\n ? `Image ${image} is available locally`\n : `Image ${image} is available from the registry`;\n } catch (error) {\n throw new Error(imageUnavailableMessage(image, error), { cause: error });\n }\n },\n \"warn\",\n )\n : ({\n name: \"image\",\n status: \"warn\",\n message: \"Skipped image check because Docker is not reachable.\",\n } satisfies CheckOutcome);\n\n return [\n docker,\n imageCheck,\n await check(\n \"state-dir\",\n \"Local state directory is writable\",\n async () => {\n const paths = localRuntimePaths(cwd);\n await assertWritableDirectory(paths.dataDir);\n return `${paths.dataDir} is writable`;\n },\n \"warn\",\n ),\n await check(\n \"port\",\n `Port ${String(port)} is available`,\n async () => {\n if (runtime && (await checkLocalServerHealth(runtime.server_url))) {\n return `${runtime.server_url} is already healthy`;\n }\n if (!(await isPortAvailable(port))) {\n throw new Error(`Port ${String(port)} is already in use`);\n }\n return `Port ${String(port)} is available`;\n },\n \"warn\",\n ),\n await check(\"runtime\", \"Existing local runtime is healthy\", async () => {\n if (!runtime) {\n return \"No existing runtime metadata\";\n }\n if (!(await checkLocalServerHealth(runtime.server_url))) {\n throw new Error(`${runtime.server_url} did not respond to /healthz`);\n }\n return `${runtime.server_url} is healthy`;\n }),\n ];\n}\n\nasync function check(\n name: string,\n fallback: string,\n run: () => Promise<string>,\n failureStatus: \"warn\" | \"fail\" = \"fail\",\n): Promise<CheckOutcome> {\n try {\n return { name, status: \"pass\", message: await run() };\n } catch (error) {\n return {\n name,\n status: failureStatus,\n message: error instanceof Error ? error.message : fallback,\n };\n }\n}\n\nfunction 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}; \\`zitadel start\\` needs Docker, but cloud setup can continue.`;\n}\n\nfunction imageUnavailableMessage(image: string, error: unknown): string {\n const detail = error instanceof Error ? error.message : String(error);\n const suffix = detail.trim() ? ` (${detail.trim()})` : \"\";\n return `Image ${image} is not available to Docker${suffix}; \\`zitadel start\\` may need a pull or a different image.`;\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { T as ZitadelError, t as BaseCommand } from "../oclif-DSPO9Sck.mjs";
2
- import { t as createOrca } from "../orca-DOxshV9n.mjs";
3
- import { a as readZitadelConfig, i as readRendererId } from "../project-Dwb9WVAT.mjs";
4
- import { readFile, rename, rm, stat } from "node:fs/promises";
1
+ import { E as ZitadelError, t as BaseCommand } from "../oclif-CqkWBQ7i.mjs";
2
+ import { t as createOrca } from "../orca-S1tVnngd.mjs";
3
+ import { a as readZitadelConfig, i as readRendererId } from "../project-B6YfSaZw.mjs";
5
4
  import { join } from "node:path";
5
+ import { readFile, rename, rm, stat } from "node:fs/promises";
6
6
  //#region src/commands/eject.ts
7
7
  /**
8
8
  * Asks the framework patcher which artifacts it owns. Falls back to the
@@ -1,5 +1,5 @@
1
- import { T as ZitadelError, _ as readRuntimeMetadata, t as BaseCommand } from "../oclif-DSPO9Sck.mjs";
2
- import { a as followContainerLogs, t as containerLogs } from "../docker-C0aVpJqm.mjs";
1
+ import { E as ZitadelError, g as readRuntimeMetadata, t as BaseCommand, x as publicCliCommand } from "../oclif-CqkWBQ7i.mjs";
2
+ import { a as followContainerLogs, t as containerLogs } from "../docker-DrOBycgG.mjs";
3
3
  import { Flags } from "@oclif/core";
4
4
  //#region src/commands/logs.ts
5
5
  var Logs = class Logs extends BaseCommand {
@@ -20,7 +20,7 @@ var Logs = class Logs extends BaseCommand {
20
20
  });
21
21
  if (!runtime) throw new ZitadelError("E_VALIDATION", "Local Zitadel runtime has not been started", {
22
22
  hint: "Run `zitadel start` first.",
23
- nextCommands: ["zitadel start"]
23
+ nextCommands: [publicCliCommand("start", this.meta.cliVersion)]
24
24
  });
25
25
  const tail = flags.tail ?? 200;
26
26
  if (!Number.isInteger(tail) || tail < 1) throw new ZitadelError("E_VALIDATION", `Invalid tail value ${String(tail)}`, { hint: "Use a positive integer." });
@@ -1 +1 @@
1
- {"version":3,"file":"logs.mjs","names":[],"sources":["../../src/commands/logs.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { ZitadelError } from \"../lib/errors\";\nimport { containerLogs, followContainerLogs } from \"../lib/local-server/docker\";\nimport { DEFAULT_LOCAL_SERVER_URL, readRuntimeMetadata } from \"../lib/local-server/runtime\";\n\nexport default class Logs extends BaseCommand {\n static override description = \"Show local Zitadel server logs.\";\n static override flags = {\n follow: Flags.boolean({ description: \"Follow logs.\" }),\n tail: Flags.integer({ description: \"Number of lines to show.\", default: 200 }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Logs);\n const runtime = await readRuntimeMetadata(flags.cwd ? String(flags.cwd) : process.cwd());\n await this.toMeta(flags, {\n resolveServer: false,\n source: runtime?.server_url ?? DEFAULT_LOCAL_SERVER_URL,\n });\n\n if (!runtime) {\n throw new ZitadelError(\"E_VALIDATION\", \"Local Zitadel runtime has not been started\", {\n hint: \"Run `zitadel start` first.\",\n nextCommands: [\"zitadel start\"],\n });\n }\n\n const tail = flags.tail ?? 200;\n if (!Number.isInteger(tail) || tail < 1) {\n throw new ZitadelError(\"E_VALIDATION\", `Invalid tail value ${String(tail)}`, {\n hint: \"Use a positive integer.\",\n });\n }\n\n if (flags.follow) {\n if (this.jsonEnabled()) {\n throw new ZitadelError(\"E_VALIDATION\", \"Cannot stream logs with --json\", {\n hint: \"Run without --json, or omit --follow.\",\n });\n }\n await followContainerLogs(runtime.container_name, tail);\n return this.emit({\n status: \"ok\",\n data: { title: \"Stopped following local Zitadel logs.\" },\n });\n }\n\n const logs = await containerLogs(runtime.container_name, tail);\n return this.emit({\n status: \"ok\",\n pretty: logs.trimEnd(),\n data: {\n title: \"Local Zitadel server logs.\",\n container_name: runtime.container_name,\n logs,\n },\n });\n }\n}\n"],"mappings":";;;;AAOA,IAAqB,OAArB,MAAqB,aAAa,YAAY;CAC5C,OAAgB,cAAc;CAC9B,OAAgB,QAAQ;EACtB,QAAQ,MAAM,QAAQ,EAAE,aAAa,gBAAgB,CAAC;EACtD,MAAM,MAAM,QAAQ;GAAE,aAAa;GAA4B,SAAS;GAAK,CAAC;EAC/E;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,KAAK;EACxC,MAAM,UAAU,MAAM,oBAAoB,MAAM,MAAM,OAAO,MAAM,IAAI,GAAG,QAAQ,KAAK,CAAC;AACxF,QAAM,KAAK,OAAO,OAAO;GACvB,eAAe;GACf,QAAQ,SAAS,cAAA;GAClB,CAAC;AAEF,MAAI,CAAC,QACH,OAAM,IAAI,aAAa,gBAAgB,8CAA8C;GACnF,MAAM;GACN,cAAc,CAAC,gBAAgB;GAChC,CAAC;EAGJ,MAAM,OAAO,MAAM,QAAQ;AAC3B,MAAI,CAAC,OAAO,UAAU,KAAK,IAAI,OAAO,EACpC,OAAM,IAAI,aAAa,gBAAgB,sBAAsB,OAAO,KAAK,IAAI,EAC3E,MAAM,2BACP,CAAC;AAGJ,MAAI,MAAM,QAAQ;AAChB,OAAI,KAAK,aAAa,CACpB,OAAM,IAAI,aAAa,gBAAgB,kCAAkC,EACvE,MAAM,yCACP,CAAC;AAEJ,SAAM,oBAAoB,QAAQ,gBAAgB,KAAK;AACvD,UAAO,KAAK,KAAK;IACf,QAAQ;IACR,MAAM,EAAE,OAAO,yCAAyC;IACzD,CAAC;;EAGJ,MAAM,OAAO,MAAM,cAAc,QAAQ,gBAAgB,KAAK;AAC9D,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,QAAQ,KAAK,SAAS;GACtB,MAAM;IACJ,OAAO;IACP,gBAAgB,QAAQ;IACxB;IACD;GACF,CAAC"}
1
+ {"version":3,"file":"logs.mjs","names":[],"sources":["../../src/commands/logs.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\n\nimport { ZitadelError } from \"../lib/errors\";\nimport { containerLogs, followContainerLogs } from \"../lib/local-server/docker\";\nimport { DEFAULT_LOCAL_SERVER_URL, readRuntimeMetadata } from \"../lib/local-server/runtime\";\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { publicCliCommand } from \"../lib/public-cli\";\n\nexport default class Logs extends BaseCommand {\n static override description = \"Show local Zitadel server logs.\";\n static override flags = {\n follow: Flags.boolean({ description: \"Follow logs.\" }),\n tail: Flags.integer({ description: \"Number of lines to show.\", default: 200 }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Logs);\n const runtime = await readRuntimeMetadata(flags.cwd ? String(flags.cwd) : process.cwd());\n await this.toMeta(flags, {\n resolveServer: false,\n source: runtime?.server_url ?? DEFAULT_LOCAL_SERVER_URL,\n });\n\n if (!runtime) {\n throw new ZitadelError(\"E_VALIDATION\", \"Local Zitadel runtime has not been started\", {\n hint: \"Run `zitadel start` first.\",\n nextCommands: [publicCliCommand(\"start\", this.meta.cliVersion)],\n });\n }\n\n const tail = flags.tail ?? 200;\n if (!Number.isInteger(tail) || tail < 1) {\n throw new ZitadelError(\"E_VALIDATION\", `Invalid tail value ${String(tail)}`, {\n hint: \"Use a positive integer.\",\n });\n }\n\n if (flags.follow) {\n if (this.jsonEnabled()) {\n throw new ZitadelError(\"E_VALIDATION\", \"Cannot stream logs with --json\", {\n hint: \"Run without --json, or omit --follow.\",\n });\n }\n await followContainerLogs(runtime.container_name, tail);\n return this.emit({\n status: \"ok\",\n data: { title: \"Stopped following local Zitadel logs.\" },\n });\n }\n\n const logs = await containerLogs(runtime.container_name, tail);\n return this.emit({\n status: \"ok\",\n pretty: logs.trimEnd(),\n data: {\n title: \"Local Zitadel server logs.\",\n container_name: runtime.container_name,\n logs,\n },\n });\n }\n}\n"],"mappings":";;;;AAQA,IAAqB,OAArB,MAAqB,aAAa,YAAY;CAC5C,OAAgB,cAAc;CAC9B,OAAgB,QAAQ;EACtB,QAAQ,MAAM,QAAQ,EAAE,aAAa,gBAAgB,CAAC;EACtD,MAAM,MAAM,QAAQ;GAAE,aAAa;GAA4B,SAAS;GAAK,CAAC;EAC/E;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,KAAK;EACxC,MAAM,UAAU,MAAM,oBAAoB,MAAM,MAAM,OAAO,MAAM,IAAI,GAAG,QAAQ,KAAK,CAAC;AACxF,QAAM,KAAK,OAAO,OAAO;GACvB,eAAe;GACf,QAAQ,SAAS,cAAA;GAClB,CAAC;AAEF,MAAI,CAAC,QACH,OAAM,IAAI,aAAa,gBAAgB,8CAA8C;GACnF,MAAM;GACN,cAAc,CAAC,iBAAiB,SAAS,KAAK,KAAK,WAAW,CAAC;GAChE,CAAC;EAGJ,MAAM,OAAO,MAAM,QAAQ;AAC3B,MAAI,CAAC,OAAO,UAAU,KAAK,IAAI,OAAO,EACpC,OAAM,IAAI,aAAa,gBAAgB,sBAAsB,OAAO,KAAK,IAAI,EAC3E,MAAM,2BACP,CAAC;AAGJ,MAAI,MAAM,QAAQ;AAChB,OAAI,KAAK,aAAa,CACpB,OAAM,IAAI,aAAa,gBAAgB,kCAAkC,EACvE,MAAM,yCACP,CAAC;AAEJ,SAAM,oBAAoB,QAAQ,gBAAgB,KAAK;AACvD,UAAO,KAAK,KAAK;IACf,QAAQ;IACR,MAAM,EAAE,OAAO,yCAAyC;IACzD,CAAC;;EAGJ,MAAM,OAAO,MAAM,cAAc,QAAQ,gBAAgB,KAAK;AAC9D,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,QAAQ,KAAK,SAAS;GACtB,MAAM;IACJ,OAAO;IACP,gBAAgB,QAAQ;IACxB;IACD;GACF,CAAC"}
@@ -1,9 +1,9 @@
1
- import { t as BaseCommand } from "../oclif-DSPO9Sck.mjs";
2
- import { o as readZitadelSecret } from "../project-Dwb9WVAT.mjs";
3
- import { a as makeSyncers, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-DmtTYNmq.mjs";
1
+ import { t as BaseCommand } from "../oclif-CqkWBQ7i.mjs";
2
+ import { o as readZitadelSecret } from "../project-B6YfSaZw.mjs";
3
+ import { a as makeSyncers, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-DN4oNLVH.mjs";
4
4
  import { Flags } from "@oclif/core";
5
- import { consola as consola$1 } from "consola";
6
5
  import { createZitadelClient } from "@zitadel/api/client";
6
+ import { consola as consola$1 } from "consola";
7
7
  //#region src/commands/plan.ts
8
8
  /**
9
9
  * `zitadel plan` — validate config and preview the sync diff without mutating.