@zitadel/cli 0.1.0-alpha.3 → 0.1.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # @zitadel/cli
2
2
 
3
- Scaffolds Zitadel auth (login, register, profile, middleware) into a Next.js app.
3
+ Scaffolds Zitadel auth (login, register, profile, middleware) into a Next.js, React, Vue, Angular, or Nuxt app.
4
4
 
5
5
  ```sh
6
6
  npx @zitadel/cli@alpha start
7
7
  npx @zitadel/cli@alpha setup --server local
8
8
  ```
9
9
 
10
+ During the public alpha, bare `npx @zitadel/cli` resolves to the same tested
11
+ alpha CLI. Use `@alpha` or an exact `0.1.0-alpha.N` selector in bug reports and
12
+ automation when reproducibility matters.
13
+
10
14
  > **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.
11
15
 
12
16
  ## Requirements
@@ -33,12 +37,15 @@ back to `ghcr.io/zitadel/nextgen:latest`. Override with `--image` or
33
37
  `ZITADEL_LOCAL_IMAGE` for advanced debugging.
34
38
  `setup --server local` creates a project on that local server, asks which
35
39
  framework to scaffold when the directory is fresh, writes the Next.js app into
36
- the current directory, scaffolds `app/login`, `app/register`, and
37
- `middleware.ts`, writes `.env.local` and `.zitadel/`, and installs dependencies
38
- with the detected package manager. Pass `--skip-install` to install them
39
- yourself. The project's default user schema and login flow are provisioned
40
+ the current directory, scaffolds `app/login`, `app/register`, `app/profile`, and
41
+ `proxy.ts` for Next 16+ or `middleware.ts` for older Next versions. Fresh
42
+ scaffolds also replace the starter `app/page.tsx` with links to sign in, create
43
+ an account, and profile. Setup writes `.env.local` and `.zitadel/`, and installs
44
+ dependencies with the detected package manager. Pass `--skip-install` to install
45
+ them yourself. The project's default user schema and login flow are provisioned
40
46
  server-side at creation time, so the CLI does not scaffold or upload them. Open
41
- `http://localhost:3000/login` to see the login page.
47
+ the dev server URL printed by your framework, register a user, log out, log back
48
+ in, and end on the signed-in profile page.
42
49
 
43
50
  For a reproducible tester report, use the exact alpha train from the GitHub
44
51
  Release:
@@ -58,6 +65,8 @@ passkey can sign in with either credential.
58
65
 
59
66
  - `zitadel doctor` — verify the local Docker runtime and generated project files
60
67
  - `zitadel status` — summarise the local Docker runtime and project
68
+ - `zitadel plan` — validate config and preview sync changes without mutation
69
+ - `zitadel apply` — validate and upload repo config to Zitadel
61
70
  - `zitadel eject` — remove what setup wrote (alias: `zitadel uninstall`)
62
71
  - `zitadel start|stop|logs|reset` — manage the local Docker runtime
63
72
 
@@ -67,22 +76,50 @@ passkey can sign in with either credential.
67
76
  <summary>Full command reference</summary>
68
77
 
69
78
  <!-- commands -->
