@zitadel/cli 0.1.0-alpha.0 → 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 (35) hide show
  1. package/README.md +158 -24
  2. package/SKILLS.md +40 -8
  3. package/dist/commands/apply.mjs +4 -3
  4. package/dist/commands/apply.mjs.map +1 -1
  5. package/dist/commands/doctor.mjs +150 -16
  6. package/dist/commands/doctor.mjs.map +1 -1
  7. package/dist/commands/eject.mjs +4 -3
  8. package/dist/commands/eject.mjs.map +1 -1
  9. package/dist/commands/logs.mjs +50 -0
  10. package/dist/commands/logs.mjs.map +1 -0
  11. package/dist/commands/plan.mjs +4 -3
  12. package/dist/commands/plan.mjs.map +1 -1
  13. package/dist/commands/reset.mjs +62 -0
  14. package/dist/commands/reset.mjs.map +1 -0
  15. package/dist/commands/setup.mjs +189 -23
  16. package/dist/commands/setup.mjs.map +1 -1
  17. package/dist/commands/start.mjs +128 -0
  18. package/dist/commands/start.mjs.map +1 -0
  19. package/dist/commands/status.mjs +74 -27
  20. package/dist/commands/status.mjs.map +1 -1
  21. package/dist/commands/stop.mjs +43 -0
  22. package/dist/commands/stop.mjs.map +1 -0
  23. package/dist/docker-DrOBycgG.mjs +210 -0
  24. package/dist/docker-DrOBycgG.mjs.map +1 -0
  25. package/dist/{project-C3pSfbao.mjs → oclif-CqkWBQ7i.mjs} +300 -119
  26. package/dist/oclif-CqkWBQ7i.mjs.map +1 -0
  27. package/dist/{orca-COsUnVoz.mjs → orca-S1tVnngd.mjs} +41 -12
  28. package/dist/{orca-COsUnVoz.mjs.map → orca-S1tVnngd.mjs.map} +1 -1
  29. package/dist/project-B6YfSaZw.mjs +87 -0
  30. package/dist/project-B6YfSaZw.mjs.map +1 -0
  31. package/dist/{sync-Cuyh-X1J.mjs → sync-DN4oNLVH.mjs} +4 -4
  32. package/dist/{sync-Cuyh-X1J.mjs.map → sync-DN4oNLVH.mjs.map} +1 -1
  33. package/oclif.manifest.json +357 -3
  34. package/package.json +3 -3
  35. package/dist/project-C3pSfbao.mjs.map +0 -1
@@ -1,9 +1,12 @@
1
1
  import { Command, Flags } from "@oclif/core";
2
2
  import consola from "consola";
3
- import { readFile, stat } from "node:fs/promises";
4
- import { join, resolve } from "node:path";
5
3
  import { ApiError } from "@zitadel/api/runtime/fetch";
6
4
  import { stringify } from "safe-stable-stringify";
5
+ import { join, resolve } from "node:path";
6
+ import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
7
+ import { createHash } from "node:crypto";
8
+ import { constants } from "node:fs";
9
+ import { createServer } from "node:net";
7
10
  //#region src/lib/errors.ts