79
+ * [`zitadel apply`](#zitadel-apply)
80
+ * [`zitadel autocomplete [SHELL]`](#zitadel-autocomplete-shell)
81
+ * [`zitadel commands`](#zitadel-commands)
82
+ * [`zitadel doctor`](#zitadel-doctor)
83
+ * [`zitadel eject`](#zitadel-eject)
84
+ * [`zitadel help [COMMAND]`](#zitadel-help-command)
85
+ * [`zitadel logs`](#zitadel-logs)
86
+ * [`zitadel plan`](#zitadel-plan)
87
+ * [`zitadel reset`](#zitadel-reset)
88
+ * [`zitadel search`](#zitadel-search)
89
+ * [`zitadel setup`](#zitadel-setup)
90
+ * [`zitadel start`](#zitadel-start)
91
+ * [`zitadel status`](#zitadel-status)
92
+ * [`zitadel stop`](#zitadel-stop)
93
+ * [`zitadel uninstall`](#zitadel-uninstall)
94
+ * [`zitadel version`](#zitadel-version)
95
+ * [`zitadel which`](#zitadel-which)
96
+
97
+ ## `zitadel apply`
98
+
99
+ Validate and upload repo config to the platform.
70
100
 
71
- - [`zitadel autocomplete [SHELL]`](#zitadel-autocomplete-shell)
72
- - [`zitadel commands`](#zitadel-commands)
73
- - [`zitadel doctor`](#zitadel-doctor)
74
- - [`zitadel eject`](#zitadel-eject)
75
- - [`zitadel help [COMMAND]`](#zitadel-help-command)
76
- - [`zitadel logs`](#zitadel-logs)
77
- - [`zitadel reset`](#zitadel-reset)
78
- - [`zitadel search`](#zitadel-search)
79
- - [`zitadel setup`](#zitadel-setup)
80
- - [`zitadel start`](#zitadel-start)
81
- - [`zitadel status`](#zitadel-status)
82
- - [`zitadel stop`](#zitadel-stop)
83
- - [`zitadel uninstall`](#zitadel-uninstall)
84
- - [`zitadel version`](#zitadel-version)
85
- - [`zitadel which`](#zitadel-which)
101
+ ```
102
+ USAGE
103
+ $ zitadel apply [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug] [-e
104
+ development|preview|production]
105
+
106
+ FLAGS
107
+ -c, --cwd=<value> Project directory to operate on.
108
+ -e, --environment=<option> Target environment (default: development).
109
+ <options: development|preview|production>
110
+ -f, --force Overwrite protected files on conflict.
111
+ -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
112
+ -s, --server=<value> Override the resolved server URL.
113
+ --debug Debug logging.
114
+ --dry-run Preview without mutating files or the platform.
115
+ --verbose Verbose logging.
116
+
117
+ GLOBAL FLAGS
118
+ --json Format output as json.
119
+
120
+ DESCRIPTION
121
+ Validate and upload repo config to the platform.
122
+ ```
86
123
 
87
124
  ## `zitadel autocomplete [SHELL]`
88
125
 
@@ -246,6 +283,33 @@ DESCRIPTION
246
283
  Show local Zitadel server logs.
247
284
  ```
248
285
 
286
+ ## `zitadel plan`
287
+
288
+ Validate config without mutation and preview the sync diff.
289
+
290
+ ```
291
+ USAGE
292
+ $ zitadel plan [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug] [-e
293
+ development|preview|production]
294
+
295
+ FLAGS
296
+ -c, --cwd=<value> Project directory to operate on.
297
+ -e, --environment=<option> Target environment (default: development).
298
+ <options: development|preview|production>
299
+ -f, --force Overwrite protected files on conflict.
300
+ -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
301
+ -s, --server=<value> Override the resolved server URL.
302
+ --debug Debug logging.
303
+ --dry-run Preview without mutating files or the platform.
304
+ --verbose Verbose logging.
305
+
306
+ GLOBAL FLAGS
307
+ --json Format output as json.
308
+
309
+ DESCRIPTION
310
+ Validate config without mutation and preview the sync diff.
311
+ ```
312
+
249
313
  ## `zitadel reset`
250
314
 
251
315
  Delete the local Zitadel server runtime and data.
@@ -293,7 +357,7 @@ Create a Zitadel project and scaffold local auth.
293
357
  ```
294
358
  USAGE
295
359
  $ zitadel setup [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
296
- [--framework next] [--renderer react|web-component] [--skip-install]
360
+ [--framework next|nuxt|react|vue|angular] [--renderer react|web-component] [--dev-port <value>] [--skip-install]
297
361
 
298
362
  FLAGS
299
363
  -c, --cwd=<value> Project directory to operate on.
@@ -301,9 +365,11 @@ FLAGS
301
365
  -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
302
366
  -s, --server=<value> Override the resolved server URL.
303
367
  --debug Debug logging.
368
+ --dev-port=<value> Dev-server port; also the issuer origin registered with Zitadel. Defaults to the detected
369
+ port. Use distinct ports to run several scaffolded apps side by side.
304
370
  --dry-run Preview without mutating files or the platform.
305
371
  --framework=<option> Framework to target.
306
- <options: next>
372
+ <options: next|nuxt|react|vue|angular>
307
373
  --renderer=<option> Renderer (default: react).
308
374
  <options: react|web-component>
309
375
  --skip-install Do not install dependencies after setup updates package.json.
@@ -317,6 +383,8 @@ DESCRIPTION
317
383
 
318
384
  EXAMPLES
319
385
  $ zitadel setup --framework next
386
+
387
+ $ zitadel setup --framework react --dev-port 3000
320
388
  ```
321
389
 
322
390
  ## `zitadel start`
@@ -474,7 +542,6 @@ EXAMPLES
474
542
  ```
475
543
 
476
544
  _See code: [@oclif/plugin-which](https://github.com/oclif/plugin-which/blob/3.2.55/src/commands/which.ts)_
477
-
478
545
  <!-- commandsstop -->
479
546
 
480
547
  </details>
package/SKILLS.md CHANGED
@@ -4,8 +4,8 @@ description: >-
4
4
  Set up and manage Zitadel authentication in a local project with the
5
5
  agent-friendly `zitadel` CLI. Use when the user wants to add login,
6
6
  registration, or session handling, create a Zitadel project, scaffold auth
7
- routes for a Next.js App Router app, or plan and apply Zitadel config changes
8
- from repo state.
7
+ for a Next.js, React, Vue, Angular, or Nuxt app, or plan and apply Zitadel
8
+ config changes from repo state.
9
9
  ---
10
10
 
11
11
  # Zitadel CLI
@@ -27,6 +27,10 @@ parse the result rather than scraping human output.
27
27
  npx @zitadel/cli@alpha <command> --non-interactive --json
28
28
  ```
29
29
 
30
+ During the public alpha, bare `npx @zitadel/cli` is promoted to the same tested
31
+ alpha CLI so discovery works for first-time users. Prefer `@alpha` or an exact
32
+ `0.1.0-alpha.N` selector in agent scripts and bug reports for reproducibility.
33
+
30
34
  ## Reading the envelope
31
35
 
32
36
  Each invocation prints one JSON object:
@@ -52,7 +56,12 @@ layer, not the envelope.
52
56
  and login flow are provisioned server-side at creation, so setup neither
53
57
  scaffolds nor uploads them. Agents must pass `--framework` when scaffolding
54
58
  into a fresh directory; interactive humans can omit it and choose from the
55
- prompt. Flags: `--framework`, `--renderer`.
59
+ prompt. Flags: `--framework next|react|vue|angular|nuxt`, `--renderer
60
+ react|web-component` (selects the Next.js auth-page renderer; accepted for any
61
+ framework and recorded in `zitadel.json` branding, but only Next varies its
62
+ generated templates by it), `--dev-port` (dev-server port, also the issuer
63
+ origin registered with Zitadel — use distinct ports to run several scaffolded
64
+ apps side by side), `--skip-install`.
56
65
  - `plan` — validate config and preview the sync diff without mutating anything.
57
66
  - `apply` — validate and upload repo config to the platform.
58
67
  - `doctor` — verify generated app files and local state once `zitadel.json`
@@ -95,6 +104,14 @@ npx @zitadel/cli@0.1.0-alpha.N start --non-interactive --json
95
104
  npx @zitadel/cli@0.1.0-alpha.N setup --framework next --server local --non-interactive --json
96
105
  ```
97
106
 
107
+ After `setup`, follow `data.next_commands` to start the app. Prove the generated
108
+ auth flow in a visible browser by registering a unique user, logging out, logging
109
+ back in with the same email/password, and ending on the signed-in profile page.
110
+ Do not treat a rendered login or registration form as completion. If browser DOM
111
+ snapshots are sparse, target the component hooks exposed by the generated UI:
112
+ `zitadel-field-email-input`, `zitadel-field-password-input`, and
113
+ `zitadel-action-submit-button`.
114
+
98
115
  Repo config is authoritative: edit `zitadel.json` or files under `.zitadel/`,
99
116
  then re-run `plan` and `apply`. Managed files carry a marker comment; `eject`
100
117
  removes only files that still carry it, preserving anything the user replaced.
@@ -1,6 +1,6 @@
1
- import { t as BaseCommand } from "../oclif-D-R4dfQr.mjs";
2
- import { o as readZitadelSecret } from "../project-DZJfxYKW.mjs";
3
- import { a as makeSyncers, i as runSyncLoop, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-BJ0Sqb8w.mjs";
1
+ import { t as BaseCommand } from "../oclif-2t97lHfY.mjs";
2
+ import { o as readZitadelSecret } from "../project-IzPVR0Pr.mjs";
3
+ import { a as makeSyncers, i as runSyncLoop, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-Df9S8Pio.mjs";
4
4
  import { Flags } from "@oclif/core";
5
5
  import { createZitadelClient } from "@zitadel/api/client";
6
6
  import { consola as consola$1 } from "consola";
@@ -16,7 +16,6 @@ import { consola as consola$1 } from "consola";
16
16
  */
17
17
  var Apply = class Apply extends BaseCommand {
18
18
  static description = "Validate and upload repo config to the platform.";
19
- static hidden = true;
20
19
  static flags = { environment: Flags.string({
21
20
  char: "e",
22
21
  description: "Target environment (default: development).",
@@ -1 +1 @@
1
- {"version":3,"file":"apply.mjs","names":[],"sources":["../../src/commands/apply.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient } from \"@zitadel/api/client\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { environmentSchema } from \"../lib/environment\";\nimport { buildSyncPlan, makeSyncers, renderPlan, runSyncLoop, summarizePlan } from \"../lib/sync\";\nimport { readZitadelSecret } from \"../lib/project\";\n\n/**\n * `zitadel apply` — validate and upload repo config to the platform.\n *\n * Runs the sync loop to convergence, or (with `--dry-run`) previews the diff\n * without mutating. All validation — structural shape and `${VAR}` / `*_env`\n * reference presence — happens inside the sync engine ({@link buildSyncPlan}),\n * so an invalid or under-configured file fails with `E_VALIDATION` before any\n * platform call.\n */\nexport default class Apply extends BaseCommand {\n static override description = \"Validate and upload repo config to the platform.\";\n // Temporarily hidden while we collapse the dev workflow around `setup`'s\n // auto-apply. The logic stays wired up so re-exposing this command is a\n // one-line flip when we settle on the surface area.\n static override hidden = true;\n static override flags = {\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Apply);\n await this.toMeta(flags);\n const { cwd, source, env, dryRun, isTTY } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n const syncers = makeSyncers({ client, projectId: secret.project_id, env });\n\n if (!dryRun) {\n consola.start(\"Syncing schemas and flows to Zitadel\");\n await runSyncLoop(cwd, syncers);\n consola.success(\"Sync complete\");\n return this.emit({ status: \"ok\", data: { synced: true } });\n }\n\n consola.start(\"Building plan (dry run)\");\n const plan = await buildSyncPlan(cwd, syncers, true);\n const summary = summarizePlan(plan);\n consola.success(\n `Plan: ${summary.creates} create${summary.creates === 1 ? \"\" : \"s\"}, ` +\n `${summary.updates} update${summary.updates === 1 ? \"\" : \"s\"}, ` +\n `${summary.deletes} delete${summary.deletes === 1 ? \"\" : \"s\"}`,\n );\n return this.emit({\n status: \"ok\",\n data: summary,\n pretty: renderPlan(plan, isTTY),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,IAAqB,QAArB,MAAqB,cAAc,YAAY;CAC7C,OAAgB,cAAc;CAI9B,OAAgB,SAAS;CACzB,OAAgB,QAAQ,EACtB,aAAa,MAAM,OAAO;EACxB,MAAM;EACN,aAAa;EACb,SAAS,CAAC,GAAG,kBAAkB,QAAQ;EACxC,CAAC,EACH;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,MAAM;AACzC,QAAM,KAAK,OAAO,MAAM;EACxB,MAAM,EAAE,KAAK,QAAQ,KAAK,QAAQ,UAAU,KAAK;EAEjD,MAAM,SAAS,MAAM,kBAAkB,IAAI;AAC3C,YAAQ,KAAK,aAAa,OAAO,aAAa;AAC9C,YAAQ,KAAK,aAAa,SAAS;EAKnC,MAAM,UAAU,YAAY;GAAE,QAJf,oBAAoB;IACjC,SAAS;IACT,OAAO,OAAO;IACf,CACmC;GAAE,WAAW,OAAO;GAAY;GAAK,CAAC;AAE1E,MAAI,CAAC,QAAQ;AACX,aAAQ,MAAM,uCAAuC;AACrD,SAAM,YAAY,KAAK,QAAQ;AAC/B,aAAQ,QAAQ,gBAAgB;AAChC,UAAO,KAAK,KAAK;IAAE,QAAQ;IAAM,MAAM,EAAE,QAAQ,MAAM;IAAE,CAAC;;AAG5D,YAAQ,MAAM,0BAA0B;EACxC,MAAM,OAAO,MAAM,cAAc,KAAK,SAAS,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK;AACnC,YAAQ,QACN,SAAS,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC9D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,MAC5D;AACD,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;GACN,QAAQ,WAAW,MAAM,MAAM;GAChC,CAAC"}
1
+ {"version":3,"file":"apply.mjs","names":[],"sources":["../../src/commands/apply.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient } from \"@zitadel/api/client\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { environmentSchema } from \"../lib/environment\";\nimport { buildSyncPlan, makeSyncers, renderPlan, runSyncLoop, summarizePlan } from \"../lib/sync\";\nimport { readZitadelSecret } from \"../lib/project\";\n\n/**\n * `zitadel apply` — validate and upload repo config to the platform.\n *\n * Runs the sync loop to convergence, or (with `--dry-run`) previews the diff\n * without mutating. All validation — structural shape and `${VAR}` / `*_env`\n * reference presence — happens inside the sync engine ({@link buildSyncPlan}),\n * so an invalid or under-configured file fails with `E_VALIDATION` before any\n * platform call.\n */\nexport default class Apply extends BaseCommand {\n static override description = \"Validate and upload repo config to the platform.\";\n static override flags = {\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Apply);\n await this.toMeta(flags);\n const { cwd, source, env, dryRun, isTTY } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n const syncers = makeSyncers({ client, projectId: secret.project_id, env });\n\n if (!dryRun) {\n consola.start(\"Syncing schemas and flows to Zitadel\");\n await runSyncLoop(cwd, syncers);\n consola.success(\"Sync complete\");\n return this.emit({ status: \"ok\", data: { synced: true } });\n }\n\n consola.start(\"Building plan (dry run)\");\n const plan = await buildSyncPlan(cwd, syncers, true);\n const summary = summarizePlan(plan);\n consola.success(\n `Plan: ${summary.creates} create${summary.creates === 1 ? \"\" : \"s\"}, ` +\n `${summary.updates} update${summary.updates === 1 ? \"\" : \"s\"}, ` +\n `${summary.deletes} delete${summary.deletes === 1 ? \"\" : \"s\"}`,\n );\n return this.emit({\n status: \"ok\",\n data: summary,\n pretty: renderPlan(plan, isTTY),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,IAAqB,QAArB,MAAqB,cAAc,YAAY;CAC7C,OAAgB,cAAc;CAC9B,OAAgB,QAAQ,EACtB,aAAa,MAAM,OAAO;EACxB,MAAM;EACN,aAAa;EACb,SAAS,CAAC,GAAG,kBAAkB,QAAQ;EACxC,CAAC,EACH;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,MAAM;AACzC,QAAM,KAAK,OAAO,MAAM;EACxB,MAAM,EAAE,KAAK,QAAQ,KAAK,QAAQ,UAAU,KAAK;EAEjD,MAAM,SAAS,MAAM,kBAAkB,IAAI;AAC3C,YAAQ,KAAK,aAAa,OAAO,aAAa;AAC9C,YAAQ,KAAK,aAAa,SAAS;EAKnC,MAAM,UAAU,YAAY;GAAE,QAJf,oBAAoB;IACjC,SAAS;IACT,OAAO,OAAO;IACf,CACmC;GAAE,WAAW,OAAO;GAAY;GAAK,CAAC;AAE1E,MAAI,CAAC,QAAQ;AACX,aAAQ,MAAM,uCAAuC;AACrD,SAAM,YAAY,KAAK,QAAQ;AAC/B,aAAQ,QAAQ,gBAAgB;AAChC,UAAO,KAAK,KAAK;IAAE,QAAQ;IAAM,MAAM,EAAE,QAAQ,MAAM;IAAE,CAAC;;AAG5D,YAAQ,MAAM,0BAA0B;EACxC,MAAM,OAAO,MAAM,cAAc,KAAK,SAAS,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK;AACnC,YAAQ,QACN,SAAS,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC9D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,MAC5D;AACD,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;GACN,QAAQ,WAAW,MAAM,MAAM;GAChC,CAAC"}
@@ -1,7 +1,7 @@
1
- import { C as isObject, E as ZitadelError, a as DEFAULT_LOCAL_SERVER_PORT, b as publicCliCommand, c as checkLocalServerHealth, f as isPortAvailable, h as readRuntimeMetadata, l as defaultLocalServerImageForCliVersion, m as localServerUrl, s as assertLocalStateWritable, t as BaseCommand } from "../oclif-D-R4dfQr.mjs";
2
- import { r as issuerFromPort, t as createOrca } from "../orca-BX4AhKLD.mjs";
3
- import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-DZJfxYKW.mjs";
4
- import { o as imageAvailable, r as dockerAvailable } from "../docker-D6pJKCLR.mjs";
1
+ import { D as ZitadelError, a as DEFAULT_LOCAL_SERVER_PORT, c as checkLocalServerHealth, f as isPortAvailable, h as readRuntimeMetadata, l as defaultLocalServerImageForCliVersion, m as localServerUrl, s as assertLocalStateWritable, t as BaseCommand, w as isObject, x as publicCliCommand } from "../oclif-2t97lHfY.mjs";
2
+ import { r as issuerFromPort, t as createOrca } from "../orca-CYqJP4ZJ.mjs";
3
+ import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-IzPVR0Pr.mjs";
4
+ import { o as imageAvailable, r as dockerAvailable } from "../docker--EAWr_WY.mjs";
5
5
  import { Flags } from "@oclif/core";
6
6
  import consola from "consola";
7
7
  import { join } from "node:path";
@@ -1,6 +1,6 @@
1
- import { E as ZitadelError, t as BaseCommand } from "../oclif-D-R4dfQr.mjs";
2
- import { t as createOrca } from "../orca-BX4AhKLD.mjs";
3
- import { a as readZitadelConfig, i as readRendererId } from "../project-DZJfxYKW.mjs";
1
+ import { D as ZitadelError, t as BaseCommand } from "../oclif-2t97lHfY.mjs";
2
+ import { t as createOrca } from "../orca-CYqJP4ZJ.mjs";
3
+ import { a as readZitadelConfig, i as readRendererId } from "../project-IzPVR0Pr.mjs";
4
4
  import { join } from "node:path";
5
5
  import { readFile, rename, rm, stat } from "node:fs/promises";
6
6
  //#region src/commands/eject.ts
@@ -16,7 +16,8 @@ async function resolveEjectActions(cwd) {
16
16
  rootConfigFiles: ["zitadel.json"],
17
17
  directories: [".zitadel"],
18
18
  envBackups: [".env.local"],
19
- dependencies: []
19
+ dependencies: [],
20
+ configEdits: []
20
21
  };
21
22
  const orca = createOrca();
22
23
  const framework = await orca.tryDetect(cwd);
@@ -114,7 +115,12 @@ var Eject = class Eject extends BaseCommand {
114
115
  });
115
116
  removed.push(rel);
116
117
  }
117
- if (removed.length === 0 && backedUp.length === 0) return this.emit({
118
+ const manualSteps = actions.configEdits.map((rel) => {
119
+ if (rel === "package.json" || rel.endsWith("/package.json")) return `Remove the "dev" script setup added to ${rel}`;
120
+ if (rel === "angular.json" || rel.endsWith("/angular.json")) return `Remove the Zitadel proxyConfig (and dev-server port) from the serve target in ${rel}`;
121
+ return `Remove the Zitadel configuration block from ${rel}`;
122
+ });
123
+ if (removed.length === 0 && backedUp.length === 0 && manualSteps.length === 0) return this.emit({
118
124
  status: "skipped",
119
125
  reason: "nothing-to-eject",
120
126
  data: { cwd }
@@ -127,7 +133,8 @@ var Eject = class Eject extends BaseCommand {
127
133
  files_removed: removed,
128
134
  files_preserved: preserved,
129
135
  backed_up: backedUp,
130
- next_commands: nextCommands
136
+ next_commands: nextCommands,
137
+ manual_steps: manualSteps
131
138
  }
132
139
  });
133
140
  }
@@ -1 +1 @@
1
- {"version":3,"file":"eject.mjs","names":[],"sources":["../../src/commands/eject.ts"],"sourcesContent":["import { readFile, rename, rm, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { ZitadelError } from \"../lib/errors\";\nimport { createOrca } from \"../lib/orca\";\nimport type { EjectActions } from \"../lib/orca/patchers/types\";\nimport { MANAGED_MARKER } from \"../lib/paths\";\nimport { readRendererId, readZitadelConfig } from \"../lib/project\";\n\n/**\n * Asks the framework patcher which artifacts it owns. Falls back to the\n * framework-agnostic set (`zitadel.json`, `.zitadel/`, `.env.local`) when the\n * framework or its patcher cannot be resolved, so an orphaned/partial project\n * can still be cleaned up.\n */\nasync function resolveEjectActions(cwd: string): Promise<EjectActions> {\n const fallback: EjectActions = {\n markedFiles: [],\n rootConfigFiles: [\"zitadel.json\"],\n directories: [\".zitadel\"],\n envBackups: [\".env.local\"],\n dependencies: [],\n };\n const orca = createOrca();\n const framework = await orca.tryDetect(cwd);\n if (!framework) {\n return fallback;\n }\n try {\n const config = await readZitadelConfig(cwd).catch(() => ({}) as Record<string, unknown>);\n return orca.patcherFor(framework.id).artifacts({\n framework,\n rendererId: readRendererId(config),\n });\n } catch {\n return fallback;\n }\n}\n\n/**\n * Builds the `next_commands` envelope field — manual follow-ups `eject` can't\n * safely run itself: deleting the `.env.local.ejected-*` backups it created\n * (only when some were made), and uninstalling the SDK packages the patcher\n * added (the CLI never modifies the user's `package.json` + lockfile +\n * `node_modules` directly; it just suggests the command).\n */\nfunction assembleNextCommands(\n backedUp: ReadonlyArray<unknown>,\n dependencies: ReadonlyArray<string>,\n): ReadonlyArray<string> {\n const commands: string[] = [];\n if (backedUp.length > 0) {\n commands.push(\"rm -f .env.local.ejected-*\");\n }\n for (const dep of dependencies) {\n commands.push(`npm uninstall ${dep}`);\n }\n return commands;\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * `zitadel eject` — remove managed files and local Zitadel state.\n *\n * Removes Zitadel-managed files from the project, leaving the remote project\n * untouched. The set of files comes from the framework patcher's\n * {@link import(\"../lib/orca/patchers/types\").Patcher.artifacts}, so the patcher\n * is the single source of truth for what its integration owns.\n *\n * Marked code files are removed only when they still carry the managed marker\n * (user-replaced files are preserved); `zitadel.json` is removed; `.env.local`\n * is renamed to a timestamped backup; and `.zitadel/` is removed wholesale.\n * `--dry-run` reports without touching the filesystem; non-interactive runs\n * require `--force`.\n */\nexport default class Eject extends BaseCommand {\n static override description = \"Remove managed files and local Zitadel state.\";\n static override aliases = [\"uninstall\"];\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Eject);\n await this.toMeta(flags);\n const { cwd, force, nonInteractive, dryRun } = this.meta;\n\n if (!force && nonInteractive) {\n throw new ZitadelError(\"E_VALIDATION\", \"Eject requires --force in non-interactive mode\", {\n hint: \"Re-run with --force to confirm deletion of managed files.\",\n });\n }\n\n const actions = await resolveEjectActions(cwd);\n const removed: string[] = [];\n const preserved: string[] = [];\n const backedUp: string[] = [];\n\n for (const rel of actions.markedFiles) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n const contents = await readFile(abs, \"utf8\").catch(() => \"\");\n if (!contents.includes(MANAGED_MARKER)) {\n preserved.push(rel);\n continue;\n }\n if (!dryRun) {\n await rm(abs, { force: true });\n }\n removed.push(rel);\n }\n\n for (const rel of actions.rootConfigFiles) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n if (!dryRun) {\n await rm(abs, { force: true });\n }\n removed.push(rel);\n }\n\n for (const rel of actions.envBackups) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n if (dryRun) {\n backedUp.push(`${rel} -> ${rel}.ejected-<timestamp>`);\n continue;\n }\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const backup = `${abs}.ejected-${stamp}`;\n await rename(abs, backup);\n backedUp.push(`${rel} -> ${backup.slice(cwd.length + 1)}`);\n }\n\n for (const rel of actions.directories) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n if (!dryRun) {\n await rm(abs, { recursive: true, force: true });\n }\n removed.push(rel);\n }\n\n if (removed.length === 0 && backedUp.length === 0) {\n return this.emit({ status: \"skipped\", reason: \"nothing-to-eject\", data: { cwd } });\n }\n\n const nextCommands = assembleNextCommands(backedUp, actions.dependencies);\n\n return this.emit({\n status: \"ok\",\n data: {\n title: \"Zitadel ejected. Remote project is untouched.\",\n files_removed: removed,\n files_preserved: preserved,\n backed_up: backedUp,\n next_commands: nextCommands,\n },\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"eject.mjs","names":[],"sources":["../../src/commands/eject.ts"],"sourcesContent":["import { readFile, rename, rm, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { ZitadelError } from \"../lib/errors\";\nimport { createOrca } from \"../lib/orca\";\nimport type { EjectActions } from \"../lib/orca/patchers/types\";\nimport { MANAGED_MARKER } from \"../lib/paths\";\nimport { readRendererId, readZitadelConfig } from \"../lib/project\";\n\n/**\n * Asks the framework patcher which artifacts it owns. Falls back to the\n * framework-agnostic set (`zitadel.json`, `.zitadel/`, `.env.local`) when the\n * framework or its patcher cannot be resolved, so an orphaned/partial project\n * can still be cleaned up.\n */\nasync function resolveEjectActions(cwd: string): Promise<EjectActions> {\n const fallback: EjectActions = {\n markedFiles: [],\n rootConfigFiles: [\"zitadel.json\"],\n directories: [\".zitadel\"],\n envBackups: [\".env.local\"],\n dependencies: [],\n configEdits: [],\n };\n const orca = createOrca();\n const framework = await orca.tryDetect(cwd);\n if (!framework) {\n return fallback;\n }\n try {\n const config = await readZitadelConfig(cwd).catch(() => ({}) as Record<string, unknown>);\n return orca.patcherFor(framework.id).artifacts({\n framework,\n rendererId: readRendererId(config),\n });\n } catch {\n return fallback;\n }\n}\n\n/**\n * Builds the `next_commands` envelope field — manual follow-ups `eject` can't\n * safely run itself: deleting the `.env.local.ejected-*` backups it created\n * (only when some were made), and uninstalling the SDK packages the patcher\n * added (the CLI never modifies the user's `package.json` + lockfile +\n * `node_modules` directly; it just suggests the command).\n */\nfunction assembleNextCommands(\n backedUp: ReadonlyArray<unknown>,\n dependencies: ReadonlyArray<string>,\n): ReadonlyArray<string> {\n const commands: string[] = [];\n if (backedUp.length > 0) {\n commands.push(\"rm -f .env.local.ejected-*\");\n }\n for (const dep of dependencies) {\n commands.push(`npm uninstall ${dep}`);\n }\n return commands;\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * `zitadel eject` — remove managed files and local Zitadel state.\n *\n * Removes Zitadel-managed files from the project, leaving the remote project\n * untouched. The set of files comes from the framework patcher's\n * {@link import(\"../lib/orca/patchers/types\").Patcher.artifacts}, so the patcher\n * is the single source of truth for what its integration owns.\n *\n * Marked code files are removed only when they still carry the managed marker\n * (user-replaced files are preserved); `zitadel.json` is removed; `.env.local`\n * is renamed to a timestamped backup; and `.zitadel/` is removed wholesale.\n * `--dry-run` reports without touching the filesystem; non-interactive runs\n * require `--force`.\n */\nexport default class Eject extends BaseCommand {\n static override description = \"Remove managed files and local Zitadel state.\";\n static override aliases = [\"uninstall\"];\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Eject);\n await this.toMeta(flags);\n const { cwd, force, nonInteractive, dryRun } = this.meta;\n\n if (!force && nonInteractive) {\n throw new ZitadelError(\"E_VALIDATION\", \"Eject requires --force in non-interactive mode\", {\n hint: \"Re-run with --force to confirm deletion of managed files.\",\n });\n }\n\n const actions = await resolveEjectActions(cwd);\n const removed: string[] = [];\n const preserved: string[] = [];\n const backedUp: string[] = [];\n\n for (const rel of actions.markedFiles) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n const contents = await readFile(abs, \"utf8\").catch(() => \"\");\n if (!contents.includes(MANAGED_MARKER)) {\n preserved.push(rel);\n continue;\n }\n if (!dryRun) {\n await rm(abs, { force: true });\n }\n removed.push(rel);\n }\n\n for (const rel of actions.rootConfigFiles) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n if (!dryRun) {\n await rm(abs, { force: true });\n }\n removed.push(rel);\n }\n\n for (const rel of actions.envBackups) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n if (dryRun) {\n backedUp.push(`${rel} -> ${rel}.ejected-<timestamp>`);\n continue;\n }\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const backup = `${abs}.ejected-${stamp}`;\n await rename(abs, backup);\n backedUp.push(`${rel} -> ${backup.slice(cwd.length + 1)}`);\n }\n\n for (const rel of actions.directories) {\n const abs = join(cwd, rel);\n if (!(await pathExists(abs))) {\n continue;\n }\n if (!dryRun) {\n await rm(abs, { recursive: true, force: true });\n }\n removed.push(rel);\n }\n\n // In-place config merges (vite.config.ts / angular.json / nuxt.config.ts)\n // can't be auto-reverted, so surface them as manual cleanup steps. The\n // Angular patcher also edits package.json (a `dev` script, not a config\n // block), so word that one accurately.\n const manualSteps = actions.configEdits.map((rel) => {\n if (rel === \"package.json\" || rel.endsWith(\"/package.json\")) {\n return `Remove the \"dev\" script setup added to ${rel}`;\n }\n if (rel === \"angular.json\" || rel.endsWith(\"/angular.json\")) {\n return `Remove the Zitadel proxyConfig (and dev-server port) from the serve target in ${rel}`;\n }\n return `Remove the Zitadel configuration block from ${rel}`;\n });\n\n if (removed.length === 0 && backedUp.length === 0 && manualSteps.length === 0) {\n return this.emit({ status: \"skipped\", reason: \"nothing-to-eject\", data: { cwd } });\n }\n\n const nextCommands = assembleNextCommands(backedUp, actions.dependencies);\n\n return this.emit({\n status: \"ok\",\n data: {\n title: \"Zitadel ejected. Remote project is untouched.\",\n files_removed: removed,\n files_preserved: preserved,\n backed_up: backedUp,\n next_commands: nextCommands,\n manual_steps: manualSteps,\n },\n });\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { E as ZitadelError, S as resolveCwd, b as publicCliCommand, h as readRuntimeMetadata, t as BaseCommand } from "../oclif-D-R4dfQr.mjs";
2
- import { a as followContainerLogs, t as containerLogs } from "../docker-D6pJKCLR.mjs";
1
+ import { C as resolveCwd, D as ZitadelError, h as readRuntimeMetadata, t as BaseCommand, x as publicCliCommand } from "../oclif-2t97lHfY.mjs";
2
+ import { a as followContainerLogs, t as containerLogs } from "../docker--EAWr_WY.mjs";
3
3
  import { Flags } from "@oclif/core";
4
4
  //#region src/commands/logs.ts
5
5
  var Logs = class Logs extends BaseCommand {
@@ -1,6 +1,6 @@
1
- import { t as BaseCommand } from "../oclif-D-R4dfQr.mjs";
2
- import { o as readZitadelSecret } from "../project-DZJfxYKW.mjs";
3
- import { a as makeSyncers, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-BJ0Sqb8w.mjs";
1
+ import { t as BaseCommand } from "../oclif-2t97lHfY.mjs";
2
+ import { o as readZitadelSecret } from "../project-IzPVR0Pr.mjs";
3
+ import { a as makeSyncers, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-Df9S8Pio.mjs";
4
4
  import { Flags } from "@oclif/core";
5
5
  import { createZitadelClient } from "@zitadel/api/client";
6
6
  import { consola as consola$1 } from "consola";
@@ -15,7 +15,6 @@ import { consola as consola$1 } from "consola";
15
15
  */
16
16
  var Plan = class Plan extends BaseCommand {
17
17
  static description = "Validate config without mutation and preview the sync diff.";
18
- static hidden = true;
19
18
  static flags = { environment: Flags.string({
20
19
  char: "e",
21
20
  description: "Target environment (default: development).",
@@ -1 +1 @@
1
- {"version":3,"file":"plan.mjs","names":[],"sources":["../../src/commands/plan.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient } from \"@zitadel/api/client\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { environmentSchema } from \"../lib/environment\";\nimport { buildSyncPlan, makeSyncers, renderPlan, summarizePlan } from \"../lib/sync\";\nimport { readZitadelSecret } from \"../lib/project\";\n\n/**\n * `zitadel plan` — validate config and preview the sync diff without mutating.\n *\n * The read-only counterpart of `apply`: it builds and renders the diff instead\n * of running the sync loop. All validation (structural shape and env-ref\n * presence) happens in the sync engine, so an invalid file fails the same way\n * `apply` would.\n */\nexport default class Plan extends BaseCommand {\n static override description = \"Validate config without mutation and preview the sync diff.\";\n // Temporarily hidden while we collapse the dev workflow around `setup`'s\n // auto-apply. The logic stays wired up so re-exposing this command is a\n // one-line flip when we settle on the surface area.\n static override hidden = true;\n static override flags = {\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Plan);\n await this.toMeta(flags);\n const { cwd, source, env, isTTY } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n const syncers = makeSyncers({ client, projectId: secret.project_id, env });\n\n consola.start(\"Building plan\");\n const plan = await buildSyncPlan(cwd, syncers, true);\n const summary = summarizePlan(plan);\n consola.success(\n `Plan: ${summary.creates} create${summary.creates === 1 ? \"\" : \"s\"}, ` +\n `${summary.updates} update${summary.updates === 1 ? \"\" : \"s\"}, ` +\n `${summary.deletes} delete${summary.deletes === 1 ? \"\" : \"s\"}, ` +\n `${summary.total - summary.creates - summary.updates - summary.deletes} unchanged`,\n );\n return this.emit({\n status: \"ok\",\n data: summary,\n pretty: renderPlan(plan, isTTY),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,IAAqB,OAArB,MAAqB,aAAa,YAAY;CAC5C,OAAgB,cAAc;CAI9B,OAAgB,SAAS;CACzB,OAAgB,QAAQ,EACtB,aAAa,MAAM,OAAO;EACxB,MAAM;EACN,aAAa;EACb,SAAS,CAAC,GAAG,kBAAkB,QAAQ;EACxC,CAAC,EACH;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,KAAK;AACxC,QAAM,KAAK,OAAO,MAAM;EACxB,MAAM,EAAE,KAAK,QAAQ,KAAK,UAAU,KAAK;EAEzC,MAAM,SAAS,MAAM,kBAAkB,IAAI;AAC3C,YAAQ,KAAK,aAAa,OAAO,aAAa;AAC9C,YAAQ,KAAK,aAAa,SAAS;EAKnC,MAAM,UAAU,YAAY;GAAE,QAJf,oBAAoB;IACjC,SAAS;IACT,OAAO,OAAO;IACf,CACmC;GAAE,WAAW,OAAO;GAAY;GAAK,CAAC;AAE1E,YAAQ,MAAM,gBAAgB;EAC9B,MAAM,OAAO,MAAM,cAAc,KAAK,SAAS,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK;AACnC,YAAQ,QACN,SAAS,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC9D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,QAAQ,QAAQ,UAAU,QAAQ,UAAU,QAAQ,QAAQ,YAC1E;AACD,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;GACN,QAAQ,WAAW,MAAM,MAAM;GAChC,CAAC"}
1
+ {"version":3,"file":"plan.mjs","names":[],"sources":["../../src/commands/plan.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient } from \"@zitadel/api/client\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { environmentSchema } from \"../lib/environment\";\nimport { buildSyncPlan, makeSyncers, renderPlan, summarizePlan } from \"../lib/sync\";\nimport { readZitadelSecret } from \"../lib/project\";\n\n/**\n * `zitadel plan` — validate config and preview the sync diff without mutating.\n *\n * The read-only counterpart of `apply`: it builds and renders the diff instead\n * of running the sync loop. All validation (structural shape and env-ref\n * presence) happens in the sync engine, so an invalid file fails the same way\n * `apply` would.\n */\nexport default class Plan extends BaseCommand {\n static override description = \"Validate config without mutation and preview the sync diff.\";\n static override flags = {\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Plan);\n await this.toMeta(flags);\n const { cwd, source, env, isTTY } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n const syncers = makeSyncers({ client, projectId: secret.project_id, env });\n\n consola.start(\"Building plan\");\n const plan = await buildSyncPlan(cwd, syncers, true);\n const summary = summarizePlan(plan);\n consola.success(\n `Plan: ${summary.creates} create${summary.creates === 1 ? \"\" : \"s\"}, ` +\n `${summary.updates} update${summary.updates === 1 ? \"\" : \"s\"}, ` +\n `${summary.deletes} delete${summary.deletes === 1 ? \"\" : \"s\"}, ` +\n `${summary.total - summary.creates - summary.updates - summary.deletes} unchanged`,\n );\n return this.emit({\n status: \"ok\",\n data: summary,\n pretty: renderPlan(plan, isTTY),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,IAAqB,OAArB,MAAqB,aAAa,YAAY;CAC5C,OAAgB,cAAc;CAC9B,OAAgB,QAAQ,EACtB,aAAa,MAAM,OAAO;EACxB,MAAM;EACN,aAAa;EACb,SAAS,CAAC,GAAG,kBAAkB,QAAQ;EACxC,CAAC,EACH;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,KAAK;AACxC,QAAM,KAAK,OAAO,MAAM;EACxB,MAAM,EAAE,KAAK,QAAQ,KAAK,UAAU,KAAK;EAEzC,MAAM,SAAS,MAAM,kBAAkB,IAAI;AAC3C,YAAQ,KAAK,aAAa,OAAO,aAAa;AAC9C,YAAQ,KAAK,aAAa,SAAS;EAKnC,MAAM,UAAU,YAAY;GAAE,QAJf,oBAAoB;IACjC,SAAS;IACT,OAAO,OAAO;IACf,CACmC;GAAE,WAAW,OAAO;GAAY;GAAK,CAAC;AAE1E,YAAQ,MAAM,gBAAgB;EAC9B,MAAM,OAAO,MAAM,cAAc,KAAK,SAAS,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK;AACnC,YAAQ,QACN,SAAS,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC9D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,QAAQ,QAAQ,UAAU,QAAQ,UAAU,QAAQ,QAAQ,YAC1E;AACD,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;GACN,QAAQ,WAAW,MAAM,MAAM;GAChC,CAAC"}
@@ -1,5 +1,5 @@
1
- import { E as ZitadelError, S as resolveCwd, _ as removeRuntimeMetadata, b as publicCliCommand, g as removeLocalData, h as readRuntimeMetadata, p as localContainerName, t as BaseCommand } from "../oclif-D-R4dfQr.mjs";
2
- import { u as stopAndRemoveContainer } from "../docker-D6pJKCLR.mjs";
1
+ import { C as resolveCwd, D as ZitadelError, _ as removeRuntimeMetadata, g as removeLocalData, h as readRuntimeMetadata, p as localContainerName, t as BaseCommand, x as publicCliCommand } from "../oclif-2t97lHfY.mjs";
2
+ import { u as stopAndRemoveContainer } from "../docker--EAWr_WY.mjs";
3
3
  import { cancel, confirm, isCancel } from "@clack/prompts";
4
4
  //#region src/commands/reset.ts
5
5
  var Reset = class Reset extends BaseCommand {
@@ -1,6 +1,6 @@
1
- import { E as ZitadelError, n as DEFAULT_SERVER, t as BaseCommand } from "../oclif-D-R4dfQr.mjs";
2
- import { n as RENDERER_IDS, r as issuerFromPort, t as createOrca } from "../orca-BX4AhKLD.mjs";
3
- import { n as hasZitadelSecret, t as hasZitadelConfig } from "../project-DZJfxYKW.mjs";
1
+ import { D as ZitadelError, O as toZitadelError, n as DEFAULT_SERVER, t as BaseCommand, x as publicCliCommand } from "../oclif-2t97lHfY.mjs";
2
+ import { n as RENDERER_IDS, r as issuerFromPort, t as createOrca } from "../orca-CYqJP4ZJ.mjs";
3
+ import { n as hasZitadelSecret, t as hasZitadelConfig } from "../project-IzPVR0Pr.mjs";
4
4
  import { cancel, confirm, intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
5
5
  import { Flags } from "@oclif/core";
6
6
  import { createZitadelClient } from "@zitadel/api/client";
@@ -141,11 +141,16 @@ async function installDependenciesForSetup(input) {
141
141
  });
142
142
  }
143
143
  function outcome(input) {
144
- const startAction = `Start your project: ${input.devCommand} (then open ${input.issuer}/login)`;
144
+ const startAction = `Start your project: ${input.devCommand} (then open ${input.issuer})`;
145
+ const verifyAction = "Verify auth in the browser: register a user, log out, log in again with the same user, and confirm /profile shows Signed in.";
145
146
  return {
146
147
  install: input.install,
147
148
  devCommand: input.devCommand,
148
- nextActions: input.includeInstallCommand ? [`Install dependencies: ${input.install.command}`, startAction] : [startAction],
149
+ nextActions: input.includeInstallCommand ? [
150
+ `Install dependencies: ${input.install.command}`,
151
+ startAction,
152
+ verifyAction
153
+ ] : [startAction, verifyAction],
149
154
  nextCommands: input.includeInstallCommand ? [input.install.command, input.devCommand] : [input.devCommand]
150
155
  };
151
156
  }
@@ -188,7 +193,8 @@ function bail(value) {
188
193
  * becomes the issuer URL (`http://localhost:<port>`) via `issuerFromPort`.
189
194
  */
190
195
  var DevPortPrompt = class {
191
- async ask(answers, _ctx) {
196
+ async ask(answers, ctx) {
197
+ if (ctx.devPortFromFlag) return answers;
192
198
  const value = await text({
193
199
  message: "Dev server port",
194
200
  placeholder: String(answers.devPort),
@@ -587,7 +593,7 @@ const FRAMEWORK_OPTIONS = createOrca().availableFrameworks().map((framework) =>
587
593
  */
588
594
  var Setup = class Setup extends BaseCommand {
589
595
  static description = "Create a Zitadel project and scaffold local auth.";
590
- static examples = ["<%= config.bin %> setup --framework next"];
596
+ static examples = ["<%= config.bin %> setup --framework next", "<%= config.bin %> setup --framework react --dev-port 3000"];
591
597
  static flags = {
592
598
  framework: Flags.string({
593
599
  description: "Framework to target.",
@@ -597,11 +603,16 @@ var Setup = class Setup extends BaseCommand {
597
603
  description: "Renderer (default: react).",
598
604
  options: [...RENDERER_IDS]
599
605
  }),
606
+ "dev-port": Flags.integer({ description: "Dev-server port; also the issuer origin registered with Zitadel. Defaults to the detected port. Use distinct ports to run several scaffolded apps side by side." }),
600
607
  "skip-install": Flags.boolean({ description: "Do not install dependencies after setup updates package.json." })
601
608
  };
602
609
  async run() {
603
610
  const { flags } = await this.parse(Setup);
604
- await this.toMeta(flags);
611
+ try {
612
+ await this.toMeta(flags);
613
+ } catch (error) {
614
+ throw localSetupHint(error, flags.framework, this.config.version);
615
+ }
605
616
  const { cwd, nonInteractive, dryRun, force } = this.meta;
606
617
  if (await hasZitadelConfig(cwd)) return this.emit({
607
618
  status: "skipped",
@@ -623,6 +634,15 @@ var Setup = class Setup extends BaseCommand {
623
634
  consola$1.success(`Scaffolded ${framework.id} skeleton`);
624
635
  } else throw error;
625
636
  }
637
+ if (flags["dev-port"] !== void 0) {
638
+ const devPort = flags["dev-port"];
639
+ if (!Number.isInteger(devPort) || devPort < 1 || devPort > 65535) throw new ZitadelError("E_VALIDATION", `--dev-port must be an integer in 1..65535, got ${devPort}`);
640
+ framework = {
641
+ ...framework,
642
+ devPort,
643
+ url: issuerFromPort(devPort)
644
+ };
645
+ }
626
646
  let answers = {
627
647
  server: this.meta.source,
628
648
  devPort: framework.devPort
@@ -631,15 +651,21 @@ var Setup = class Setup extends BaseCommand {
631
651
  intro("Zitadel setup");
632
652
  const promptCtx = {
633
653
  framework,
634
- serverFlag: this.meta.serverFlag
654
+ serverFlag: this.meta.serverFlag,
655
+ devPortFromFlag: flags["dev-port"] !== void 0
635
656
  };
636
657
  for (const prompt of SETUP_PROMPTS) answers = await prompt.ask(answers, promptCtx);
637
658
  outro("Configuration captured");
638
659
  }
639
660
  const issuer = issuerFromPort(answers.devPort);
661
+ framework = {
662
+ ...framework,
663
+ devPort: answers.devPort,
664
+ url: issuer
665
+ };
640
666
  consola$1.start(`Creating project on ${answers.server}${dryRun ? " (dry run)" : ""}`);
641
667
  const unauthClient = createZitadelClient({ baseUrl: answers.server });
642
- const project = dryRun ? dryRunProject() : await unauthClient.createProject({ previewOrigins: [] });
668
+ const project = dryRun ? dryRunProject(issuer) : await createProjectWithLocalHint(unauthClient, answers.server, this.meta.cliVersion, issuer, framework.id);
643
669
  consola$1.success(`Created project ${project.id}`);
644
670
  const ctx = {
645
671
  framework,
@@ -647,7 +673,8 @@ var Setup = class Setup extends BaseCommand {
647
673
  project,
648
674
  issuer,
649
675
  server: answers.server,
650
- cliVersion: this.meta.cliVersion
676
+ cliVersion: this.meta.cliVersion,
677
+ scaffoldedFramework
651
678
  };
652
679
  consola$1.start(`Patching project files${dryRun ? " (dry run)" : ""}`);
653
680
  const result = await orca.patcherFor(framework.id).patch(ctx, {
@@ -726,15 +753,40 @@ async function resolveScaffoldFramework(framework, nonInteractive, orca) {
726
753
  return new PickFrameworkPrompt().ask(orca.availableFrameworks());
727
754
  }
728
755
  /** A deterministic stand-in project for `--dry-run`, so no remote call is made. */
729
- function dryRunProject() {
756
+ function dryRunProject(issuer) {
730
757
  return {
731
758
  id: "dry-run-0000",
732
759
  projectSecret: "sk_proj_dry_run_full",
733
760
  previewSecret: "sk_proj_dry_run_preview",
734
- previewOrigins: [],
761
+ previewOrigins: [issuer],
735
762
  createdAt: "2026-04-21T14:03:11.000Z"
736
763
  };
737
764
  }
765
+ async function createProjectWithLocalHint(client, server, cliVersion, issuer, framework) {
766
+ try {
767
+ return await client.createProject({ previewOrigins: [issuer] });
768
+ } catch (error) {
769
+ const normalized = toZitadelError(error);
770
+ throw new ZitadelError(normalized.code, normalized.message, {
771
+ hint: `${normalized.hint ? `${normalized.hint} ` : ""}If you meant to use a local Zitadel server, start it first and retry setup with --framework ${framework} --server local.`,
772
+ nextCommands: [publicCliCommand("start", cliVersion), publicCliCommand(`setup --framework ${framework} --server local`, cliVersion)],
773
+ details: {
774
+ server,
775
+ original: normalized.details
776
+ }
777
+ });
778
+ }
779
+ }
780
+ function localSetupHint(error, framework, cliVersion) {
781
+ const normalized = toZitadelError(error);
782
+ if (normalized.code !== "E_LOCAL_SERVER_NOT_RUNNING") return error;
783
+ const setupCommand = framework ? `setup --framework ${framework} --server local` : "setup --server local";
784
+ return new ZitadelError(normalized.code, normalized.message, {
785
+ hint: `${normalized.hint ? `${normalized.hint} ` : ""}Start local Zitadel first, then rerun setup. After setup succeeds, follow its next_commands to start the app and verify registration, logout, and login in the browser.`,
786
+ nextCommands: [publicCliCommand("start", cliVersion), publicCliCommand(setupCommand, cliVersion)],
787
+ details: normalized.details
788
+ });
789
+ }
738
790
  /** Renders an absolute path relative to `cwd` for human-readable output. */
739
791
  function relativeDisplay(cwd, path) {
740
792
  return path.startsWith(cwd) ? path.slice(cwd.length + 1) : path;
@@ -786,10 +838,12 @@ const SENTENCE_BY_PATH = {
786
838
  ".env.example": { subject: "the .env example template" },
787
839
  ".env.local": { subject: "the local development environment variables" },
788
840
  ".zitadel/state.json": { subject: "the empty sync state file" },
841
+ "app/page.tsx": { subject: "the auth home page" },
789
842
  "app/login/page.tsx": { subject: "the login page" },
790
843
  "app/register/page.tsx": { subject: "the registration page" },
791
844
  "app/profile/page.tsx": { subject: "the profile page" },
792
845
  "middleware.ts": { subject: "the Next.js middleware" },
846
+ "proxy.ts": { subject: "the Next.js proxy" },
793
847
  "custom-elements.d.ts": { subject: "the web-component type declarations" },
794
848
  "package.json": { subject: "package.json with the SDK dependency" }
795
849
  };
@@ -813,9 +867,11 @@ function buildSummary(opts) {
813
867
  secondary: path(fileNameOf(packageJsonHit))
814
868
  });
815
869
  for (const [label, suffix] of [
870
+ ["Home page", "app/page.tsx"],
816
871
  ["Login page", "app/login/page.tsx"],
817
872
  ["Register page", "app/register/page.tsx"],
818
873
  ["Profile page", "app/profile/page.tsx"],
874
+ ["Request proxy", "proxy.ts"],
819
875
  ["Middleware", "middleware.ts"],
820
876
  ["Env vars", ".env.local"]
821
877
  ]) {