8
11
  /**
9
12
  * Maps each {@link ZitadelErrorCode} to the process exit code the CLI
@@ -17,6 +20,7 @@ const EXIT_CODES = {
17
20
  E_NETWORK: 4,
18
21
  E_AUTH: 1,
19
22
  E_CONFLICT: 5,
23
+ E_LOCAL_SERVER_NOT_RUNNING: 4,
20
24
  E_VALIDATION: 3,
21
25
  E_NOT_IMPLEMENTED: 2
22
26
  };
@@ -144,6 +148,248 @@ function isObject(value) {
144
148
  return typeof value === "object" && value !== null && !Array.isArray(value);
145
149
  }
146
150
  //#endregion
151
+ //#region src/lib/paths.ts
152
+ /**
153
+ * Resolve the working directory the CLI should operate against, defaulting to
154
+ * the process CWD when no `--cwd` override is given. Always returns an
155
+ * absolute path so downstream `join`/`readFile` calls are unaffected by later
156
+ * `process.chdir` or relative-path ambiguity.
157
+ */
158
+ function resolveCwd(cwd) {
159
+ return resolve(cwd ?? process.cwd());
160
+ }
161
+ /**
162
+ * Sentinel comment stamped at the top of every file the CLI generates and
163
+ * owns. Commands like `doctor` and `eject` look for this marker to decide
164
+ * whether a file is safe to touch; the trailing `v1` lets the format evolve
165
+ * without mistaking newer managed files for hand-edited ones.
166
+ */
167
+ const MANAGED_MARKER = "// zitadel-cli: managed-file v1";
168
+ //#endregion
169
+ //#region src/lib/public-cli.ts
170
+ const CLI_PACKAGE_NAME = "@zitadel/cli";
171
+ function npmDistTagForCliVersion(cliVersion) {
172
+ return cliVersion.trim().replace(/^v/, "").match(/^\d+\.\d+\.\d+-([0-9A-Za-z][0-9A-Za-z-]*)/)?.[1] ?? "latest";
173
+ }
174
+ function npmSelectorForCliVersion(cliVersion) {
175
+ const normalized = cliVersion.trim().replace(/^v/, "");
176
+ if (/^\d+\.\d+\.\d+-alpha\.\d+$/.test(normalized)) return normalized;
177
+ return npmDistTagForCliVersion(normalized);
178
+ }
179
+ function publicCliCommand(args, cliVersion) {
180
+ const prefix = `npx ${CLI_PACKAGE_NAME}@${npmSelectorForCliVersion(cliVersion)}`;
181
+ return args.length > 0 ? `${prefix} ${args}` : prefix;
182
+ }
183
+ function normalizePublicCliCommand(command, cliVersion) {
184
+ if (command === "zitadel") return publicCliCommand("", cliVersion);
185
+ if (command.startsWith("zitadel ")) return publicCliCommand(command.slice(8), cliVersion);
186
+ return command;
187
+ }
188
+ function normalizePublicCliCommands(commands, cliVersion) {
189
+ return commands?.map((command) => normalizePublicCliCommand(command, cliVersion));
190
+ }
191
+ //#endregion
192
+ //#region src/lib/local-server/runtime.ts
193
+ const LOCAL_SERVER_IMAGE_NAME = "ghcr.io/zitadel/nextgen";
194
+ const DEFAULT_LOCAL_SERVER_IMAGE = `${LOCAL_SERVER_IMAGE_NAME}:latest`;
195
+ const DEFAULT_LOCAL_SERVER_PORT = 8080;
196
+ const DEFAULT_LOCAL_SERVER_URL = "http://localhost:8080";
197
+ const LOCAL_RUNTIME_DIR = ".zitadel/local";
198
+ const LOCAL_DATA_DIR = ".zitadel/local/nextgen-data";
199
+ const LOCAL_RUNTIME_FILE = ".zitadel/local/runtime.json";
200
+ const LOCAL_CONTAINER_PASSWD_FILE = ".zitadel/local/container-passwd";
201
+ const LOCAL_CONTAINER_GROUP_FILE = ".zitadel/local/container-group";
202
+ const CONTAINER_DATA_DIR = "/var/lib/zitadel/nextgen-data";
203
+ const CONTAINER_HTTP_PORT = 8080;
204
+ function localRuntimePaths(cwd) {
205
+ return {
206
+ runtimeDir: join(cwd, LOCAL_RUNTIME_DIR),
207
+ dataDir: join(cwd, LOCAL_DATA_DIR),
208
+ runtimeFile: join(cwd, LOCAL_RUNTIME_FILE),
209
+ containerPasswdFile: join(cwd, LOCAL_CONTAINER_PASSWD_FILE),
210
+ containerGroupFile: join(cwd, LOCAL_CONTAINER_GROUP_FILE)
211
+ };
212
+ }
213
+ function localContainerName(cwd) {
214
+ return `zitadel-server-${createHash("sha256").update(resolve(cwd)).digest("hex").slice(0, 12)}`;
215
+ }
216
+ function localServerUrl(port) {
217
+ return `http://localhost:${port}`;
218
+ }
219
+ function defaultLocalServerImageForCliVersion(cliVersion) {
220
+ const normalized = cliVersion.trim().replace(/^v/, "");
221
+ if (/^\d+\.\d+\.\d+-alpha\.\d+$/.test(normalized)) return `${LOCAL_SERVER_IMAGE_NAME}:${normalized}`;
222
+ return DEFAULT_LOCAL_SERVER_IMAGE;
223
+ }
224
+ async function ensureLocalState(cwd) {
225
+ const paths = localRuntimePaths(cwd);
226
+ await mkdir(paths.dataDir, {
227
+ recursive: true,
228
+ mode: 448
229
+ });
230
+ await appendGitignoreEntry(cwd, `${LOCAL_RUNTIME_DIR}/`);
231
+ return paths;
232
+ }
233
+ async function ensureContainerIdentity(cwd, user) {
234
+ if (user.uid === void 0 || user.uid <= 0) return;
235
+ const gid = user.gid ?? user.uid;
236
+ const paths = localRuntimePaths(cwd);
237
+ await mkdir(paths.runtimeDir, {
238
+ recursive: true,
239
+ mode: 448
240
+ });
241
+ await writeFile(paths.containerPasswdFile, [
242
+ "root:x:0:0:root:/root:/bin/sh",
243
+ "nonroot:x:65532:65532:nonroot:/nonexistent:/usr/sbin/nologin",
244
+ `zitadel-local:x:${String(user.uid)}:${String(gid)}:Zitadel local user:/tmp:/usr/sbin/nologin`,
245
+ ""
246
+ ].join("\n"), { mode: 420 });
247
+ await writeFile(paths.containerGroupFile, [
248
+ "root:x:0:",
249
+ "nonroot:x:65532:",
250
+ `zitadel-local:x:${String(gid)}:`,
251
+ ""
252
+ ].join("\n"), { mode: 420 });
253
+ return {
254
+ uid: user.uid,
255
+ gid,
256
+ passwdFile: paths.containerPasswdFile,
257
+ groupFile: paths.containerGroupFile
258
+ };
259
+ }
260
+ async function readRuntimeMetadata(cwd) {
261
+ const paths = localRuntimePaths(cwd);
262
+ let raw;
263
+ try {
264
+ raw = await readFile(paths.runtimeFile, "utf8");
265
+ } catch (error) {
266
+ if (isErrno(error, "ENOENT")) return;
267
+ throw error;
268
+ }
269
+ return normalizeRuntimeMetadata(parseJsonObject(raw, LOCAL_RUNTIME_FILE));
270
+ }
271
+ async function writeRuntimeMetadata(cwd, metadata) {
272
+ const paths = localRuntimePaths(cwd);
273
+ await mkdir(paths.runtimeDir, {
274
+ recursive: true,
275
+ mode: 448
276
+ });
277
+ await writeFile(paths.runtimeFile, `${JSON.stringify(metadata, null, 2)}\n`, { mode: 384 });
278
+ }
279
+ async function removeRuntimeMetadata(cwd) {
280
+ await rm(localRuntimePaths(cwd).runtimeFile, { force: true });
281
+ }
282
+ async function removeLocalData(cwd) {
283
+ await rm(localRuntimePaths(cwd).dataDir, {
284
+ recursive: true,
285
+ force: true
286
+ });
287
+ }
288
+ async function checkLocalServerHealth(serverUrl, timeoutMs = 1500) {
289
+ try {
290
+ const healthUrl = new URL("/healthz", serverUrl);
291
+ return (await fetch(healthUrl, { signal: AbortSignal.timeout(timeoutMs) })).ok;
292
+ } catch {
293
+ return false;
294
+ }
295
+ }
296
+ async function isPortAvailable(port) {
297
+ return new Promise((resolvePort) => {
298
+ const server = createServer();
299
+ server.once("error", () => resolvePort(false));
300
+ server.once("listening", () => {
301
+ server.close(() => resolvePort(true));
302
+ });
303
+ server.listen(port, "127.0.0.1");
304
+ });
305
+ }
306
+ async function resolveLocalServer(cwd) {
307
+ const runtime = await readRuntimeMetadata(cwd);
308
+ if (runtime) {
309
+ if (await checkLocalServerHealth(runtime.server_url)) return runtime.server_url;
310
+ throw localServerNotRunning(runtime.server_url);
311
+ }
312
+ if (await checkLocalServerHealth("http://localhost:8080")) return DEFAULT_LOCAL_SERVER_URL;
313
+ throw localServerNotRunning(DEFAULT_LOCAL_SERVER_URL);
314
+ }
315
+ function localServerNotRunning(serverUrl) {
316
+ return new ZitadelError("E_LOCAL_SERVER_NOT_RUNNING", "Local Zitadel server is not running", {
317
+ hint: `No healthy local server responded at ${serverUrl}.`,
318
+ nextCommands: ["zitadel start"],
319
+ details: { server_url: serverUrl }
320
+ });
321
+ }
322
+ async function appendGitignoreEntry(cwd, entry) {
323
+ const path = join(cwd, ".gitignore");
324
+ let existing = "";
325
+ try {
326
+ existing = await readFile(path, "utf8");
327
+ } catch (error) {
328
+ if (!isErrno(error, "ENOENT")) throw error;
329
+ }
330
+ if (existing.split(/\r?\n/).map((line) => line.trim()).includes(entry)) return;
331
+ const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
332
+ await writeFile(path, `${existing}${prefix}${entry}\n`);
333
+ }
334
+ function normalizeRuntimeMetadata(input) {
335
+ if (input.schema_version !== 1 || typeof input.container_name !== "string" || typeof input.container_id !== "string" || typeof input.image !== "string" || typeof input.port !== "number" || !isValidPort(input.port) || typeof input.server_url !== "string" || !isValidServerUrl(input.server_url, input.port) || typeof input.data_dir !== "string" || typeof input.created_at !== "string" || typeof input.cli_version !== "string") throw new ZitadelError("E_VALIDATION", `${LOCAL_RUNTIME_FILE} is malformed`, {
336
+ hint: "Run `zitadel reset --force`, then `zitadel start`.",
337
+ nextCommands: ["zitadel reset --force", "zitadel start"],
338
+ details: input
339
+ });
340
+ return {
341
+ schema_version: 1,
342
+ container_name: input.container_name,
343
+ container_id: input.container_id,
344
+ image: input.image,
345
+ port: input.port,
346
+ server_url: input.server_url,
347
+ data_dir: input.data_dir,
348
+ created_at: input.created_at,
349
+ cli_version: input.cli_version
350
+ };
351
+ }
352
+ async function assertWritableDirectory(path) {
353
+ await mkdir(path, {
354
+ recursive: true,
355
+ mode: 448
356
+ });
357
+ await access(path, constants.W_OK);
358
+ }
359
+ function isErrno(error, code) {
360
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
361
+ }
362
+ function runtimeSummary(metadata) {
363
+ if (!metadata) return { configured: false };
364
+ return {
365
+ configured: true,
366
+ container_name: metadata.container_name,
367
+ container_id: metadata.container_id,
368
+ image: metadata.image,
369
+ port: metadata.port,
370
+ server_url: metadata.server_url,
371
+ data_dir: metadata.data_dir,
372
+ created_at: metadata.created_at
373
+ };
374
+ }
375
+ function isValidPort(value) {
376
+ return Number.isInteger(value) && value >= 1 && value <= 65535;
377
+ }
378
+ function isValidServerUrl(value, port) {
379
+ try {
380
+ const url = new URL(value);
381
+ return (url.protocol === "http:" || url.protocol === "https:") && url.hostname.length > 0 && explicitUrlPort(value) === port;
382
+ } catch {
383
+ return false;
384
+ }
385
+ }
386
+ function explicitUrlPort(value) {
387
+ const match = value.match(/^[a-z][a-z\d+\-.]*:\/\/(?:\[[^\]]+\]|[^/?#:]+):(\d+)(?:[/?#]|$)/i);
388
+ if (!match) return;
389
+ const port = Number(match[1]);
390
+ return isValidPort(port) ? port : void 0;
391
+ }
392
+ //#endregion
147
393
  //#region src/lib/server.ts
148
394
  /**
149
395
  * Server URL used when nothing else resolves. Also surfaced in hints and
@@ -160,23 +406,23 @@ const DEFAULT_SERVER = "https://api.zitadel.cloud";
160
406
  * `ZitadelError` rather than silently falling through.
161
407
  */
162
408
  async function resolveServer(input) {
163
- if (input.serverFlag) return validate({
409
+ if (input.serverFlag) return validate(input.cwd, {
164
410
  value: input.serverFlag,
165
411
  origin: "flag"
166
412
  });
167
413
  const envValue = input.env.ZITADEL_API_BASE;
168
- if (envValue) return validate({
414
+ if (envValue) return validate(input.cwd, {
169
415
  value: envValue,
170
416
  origin: "env"
171
417
  });
172
418
  const config = await readConfig(input.cwd);
173
419
  if (config) {
174
420
  const envBranch = readEnvServer(config, input.environment);
175
- if (envBranch) return validate({
421
+ if (envBranch) return validate(input.cwd, {
176
422
  value: envBranch,
177
423
  origin: "config-env"
178
424
  });
179
- if (typeof config.server === "string") return validate({
425
+ if (typeof config.server === "string") return validate(input.cwd, {
180
426
  value: config.server,
181
427
  origin: "config-top"
182
428
  });
@@ -186,7 +432,11 @@ async function resolveServer(input) {
186
432
  origin: "default"
187
433
  };
188
434
  }
189
- function validate(resolved) {
435
+ async function validate(cwd, resolved) {
436
+ if (resolved.value === "local") return {
437
+ value: await resolveLocalServer(cwd),
438
+ origin: "local"
439
+ };
190
440
  try {
191
441
  const url = new URL(resolved.value);
192
442
  if (url.protocol !== "https:" && url.protocol !== "http:") throw new ZitadelError("E_VALIDATION", `Server URL must use http(s): ${resolved.value}`, { hint: `Set "server" in zitadel.json to a URL like ${DEFAULT_SERVER}.` });
@@ -219,24 +469,6 @@ function readEnvServer(config, environment) {
219
469
  return typeof branch.server === "string" ? branch.server : void 0;
220
470
  }
221
471
  //#endregion
222
- //#region src/lib/paths.ts
223
- /**
224
- * Resolve the working directory the CLI should operate against, defaulting to
225
- * the process CWD when no `--cwd` override is given. Always returns an
226
- * absolute path so downstream `join`/`readFile` calls are unaffected by later
227
- * `process.chdir` or relative-path ambiguity.
228
- */
229
- function resolveCwd(cwd) {
230
- return resolve(cwd ?? process.cwd());
231
- }
232
- /**
233
- * Sentinel comment stamped at the top of every file the CLI generates and
234
- * owns. Commands like `doctor` and `eject` look for this marker to decide
235
- * whether a file is safe to touch; the trailing `v1` lets the format evolve
236
- * without mistaking newer managed files for hand-edited ones.
237
- */
238
- const MANAGED_MARKER = "// zitadel-cli: managed-file v1";
239
- //#endregion
240
472
  //#region src/lib/oclif/base.ts
241
473
  /**
242
474
  * Base class for every oclif command. Owns the global flags, builds the
@@ -281,11 +513,14 @@ var BaseCommand = class extends Command {
281
513
  * `source` by the documented precedence and storing the result on
282
514
  * `this.meta` so the error handler can render a complete envelope.
283
515
  */
284
- async toMeta(flags) {
516
+ async toMeta(flags, options = {}) {
285
517
  const cwd = resolveCwd(typeof flags.cwd === "string" ? flags.cwd : void 0);
286
518
  const serverFlag = typeof flags.server === "string" ? flags.server : void 0;
287
519
  const environment = typeof flags.environment === "string" ? flags.environment : "development";
288
- const source = await resolveServer({
520
+ const source = options.resolveServer === false ? {
521
+ value: options.source ?? "",
522
+ origin: "default"
523
+ } : await resolveServer({
289
524
  cwd,
290
525
  env: process.env,
291
526
  serverFlag,
@@ -324,8 +559,9 @@ var BaseCommand = class extends Command {
324
559
  * envelope so oclif's `--json` path serialises it.
325
560
  */
326
561
  emit(result) {
327
- this.log(renderPretty(result, this.meta));
328
- return toEnvelope(result, this.meta);
562
+ const normalized = normalizeCommandResult(result, this.meta);
563
+ this.log(renderPretty(normalized, this.meta));
564
+ return toEnvelope(normalized, this.meta);
329
565
  }
330
566
  /**
331
567
  * Renders any thrown error as the failure envelope and exits with its code.
@@ -340,7 +576,7 @@ var BaseCommand = class extends Command {
340
576
  };
341
577
  const zitadelError = toZitadelError(error);
342
578
  if (this.jsonEnabled()) this.logJson(toErrorEnvelope(zitadelError, meta));
343
- else this.logToStderr(renderError(zitadelError));
579
+ else this.logToStderr(renderError(zitadelError, meta));
344
580
  return this.exit(zitadelError.exitCode);
345
581
  }
346
582
  /**
@@ -364,6 +600,24 @@ var BaseCommand = class extends Command {
364
600
  };
365
601
  }
366
602
  };
603
+ function normalizeCommandResult(result, meta) {
604
+ if (result.status === "ok") return {
605
+ ...result,
606
+ data: normalizeDataNextCommands(result.data, meta)
607
+ };
608
+ return {
609
+ ...result,
610
+ data: normalizeDataNextCommands(result.data, meta),
611
+ nextCommands: normalizePublicCliCommands(result.nextCommands, meta.cliVersion)
612
+ };
613
+ }
614
+ function normalizeDataNextCommands(data, meta) {
615
+ if (!isObject(data) || !Array.isArray(data.next_commands)) return data;
616
+ return {
617
+ ...data,
618
+ next_commands: data.next_commands.map((command) => typeof command === "string" ? normalizePublicCliCommand(command, meta.cliVersion) : command)
619
+ };
620
+ }
367
621
  /** Wraps a {@link CommandResult} with the invocation metadata into the final envelope. */
368
622
  function toEnvelope(result, meta) {
369
623
  const base = {
@@ -395,7 +649,7 @@ function toErrorEnvelope(error, meta) {
395
649
  code: error.code,
396
650
  message: error.message,
397
651
  hint: error.hint,
398
- next_commands: error.nextCommands,
652
+ next_commands: normalizePublicCliCommands(error.nextCommands, meta.cliVersion),
399
653
  details: error.details
400
654
  };
401
655
  }
@@ -419,12 +673,13 @@ function renderPretty(result, meta) {
419
673
  * Renders a {@link ZitadelError} as a human-readable block for stderr: the
420
674
  * coded message, an optional hint, and any suggested next commands.
421
675
  */
422
- function renderError(error) {
676
+ function renderError(error, meta) {
423
677
  const lines = [`Error ${error.code}: ${error.message}`];
424
678
  if (error.hint) lines.push(error.hint);
425
- if (error.nextCommands && error.nextCommands.length > 0) {
679
+ const nextCommands = normalizePublicCliCommands(error.nextCommands, meta.cliVersion);
680
+ if (nextCommands && nextCommands.length > 0) {
426
681
  lines.push("Next:");
427
- for (const cmd of error.nextCommands) lines.push(` $ ${cmd}`);
682
+ for (const cmd of nextCommands) lines.push(` $ ${cmd}`);
428
683
  }
429
684
  return lines.join("\n");
430
685
  }
@@ -453,9 +708,16 @@ function formatData(data, warnings, opts) {
453
708
  for (const cmd of data.next_commands) lines.push(` $ ${String(cmd)}`);
454
709
  }
455
710
  }
456
- for (const warning of warnings) lines.push(`Warning: ${warning}`);
711
+ for (const warning of warnings.filter((warning) => !warningRenderedInChecks(data, warning))) lines.push(`Warning: ${warning}`);
457
712
  return lines.join("\n");
458
713
  }
714
+ function warningRenderedInChecks(data, warning) {
715
+ if (!isObject(data) || !Array.isArray(data.checks)) return false;
716
+ return data.checks.some((check) => {
717
+ if (!isObject(check) || check.status !== "warn") return false;
718
+ return warning === `${String(check.name ?? "check")}: ${String(check.message ?? "")}`;
719
+ });
720
+ }
459
721
  function renderKnownSections(lines, data) {
460
722
  if (isObject(data.project)) {
461
723
  const project = data.project;
@@ -483,7 +745,7 @@ function renderKnownSections(lines, data) {
483
745
  lines.push("Checks:");
484
746
  for (const check of data.checks) {
485
747
  if (!isObject(check)) continue;
486
- const status = check.status === "pass" ? "ok" : "fail";
748
+ const status = check.status === "pass" ? "ok" : check.status === "warn" ? "warn" : "fail";
487
749
  lines.push(` [${status}] ${String(check.name ?? "check")}: ${String(check.message ?? "")}`);
488
750
  }
489
751
  }
@@ -502,87 +764,6 @@ function suffixBlock(opts) {
502
764
  return suffix ? ` ${suffix}` : "";
503
765
  }
504
766
  //#endregion
505
- //#region src/lib/project.ts
506
- /**
507
- * Reports whether `cwd` has already been initialized, i.e. a committed
508
- * `zitadel.json` exists. Used to decide whether setup should run or skip.
509
- */
510
- async function hasZitadelConfig(cwd) {
511
- return exists(join(cwd, "zitadel.json"));
512
- }
513
- /**
514
- * Reports whether local secret material (`.zitadel/secret`) is present. Gates
515
- * commands that need credentials, and signals that secrets were already pulled.
516
- */
517
- async function hasZitadelSecret(cwd) {
518
- return exists(join(cwd, ".zitadel/secret"));
519
- }
520
- async function exists(path) {
521
- try {
522
- await stat(path);
523
- return true;
524
- } catch (error) {
525
- if (isNotFound(error)) return false;
526
- throw error;
527
- }
528
- }
529
- /**
530
- * Reads and parses `zitadel.json` into a plain object. Translates a missing
531
- * file into an actionable `E_VALIDATION` error pointing at `zitadel setup`;
532
- * other errors (e.g. malformed JSON) propagate unchanged.
533
- */
534
- async function readZitadelConfig(cwd) {
535
- try {
536
- return parseJsonObject(await readFile(join(cwd, "zitadel.json"), "utf8"), "zitadel.json");
537
- } catch (error) {
538
- if (isNotFound(error)) throw new ZitadelError("E_VALIDATION", "zitadel.json was not found", {
539
- hint: "Run `zitadel setup` first.",
540
- nextCommands: ["zitadel setup"]
541
- });
542
- throw error;
543
- }
544
- }
545
- /**
546
- * Reads, parses, and structurally validates `.zitadel/secret`, returning it
547
- * as a {@link ZitadelSecret}. A missing file becomes an actionable
548
- * `E_VALIDATION` error pointing at `zitadel setup` / `zitadel doctor --fix`;
549
- * a present-but-incomplete file throws so callers never proceed with partial
550
- * credentials.
551
- */
552
- async function readZitadelSecret(cwd) {
553
- try {
554
- const secret = parseJsonObject(await readFile(join(cwd, ".zitadel/secret"), "utf8"), ".zitadel/secret");
555
- if (typeof secret.project_id !== "string" || typeof secret.project_secret !== "string" || typeof secret.preview_secret !== "string" || !Array.isArray(secret.preview_origins)) throw new Error(".zitadel/secret is missing required fields");
556
- return secret;
557
- } catch (error) {
558
- if (isNotFound(error)) throw new ZitadelError("E_VALIDATION", ".zitadel/secret was not found", {
559
- hint: "Run `zitadel setup` first, or restore the project secret with `zitadel doctor --fix`.",
560
- nextCommands: ["zitadel setup", "zitadel doctor --fix"]
561
- });
562
- throw error;
563
- }
564
- }
565
- /**
566
- * Reads the configured renderer id from a parsed `zitadel.json`, normalising the
567
- * legacy `default` alias to `react` and falling back to `react` when unset. The
568
- * value is validated downstream by `getRenderer`, so callers need not re-check.
569
- */
570
- function readRendererId(config) {
571
- const branding = isObject(config.branding) ? config.branding : void 0;
572
- const value = branding && typeof branding.renderer === "string" ? branding.renderer : "react";
573
- return value === "default" ? "react" : value;
574
- }
575
- /** Reads `environments.development.issuer` from a parsed `zitadel.json`, if present. */
576
- function readDevelopmentIssuer(config) {
577
- if (isObject(config.environments) && isObject(config.environments.development)) {
578
- const issuer = config.environments.development.issuer;
579
- return typeof issuer === "string" ? issuer : void 0;
580
- }
581
- }
582
- function isNotFound(error) {
583
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
584
- }
585
- //#endregion
586
- export { readZitadelConfig as a, MANAGED_MARKER as c, parseJsonObject as d, stableStringify as f, readRendererId as i, DEFAULT_SERVER as l, hasZitadelSecret as n, readZitadelSecret as o, ZitadelError as p, readDevelopmentIssuer as r, BaseCommand as s, hasZitadelConfig as t, isObject as u };
767
+ export { isObject as C, ZitadelError as E, MANAGED_MARKER as S, stableStringify as T, removeLocalData as _, DEFAULT_LOCAL_SERVER_PORT as a, writeRuntimeMetadata as b, checkLocalServerHealth as c, ensureLocalState as d, isPortAvailable as f, readRuntimeMetadata as g, localServerUrl as h, CONTAINER_HTTP_PORT as i, defaultLocalServerImageForCliVersion as l, localRuntimePaths as m, DEFAULT_SERVER as n, DEFAULT_LOCAL_SERVER_URL as o, localContainerName as p, CONTAINER_DATA_DIR as r, assertWritableDirectory as s, BaseCommand as t, ensureContainerIdentity as u, removeRuntimeMetadata as v, parseJsonObject as w, publicCliCommand as x, runtimeSummary as y };
587
768
 
588
- //# sourceMappingURL=project-C3pSfbao.mjs.map
769
+ //# sourceMappingURL=oclif-CqkWBQ7i.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oclif-CqkWBQ7i.mjs","names":[],"sources":["../src/lib/errors.ts","../src/lib/json.ts","../src/lib/paths.ts","../src/lib/public-cli.ts","../src/lib/local-server/runtime.ts","../src/lib/server.ts","../src/lib/oclif/base.ts"],"sourcesContent":["import { ApiError } from \"@zitadel/api/runtime/fetch\";\n\n/**\n * Closed set of failure categories the CLI can surface. Every error the\n * user sees is funnelled into one of these so messaging, exit codes, and\n * machine-readable output stay consistent regardless of where the failure\n * originated.\n */\nexport type ZitadelErrorCode =\n | \"E_ALREADY_INIT\"\n | \"E_FRAMEWORK_NOT_DETECTED\"\n | \"E_UNSUPPORTED_PROJECT_SHAPE\"\n | \"E_NETWORK\"\n | \"E_AUTH\"\n | \"E_CONFLICT\"\n | \"E_LOCAL_SERVER_NOT_RUNNING\"\n | \"E_VALIDATION\"\n | \"E_NOT_IMPLEMENTED\";\n\n/**\n * Maps each {@link ZitadelErrorCode} to the process exit code the CLI\n * returns. The table is the single source of truth for exit semantics so\n * scripts and CI can branch on stable, documented numbers.\n */\nexport const EXIT_CODES: Record<ZitadelErrorCode, number> = {\n E_ALREADY_INIT: 0,\n E_FRAMEWORK_NOT_DETECTED: 3,\n E_UNSUPPORTED_PROJECT_SHAPE: 3,\n E_NETWORK: 4,\n E_AUTH: 1,\n E_CONFLICT: 5,\n E_LOCAL_SERVER_NOT_RUNNING: 4,\n E_VALIDATION: 3,\n E_NOT_IMPLEMENTED: 2,\n};\n\n/**\n * Optional, user-facing extras attached to a {@link ZitadelError}. Kept\n * separate from the message so the renderer can present a hint, suggested\n * follow-up commands, and structured details independently (e.g. as JSON\n * fields) rather than concatenating everything into one string.\n */\nexport type ZitadelErrorOptions = {\n hint?: string;\n nextCommands?: string[];\n details?: unknown;\n};\n\n/**\n * The CLI's single error type. Carries a {@link ZitadelErrorCode} so the\n * top-level handler can derive an exit code and structured output without\n * pattern-matching on messages. Throwing this anywhere guarantees the user\n * gets a categorised, hint-bearing failure instead of a raw stack trace.\n */\nexport class ZitadelError extends Error {\n readonly code: ZitadelErrorCode;\n readonly hint?: string;\n readonly nextCommands?: string[];\n readonly details?: unknown;\n\n constructor(code: ZitadelErrorCode, message: string, opts: ZitadelErrorOptions = {}) {\n super(message);\n this.name = \"ZitadelError\";\n this.code = code;\n this.hint = opts.hint;\n this.nextCommands = opts.nextCommands;\n this.details = opts.details;\n }\n\n get exitCode(): number {\n return EXIT_CODES[this.code] ?? 1;\n }\n}\n\n/**\n * Normalises any thrown value into a {@link ZitadelError}. Inspection is\n * ordered most-specific-first (already-normalised, then errno/filesystem,\n * network, Zod-like, generic `Error`, then a catch-all) so the most\n * actionable category and hint win. This is the boundary that lets the rest\n * of the CLI `throw` plain errors yet still produce consistent, categorised\n * output. The original error shape is preserved under `details` for\n * debugging without leaking it into the user-facing message.\n */\nexport function toZitadelError(error: unknown): ZitadelError {\n if (error instanceof ZitadelError) {\n return error;\n }\n\n if (error instanceof ApiError) {\n // `401`/`403` → bad or missing project secret; `5xx` → transport or\n // server fault; everything else 4xx → the body the CLI sent was\n // rejected (validation, conflict, not-found, …).\n const code: ZitadelErrorCode =\n error.status === 401 || error.status === 403\n ? \"E_AUTH\"\n : error.status >= 500\n ? \"E_NETWORK\"\n : \"E_VALIDATION\";\n return new ZitadelError(code, error.message, {\n details: { status: error.status, url: error.url, body: error.body },\n });\n }\n\n if (isErrnoException(error)) {\n const details = { original: pickErrorShape(error) };\n if (error.code === \"EACCES\" || error.code === \"EPERM\") {\n return new ZitadelError(\"E_AUTH\", `Permission denied: ${error.message}`, {\n hint: \"Check file permissions or run with the right user.\",\n details,\n });\n }\n if (error.code === \"EEXIST\") {\n return new ZitadelError(\"E_CONFLICT\", error.message, {\n hint: \"A file already exists. Use --force to overwrite or remove it first.\",\n details,\n });\n }\n if (error.code === \"ENOENT\") {\n return new ZitadelError(\"E_VALIDATION\", error.message, {\n hint: \"A required file or directory is missing.\",\n details,\n });\n }\n }\n\n if (isNetworkError(error)) {\n return new ZitadelError(\"E_NETWORK\", errorMessage(error), {\n hint: \"Check your connection, ZITADEL_API_BASE, or the configured server URL.\",\n details: { original: pickErrorShape(error as Error) },\n });\n }\n\n if (isZodLikeError(error)) {\n return new ZitadelError(\"E_VALIDATION\", errorMessage(error), {\n details: { issues: (error as { issues: unknown }).issues },\n });\n }\n\n if (error instanceof Error) {\n return new ZitadelError(\"E_VALIDATION\", error.message, {\n details: { original: pickErrorShape(error) },\n });\n }\n\n return new ZitadelError(\"E_VALIDATION\", \"Unknown error\", { details: error });\n}\n\nfunction isErrnoException(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && typeof (error as NodeJS.ErrnoException).code === \"string\";\n}\n\nfunction isNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n if (\n error.name === \"TypeError\" &&\n /fetch failed|network|ECONNREFUSED|ENOTFOUND/i.test(error.message)\n ) {\n return true;\n }\n const cause = (error as { cause?: unknown }).cause;\n if (cause && typeof cause === \"object\" && \"code\" in cause) {\n const code = String((cause as { code: unknown }).code);\n return /^(ECONNREFUSED|ECONNRESET|ENOTFOUND|ETIMEDOUT|EAI_AGAIN|UND_ERR)/i.test(code);\n }\n return false;\n}\n\nfunction isZodLikeError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"issues\" in error &&\n Array.isArray((error as { issues: unknown }).issues)\n );\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === \"string\") {\n return error;\n }\n return String(error);\n}\n\nfunction pickErrorShape(error: Error): Record<string, unknown> {\n return {\n name: error.name,\n message: error.message,\n code: (error as NodeJS.ErrnoException).code,\n };\n}\n","import { stringify } from \"safe-stable-stringify\";\n\n/**\n * Serialise a value to pretty-printed JSON with object keys sorted at every\n * depth. Determinism is the point: managed files written by the CLI must be\n * byte-stable across runs so diffs stay clean and content hashes don't churn\n * when only key ordering would otherwise differ. Delegates the deterministic\n * sort to `safe-stable-stringify`, matching `JSON.stringify(value, null, 2)`\n * formatting. The `?? \"null\"` only applies to `undefined`/function inputs,\n * which the CLI never serialises.\n */\nexport function stableStringify(value: unknown): string {\n return stringify(value, null, 2) ?? \"null\";\n}\n\n/**\n * Parse `contents` as JSON and assert the root is a plain object (not an\n * array or scalar). The CLI's config and secret files are always objects, so\n * this guards callers from the `JSON.parse` return type of `any` and produces\n * a `path`-qualified error message pointing at the offending file.\n */\nexport function parseJsonObject(contents: string, path: string): Record<string, unknown> {\n const value = JSON.parse(contents) as unknown;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${path} must contain a JSON object`);\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Narrows an unknown value to a plain (non-array, non-null) object. Shared by\n * the commands and the file-writer that walk parsed JSON, so the predicate\n * isn't reimplemented per call site.\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { resolve } from \"node:path\";\n\n/**\n * Resolve the working directory the CLI should operate against, defaulting to\n * the process CWD when no `--cwd` override is given. Always returns an\n * absolute path so downstream `join`/`readFile` calls are unaffected by later\n * `process.chdir` or relative-path ambiguity.\n */\nexport function resolveCwd(cwd?: string): string {\n return resolve(cwd ?? process.cwd());\n}\n\n/**\n * Sentinel comment stamped at the top of every file the CLI generates and\n * owns. Commands like `doctor` and `eject` look for this marker to decide\n * whether a file is safe to touch; the trailing `v1` lets the format evolve\n * without mistaking newer managed files for hand-edited ones.\n */\nexport const MANAGED_MARKER = \"// zitadel-cli: managed-file v1\";\n","const CLI_PACKAGE_NAME = \"@zitadel/cli\";\n\nexport function npmDistTagForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n const match = normalized.match(/^\\d+\\.\\d+\\.\\d+-([0-9A-Za-z][0-9A-Za-z-]*)/);\n return match?.[1] ?? \"latest\";\n}\n\nexport function npmSelectorForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n if (/^\\d+\\.\\d+\\.\\d+-alpha\\.\\d+$/.test(normalized)) {\n return normalized;\n }\n return npmDistTagForCliVersion(normalized);\n}\n\nexport function publicCliCommand(args: string, cliVersion: string): string {\n const prefix = `npx ${CLI_PACKAGE_NAME}@${npmSelectorForCliVersion(cliVersion)}`;\n return args.length > 0 ? `${prefix} ${args}` : prefix;\n}\n\nexport function normalizePublicCliCommand(command: string, cliVersion: string): string {\n if (command === \"zitadel\") {\n return publicCliCommand(\"\", cliVersion);\n }\n if (command.startsWith(\"zitadel \")) {\n return publicCliCommand(command.slice(\"zitadel \".length), cliVersion);\n }\n return command;\n}\n\nexport function normalizePublicCliCommands(\n commands: ReadonlyArray<string> | undefined,\n cliVersion: string,\n): string[] | undefined {\n return commands?.map((command) => normalizePublicCliCommand(command, cliVersion));\n}\n","import { createHash } from \"node:crypto\";\nimport { access, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { createServer } from \"node:net\";\nimport { join, resolve } from \"node:path\";\n\nimport { ZitadelError } from \"../errors\";\nimport { isObject, parseJsonObject } from \"../json\";\n\nexport const LOCAL_SERVER_IMAGE_NAME = \"ghcr.io/zitadel/nextgen\";\nexport const DEFAULT_LOCAL_SERVER_IMAGE = `${LOCAL_SERVER_IMAGE_NAME}:latest`;\nexport const DEFAULT_LOCAL_SERVER_PORT = 8080;\nexport const DEFAULT_LOCAL_SERVER_URL = \"http://localhost:8080\";\nexport const LOCAL_RUNTIME_DIR = \".zitadel/local\";\nexport const LOCAL_DATA_DIR = \".zitadel/local/nextgen-data\";\nexport const LOCAL_RUNTIME_FILE = \".zitadel/local/runtime.json\";\nexport const LOCAL_CONTAINER_PASSWD_FILE = \".zitadel/local/container-passwd\";\nexport const LOCAL_CONTAINER_GROUP_FILE = \".zitadel/local/container-group\";\nexport const CONTAINER_DATA_DIR = \"/var/lib/zitadel/nextgen-data\";\nexport const CONTAINER_HTTP_PORT = 8080;\n\nexport type RuntimeMetadata = {\n schema_version: 1;\n container_name: string;\n container_id: string;\n image: string;\n port: number;\n server_url: string;\n data_dir: string;\n created_at: string;\n cli_version: string;\n};\n\nexport type LocalRuntimePaths = {\n runtimeDir: string;\n dataDir: string;\n runtimeFile: string;\n containerPasswdFile: string;\n containerGroupFile: string;\n};\n\nexport type ContainerIdentity = {\n uid: number;\n gid: number;\n passwdFile: string;\n groupFile: string;\n};\n\nexport function localRuntimePaths(cwd: string): LocalRuntimePaths {\n return {\n runtimeDir: join(cwd, LOCAL_RUNTIME_DIR),\n dataDir: join(cwd, LOCAL_DATA_DIR),\n runtimeFile: join(cwd, LOCAL_RUNTIME_FILE),\n containerPasswdFile: join(cwd, LOCAL_CONTAINER_PASSWD_FILE),\n containerGroupFile: join(cwd, LOCAL_CONTAINER_GROUP_FILE),\n };\n}\n\nexport function localContainerName(cwd: string): string {\n const hash = createHash(\"sha256\").update(resolve(cwd)).digest(\"hex\").slice(0, 12);\n return `zitadel-server-${hash}`;\n}\n\nexport function localServerUrl(port: number): string {\n return `http://localhost:${port}`;\n}\n\nexport function defaultLocalServerImageForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n if (/^\\d+\\.\\d+\\.\\d+-alpha\\.\\d+$/.test(normalized)) {\n return `${LOCAL_SERVER_IMAGE_NAME}:${normalized}`;\n }\n return DEFAULT_LOCAL_SERVER_IMAGE;\n}\n\nexport async function ensureLocalState(cwd: string): Promise<LocalRuntimePaths> {\n const paths = localRuntimePaths(cwd);\n await mkdir(paths.dataDir, { recursive: true, mode: 0o700 });\n await appendGitignoreEntry(cwd, `${LOCAL_RUNTIME_DIR}/`);\n return paths;\n}\n\nexport async function ensureContainerIdentity(\n cwd: string,\n user: { uid?: number; gid?: number },\n): Promise<ContainerIdentity | undefined> {\n if (user.uid === undefined || user.uid <= 0) {\n return undefined;\n }\n const gid = user.gid ?? user.uid;\n const paths = localRuntimePaths(cwd);\n await mkdir(paths.runtimeDir, { recursive: true, mode: 0o700 });\n await writeFile(\n paths.containerPasswdFile,\n [\n \"root:x:0:0:root:/root:/bin/sh\",\n \"nonroot:x:65532:65532:nonroot:/nonexistent:/usr/sbin/nologin\",\n `zitadel-local:x:${String(user.uid)}:${String(gid)}:Zitadel local user:/tmp:/usr/sbin/nologin`,\n \"\",\n ].join(\"\\n\"),\n { mode: 0o644 },\n );\n await writeFile(\n paths.containerGroupFile,\n [\n \"root:x:0:\",\n \"nonroot:x:65532:\",\n `zitadel-local:x:${String(gid)}:`,\n \"\",\n ].join(\"\\n\"),\n { mode: 0o644 },\n );\n return {\n uid: user.uid,\n gid,\n passwdFile: paths.containerPasswdFile,\n groupFile: paths.containerGroupFile,\n };\n}\n\nexport async function readRuntimeMetadata(cwd: string): Promise<RuntimeMetadata | undefined> {\n const paths = localRuntimePaths(cwd);\n let raw: string;\n try {\n raw = await readFile(paths.runtimeFile, \"utf8\");\n } catch (error) {\n if (isErrno(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n }\n\n const parsed = parseJsonObject(raw, LOCAL_RUNTIME_FILE);\n return normalizeRuntimeMetadata(parsed);\n}\n\nexport async function writeRuntimeMetadata(cwd: string, metadata: RuntimeMetadata): Promise<void> {\n const paths = localRuntimePaths(cwd);\n await mkdir(paths.runtimeDir, { recursive: true, mode: 0o700 });\n await writeFile(paths.runtimeFile, `${JSON.stringify(metadata, null, 2)}\\n`, { mode: 0o600 });\n}\n\nexport async function removeRuntimeMetadata(cwd: string): Promise<void> {\n await rm(localRuntimePaths(cwd).runtimeFile, { force: true });\n}\n\nexport async function removeLocalData(cwd: string): Promise<void> {\n await rm(localRuntimePaths(cwd).dataDir, { recursive: true, force: true });\n}\n\nexport async function checkLocalServerHealth(serverUrl: string, timeoutMs = 1500): Promise<boolean> {\n try {\n const healthUrl = new URL(\"/healthz\", serverUrl);\n const response = await fetch(healthUrl, { signal: AbortSignal.timeout(timeoutMs) });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport async function isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolvePort) => {\n const server = createServer();\n server.once(\"error\", () => resolvePort(false));\n server.once(\"listening\", () => {\n server.close(() => resolvePort(true));\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport async function resolveLocalServer(cwd: string): Promise<string> {\n const runtime = await readRuntimeMetadata(cwd);\n if (runtime) {\n if (await checkLocalServerHealth(runtime.server_url)) {\n return runtime.server_url;\n }\n throw localServerNotRunning(runtime.server_url);\n }\n\n if (await checkLocalServerHealth(DEFAULT_LOCAL_SERVER_URL)) {\n return DEFAULT_LOCAL_SERVER_URL;\n }\n throw localServerNotRunning(DEFAULT_LOCAL_SERVER_URL);\n}\n\nexport function localServerNotRunning(serverUrl: string): ZitadelError {\n return new ZitadelError(\"E_LOCAL_SERVER_NOT_RUNNING\", \"Local Zitadel server is not running\", {\n hint: `No healthy local server responded at ${serverUrl}.`,\n nextCommands: [\"zitadel start\"],\n details: { server_url: serverUrl },\n });\n}\n\nasync function appendGitignoreEntry(cwd: string, entry: string): Promise<void> {\n const path = join(cwd, \".gitignore\");\n let existing = \"\";\n try {\n existing = await readFile(path, \"utf8\");\n } catch (error) {\n if (!isErrno(error, \"ENOENT\")) {\n throw error;\n }\n }\n\n const lines = existing.split(/\\r?\\n/).map((line) => line.trim());\n if (lines.includes(entry)) {\n return;\n }\n const prefix = existing.length === 0 || existing.endsWith(\"\\n\") ? \"\" : \"\\n\";\n await writeFile(path, `${existing}${prefix}${entry}\\n`);\n}\n\nfunction normalizeRuntimeMetadata(input: Record<string, unknown>): RuntimeMetadata {\n if (\n input.schema_version !== 1 ||\n typeof input.container_name !== \"string\" ||\n typeof input.container_id !== \"string\" ||\n typeof input.image !== \"string\" ||\n typeof input.port !== \"number\" ||\n !isValidPort(input.port) ||\n typeof input.server_url !== \"string\" ||\n !isValidServerUrl(input.server_url, input.port) ||\n typeof input.data_dir !== \"string\" ||\n typeof input.created_at !== \"string\" ||\n typeof input.cli_version !== \"string\"\n ) {\n throw new ZitadelError(\"E_VALIDATION\", `${LOCAL_RUNTIME_FILE} is malformed`, {\n hint: \"Run `zitadel reset --force`, then `zitadel start`.\",\n nextCommands: [\"zitadel reset --force\", \"zitadel start\"],\n details: input,\n });\n }\n return {\n schema_version: 1,\n container_name: input.container_name,\n container_id: input.container_id,\n image: input.image,\n port: input.port,\n server_url: input.server_url,\n data_dir: input.data_dir,\n created_at: input.created_at,\n cli_version: input.cli_version,\n };\n}\n\nexport async function assertWritableDirectory(path: string): Promise<void> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n await access(path, constants.W_OK);\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: unknown }).code === code\n );\n}\n\nexport function runtimeSummary(metadata: RuntimeMetadata | undefined): Record<string, unknown> {\n if (!metadata) {\n return { configured: false };\n }\n return {\n configured: true,\n container_name: metadata.container_name,\n container_id: metadata.container_id,\n image: metadata.image,\n port: metadata.port,\n server_url: metadata.server_url,\n data_dir: metadata.data_dir,\n created_at: metadata.created_at,\n };\n}\n\nexport function isRuntimeObject(value: unknown): value is RuntimeMetadata {\n return isObject(value) && value.schema_version === 1;\n}\n\nfunction isValidPort(value: number): boolean {\n return Number.isInteger(value) && value >= 1 && value <= 65_535;\n}\n\nfunction isValidServerUrl(value: string, port: number): boolean {\n try {\n const url = new URL(value);\n return (\n (url.protocol === \"http:\" || url.protocol === \"https:\") &&\n url.hostname.length > 0 &&\n explicitUrlPort(value) === port\n );\n } catch {\n return false;\n }\n}\n\nfunction explicitUrlPort(value: string): number | undefined {\n const match = value.match(/^[a-z][a-z\\d+\\-.]*:\\/\\/(?:\\[[^\\]]+\\]|[^/?#:]+):(\\d+)(?:[/?#]|$)/i);\n if (!match) {\n return undefined;\n }\n const port = Number(match[1]);\n return isValidPort(port) ? port : undefined;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ZitadelError } from \"./errors\";\nimport { resolveLocalServer } from \"./local-server/runtime\";\nimport { isObject, parseJsonObject } from \"./json\";\n\n/**\n * Server URL used when nothing else resolves. Also surfaced in hints and\n * the interactive setup prompt as the suggested value, so it is exported\n * rather than kept private.\n */\nexport const DEFAULT_SERVER = \"https://api.zitadel.cloud\";\n\n/**\n * The resolved target server plus the source it came from. `origin` is\n * retained (not just the value) so callers can report *why* a server was\n * chosen and so the precedence order stays auditable.\n */\nexport type ResolvedServer = {\n value: string;\n origin: \"flag\" | \"env\" | \"config-env\" | \"config-top\" | \"default\" | \"local\";\n};\n\n/**\n * Inputs to {@link resolveServer}. Passed explicitly (cwd, env) rather\n * than read from globals so resolution is pure and testable. `serverFlag`\n * and `environment` come from the parsed CLI invocation.\n */\nexport type ResolveServerInput = {\n cwd: string;\n env: NodeJS.ProcessEnv;\n serverFlag?: string;\n environment?: string;\n};\n\n/**\n * Resolves which server the CLI should target, applying a fixed\n * precedence: explicit `--server` flag, then `ZITADEL_API_BASE`, then the\n * selected environment block in `zitadel.json`, then the config's\n * top-level `server`, falling back to {@link DEFAULT_SERVER}. Every\n * candidate is validated to a normalised origin; an invalid URL throws a\n * `ZitadelError` rather than silently falling through.\n */\nexport async function resolveServer(input: ResolveServerInput): Promise<ResolvedServer> {\n if (input.serverFlag) {\n return validate(input.cwd, { value: input.serverFlag, origin: \"flag\" });\n }\n const envValue = input.env.ZITADEL_API_BASE;\n if (envValue) {\n return validate(input.cwd, { value: envValue, origin: \"env\" });\n }\n\n const config = await readConfig(input.cwd);\n if (config) {\n const envBranch = readEnvServer(config, input.environment);\n if (envBranch) {\n return validate(input.cwd, { value: envBranch, origin: \"config-env\" });\n }\n if (typeof config.server === \"string\") {\n return validate(input.cwd, { value: config.server, origin: \"config-top\" });\n }\n }\n\n return { value: DEFAULT_SERVER, origin: \"default\" };\n}\n\nasync function validate(cwd: string, resolved: ResolvedServer): Promise<ResolvedServer> {\n if (resolved.value === \"local\") {\n return { value: await resolveLocalServer(cwd), origin: \"local\" };\n }\n\n try {\n const url = new URL(resolved.value);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new ZitadelError(\"E_VALIDATION\", `Server URL must use http(s): ${resolved.value}`, {\n hint: `Set \"server\" in zitadel.json to a URL like ${DEFAULT_SERVER}.`,\n });\n }\n return { value: url.origin, origin: resolved.origin };\n } catch (error) {\n if (error instanceof ZitadelError) {\n throw error;\n }\n throw new ZitadelError(\"E_VALIDATION\", `Invalid server \"${resolved.value}\"`, {\n hint: `Use a URL like ${DEFAULT_SERVER}.`,\n details: { origin: resolved.origin },\n });\n }\n}\n\nasync function readConfig(cwd: string): Promise<Record<string, unknown> | undefined> {\n try {\n const contents = await readFile(join(cwd, \"zitadel.json\"), \"utf8\");\n return parseJsonObject(contents, \"zitadel.json\");\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: string }).code === \"ENOENT\"\n ) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction readEnvServer(\n config: Record<string, unknown>,\n environment: string | undefined,\n): string | undefined {\n if (!environment) {\n return undefined;\n }\n const envs = config.environments;\n if (!isObject(envs)) {\n return undefined;\n }\n const branch = envs[environment];\n if (!isObject(branch)) {\n return undefined;\n }\n return typeof branch.server === \"string\" ? branch.server : undefined;\n}\n","import { Command, Flags } from \"@oclif/core\";\nimport consola from \"consola\";\n\nimport { toZitadelError, type ZitadelError } from \"../errors\";\nimport { isObject } from \"../json\";\nimport { resolveCwd } from \"../paths\";\nimport { normalizePublicCliCommand, normalizePublicCliCommands } from \"../public-cli\";\nimport { resolveServer } from \"../server\";\nimport type {\n CommandResult,\n ErrorEnvelope,\n EnvelopeMeta,\n GlobalOptions,\n JsonEnvelope,\n} from \"./types\";\n\n/**\n * Base class for every oclif command. Owns the global flags, builds the\n * {@link GlobalOptions} context (including server `source` resolution) the\n * subclass's `run` reads via `this.meta`, and turns the {@link CommandResult}\n * it returns into the JSON envelope (oclif serialises it natively in `--json`\n * mode) or human-facing text. Errors are translated into the failure envelope\n * and the mapped process exit code. Subclasses stay thin: parse flags, call\n * {@link toMeta}, do their work, and `return this.emit(...)`. The agent\n * contract (ADR 004) is preserved — oclif only replaces parsing, dispatch,\n * help, and JSON emission.\n */\nexport abstract class BaseCommand extends Command {\n /** Opt into oclif's native `--json` flag and JSON serialisation of the result. */\n static override enableJsonFlag = true;\n\n /** Flags shared by every command, inherited via oclif `baseFlags`. */\n static override baseFlags = {\n cwd: Flags.string({ char: \"c\", description: \"Project directory to operate on.\" }),\n server: Flags.string({ char: \"s\", description: \"Override the resolved server URL.\" }),\n \"non-interactive\": Flags.boolean({\n char: \"n\",\n description: \"Disable prompts. Required when scripting or running as an agent.\",\n }),\n force: Flags.boolean({ char: \"f\", description: \"Overwrite protected files on conflict.\" }),\n \"dry-run\": Flags.boolean({ description: \"Preview without mutating files or the platform.\" }),\n verbose: Flags.boolean({ description: \"Verbose logging.\" }),\n debug: Flags.boolean({ description: \"Debug logging.\" }),\n };\n\n /** Resolved context for the current invocation; set by {@link toMeta}. */\n protected meta: GlobalOptions = this.fallbackMeta();\n\n /**\n * Builds {@link GlobalOptions} from parsed flags, resolving the server\n * `source` by the documented precedence and storing the result on\n * `this.meta` so the error handler can render a complete envelope.\n */\n protected async toMeta(\n flags: Record<string, unknown>,\n options: { resolveServer?: boolean; source?: string } = {},\n ): Promise<GlobalOptions> {\n const cwd = resolveCwd(typeof flags.cwd === \"string\" ? flags.cwd : undefined);\n const serverFlag = typeof flags.server === \"string\" ? flags.server : undefined;\n const environment = typeof flags.environment === \"string\" ? flags.environment : \"development\";\n const source =\n options.resolveServer === false\n ? { value: options.source ?? \"\", origin: \"default\" as const }\n : await resolveServer({ cwd, env: process.env, serverFlag, environment });\n const json = this.jsonEnabled();\n const isTTY = Boolean(process.stdout.isTTY && process.stdin.isTTY);\n const verbose = Boolean(flags.verbose);\n const debug = Boolean(flags.debug);\n // Default to `info` (3) so users see step-by-step narration (start/info/\n // success/box). `--json` silences consola entirely so the structured\n // envelope is the only thing on stdout. `--debug` raises to 4 (debug);\n // `--verbose` is reserved for richer per-step detail and currently maps\n // to the same level as default.\n consola.level = json ? -999 : debug ? 4 : 3;\n // Drop the right-aligned timestamp the FancyReporter adds by default.\n // Timestamps add no value in a one-off CLI run, wrap awkwardly on long\n // lines (e.g. created-schema URL), and clutter the visual rhythm of the\n // ◐/✔/ℹ glyphs that anchor each step.\n consola.options.formatOptions = {\n ...consola.options.formatOptions,\n date: false,\n colors: true,\n compact: true,\n };\n this.meta = {\n cwd,\n nonInteractive: Boolean(flags[\"non-interactive\"]) || !isTTY || json,\n dryRun: Boolean(flags[\"dry-run\"]),\n force: Boolean(flags.force),\n command: this.id ?? \"(default)\",\n cliVersion: this.config.version,\n source: source.value,\n serverFlag,\n verbose,\n debug,\n env: process.env,\n isTTY,\n };\n return this.meta;\n }\n\n /**\n * Final step of every command: in human mode it prints the rendered result\n * (oclif suppresses {@link Command.log} under `--json`); it returns the\n * envelope so oclif's `--json` path serialises it.\n */\n protected emit(result: CommandResult): JsonEnvelope {\n const normalized = normalizeCommandResult(result, this.meta);\n this.log(renderPretty(normalized, this.meta));\n return toEnvelope(normalized, this.meta);\n }\n\n /**\n * Renders any thrown error as the failure envelope and exits with its code.\n * A flag-parse error fires before {@link toMeta} runs, so the local `meta`\n * here refreshes `command` from the now-resolved command id to keep the\n * envelope's `command` field accurate.\n */\n protected override async catch(error: unknown): Promise<never> {\n const meta: GlobalOptions = { ...this.meta, command: this.id ?? this.meta.command };\n const zitadelError = toZitadelError(error);\n if (this.jsonEnabled()) {\n this.logJson(toErrorEnvelope(zitadelError, meta));\n } else {\n this.logToStderr(renderError(zitadelError, meta));\n }\n return this.exit(zitadelError.exitCode);\n }\n\n /**\n * Context used before {@link toMeta} runs, so an error thrown during flag\n * parsing still renders a complete envelope. Version comes from oclif's\n * resolved {@link Command.config}.\n */\n private fallbackMeta(): GlobalOptions {\n return {\n cwd: resolveCwd(undefined),\n nonInteractive: false,\n dryRun: false,\n force: false,\n command: \"(default)\",\n cliVersion: this.config.version,\n source: \"\",\n verbose: false,\n debug: false,\n env: process.env,\n isTTY: Boolean(process.stdout.isTTY && process.stdin.isTTY),\n };\n }\n}\n\nfunction normalizeCommandResult(result: CommandResult, meta: GlobalOptions): CommandResult {\n if (result.status === \"ok\") {\n return {\n ...result,\n data: normalizeDataNextCommands(result.data, meta),\n };\n }\n return {\n ...result,\n data: normalizeDataNextCommands(result.data, meta),\n nextCommands: normalizePublicCliCommands(result.nextCommands, meta.cliVersion),\n };\n}\n\nfunction normalizeDataNextCommands(data: unknown, meta: GlobalOptions): unknown {\n if (!isObject(data) || !Array.isArray(data.next_commands)) {\n return data;\n }\n return {\n ...data,\n next_commands: data.next_commands.map((command) =>\n typeof command === \"string\" ? normalizePublicCliCommand(command, meta.cliVersion) : command,\n ),\n };\n}\n\n/** Wraps a {@link CommandResult} with the invocation metadata into the final envelope. */\nfunction toEnvelope(result: CommandResult, meta: GlobalOptions): JsonEnvelope {\n const base: EnvelopeMeta = {\n cli_version: meta.cliVersion,\n command: meta.command,\n source: meta.source,\n };\n if (result.status === \"ok\") {\n return {\n ...base,\n status: \"ok\",\n data: result.data,\n warnings: result.warnings ? [...result.warnings] : [],\n };\n }\n return {\n ...base,\n status: \"skipped\",\n reason: result.reason,\n data: result.data,\n next_commands: result.nextCommands ? [...result.nextCommands] : undefined,\n };\n}\n\n/** Builds the failure envelope from a {@link ZitadelError} and the invocation metadata. */\nfunction toErrorEnvelope(error: ZitadelError, meta: GlobalOptions): ErrorEnvelope {\n return {\n status: \"error\",\n cli_version: meta.cliVersion,\n command: meta.command,\n source: meta.source,\n code: error.code,\n message: error.message,\n hint: error.hint,\n next_commands: normalizePublicCliCommands(error.nextCommands, meta.cliVersion),\n details: error.details,\n };\n}\n\n/**\n * Renders a {@link CommandResult} as human-facing text for non-JSON mode. A\n * command may supply a bespoke `pretty` string (e.g. the `apply` plan diff);\n * otherwise success payloads are summarised by {@link formatData} and skips are\n * shown with their reason and follow-up commands.\n */\nfunction renderPretty(result: CommandResult, meta: GlobalOptions): string {\n if (result.pretty !== undefined) {\n return result.pretty;\n }\n if (result.status === \"ok\") {\n return formatData(result.data, result.warnings ? [...result.warnings] : [], meta);\n }\n const lines = [`Skipped: ${result.reason}${suffixBlock(meta)}`];\n if (result.nextCommands && result.nextCommands.length > 0) {\n lines.push(\"Next:\");\n for (const cmd of result.nextCommands) {\n lines.push(` $ ${cmd}`);\n }\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Renders a {@link ZitadelError} as a human-readable block for stderr: the\n * coded message, an optional hint, and any suggested next commands.\n */\nfunction renderError(error: ZitadelError, meta: GlobalOptions): string {\n const lines = [`Error ${error.code}: ${error.message}`];\n if (error.hint) {\n lines.push(error.hint);\n }\n const nextCommands = normalizePublicCliCommands(error.nextCommands, meta.cliVersion);\n if (nextCommands && nextCommands.length > 0) {\n lines.push(\"Next:\");\n for (const cmd of nextCommands) {\n lines.push(` $ ${cmd}`);\n }\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatData(data: unknown, warnings: string[], opts: GlobalOptions): string {\n if (typeof data === \"string\") {\n const suffix = sourceSuffix(opts);\n return suffix ? `${data}\\n${suffix}` : data;\n }\n\n const lines: string[] = [];\n const titleLine =\n isObject(data) && typeof data.title === \"string\"\n ? String(data.title)\n : \"Zitadel command completed.\";\n lines.push(titleLine);\n const suffix = sourceSuffix(opts);\n if (suffix) {\n lines.push(suffix);\n }\n\n if (isObject(data)) {\n renderKnownSections(lines, data);\n\n if (Array.isArray(data.next_actions) && data.next_actions.length > 0) {\n lines.push(\"\");\n lines.push(\"Next:\");\n for (const action of data.next_actions) {\n lines.push(` ${String(action)}`);\n }\n }\n if (Array.isArray(data.next_commands) && data.next_commands.length > 0) {\n if (!Array.isArray(data.next_actions) || data.next_actions.length === 0) {\n lines.push(\"\");\n lines.push(\"Next:\");\n }\n for (const cmd of data.next_commands) {\n lines.push(` $ ${String(cmd)}`);\n }\n }\n }\n\n for (const warning of warnings.filter((warning) => !warningRenderedInChecks(data, warning))) {\n lines.push(`Warning: ${warning}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction warningRenderedInChecks(data: unknown, warning: string): boolean {\n if (!isObject(data) || !Array.isArray(data.checks)) {\n return false;\n }\n return data.checks.some((check) => {\n if (!isObject(check) || check.status !== \"warn\") {\n return false;\n }\n return warning === `${String(check.name ?? \"check\")}: ${String(check.message ?? \"\")}`;\n });\n}\n\nfunction renderKnownSections(lines: string[], data: Record<string, unknown>): void {\n if (isObject(data.project)) {\n const project = data.project;\n const segments: string[] = [];\n if (typeof project.project_id === \"string\") {\n segments.push(`project=${project.project_id}`);\n }\n if (typeof project.lifecycle === \"string\") {\n segments.push(`lifecycle=${project.lifecycle}`);\n }\n if (typeof project.issuer === \"string\") {\n segments.push(`issuer=${project.issuer}`);\n }\n if (segments.length > 0) {\n lines.push(`Project: ${segments.join(\" \")}`);\n }\n }\n\n if (typeof data.framework === \"string\") {\n lines.push(`framework=${data.framework}`);\n }\n\n if (Array.isArray(data.files_written) || Array.isArray(data.files_skipped)) {\n const written = Array.isArray(data.files_written) ? data.files_written.length : 0;\n const skippedCount = Array.isArray(data.files_skipped) ? data.files_skipped.length : 0;\n lines.push(`Files: ${written} written, ${skippedCount} unchanged`);\n }\n\n if (isObject(data.apply)) {\n const apply = data.apply;\n const bits: string[] = [];\n if (typeof apply.config_version === \"number\") {\n bits.push(`v${apply.config_version}`);\n }\n if (typeof apply.hash === \"string\") {\n bits.push(`hash=${String(apply.hash).slice(0, 12)}`);\n }\n if (typeof apply.environment === \"string\") {\n bits.push(`env=${apply.environment}`);\n }\n if (bits.length > 0) {\n lines.push(`Apply: ${bits.join(\" \")}`);\n }\n }\n\n if (Array.isArray(data.checks) && data.checks.length > 0) {\n lines.push(\"Checks:\");\n for (const check of data.checks) {\n if (!isObject(check)) {\n continue;\n }\n const status = check.status === \"pass\" ? \"ok\" : check.status === \"warn\" ? \"warn\" : \"fail\";\n lines.push(` [${status}] ${String(check.name ?? \"check\")}: ${String(check.message ?? \"\")}`);\n }\n }\n}\n\nfunction sourceSuffix(opts: GlobalOptions): string {\n try {\n const url = new URL(opts.source);\n if (url.host === \"api.zitadel.cloud\") {\n return \"\";\n }\n return `(server: ${url.host})`;\n } catch {\n return \"\";\n }\n}\n\nfunction suffixBlock(opts: GlobalOptions): string {\n const suffix = sourceSuffix(opts);\n return suffix ? ` ${suffix}` : \"\";\n}\n"],"mappings":"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"}