@zitadel/cli 0.1.0-alpha.13 → 0.1.0-alpha.15
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 +137 -57
- package/SKILLS.md +26 -13
- package/dist/commands/apply.mjs +11 -6
- package/dist/commands/apply.mjs.map +1 -1
- package/dist/commands/doctor.mjs +89 -12
- package/dist/commands/doctor.mjs.map +1 -1
- package/dist/commands/eject.mjs +4 -4
- package/dist/commands/logs.mjs +2 -2
- package/dist/commands/plan.mjs +6 -4
- package/dist/commands/plan.mjs.map +1 -1
- package/dist/commands/reset.mjs +2 -2
- package/dist/commands/schemas/list.mjs +134 -0
- package/dist/commands/schemas/list.mjs.map +1 -0
- package/dist/commands/setup.mjs +158 -23
- package/dist/commands/setup.mjs.map +1 -1
- package/dist/commands/start.mjs +4 -4
- package/dist/commands/status.mjs +3 -3
- package/dist/commands/stop.mjs +3 -3
- package/dist/{docker-Djz6BLp9.mjs → docker-D7BSD5C9.mjs} +3 -3
- package/dist/{docker-Djz6BLp9.mjs.map → docker-D7BSD5C9.mjs.map} +1 -1
- package/dist/{docker-guidance-D-33g1uV.mjs → docker-guidance-mcTT3_0E.mjs} +2 -2
- package/dist/{docker-guidance-D-33g1uV.mjs.map → docker-guidance-mcTT3_0E.mjs.map} +1 -1
- package/dist/environment-BQF7LeCz.mjs +17 -0
- package/dist/environment-BQF7LeCz.mjs.map +1 -0
- package/dist/{oclif-BoUVygsZ.mjs → oclif-Bm-FkF6z.mjs} +66 -13
- package/dist/oclif-Bm-FkF6z.mjs.map +1 -0
- package/dist/{orca-DU8myWGm.mjs → orca-CpXj_XsA.mjs} +46 -94
- package/dist/orca-CpXj_XsA.mjs.map +1 -0
- package/dist/{ports-B09RjuHx.mjs → ports-CxBKS1ga.mjs} +1 -1
- package/dist/{ports-B09RjuHx.mjs.map → ports-CxBKS1ga.mjs.map} +1 -1
- package/dist/{processes-Cw8TO1SY.mjs → processes-BVqYsxT8.mjs} +1 -1
- package/dist/{processes-Cw8TO1SY.mjs.map → processes-BVqYsxT8.mjs.map} +1 -1
- package/dist/{project-B1qVQMKS.mjs → project-Dk7V0xka.mjs} +3 -3
- package/dist/{project-B1qVQMKS.mjs.map → project-Dk7V0xka.mjs.map} +1 -1
- package/dist/{sync-B8Z2it_E.mjs → sync-CYuHVQT5.mjs} +344 -116
- package/dist/sync-CYuHVQT5.mjs.map +1 -0
- package/dist/user-schema-DDz5-lX5.mjs +13 -0
- package/dist/user-schema-DDz5-lX5.mjs.map +1 -0
- package/oclif.manifest.json +106 -1
- package/package.json +6 -5
- package/dist/oclif-BoUVygsZ.mjs.map +0 -1
- package/dist/orca-DU8myWGm.mjs.map +0 -1
- package/dist/sync-B8Z2it_E.mjs.map +0 -1
package/dist/commands/doctor.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { C as isObject, E as ZitadelError, a as DEFAULT_LOCAL_SERVER_PORT, b as publicCliCommand, c as checkLocalServerHealth, l as defaultLocalServerImageForCliVersion, m as readRuntimeMetadata, p as localServerUrl, s as assertLocalStateWritable, t as BaseCommand } from "../oclif-
|
|
2
|
-
import { i as issuerFromPort, t as createOrca } from "../orca-
|
|
3
|
-
import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { t as
|
|
1
|
+
import { C as isObject, E as ZitadelError, a as DEFAULT_LOCAL_SERVER_PORT, b as publicCliCommand, c as checkLocalServerHealth, l as defaultLocalServerImageForCliVersion, m as readRuntimeMetadata, p as localServerUrl, s as assertLocalStateWritable, t as BaseCommand } from "../oclif-Bm-FkF6z.mjs";
|
|
2
|
+
import { i as issuerFromPort, t as createOrca } from "../orca-CpXj_XsA.mjs";
|
|
3
|
+
import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-Dk7V0xka.mjs";
|
|
4
|
+
import { t as SCHEMAS_DIR } from "../user-schema-DDz5-lX5.mjs";
|
|
5
|
+
import { n as listenersForPort } from "../ports-CxBKS1ga.mjs";
|
|
6
|
+
import { d as assertServerPackageAvailable, o as imageAvailable, r as dockerAvailable } from "../docker-D7BSD5C9.mjs";
|
|
7
|
+
import { n as dockerUnavailableMessage, t as dockerRuntimeGuidance } from "../docker-guidance-mcTT3_0E.mjs";
|
|
8
|
+
import { t as discoverManagedRuntimeProcesses } from "../processes-BVqYsxT8.mjs";
|
|
9
|
+
import { chmod, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
10
|
+
import { join } from "node:path";
|
|
8
11
|
import { Flags } from "@oclif/core";
|
|
9
12
|
import consola from "consola";
|
|
10
|
-
import {
|
|
11
|
-
import { chmod, readFile, stat, writeFile } from "node:fs/promises";
|
|
12
|
-
import "@zitadel/api/generated/endpoints/zitadelNextGen.zod";
|
|
13
|
+
import { schemaConfigSchema } from "@zitadel/config/schemas";
|
|
13
14
|
//#region src/commands/doctor/checks/types.ts
|
|
14
15
|
/**
|
|
15
16
|
* Base class for checks: subclasses declare `name`, `path`, and a success
|
|
@@ -150,8 +151,8 @@ var FrameworkCheck = class extends AbstractSanityCheck {
|
|
|
150
151
|
* Reconstructs a {@link PatchContext} from the on-disk project (config, secret)
|
|
151
152
|
* plus fresh framework detection, so a patcher repair can rebuild its plan.
|
|
152
153
|
* Used by the dependency check's `fix`, which reclaims the framework-specific
|
|
153
|
-
* SDK package via `patcher.repair`.
|
|
154
|
-
*
|
|
154
|
+
* SDK package via `patcher.repair`. Schema and flow config are user-editable
|
|
155
|
+
* sync resources, not patcher inputs, so nothing here reads them.
|
|
155
156
|
*/
|
|
156
157
|
async function loadPatchContext(cwd, orca, cliVersion) {
|
|
157
158
|
const config = await readZitadelConfig(cwd);
|
|
@@ -235,6 +236,81 @@ var ProjectMatchCheck = class extends AbstractSanityCheck {
|
|
|
235
236
|
}
|
|
236
237
|
};
|
|
237
238
|
//#endregion
|
|
239
|
+
//#region src/lib/json-dir.ts
|
|
240
|
+
/**
|
|
241
|
+
* Read every `*.json` file under `absDir` and return each body as a plain
|
|
242
|
+
* object. Files are read in lexical filename order so the result is
|
|
243
|
+
* deterministic for downstream hashing and diffs. Each file is parsed by
|
|
244
|
+
* `JSON.parse`; this function does **not** apply any schema validation —
|
|
245
|
+
* unknown keys, forward-compatible fields, and `${VAR}` placeholders survive
|
|
246
|
+
* intact. Callers that need a typed shape pass the result through their
|
|
247
|
+
* resource's Zod schema.
|
|
248
|
+
*
|
|
249
|
+
* Returns an empty array when the directory is missing. Throws `E_VALIDATION`
|
|
250
|
+
* `ZitadelError` on invalid JSON or when a file's root value is not an object.
|
|
251
|
+
*
|
|
252
|
+
* @param absDir - Absolute path to the directory to scan.
|
|
253
|
+
*/
|
|
254
|
+
async function readJsonDir(absDir) {
|
|
255
|
+
let entries;
|
|
256
|
+
try {
|
|
257
|
+
entries = await readdir(absDir);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") return [];
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
const result = [];
|
|
263
|
+
for (const entry of entries.filter((name) => name.endsWith(".json")).sort()) {
|
|
264
|
+
const abs = join(absDir, entry);
|
|
265
|
+
let raw;
|
|
266
|
+
try {
|
|
267
|
+
raw = JSON.parse(await readFile(abs, "utf8"));
|
|
268
|
+
} catch {
|
|
269
|
+
throw new ZitadelError("E_VALIDATION", `${entry} is not valid JSON`);
|
|
270
|
+
}
|
|
271
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new ZitadelError("E_VALIDATION", `${entry} must contain a JSON object at the root`);
|
|
272
|
+
result.push(raw);
|
|
273
|
+
}
|
|
274
|
+
return result;
|
|
275
|
+
}
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/commands/doctor/checks/schema.ts
|
|
278
|
+
/**
|
|
279
|
+
* Verifies local schema config files round-trip through the canonical
|
|
280
|
+
* `schemaConfigSchema` from `@zitadel/config/schemas` — the same Zod the
|
|
281
|
+
* sync engine validates with, so doctor and `apply` can never disagree
|
|
282
|
+
* about a file. The union enforces the `kind` discriminator
|
|
283
|
+
* (`user-schema` / `schema-url`) and the `metaSchema`/`x-auth-methods`/etc.
|
|
284
|
+
* fields the platform requires.
|
|
285
|
+
*/
|
|
286
|
+
var SchemaCheck = class extends AbstractSanityCheck {
|
|
287
|
+
name = "schema";
|
|
288
|
+
path = SCHEMAS_DIR;
|
|
289
|
+
summary = "User schemas are valid Zitadel schema bodies";
|
|
290
|
+
/**
|
|
291
|
+
* An empty `.zitadel/schemas/` is a warning, not a failure: projects
|
|
292
|
+
* created before editable config existed were seeded server-side and have
|
|
293
|
+
* no local schema files, and there is no safe auto-fix that could invent
|
|
294
|
+
* them. Only invalid files fail the check.
|
|
295
|
+
*/
|
|
296
|
+
async run(ctx) {
|
|
297
|
+
if ((await readJsonDir(join(ctx.cwd, ".zitadel/schemas"))).length === 0) return {
|
|
298
|
+
name: this.name,
|
|
299
|
+
status: "warn",
|
|
300
|
+
message: `No schema files found in ${SCHEMAS_DIR} — this project predates editable schema config or setup was interrupted. New projects scaffold editable defaults via \`zitadel setup\`.`,
|
|
301
|
+
path: this.path
|
|
302
|
+
};
|
|
303
|
+
return super.run(ctx);
|
|
304
|
+
}
|
|
305
|
+
async verify(ctx) {
|
|
306
|
+
const schemas = await readJsonDir(join(ctx.cwd, SCHEMAS_DIR));
|
|
307
|
+
for (const schema of schemas) {
|
|
308
|
+
const result = schemaConfigSchema.safeParse(schema);
|
|
309
|
+
if (!result.success) throw new Error(result.error.issues.map((issue) => `${issue.path.join(".") || "/"} ${issue.message}`).join("; "));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
//#endregion
|
|
238
314
|
//#region src/commands/doctor/checks/index.ts
|
|
239
315
|
/** Every diagnostic the `doctor` command runs, in display order. */
|
|
240
316
|
const SANITY_CHECKS = [
|
|
@@ -244,6 +320,7 @@ const SANITY_CHECKS = [
|
|
|
244
320
|
new GitignoreCheck(),
|
|
245
321
|
new EnvExampleCheck(),
|
|
246
322
|
new FrameworkCheck(),
|
|
323
|
+
new SchemaCheck(),
|
|
247
324
|
new DependencyCheck(),
|
|
248
325
|
new ProjectMatchCheck()
|
|
249
326
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.mjs","names":[],"sources":["../../src/commands/doctor/checks/types.ts","../../src/commands/doctor/checks/config.ts","../../src/commands/doctor/checks/secret.ts","../../src/commands/doctor/checks/secret-permissions.ts","../../src/commands/doctor/checks/gitignore.ts","../../src/commands/doctor/checks/env-example.ts","../../src/commands/doctor/checks/framework.ts","../../src/commands/doctor/patch-context.ts","../../src/commands/doctor/checks/dependency.ts","../../src/commands/doctor/checks/project-match.ts","../../src/commands/doctor/checks/index.ts","../../src/commands/doctor/index.ts"],"sourcesContent":["import type { Orca } from \"../../../lib/orca\";\n\n/** Pass/fail/advisory outcome of a single {@link SanityCheck}. */\nexport type CheckOutcome = {\n details?: unknown;\n name: string;\n status: \"pass\" | \"warn\" | \"fail\";\n message: string;\n path?: string;\n};\n\n/** Everything a check needs to inspect or repair a project. */\nexport type CheckContext = {\n readonly cwd: string;\n readonly orca: Orca;\n readonly cliVersion: string;\n /** When true, {@link SanityCheck.fix} must preview without writing. */\n readonly dryRun: boolean;\n};\n\n/**\n * One diagnostic the `doctor` command runs. Each concrete check is a small\n * standalone class that both verifies its concern ({@link run}) and knows how\n * to repair it ({@link fix}); the command executes every registered check,\n * aggregates the {@link CheckOutcome}s, and (under `--fix`) repairs the ones\n * that failed.\n */\nexport interface SanityCheck {\n /** Stable identifier surfaced in logs and the JSON envelope. */\n readonly name: string;\n run(ctx: CheckContext): Promise<CheckOutcome>;\n /** Repair what this check verifies. A no-op when there is no safe auto-fix. */\n fix(ctx: CheckContext): Promise<void>;\n}\n\n/**\n * Base class for checks: subclasses declare `name`, `path`, and a success\n * `summary`, and implement the single {@link verify} method that throws on\n * failure. {@link run} wraps it so a thrown error becomes a `fail` outcome\n * carrying the error message, and success becomes a `pass` with `summary`.\n *\n * {@link fix} defaults to a no-op: checks whose failure has no safe automatic\n * remedy (a missing secret, an invalid user schema) simply do not override it.\n */\nexport abstract class AbstractSanityCheck implements SanityCheck {\n abstract readonly name: string;\n abstract readonly path: string;\n protected abstract readonly summary: string;\n\n /** Throw to signal failure; the thrown message is surfaced to the user. */\n protected abstract verify(ctx: CheckContext): Promise<void>;\n\n async run(ctx: CheckContext): Promise<CheckOutcome> {\n try {\n await this.verify(ctx);\n return { name: this.name, status: \"pass\", message: this.summary, path: this.path };\n } catch (error) {\n return {\n name: this.name,\n status: \"fail\",\n message: error instanceof Error ? error.message : String(error),\n path: this.path,\n };\n }\n }\n\n async fix(_ctx: CheckContext): Promise<void> {\n return;\n }\n}\n","import { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `zitadel.json` exists and parses. */\nexport class ConfigCheck extends AbstractSanityCheck {\n readonly name = \"config\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"zitadel.json parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelConfig(ctx.cwd);\n }\n}\n","import { readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` exists and parses. */\nexport class SecretCheck extends AbstractSanityCheck {\n readonly name = \"secret\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelSecret(ctx.cwd);\n }\n}\n","import { chmod, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` is locked down to `0600`, and re-locks it on fix. */\nexport class SecretPermissionsCheck extends AbstractSanityCheck {\n readonly name = \"secret-permissions\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret has 0600 permissions\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const mode = (await stat(join(ctx.cwd, \".zitadel/secret\"))).mode & 0o777;\n if (mode !== 0o600) {\n throw new Error(`expected 0600, got ${mode.toString(8)}`);\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n if (ctx.dryRun) {\n return;\n }\n await chmod(join(ctx.cwd, \".zitadel/secret\"), 0o600);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The entries `.gitignore` must carry to keep secrets and env files untracked. */\nconst REQUIRED_ENTRIES = [\".zitadel/secret\", \".env*\", \"!.env.example\"];\n\n/** Verifies `.gitignore` excludes the local secret and env files; appends any missing. */\nexport class GitignoreCheck extends AbstractSanityCheck {\n readonly name = \"gitignore\";\n readonly path = \".gitignore\";\n protected readonly summary = \".gitignore protects local secret/env files\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const lines = (await readFile(join(ctx.cwd, \".gitignore\"), \"utf8\")).split(/\\r?\\n/g);\n for (const entry of REQUIRED_ENTRIES) {\n if (!lines.includes(entry)) {\n throw new Error(`missing ${entry}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".gitignore\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const lines = existing.split(/\\r?\\n/g);\n const missing = REQUIRED_ENTRIES.filter((entry) => !lines.includes(entry));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.join(\"\\n\")}\\n`);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The keys `.env.example` must document for a Zitadel-managed project. */\nconst REQUIRED_KEYS = [\"ZITADEL_PROJECT_ID\", \"ZITADEL_ENVIRONMENT\", \"ZITADEL_ISSUER\"];\n\n/** Verifies `.env.example` documents the required Zitadel keys; appends any missing. */\nexport class EnvExampleCheck extends AbstractSanityCheck {\n readonly name = \"env-example\";\n readonly path = \".env.example\";\n protected readonly summary = \".env.example references required keys\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const contents = await readFile(join(ctx.cwd, \".env.example\"), \"utf8\");\n for (const key of REQUIRED_KEYS) {\n if (!contents.includes(`${key}=`)) {\n throw new Error(`missing ${key}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".env.example\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const missing = REQUIRED_KEYS.filter((key) => !existing.includes(`${key}=`));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.map((key) => `${key}=`).join(\"\\n\")}\\n`);\n }\n}\n","import { isObject } from \"../../../lib/json\";\nimport { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies the framework detected on disk matches the one recorded in config. */\nexport class FrameworkCheck extends AbstractSanityCheck {\n readonly name = \"framework\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"Detected framework matches recorded framework\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const detected = await ctx.orca.detect(ctx.cwd);\n const recorded = isObject(config.framework) ? config.framework.id : undefined;\n if (recorded !== detected.id) {\n throw new Error(`expected ${String(recorded)}, detected ${detected.id}`);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { issuerFromPort, type FrameworkFacts, type Orca } from \"../../lib/orca\";\nimport type { PatchContext } from \"../../lib/orca/patchers/types\";\nimport { readDevelopmentIssuer, readRendererId, readZitadelConfig, readZitadelSecret } from \"../../lib/project\";\n\n/**\n * Reconstructs a {@link PatchContext} from the on-disk project (config, secret)\n * plus fresh framework detection, so a patcher repair can rebuild its plan.\n * Used by the dependency check's `fix`, which reclaims the framework-specific\n * SDK package via `patcher.repair`. The user schema and flow definition are\n * server-owned and no longer scaffolded locally, so nothing here reads them.\n */\nexport async function loadPatchContext(\n cwd: string,\n orca: Orca,\n cliVersion: string,\n): Promise<PatchContext> {\n const config = await readZitadelConfig(cwd);\n const secret = await readZitadelSecret(cwd);\n const framework = await orca.detect(cwd);\n return {\n framework,\n rendererId: readRendererId(config),\n issuer: await resolveIssuer(cwd, config, framework),\n server: typeof config.server === \"string\" ? config.server : \"\",\n cliVersion,\n project: {\n id: secret.project_id,\n projectSecret: secret.project_secret,\n previewSecret: secret.preview_secret,\n previewOrigins: secret.preview_origins,\n createdAt: secret.created_at,\n },\n };\n}\n\nasync function resolveIssuer(\n cwd: string,\n config: Record<string, unknown>,\n facts: FrameworkFacts,\n): Promise<string> {\n const fromConfig = readDevelopmentIssuer(config);\n if (fromConfig && fromConfig.length > 0) {\n return fromConfig;\n }\n const state = await readState(cwd);\n if (typeof state?.dev_port === \"number\") {\n return issuerFromPort(state.dev_port);\n }\n return facts.url;\n}\n\nasync function readState(cwd: string): Promise<{ dev_port?: number } | undefined> {\n try {\n const contents = await readFile(join(cwd, \".zitadel/state.json\"), \"utf8\");\n return JSON.parse(contents) as { dev_port?: number };\n } catch {\n return undefined;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { loadPatchContext } from \"../patch-context\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/**\n * Verifies the project still declares a Zitadel SDK dependency in\n * `package.json`. The patcher adds a scoped package (e.g.\n * `@zitadel/sdk-next`); the check is generic over the `@zitadel*`\n * scope so any framework renderer's dependency satisfies it.\n */\nexport class DependencyCheck extends AbstractSanityCheck {\n readonly name = \"dependency\";\n readonly path = \"package.json\";\n protected readonly summary = \"package.json depends on a Zitadel SDK package\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const pkg = JSON.parse(await readFile(join(ctx.cwd, \"package.json\"), \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const names = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n if (!names.some((name) => name.startsWith(\"@zitadel\"))) {\n throw new Error(\"no @zitadel* dependency found in package.json\");\n }\n }\n\n /**\n * Repairs by reclaiming the patcher's managed artifacts: rebuilds the\n * `PatchContext` from disk and calls `patcher.repair`, which re-adds the\n * SDK dependency via its `add-dep` op. The exact package name is framework\n * + renderer specific and known only to the patcher (which deliberately\n * hides its file-op plan behind the family-neutral `Patcher` interface),\n * so going through `repair` is the only sanctioned path.\n */\n override async fix(ctx: CheckContext): Promise<void> {\n const patchCtx = await loadPatchContext(ctx.cwd, ctx.orca, ctx.cliVersion);\n await ctx.orca.patcherFor(patchCtx.framework.id).repair(patchCtx, {\n cwd: ctx.cwd,\n dryRun: ctx.dryRun,\n force: true,\n });\n }\n}\n","import { readZitadelConfig, readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret`'s project_id matches `zitadel.json`'s project. */\nexport class ProjectMatchCheck extends AbstractSanityCheck {\n readonly name = \"project-match\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret project_id matches zitadel.json project\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const secret = await readZitadelSecret(ctx.cwd);\n const configProject = typeof config.project === \"string\" ? config.project : undefined;\n if (secret.project_id !== configProject) {\n throw new Error(\".zitadel/secret project_id does not match zitadel.json project\");\n }\n }\n}\n","/**\n * Public surface for the doctor sanity checks. The `doctor` command imports\n * {@link SANITY_CHECKS} and runs every entry, aggregating the outcomes. Each\n * check is a small standalone class (see its own file); add a new diagnostic\n * by writing a class and appending an instance to the registry below.\n */\nimport type { SanityCheck } from \"./types\";\nimport { ConfigCheck } from \"./config\";\nimport { SecretCheck } from \"./secret\";\nimport { SecretPermissionsCheck } from \"./secret-permissions\";\nimport { GitignoreCheck } from \"./gitignore\";\nimport { EnvExampleCheck } from \"./env-example\";\nimport { FrameworkCheck } from \"./framework\";\nimport { DependencyCheck } from \"./dependency\";\nimport { ProjectMatchCheck } from \"./project-match\";\n\nexport type { SanityCheck, CheckContext, CheckOutcome } from \"./types\";\nexport { AbstractSanityCheck } from \"./types\";\nexport { ConfigCheck } from \"./config\";\nexport { SecretCheck } from \"./secret\";\nexport { SecretPermissionsCheck } from \"./secret-permissions\";\nexport { GitignoreCheck } from \"./gitignore\";\nexport { EnvExampleCheck } from \"./env-example\";\nexport { FrameworkCheck } from \"./framework\";\nexport { SchemaCheck } from \"./schema\";\nexport { DependencyCheck } from \"./dependency\";\nexport { ProjectMatchCheck } from \"./project-match\";\n\n/** Every diagnostic the `doctor` command runs, in display order. */\nexport const SANITY_CHECKS: ReadonlyArray<SanityCheck> = [\n new ConfigCheck(),\n new SecretCheck(),\n new SecretPermissionsCheck(),\n new GitignoreCheck(),\n new EnvExampleCheck(),\n new FrameworkCheck(),\n // SchemaCheck is disabled: the user schema is now provisioned server-side\n // and no longer scaffolded into `.zitadel/schemas/user.json`, so there is\n // no local file to verify. The check is kept (imported/exported below) for\n // the future pull-based workflow that will re-introduce local resources.\n // new SchemaCheck(),\n new DependencyCheck(),\n new ProjectMatchCheck(),\n];\n","import { Flags } from \"@oclif/core\";\nimport consola from \"consola\";\n\nimport { ZitadelError } from \"../../lib/errors\";\nimport { assertServerPackageAvailable } from \"../../lib/local-server/binary\";\nimport { dockerAvailable, imageAvailable } from \"../../lib/local-server/docker\";\nimport {\n dockerRuntimeGuidance,\n dockerUnavailableMessage,\n} from \"../../lib/local-server/docker-guidance\";\nimport {\n discoverManagedRuntimeProcesses,\n type ManagedRuntimeProcess,\n} from \"../../lib/local-server/processes\";\nimport {\n DEFAULT_LOCAL_SERVER_PORT,\n assertLocalStateWritable,\n checkLocalServerHealth,\n defaultLocalServerImageForCliVersion,\n localServerUrl,\n readRuntimeMetadata,\n type RuntimeBackend,\n type RuntimeMetadata,\n} from \"../../lib/local-server/runtime\";\nimport { BaseCommand, type JsonEnvelope } from \"../../lib/oclif\";\nimport { createOrca } from \"../../lib/orca\";\nimport { hasZitadelConfig } from \"../../lib/project\";\nimport { listenersForPort } from \"../../lib/prober/ports\";\nimport { publicCliCommand } from \"../../lib/public-cli\";\nimport { SANITY_CHECKS, type CheckContext, type CheckOutcome } from \"./checks\";\n\nconst LOCAL_RUNTIME_CHECK_NAMES = new Set([\n \"server-binary\",\n \"docker-cli\",\n \"image\",\n \"state-dir\",\n \"port\",\n \"runtime\",\n]);\n\n/**\n * `zitadel doctor` — verify generated files and local state.\n *\n * Runs every registered {@link SANITY_CHECKS} entry and emits the aggregate\n * result; if any check fails it throws `E_VALIDATION` carrying the full check\n * details. With `--fix`, each failing check first attempts its own repair (a\n * no-op for checks with no safe automatic remedy), then the battery re-runs.\n *\n * The `--fix` loop is best-effort: a repair that throws (e.g. a missing\n * prerequisite file the check itself would also flag) is logged at debug\n * level and skipped, not propagated — the post-fix re-verify still reports\n * whatever remains broken.\n */\nexport default class Doctor extends BaseCommand {\n static override description = \"Verify local runtime and project state.\";\n static override flags = {\n fix: Flags.boolean({ description: \"Re-apply missing managed files.\" }),\n image: Flags.string({ description: \"Container image to check.\" }),\n port: Flags.integer({ description: \"Local HTTP port.\", default: DEFAULT_LOCAL_SERVER_PORT }),\n runtime: Flags.string({\n description: \"Local runtime backend.\",\n options: [\"binary\", \"docker\"],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Doctor);\n const port = flags.port ?? DEFAULT_LOCAL_SERVER_PORT;\n await this.toMeta(flags, { resolveServer: false, source: localServerUrl(port) });\n const { cwd, dryRun } = this.meta;\n const existingRuntime = await readRuntimeMetadata(cwd);\n const runtimeBackend = resolveRuntimeBackend({\n runtime: flags.runtime,\n image: flags.image,\n envImage: this.meta.env.ZITADEL_LOCAL_IMAGE,\n existingRuntime,\n });\n const image =\n flags.image ??\n this.meta.env.ZITADEL_LOCAL_IMAGE ??\n defaultLocalServerImageForCliVersion(this.meta.cliVersion);\n const runtimeChecks = await runLocalRuntimeChecks(cwd, runtimeBackend, image, port);\n const hasConfig = await hasZitadelConfig(cwd);\n const ctx: CheckContext = { cwd, orca: createOrca(), cliVersion: this.meta.cliVersion, dryRun };\n\n if (hasConfig && flags.fix) {\n const before = await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)));\n for (const [index, check] of SANITY_CHECKS.entries()) {\n if (before[index]?.status !== \"fail\") {\n continue;\n }\n try {\n await check.fix(ctx);\n } catch (error) {\n consola.debug(`doctor --fix: ${check.name} repair failed`, error);\n }\n }\n }\n\n const projectChecks = hasConfig\n ? await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)))\n : [];\n const checks = [...runtimeChecks, ...projectChecks];\n const failed = checks.filter((check) => check.status === \"fail\");\n const warnings = checks.filter((check) => check.status === \"warn\");\n const warningAdvice = advisoryForWarnings(warnings, this.meta.cliVersion);\n this.recordTelemetry({\n runtime: runtimeBackend,\n checks_total: checks.length,\n checks_failed: failed.length,\n checks_warn: warnings.length,\n failed_checks: failed.length > 0 ? failed.map((check) => check.name).join(\",\") : undefined,\n });\n const data = {\n title:\n failed.length > 0\n ? \"Zitadel doctor found issues.\"\n : warnings.length > 0\n ? \"Zitadel doctor passed with warnings.\"\n : \"Zitadel doctor passed.\",\n ok: failed.length === 0,\n runtime: runtimeBackend,\n ...(runtimeBackend === \"docker\" ? { image } : {}),\n port,\n project: {\n lifecycle: hasConfig ? \"configured\" : \"not-configured\",\n },\n checks,\n ...(warningAdvice\n ? {\n next_actions: warningAdvice.nextActions,\n next_commands: warningAdvice.nextCommands,\n }\n : {}),\n };\n\n if (failed.length > 0) {\n const advice = failureAdvice(failed, image, port, this.meta.cliVersion);\n const code = failed.some((check) => check.name === \"port\") ? \"E_PORT_IN_USE\" : \"E_VALIDATION\";\n throw new ZitadelError(code, \"Zitadel doctor found issues\", {\n hint: advice.hint,\n nextCommands: advice.nextCommands,\n details: data,\n });\n }\n\n return this.emit({\n status: \"ok\",\n data,\n warnings: warnings.map((warning) => `${warning.name}: ${warning.message}`),\n });\n }\n}\n\nfunction failureAdvice(\n failed: CheckOutcome[],\n image: string,\n port: number,\n cliVersion: string,\n): { hint: string; nextCommands: string[] } {\n const failedNames = new Set(failed.map((check) => check.name));\n\n if (failedNames.has(\"server-binary\")) {\n return {\n hint: \"The Zitadel server npm package is not available. Reinstall the CLI package, then retry.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"docker-cli\")) {\n const advice = dockerRuntimeGuidance(\"doctor\", cliVersion);\n return {\n hint: advice.hint,\n nextCommands: advice.nextCommands,\n };\n }\n\n if (failedNames.has(\"image\")) {\n return {\n hint: \"The local Zitadel image is not available. Check Docker registry access, build it locally, or pass --image / ZITADEL_LOCAL_IMAGE.\",\n nextCommands: [`docker pull ${image}`, publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"state-dir\")) {\n return {\n hint: \"The local Zitadel state directory is not writable. Fix directory permissions, then rerun `zitadel doctor`.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"port\")) {\n const fallbackPort = port === DEFAULT_LOCAL_SERVER_PORT ? port + 1 : DEFAULT_LOCAL_SERVER_PORT;\n const stopCommand = publicCliCommand(\"stop --all\", cliVersion);\n const retryCommand = publicCliCommand(\"doctor\", cliVersion);\n const alternatePortCommand = publicCliCommand(\n `doctor --port ${String(fallbackPort)}`,\n cliVersion,\n );\n return {\n hint:\n `Port ${String(port)} is already in use. Stop the process using it, ` +\n `run \\`${stopCommand}\\` for CLI-managed local runtimes, then rerun ` +\n `\\`${retryCommand}\\`; or choose another port with \\`${alternatePortCommand}\\`.`,\n nextCommands: [stopCommand, retryCommand, alternatePortCommand],\n };\n }\n\n if (failedNames.has(\"runtime\")) {\n return {\n hint: \"Existing local runtime metadata was found, but the local Zitadel server is not healthy. Start it again or reset stale local data.\",\n nextCommands: [\n publicCliCommand(\"start\", cliVersion),\n publicCliCommand(\"reset --force\", cliVersion),\n ],\n };\n }\n\n const hasProjectFailure = failed.some((check) => !LOCAL_RUNTIME_CHECK_NAMES.has(check.name));\n if (hasProjectFailure) {\n return {\n hint: `Run \\`${publicCliCommand(\"doctor --fix\", cliVersion)}\\` to re-apply missing managed files.`,\n nextCommands: [publicCliCommand(\"doctor --fix\", cliVersion)],\n };\n }\n\n return {\n hint: \"Fix the reported checks, then rerun `zitadel doctor`.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n}\n\nfunction advisoryForWarnings(\n warnings: CheckOutcome[],\n cliVersion: string,\n): { nextActions: string[]; nextCommands: string[] } | undefined {\n const nextActions: string[] = [];\n const nextCommands: string[] = [];\n if (warnings.some((check) => check.name === \"docker-cli\")) {\n const advice = dockerRuntimeGuidance(\"doctor\", cliVersion);\n nextActions.push(...advice.nextActions);\n nextCommands.push(...advice.nextCommands);\n }\n\n const managedRuntimeWarning = warnings.find((check) => check.name === \"managed-runtime-processes\");\n if (hasManagedRuntimeProcesses(managedRuntimeWarning)) {\n nextActions.push(\n \"Review other host-wide CLI-managed local Zitadel runtimes before starting a new one.\",\n );\n nextCommands.push(publicCliCommand(\"stop --all\", cliVersion));\n }\n\n if (nextActions.length === 0 && nextCommands.length === 0) {\n return undefined;\n }\n return { nextActions: unique(nextActions), nextCommands: unique(nextCommands) };\n}\n\nasync function runLocalRuntimeChecks(\n cwd: string,\n runtimeBackend: RuntimeBackend,\n image: string,\n port: number,\n): Promise<CheckOutcome[]> {\n const runtime = await readRuntimeMetadata(cwd);\n const managedRuntimeCheck = await checkManagedRuntimeProcesses(runtime);\n if (runtimeBackend === \"binary\") {\n return [\n await check(\"server-binary\", \"Server npm package is available\", async () => {\n const version = await assertServerPackageAvailable();\n return `@zitadel/server ${version} is available`;\n }),\n await check(\n \"state-dir\",\n \"Local state directory is writable\",\n async () => {\n const probe = await assertLocalStateWritable(cwd);\n return probe.checkedPath === probe.targetPath\n ? `${probe.targetPath} is writable`\n : `${probe.targetPath} can be created (${probe.checkedPath} is writable)`;\n },\n \"warn\",\n ),\n await check(\n \"port\",\n `Port ${String(port)} is available`,\n () => checkPortAvailability(runtime, port),\n ),\n await checkRuntime(runtime, runtimeBackend),\n managedRuntimeCheck,\n ];\n }\n\n const docker = await check(\n \"docker-cli\",\n \"Docker is reachable\",\n async () => {\n let result: Awaited<ReturnType<typeof dockerAvailable>>;\n try {\n result = await dockerAvailable();\n } catch (error) {\n throw new Error(dockerUnavailableMessage(error), { cause: error });\n }\n if (result.status !== 0) {\n throw new Error(dockerUnavailableMessage(result.stderr || \"docker version failed\"));\n }\n return `Docker engine ${result.stdout.trim() || \"available\"}`;\n },\n \"warn\",\n );\n\n const imageCheck =\n docker.status === \"pass\"\n ? await check(\n \"image\",\n `Image ${image} is available`,\n async () => {\n try {\n const source = await imageAvailable(image);\n return source === \"local\"\n ? `Image ${image} is available locally`\n : `Image ${image} is available from the registry`;\n } catch (error) {\n throw new Error(imageUnavailableMessage(image, error), { cause: error });\n }\n },\n \"warn\",\n )\n : ({\n name: \"image\",\n status: \"warn\",\n message: \"Skipped image check because Docker is not reachable.\",\n } satisfies CheckOutcome);\n\n return [\n docker,\n imageCheck,\n await check(\n \"state-dir\",\n \"Local state directory is writable\",\n async () => {\n const probe = await assertLocalStateWritable(cwd);\n return probe.checkedPath === probe.targetPath\n ? `${probe.targetPath} is writable`\n : `${probe.targetPath} can be created (${probe.checkedPath} is writable)`;\n },\n \"warn\",\n ),\n await check(\n \"port\",\n `Port ${String(port)} is available`,\n () => checkPortAvailability(runtime, port),\n ),\n await checkRuntime(runtime, runtimeBackend),\n managedRuntimeCheck,\n ];\n}\n\nasync function checkPortAvailability(\n runtime: RuntimeMetadata | undefined,\n port: number,\n): Promise<string> {\n if (runtime?.port === port && (await checkLocalServerHealth(runtime.server_url))) {\n return `${runtime.server_url} is already healthy`;\n }\n const listeners = await listenersForPort(port);\n if (listeners.length > 0) {\n throw new PortInUseCheckError(port, localServerUrl(port), listeners);\n }\n return `Port ${String(port)} is available`;\n}\n\nclass PortInUseCheckError extends Error {\n constructor(\n readonly port: number,\n readonly serverUrl: string,\n readonly listeners: Awaited<ReturnType<typeof listenersForPort>>,\n ) {\n super(`Port ${String(port)} is already in use by ${formatListeners(listeners)}`);\n }\n}\n\nasync function checkManagedRuntimeProcesses(\n runtime: RuntimeMetadata | undefined,\n): Promise<CheckOutcome> {\n const discovery = await discoverManagedRuntimeProcesses();\n if (!discovery.supported) {\n return {\n name: \"managed-runtime-processes\",\n status: \"warn\",\n message: \"Managed local runtime process discovery is unavailable.\",\n details: { supported: false, error: discovery.error },\n };\n }\n const processes = additionalManagedRuntimeProcesses(discovery.processes, runtime);\n if (processes.length === 0) {\n return {\n name: \"managed-runtime-processes\",\n status: \"pass\",\n message: \"No additional host-wide managed local runtime processes found.\",\n details: { supported: true, scope: \"host\", processes: [] },\n };\n }\n return {\n name: \"managed-runtime-processes\",\n status: \"warn\",\n message: `${String(processes.length)} other host-wide managed local runtime process${processes.length === 1 ? \"\" : \"es\"} found.`,\n details: { supported: true, scope: \"host\", processes },\n };\n}\n\nfunction additionalManagedRuntimeProcesses(\n processes: ReadonlyArray<ManagedRuntimeProcess>,\n runtime: RuntimeMetadata | undefined,\n): ReadonlyArray<ManagedRuntimeProcess> {\n if (runtime?.backend !== \"binary\") {\n return processes;\n }\n return processes.filter((processInfo) => processInfo.pid !== runtime.pid && processInfo.ppid !== runtime.pid);\n}\n\nasync function checkRuntime(\n runtime: { backend: RuntimeBackend; server_url: string } | undefined,\n runtimeBackend: RuntimeBackend,\n): Promise<CheckOutcome> {\n return check(\"runtime\", \"Existing local runtime is healthy\", async () => {\n if (!runtime) {\n return \"No existing runtime metadata\";\n }\n if (runtime.backend !== runtimeBackend) {\n throw new Error(\n `Existing local runtime uses ${runtime.backend}; run start --runtime ${runtimeBackend} to switch backends.`,\n );\n }\n if (!(await checkLocalServerHealth(runtime.server_url))) {\n throw new Error(`${runtime.server_url} did not respond to /healthz`);\n }\n return `${runtime.server_url} is healthy`;\n });\n}\n\nfunction formatListeners(listeners: Awaited<ReturnType<typeof listenersForPort>>): string {\n return listeners\n .map((listener) =>\n [listener.command ?? \"unknown\", listener.pid ? `pid ${String(listener.pid)}` : undefined]\n .filter(Boolean)\n .join(\" \"),\n )\n .join(\", \");\n}\n\nfunction hasManagedRuntimeProcesses(check: CheckOutcome | undefined): boolean {\n if (!check || check.status !== \"warn\") {\n return false;\n }\n const details = check.details;\n return (\n typeof details === \"object\" &&\n details !== null &&\n \"supported\" in details &&\n (details as { supported?: unknown }).supported === true &&\n Array.isArray((details as { processes?: unknown }).processes) &&\n ((details as { processes?: unknown[] }).processes?.length ?? 0) > 0\n );\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction resolveRuntimeBackend(input: {\n runtime: unknown;\n image: string | undefined;\n envImage: string | undefined;\n existingRuntime: { backend: RuntimeBackend } | undefined;\n}): RuntimeBackend {\n if (input.runtime === \"binary\" || input.runtime === \"docker\") {\n return input.runtime;\n }\n if (input.existingRuntime) {\n return input.existingRuntime.backend;\n }\n if (input.image || input.envImage) {\n return \"docker\";\n }\n return \"binary\";\n}\n\nasync function check(\n name: string,\n fallback: string,\n run: () => Promise<string>,\n failureStatus: \"warn\" | \"fail\" = \"fail\",\n): Promise<CheckOutcome> {\n try {\n return { name, status: \"pass\", message: await run() };\n } catch (error) {\n if (error instanceof PortInUseCheckError) {\n return {\n name,\n status: failureStatus,\n message: error.message,\n details: {\n port: error.port,\n server_url: error.serverUrl,\n listeners: error.listeners,\n },\n };\n }\n return {\n name,\n status: failureStatus,\n message: error instanceof Error ? error.message : fallback,\n };\n }\n}\n\nfunction imageUnavailableMessage(image: string, error: unknown): string {\n const detail = error instanceof Error ? error.message : String(error);\n const suffix = detail.trim() ? ` (${detail.trim()})` : \"\";\n return `Image ${image} is not available to Docker${suffix}; \\`zitadel start\\` may need a pull or a different image.`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA4CA,IAAsB,sBAAtB,MAAiE;CAQ/D,MAAM,IAAI,KAA0C;AAClD,MAAI;AACF,SAAM,KAAK,OAAO,IAAI;AACtB,UAAO;IAAE,MAAM,KAAK;IAAM,QAAQ;IAAQ,SAAS,KAAK;IAAS,MAAM,KAAK;IAAM;WAC3E,OAAO;AACd,UAAO;IACL,MAAM,KAAK;IACX,QAAQ;IACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC/D,MAAM,KAAK;IACZ;;;CAIL,MAAM,IAAI,MAAmC;;;;;AC9D/C,IAAa,cAAb,cAAiC,oBAAoB;CACnD,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;AACvD,QAAM,kBAAkB,IAAI,IAAI;;;;;;ACNpC,IAAa,cAAb,cAAiC,oBAAoB;CACnD,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;AACvD,QAAM,kBAAkB,IAAI,IAAI;;;;;;ACJpC,IAAa,yBAAb,cAA4C,oBAAoB;CAC9D,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;EACvD,MAAM,QAAQ,MAAM,KAAK,KAAK,IAAI,KAAK,kBAAkB,CAAC,EAAE,OAAO;AACnE,MAAI,SAAS,IACX,OAAM,IAAI,MAAM,sBAAsB,KAAK,SAAS,EAAE,GAAG;;CAI7D,MAAe,IAAI,KAAkC;AACnD,MAAI,IAAI,OACN;AAEF,QAAM,MAAM,KAAK,IAAI,KAAK,kBAAkB,EAAE,IAAM;;;;;;AChBxD,MAAM,mBAAmB;CAAC;CAAmB;CAAS;CAAgB;;AAGtE,IAAa,iBAAb,cAAoC,oBAAoB;CACtD,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;EACvD,MAAM,SAAS,MAAM,SAAS,KAAK,IAAI,KAAK,aAAa,EAAE,OAAO,EAAE,MAAM,SAAS;AACnF,OAAK,MAAM,SAAS,iBAClB,KAAI,CAAC,MAAM,SAAS,MAAM,CACxB,OAAM,IAAI,MAAM,WAAW,QAAQ;;CAKzC,MAAe,IAAI,KAAkC;EACnD,MAAM,OAAO,KAAK,IAAI,KAAK,aAAa;EACxC,MAAM,WAAW,MAAM,SAAS,MAAM,OAAO,CAAC,YAAY,GAAG;EAC7D,MAAM,QAAQ,SAAS,MAAM,SAAS;EACtC,MAAM,UAAU,iBAAiB,QAAQ,UAAU,CAAC,MAAM,SAAS,MAAM,CAAC;AAC1E,MAAI,QAAQ,WAAW,KAAK,IAAI,OAC9B;AAGF,QAAM,UAAU,MAAM,GAAG,WADV,SAAS,SAAS,KAAK,CAAC,SAAS,SAAS,KAAK,GAAG,OAAO,KAC3B,QAAQ,KAAK,KAAK,CAAC,IAAI;;;;;;AC1BxE,MAAM,gBAAgB;CAAC;CAAsB;CAAuB;CAAiB;;AAGrF,IAAa,kBAAb,cAAqC,oBAAoB;CACvD,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;EACvD,MAAM,WAAW,MAAM,SAAS,KAAK,IAAI,KAAK,eAAe,EAAE,OAAO;AACtE,OAAK,MAAM,OAAO,cAChB,KAAI,CAAC,SAAS,SAAS,GAAG,IAAI,GAAG,CAC/B,OAAM,IAAI,MAAM,WAAW,MAAM;;CAKvC,MAAe,IAAI,KAAkC;EACnD,MAAM,OAAO,KAAK,IAAI,KAAK,eAAe;EAC1C,MAAM,WAAW,MAAM,SAAS,MAAM,OAAO,CAAC,YAAY,GAAG;EAC7D,MAAM,UAAU,cAAc,QAAQ,QAAQ,CAAC,SAAS,SAAS,GAAG,IAAI,GAAG,CAAC;AAC5E,MAAI,QAAQ,WAAW,KAAK,IAAI,OAC9B;AAGF,QAAM,UAAU,MAAM,GAAG,WADV,SAAS,SAAS,KAAK,CAAC,SAAS,SAAS,KAAK,GAAG,OAAO,KAC3B,QAAQ,KAAK,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI;;;;;;AC1BhG,IAAa,iBAAb,cAAoC,oBAAoB;CACtD,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;EACvD,MAAM,SAAS,MAAM,kBAAkB,IAAI,IAAI;EAC/C,MAAM,WAAW,MAAM,IAAI,KAAK,OAAO,IAAI,IAAI;EAC/C,MAAM,WAAW,SAAS,OAAO,UAAU,GAAG,OAAO,UAAU,KAAK,KAAA;AACpE,MAAI,aAAa,SAAS,GACxB,OAAM,IAAI,MAAM,YAAY,OAAO,SAAS,CAAC,aAAa,SAAS,KAAK;;;;;;;;;;;;ACD9E,eAAsB,iBACpB,KACA,MACA,YACuB;CACvB,MAAM,SAAS,MAAM,kBAAkB,IAAI;CAC3C,MAAM,SAAS,MAAM,kBAAkB,IAAI;CAC3C,MAAM,YAAY,MAAM,KAAK,OAAO,IAAI;AACxC,QAAO;EACL;EACA,YAAY,eAAe,OAAO;EAClC,QAAQ,MAAM,cAAc,KAAK,QAAQ,UAAU;EACnD,QAAQ,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;EAC5D;EACA,SAAS;GACP,IAAI,OAAO;GACX,eAAe,OAAO;GACtB,eAAe,OAAO;GACtB,gBAAgB,OAAO;GACvB,WAAW,OAAO;GACnB;EACF;;AAGH,eAAe,cACb,KACA,QACA,OACiB;CACjB,MAAM,aAAa,sBAAsB,OAAO;AAChD,KAAI,cAAc,WAAW,SAAS,EACpC,QAAO;CAET,MAAM,QAAQ,MAAM,UAAU,IAAI;AAClC,KAAI,OAAO,OAAO,aAAa,SAC7B,QAAO,eAAe,MAAM,SAAS;AAEvC,QAAO,MAAM;;AAGf,eAAe,UAAU,KAAyD;AAChF,KAAI;EACF,MAAM,WAAW,MAAM,SAAS,KAAK,KAAK,sBAAsB,EAAE,OAAO;AACzE,SAAO,KAAK,MAAM,SAAS;SACrB;AACN;;;;;;;;;;;AC/CJ,IAAa,kBAAb,cAAqC,oBAAoB;CACvD,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;EACvD,MAAM,MAAM,KAAK,MAAM,MAAM,SAAS,KAAK,IAAI,KAAK,eAAe,EAAE,OAAO,CAAC;AAQ7E,MAAI,CAAC,CAHH,GAAG,OAAO,KAAK,IAAI,gBAAgB,EAAE,CAAC,EACtC,GAAG,OAAO,KAAK,IAAI,mBAAmB,EAAE,CAAC,CAEjC,CAAC,MAAM,SAAS,KAAK,WAAW,WAAW,CAAC,CACpD,OAAM,IAAI,MAAM,gDAAgD;;;;;;;;;;CAYpE,MAAe,IAAI,KAAkC;EACnD,MAAM,WAAW,MAAM,iBAAiB,IAAI,KAAK,IAAI,MAAM,IAAI,WAAW;AAC1E,QAAM,IAAI,KAAK,WAAW,SAAS,UAAU,GAAG,CAAC,OAAO,UAAU;GAChE,KAAK,IAAI;GACT,QAAQ,IAAI;GACZ,OAAO;GACR,CAAC;;;;;;ACzCN,IAAa,oBAAb,cAAuC,oBAAoB;CACzD,OAAgB;CAChB,OAAgB;CAChB,UAA6B;CAE7B,MAAgB,OAAO,KAAkC;EACvD,MAAM,SAAS,MAAM,kBAAkB,IAAI,IAAI;EAC/C,MAAM,SAAS,MAAM,kBAAkB,IAAI,IAAI;EAC/C,MAAM,gBAAgB,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU,KAAA;AAC5E,MAAI,OAAO,eAAe,cACxB,OAAM,IAAI,MAAM,iEAAiE;;;;;;ACevF,MAAa,gBAA4C;CACvD,IAAI,aAAa;CACjB,IAAI,aAAa;CACjB,IAAI,wBAAwB;CAC5B,IAAI,gBAAgB;CACpB,IAAI,iBAAiB;CACrB,IAAI,gBAAgB;CAMpB,IAAI,iBAAiB;CACrB,IAAI,mBAAmB;CACxB;;;ACZD,MAAM,4BAA4B,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;;;;;;;AAeF,IAAqB,SAArB,MAAqB,eAAe,YAAY;CAC9C,OAAgB,cAAc;CAC9B,OAAgB,QAAQ;EACtB,KAAK,MAAM,QAAQ,EAAE,aAAa,mCAAmC,CAAC;EACtE,OAAO,MAAM,OAAO,EAAE,aAAa,6BAA6B,CAAC;EACjE,MAAM,MAAM,QAAQ;GAAE,aAAa;GAAoB,SAAS;GAA2B,CAAC;EAC5F,SAAS,MAAM,OAAO;GACpB,aAAa;GACb,SAAS,CAAC,UAAU,SAAS;GAC9B,CAAC;EACH;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,OAAO;EAC1C,MAAM,OAAO,MAAM,QAAA;AACnB,QAAM,KAAK,OAAO,OAAO;GAAE,eAAe;GAAO,QAAQ,eAAe,KAAK;GAAE,CAAC;EAChF,MAAM,EAAE,KAAK,WAAW,KAAK;EAC7B,MAAM,kBAAkB,MAAM,oBAAoB,IAAI;EACtD,MAAM,iBAAiB,sBAAsB;GAC3C,SAAS,MAAM;GACf,OAAO,MAAM;GACb,UAAU,KAAK,KAAK,IAAI;GACxB;GACD,CAAC;EACF,MAAM,QACJ,MAAM,SACN,KAAK,KAAK,IAAI,uBACd,qCAAqC,KAAK,KAAK,WAAW;EAC5D,MAAM,gBAAgB,MAAM,sBAAsB,KAAK,gBAAgB,OAAO,KAAK;EACnF,MAAM,YAAY,MAAM,iBAAiB,IAAI;EAC7C,MAAM,MAAoB;GAAE;GAAK,MAAM,YAAY;GAAE,YAAY,KAAK,KAAK;GAAY;GAAQ;AAE/F,MAAI,aAAa,MAAM,KAAK;GAC1B,MAAM,SAAS,MAAM,QAAQ,IAAI,cAAc,KAAK,UAAU,MAAM,IAAI,IAAI,CAAC,CAAC;AAC9E,QAAK,MAAM,CAAC,OAAO,UAAU,cAAc,SAAS,EAAE;AACpD,QAAI,OAAO,QAAQ,WAAW,OAC5B;AAEF,QAAI;AACF,WAAM,MAAM,IAAI,IAAI;aACb,OAAO;AACd,aAAQ,MAAM,iBAAiB,MAAM,KAAK,iBAAiB,MAAM;;;;EAKvE,MAAM,gBAAgB,YAClB,MAAM,QAAQ,IAAI,cAAc,KAAK,UAAU,MAAM,IAAI,IAAI,CAAC,CAAC,GAC/D,EAAE;EACN,MAAM,SAAS,CAAC,GAAG,eAAe,GAAG,cAAc;EACnD,MAAM,SAAS,OAAO,QAAQ,UAAU,MAAM,WAAW,OAAO;EAChE,MAAM,WAAW,OAAO,QAAQ,UAAU,MAAM,WAAW,OAAO;EAClE,MAAM,gBAAgB,oBAAoB,UAAU,KAAK,KAAK,WAAW;AACzE,OAAK,gBAAgB;GACnB,SAAS;GACT,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,aAAa,SAAS;GACtB,eAAe,OAAO,SAAS,IAAI,OAAO,KAAK,UAAU,MAAM,KAAK,CAAC,KAAK,IAAI,GAAG,KAAA;GAClF,CAAC;EACF,MAAM,OAAO;GACX,OACE,OAAO,SAAS,IACZ,iCACA,SAAS,SAAS,IAChB,yCACA;GACR,IAAI,OAAO,WAAW;GACtB,SAAS;GACT,GAAI,mBAAmB,WAAW,EAAE,OAAO,GAAG,EAAE;GAChD;GACA,SAAS,EACP,WAAW,YAAY,eAAe,kBACvC;GACD;GACA,GAAI,gBACA;IACE,cAAc,cAAc;IAC5B,eAAe,cAAc;IAC9B,GACD,EAAE;GACP;AAED,MAAI,OAAO,SAAS,GAAG;GACrB,MAAM,SAAS,cAAc,QAAQ,OAAO,MAAM,KAAK,KAAK,WAAW;AAEvE,SAAM,IAAI,aADG,OAAO,MAAM,UAAU,MAAM,SAAS,OAAO,GAAG,kBAAkB,gBAClD,+BAA+B;IAC1D,MAAM,OAAO;IACb,cAAc,OAAO;IACrB,SAAS;IACV,CAAC;;AAGJ,SAAO,KAAK,KAAK;GACf,QAAQ;GACR;GACA,UAAU,SAAS,KAAK,YAAY,GAAG,QAAQ,KAAK,IAAI,QAAQ,UAAU;GAC3E,CAAC;;;AAIN,SAAS,cACP,QACA,OACA,MACA,YAC0C;CAC1C,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,UAAU,MAAM,KAAK,CAAC;AAE9D,KAAI,YAAY,IAAI,gBAAgB,CAClC,QAAO;EACL,MAAM;EACN,cAAc,CAAC,iBAAiB,UAAU,WAAW,CAAC;EACvD;AAGH,KAAI,YAAY,IAAI,aAAa,EAAE;EACjC,MAAM,SAAS,sBAAsB,UAAU,WAAW;AAC1D,SAAO;GACL,MAAM,OAAO;GACb,cAAc,OAAO;GACtB;;AAGH,KAAI,YAAY,IAAI,QAAQ,CAC1B,QAAO;EACL,MAAM;EACN,cAAc,CAAC,eAAe,SAAS,iBAAiB,UAAU,WAAW,CAAC;EAC/E;AAGH,KAAI,YAAY,IAAI,YAAY,CAC9B,QAAO;EACL,MAAM;EACN,cAAc,CAAC,iBAAiB,UAAU,WAAW,CAAC;EACvD;AAGH,KAAI,YAAY,IAAI,OAAO,EAAE;EAC3B,MAAM,eAAe,SAAA,OAAqC,OAAO,IAAI;EACrE,MAAM,cAAc,iBAAiB,cAAc,WAAW;EAC9D,MAAM,eAAe,iBAAiB,UAAU,WAAW;EAC3D,MAAM,uBAAuB,iBAC3B,iBAAiB,OAAO,aAAa,IACrC,WACD;AACD,SAAO;GACL,MACE,QAAQ,OAAO,KAAK,CAAC,uDACZ,YAAY,kDAChB,aAAa,oCAAoC,qBAAqB;GAC7E,cAAc;IAAC;IAAa;IAAc;IAAqB;GAChE;;AAGH,KAAI,YAAY,IAAI,UAAU,CAC5B,QAAO;EACL,MAAM;EACN,cAAc,CACZ,iBAAiB,SAAS,WAAW,EACrC,iBAAiB,iBAAiB,WAAW,CAC9C;EACF;AAIH,KAD0B,OAAO,MAAM,UAAU,CAAC,0BAA0B,IAAI,MAAM,KAAK,CACtE,CACnB,QAAO;EACL,MAAM,SAAS,iBAAiB,gBAAgB,WAAW,CAAC;EAC5D,cAAc,CAAC,iBAAiB,gBAAgB,WAAW,CAAC;EAC7D;AAGH,QAAO;EACL,MAAM;EACN,cAAc,CAAC,iBAAiB,UAAU,WAAW,CAAC;EACvD;;AAGH,SAAS,oBACP,UACA,YAC+D;CAC/D,MAAM,cAAwB,EAAE;CAChC,MAAM,eAAyB,EAAE;AACjC,KAAI,SAAS,MAAM,UAAU,MAAM,SAAS,aAAa,EAAE;EACzD,MAAM,SAAS,sBAAsB,UAAU,WAAW;AAC1D,cAAY,KAAK,GAAG,OAAO,YAAY;AACvC,eAAa,KAAK,GAAG,OAAO,aAAa;;AAI3C,KAAI,2BAD0B,SAAS,MAAM,UAAU,MAAM,SAAS,4BAClB,CAAC,EAAE;AACrD,cAAY,KACV,uFACD;AACD,eAAa,KAAK,iBAAiB,cAAc,WAAW,CAAC;;AAG/D,KAAI,YAAY,WAAW,KAAK,aAAa,WAAW,EACtD;AAEF,QAAO;EAAE,aAAa,OAAO,YAAY;EAAE,cAAc,OAAO,aAAa;EAAE;;AAGjF,eAAe,sBACb,KACA,gBACA,OACA,MACyB;CACzB,MAAM,UAAU,MAAM,oBAAoB,IAAI;CAC9C,MAAM,sBAAsB,MAAM,6BAA6B,QAAQ;AACvE,KAAI,mBAAmB,SACrB,QAAO;EACL,MAAM,MAAM,iBAAiB,mCAAmC,YAAY;AAE1E,UAAO,mBAAmB,MADJ,8BAA8B,CAClB;IAClC;EACF,MAAM,MACJ,aACA,qCACA,YAAY;GACV,MAAM,QAAQ,MAAM,yBAAyB,IAAI;AACjD,UAAO,MAAM,gBAAgB,MAAM,aAC/B,GAAG,MAAM,WAAW,gBACpB,GAAG,MAAM,WAAW,mBAAmB,MAAM,YAAY;KAE/D,OACD;EACD,MAAM,MACJ,QACA,QAAQ,OAAO,KAAK,CAAC,sBACf,sBAAsB,SAAS,KAAK,CAC3C;EACD,MAAM,aAAa,SAAS,eAAe;EAC3C;EACD;CAGH,MAAM,SAAS,MAAM,MACnB,cACA,uBACA,YAAY;EACV,IAAI;AACJ,MAAI;AACF,YAAS,MAAM,iBAAiB;WACzB,OAAO;AACd,SAAM,IAAI,MAAM,yBAAyB,MAAM,EAAE,EAAE,OAAO,OAAO,CAAC;;AAEpE,MAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MAAM,yBAAyB,OAAO,UAAU,wBAAwB,CAAC;AAErF,SAAO,iBAAiB,OAAO,OAAO,MAAM,IAAI;IAElD,OACD;AAyBD,QAAO;EACL;EAvBA,OAAO,WAAW,SACd,MAAM,MACJ,SACA,SAAS,MAAM,gBACf,YAAY;AACV,OAAI;AAEF,WAAO,MADc,eAAe,MAAM,KACxB,UACd,SAAS,MAAM,yBACf,SAAS,MAAM;YACZ,OAAO;AACd,UAAM,IAAI,MAAM,wBAAwB,OAAO,MAAM,EAAE,EAAE,OAAO,OAAO,CAAC;;KAG5E,OACD,GACA;GACC,MAAM;GACN,QAAQ;GACR,SAAS;GACV;EAKL,MAAM,MACJ,aACA,qCACA,YAAY;GACV,MAAM,QAAQ,MAAM,yBAAyB,IAAI;AACjD,UAAO,MAAM,gBAAgB,MAAM,aAC/B,GAAG,MAAM,WAAW,gBACpB,GAAG,MAAM,WAAW,mBAAmB,MAAM,YAAY;KAE/D,OACD;EACD,MAAM,MACJ,QACA,QAAQ,OAAO,KAAK,CAAC,sBACf,sBAAsB,SAAS,KAAK,CAC3C;EACD,MAAM,aAAa,SAAS,eAAe;EAC3C;EACD;;AAGH,eAAe,sBACb,SACA,MACiB;AACjB,KAAI,SAAS,SAAS,QAAS,MAAM,uBAAuB,QAAQ,WAAW,CAC7E,QAAO,GAAG,QAAQ,WAAW;CAE/B,MAAM,YAAY,MAAM,iBAAiB,KAAK;AAC9C,KAAI,UAAU,SAAS,EACrB,OAAM,IAAI,oBAAoB,MAAM,eAAe,KAAK,EAAE,UAAU;AAEtE,QAAO,QAAQ,OAAO,KAAK,CAAC;;AAG9B,IAAM,sBAAN,cAAkC,MAAM;CACtC,YACE,MACA,WACA,WACA;AACA,QAAM,QAAQ,OAAO,KAAK,CAAC,wBAAwB,gBAAgB,UAAU,GAAG;AAJvE,OAAA,OAAA;AACA,OAAA,YAAA;AACA,OAAA,YAAA;;;AAMb,eAAe,6BACb,SACuB;CACvB,MAAM,YAAY,MAAM,iCAAiC;AACzD,KAAI,CAAC,UAAU,UACb,QAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS;EACT,SAAS;GAAE,WAAW;GAAO,OAAO,UAAU;GAAO;EACtD;CAEH,MAAM,YAAY,kCAAkC,UAAU,WAAW,QAAQ;AACjF,KAAI,UAAU,WAAW,EACvB,QAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS;EACT,SAAS;GAAE,WAAW;GAAM,OAAO;GAAQ,WAAW,EAAE;GAAE;EAC3D;AAEH,QAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS,GAAG,OAAO,UAAU,OAAO,CAAC,gDAAgD,UAAU,WAAW,IAAI,KAAK,KAAK;EACxH,SAAS;GAAE,WAAW;GAAM,OAAO;GAAQ;GAAW;EACvD;;AAGH,SAAS,kCACP,WACA,SACsC;AACtC,KAAI,SAAS,YAAY,SACvB,QAAO;AAET,QAAO,UAAU,QAAQ,gBAAgB,YAAY,QAAQ,QAAQ,OAAO,YAAY,SAAS,QAAQ,IAAI;;AAG/G,eAAe,aACb,SACA,gBACuB;AACvB,QAAO,MAAM,WAAW,qCAAqC,YAAY;AACvE,MAAI,CAAC,QACH,QAAO;AAET,MAAI,QAAQ,YAAY,eACtB,OAAM,IAAI,MACR,+BAA+B,QAAQ,QAAQ,wBAAwB,eAAe,sBACvF;AAEH,MAAI,CAAE,MAAM,uBAAuB,QAAQ,WAAW,CACpD,OAAM,IAAI,MAAM,GAAG,QAAQ,WAAW,8BAA8B;AAEtE,SAAO,GAAG,QAAQ,WAAW;GAC7B;;AAGJ,SAAS,gBAAgB,WAAiE;AACxF,QAAO,UACJ,KAAK,aACJ,CAAC,SAAS,WAAW,WAAW,SAAS,MAAM,OAAO,OAAO,SAAS,IAAI,KAAK,KAAA,EAAU,CACtF,OAAO,QAAQ,CACf,KAAK,IAAI,CACb,CACA,KAAK,KAAK;;AAGf,SAAS,2BAA2B,OAA0C;AAC5E,KAAI,CAAC,SAAS,MAAM,WAAW,OAC7B,QAAO;CAET,MAAM,UAAU,MAAM;AACtB,QACE,OAAO,YAAY,YACnB,YAAY,QACZ,eAAe,WACd,QAAoC,cAAc,QACnD,MAAM,QAAS,QAAoC,UAAU,KAC3D,QAAsC,WAAW,UAAU,KAAK;;AAItE,SAAS,OAAO,QAA4B;AAC1C,QAAO,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC;;AAG7B,SAAS,sBAAsB,OAKZ;AACjB,KAAI,MAAM,YAAY,YAAY,MAAM,YAAY,SAClD,QAAO,MAAM;AAEf,KAAI,MAAM,gBACR,QAAO,MAAM,gBAAgB;AAE/B,KAAI,MAAM,SAAS,MAAM,SACvB,QAAO;AAET,QAAO;;AAGT,eAAe,MACb,MACA,UACA,KACA,gBAAiC,QACV;AACvB,KAAI;AACF,SAAO;GAAE;GAAM,QAAQ;GAAQ,SAAS,MAAM,KAAK;GAAE;UAC9C,OAAO;AACd,MAAI,iBAAiB,oBACnB,QAAO;GACL;GACA,QAAQ;GACR,SAAS,MAAM;GACf,SAAS;IACP,MAAM,MAAM;IACZ,YAAY,MAAM;IAClB,WAAW,MAAM;IAClB;GACF;AAEH,SAAO;GACL;GACA,QAAQ;GACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU;GACnD;;;AAIL,SAAS,wBAAwB,OAAe,OAAwB;CACtE,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAErE,QAAO,SAAS,MAAM,6BADP,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,CAAC,KAAK,GACG"}
|
|
1
|
+
{"version":3,"file":"doctor.mjs","names":[],"sources":["../../src/commands/doctor/checks/types.ts","../../src/commands/doctor/checks/config.ts","../../src/commands/doctor/checks/secret.ts","../../src/commands/doctor/checks/secret-permissions.ts","../../src/commands/doctor/checks/gitignore.ts","../../src/commands/doctor/checks/env-example.ts","../../src/commands/doctor/checks/framework.ts","../../src/commands/doctor/patch-context.ts","../../src/commands/doctor/checks/dependency.ts","../../src/commands/doctor/checks/project-match.ts","../../src/lib/json-dir.ts","../../src/commands/doctor/checks/schema.ts","../../src/commands/doctor/checks/index.ts","../../src/commands/doctor/index.ts"],"sourcesContent":["import type { Orca } from \"../../../lib/orca\";\n\n/** Pass/fail/advisory outcome of a single {@link SanityCheck}. */\nexport type CheckOutcome = {\n details?: unknown;\n name: string;\n status: \"pass\" | \"warn\" | \"fail\";\n message: string;\n path?: string;\n};\n\n/** Everything a check needs to inspect or repair a project. */\nexport type CheckContext = {\n readonly cwd: string;\n readonly orca: Orca;\n readonly cliVersion: string;\n /** When true, {@link SanityCheck.fix} must preview without writing. */\n readonly dryRun: boolean;\n};\n\n/**\n * One diagnostic the `doctor` command runs. Each concrete check is a small\n * standalone class that both verifies its concern ({@link run}) and knows how\n * to repair it ({@link fix}); the command executes every registered check,\n * aggregates the {@link CheckOutcome}s, and (under `--fix`) repairs the ones\n * that failed.\n */\nexport interface SanityCheck {\n /** Stable identifier surfaced in logs and the JSON envelope. */\n readonly name: string;\n run(ctx: CheckContext): Promise<CheckOutcome>;\n /** Repair what this check verifies. A no-op when there is no safe auto-fix. */\n fix(ctx: CheckContext): Promise<void>;\n}\n\n/**\n * Base class for checks: subclasses declare `name`, `path`, and a success\n * `summary`, and implement the single {@link verify} method that throws on\n * failure. {@link run} wraps it so a thrown error becomes a `fail` outcome\n * carrying the error message, and success becomes a `pass` with `summary`.\n *\n * {@link fix} defaults to a no-op: checks whose failure has no safe automatic\n * remedy (a missing secret, an invalid user schema) simply do not override it.\n */\nexport abstract class AbstractSanityCheck implements SanityCheck {\n abstract readonly name: string;\n abstract readonly path: string;\n protected abstract readonly summary: string;\n\n /** Throw to signal failure; the thrown message is surfaced to the user. */\n protected abstract verify(ctx: CheckContext): Promise<void>;\n\n async run(ctx: CheckContext): Promise<CheckOutcome> {\n try {\n await this.verify(ctx);\n return { name: this.name, status: \"pass\", message: this.summary, path: this.path };\n } catch (error) {\n return {\n name: this.name,\n status: \"fail\",\n message: error instanceof Error ? error.message : String(error),\n path: this.path,\n };\n }\n }\n\n async fix(_ctx: CheckContext): Promise<void> {\n return;\n }\n}\n","import { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `zitadel.json` exists and parses. */\nexport class ConfigCheck extends AbstractSanityCheck {\n readonly name = \"config\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"zitadel.json parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelConfig(ctx.cwd);\n }\n}\n","import { readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` exists and parses. */\nexport class SecretCheck extends AbstractSanityCheck {\n readonly name = \"secret\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret parses\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n await readZitadelSecret(ctx.cwd);\n }\n}\n","import { chmod, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret` is locked down to `0600`, and re-locks it on fix. */\nexport class SecretPermissionsCheck extends AbstractSanityCheck {\n readonly name = \"secret-permissions\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret has 0600 permissions\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const mode = (await stat(join(ctx.cwd, \".zitadel/secret\"))).mode & 0o777;\n if (mode !== 0o600) {\n throw new Error(`expected 0600, got ${mode.toString(8)}`);\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n if (ctx.dryRun) {\n return;\n }\n await chmod(join(ctx.cwd, \".zitadel/secret\"), 0o600);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The entries `.gitignore` must carry to keep secrets and env files untracked. */\nconst REQUIRED_ENTRIES = [\".zitadel/secret\", \".env*\", \"!.env.example\"];\n\n/** Verifies `.gitignore` excludes the local secret and env files; appends any missing. */\nexport class GitignoreCheck extends AbstractSanityCheck {\n readonly name = \"gitignore\";\n readonly path = \".gitignore\";\n protected readonly summary = \".gitignore protects local secret/env files\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const lines = (await readFile(join(ctx.cwd, \".gitignore\"), \"utf8\")).split(/\\r?\\n/g);\n for (const entry of REQUIRED_ENTRIES) {\n if (!lines.includes(entry)) {\n throw new Error(`missing ${entry}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".gitignore\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const lines = existing.split(/\\r?\\n/g);\n const missing = REQUIRED_ENTRIES.filter((entry) => !lines.includes(entry));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.join(\"\\n\")}\\n`);\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** The keys `.env.example` must document for a Zitadel-managed project. */\nconst REQUIRED_KEYS = [\"ZITADEL_PROJECT_ID\", \"ZITADEL_ENVIRONMENT\", \"ZITADEL_ISSUER\"];\n\n/** Verifies `.env.example` documents the required Zitadel keys; appends any missing. */\nexport class EnvExampleCheck extends AbstractSanityCheck {\n readonly name = \"env-example\";\n readonly path = \".env.example\";\n protected readonly summary = \".env.example references required keys\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const contents = await readFile(join(ctx.cwd, \".env.example\"), \"utf8\");\n for (const key of REQUIRED_KEYS) {\n if (!contents.includes(`${key}=`)) {\n throw new Error(`missing ${key}`);\n }\n }\n }\n\n override async fix(ctx: CheckContext): Promise<void> {\n const path = join(ctx.cwd, \".env.example\");\n const existing = await readFile(path, \"utf8\").catch(() => \"\");\n const missing = REQUIRED_KEYS.filter((key) => !existing.includes(`${key}=`));\n if (missing.length === 0 || ctx.dryRun) {\n return;\n }\n const prefix = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${prefix}${missing.map((key) => `${key}=`).join(\"\\n\")}\\n`);\n }\n}\n","import { isObject } from \"../../../lib/json\";\nimport { readZitadelConfig } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies the framework detected on disk matches the one recorded in config. */\nexport class FrameworkCheck extends AbstractSanityCheck {\n readonly name = \"framework\";\n readonly path = \"zitadel.json\";\n protected readonly summary = \"Detected framework matches recorded framework\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const detected = await ctx.orca.detect(ctx.cwd);\n const recorded = isObject(config.framework) ? config.framework.id : undefined;\n if (recorded !== detected.id) {\n throw new Error(`expected ${String(recorded)}, detected ${detected.id}`);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { issuerFromPort, type FrameworkFacts, type Orca } from \"../../lib/orca\";\nimport type { PatchContext } from \"../../lib/orca/patchers/types\";\nimport { readDevelopmentIssuer, readRendererId, readZitadelConfig, readZitadelSecret } from \"../../lib/project\";\n\n/**\n * Reconstructs a {@link PatchContext} from the on-disk project (config, secret)\n * plus fresh framework detection, so a patcher repair can rebuild its plan.\n * Used by the dependency check's `fix`, which reclaims the framework-specific\n * SDK package via `patcher.repair`. Schema and flow config are user-editable\n * sync resources, not patcher inputs, so nothing here reads them.\n */\nexport async function loadPatchContext(\n cwd: string,\n orca: Orca,\n cliVersion: string,\n): Promise<PatchContext> {\n const config = await readZitadelConfig(cwd);\n const secret = await readZitadelSecret(cwd);\n const framework = await orca.detect(cwd);\n return {\n framework,\n rendererId: readRendererId(config),\n issuer: await resolveIssuer(cwd, config, framework),\n server: typeof config.server === \"string\" ? config.server : \"\",\n cliVersion,\n project: {\n id: secret.project_id,\n projectSecret: secret.project_secret,\n previewSecret: secret.preview_secret,\n previewOrigins: secret.preview_origins,\n createdAt: secret.created_at,\n },\n };\n}\n\nasync function resolveIssuer(\n cwd: string,\n config: Record<string, unknown>,\n facts: FrameworkFacts,\n): Promise<string> {\n const fromConfig = readDevelopmentIssuer(config);\n if (fromConfig && fromConfig.length > 0) {\n return fromConfig;\n }\n const state = await readState(cwd);\n if (typeof state?.dev_port === \"number\") {\n return issuerFromPort(state.dev_port);\n }\n return facts.url;\n}\n\nasync function readState(cwd: string): Promise<{ dev_port?: number } | undefined> {\n try {\n const contents = await readFile(join(cwd, \".zitadel/state.json\"), \"utf8\");\n return JSON.parse(contents) as { dev_port?: number };\n } catch {\n return undefined;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { loadPatchContext } from \"../patch-context\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/**\n * Verifies the project still declares a Zitadel SDK dependency in\n * `package.json`. The patcher adds a scoped package (e.g.\n * `@zitadel/sdk-next`); the check is generic over the `@zitadel*`\n * scope so any framework renderer's dependency satisfies it.\n */\nexport class DependencyCheck extends AbstractSanityCheck {\n readonly name = \"dependency\";\n readonly path = \"package.json\";\n protected readonly summary = \"package.json depends on a Zitadel SDK package\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const pkg = JSON.parse(await readFile(join(ctx.cwd, \"package.json\"), \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const names = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n if (!names.some((name) => name.startsWith(\"@zitadel\"))) {\n throw new Error(\"no @zitadel* dependency found in package.json\");\n }\n }\n\n /**\n * Repairs by reclaiming the patcher's managed artifacts: rebuilds the\n * `PatchContext` from disk and calls `patcher.repair`, which re-adds the\n * SDK dependency via its `add-dep` op. The exact package name is framework\n * + renderer specific and known only to the patcher (which deliberately\n * hides its file-op plan behind the family-neutral `Patcher` interface),\n * so going through `repair` is the only sanctioned path.\n */\n override async fix(ctx: CheckContext): Promise<void> {\n const patchCtx = await loadPatchContext(ctx.cwd, ctx.orca, ctx.cliVersion);\n await ctx.orca.patcherFor(patchCtx.framework.id).repair(patchCtx, {\n cwd: ctx.cwd,\n dryRun: ctx.dryRun,\n force: true,\n });\n }\n}\n","import { readZitadelConfig, readZitadelSecret } from \"../../../lib/project\";\nimport { AbstractSanityCheck, type CheckContext } from \"./types\";\n\n/** Verifies `.zitadel/secret`'s project_id matches `zitadel.json`'s project. */\nexport class ProjectMatchCheck extends AbstractSanityCheck {\n readonly name = \"project-match\";\n readonly path = \".zitadel/secret\";\n protected readonly summary = \".zitadel/secret project_id matches zitadel.json project\";\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const config = await readZitadelConfig(ctx.cwd);\n const secret = await readZitadelSecret(ctx.cwd);\n const configProject = typeof config.project === \"string\" ? config.project : undefined;\n if (secret.project_id !== configProject) {\n throw new Error(\".zitadel/secret project_id does not match zitadel.json project\");\n }\n }\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ZitadelError } from \"./errors\";\n\n/**\n * Read every `*.json` file under `absDir` and return each body as a plain\n * object. Files are read in lexical filename order so the result is\n * deterministic for downstream hashing and diffs. Each file is parsed by\n * `JSON.parse`; this function does **not** apply any schema validation —\n * unknown keys, forward-compatible fields, and `${VAR}` placeholders survive\n * intact. Callers that need a typed shape pass the result through their\n * resource's Zod schema.\n *\n * Returns an empty array when the directory is missing. Throws `E_VALIDATION`\n * `ZitadelError` on invalid JSON or when a file's root value is not an object.\n *\n * @param absDir - Absolute path to the directory to scan.\n */\nexport async function readJsonDir(absDir: string): Promise<ReadonlyArray<Record<string, unknown>>> {\n let entries: string[];\n try {\n entries = await readdir(absDir);\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n const result: Record<string, unknown>[] = [];\n for (const entry of entries.filter((name) => name.endsWith(\".json\")).sort()) {\n const abs = join(absDir, entry);\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(abs, \"utf8\"));\n } catch {\n throw new ZitadelError(\"E_VALIDATION\", `${entry} is not valid JSON`);\n }\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new ZitadelError(\"E_VALIDATION\", `${entry} must contain a JSON object at the root`);\n }\n result.push(raw as Record<string, unknown>);\n }\n return result;\n}\n","import { join } from \"node:path\";\n\nimport { schemaConfigSchema } from \"@zitadel/config/schemas\";\n\nimport { readJsonDir } from \"../../../lib/json-dir\";\nimport { SCHEMAS_DIR } from \"../../../lib/user-schema\";\nimport { AbstractSanityCheck, type CheckContext, type CheckOutcome } from \"./types\";\n\n/**\n * Verifies local schema config files round-trip through the canonical\n * `schemaConfigSchema` from `@zitadel/config/schemas` — the same Zod the\n * sync engine validates with, so doctor and `apply` can never disagree\n * about a file. The union enforces the `kind` discriminator\n * (`user-schema` / `schema-url`) and the `metaSchema`/`x-auth-methods`/etc.\n * fields the platform requires.\n */\nexport class SchemaCheck extends AbstractSanityCheck {\n readonly name = \"schema\";\n readonly path = SCHEMAS_DIR;\n protected readonly summary = \"User schemas are valid Zitadel schema bodies\";\n\n /**\n * An empty `.zitadel/schemas/` is a warning, not a failure: projects\n * created before editable config existed were seeded server-side and have\n * no local schema files, and there is no safe auto-fix that could invent\n * them. Only invalid files fail the check.\n */\n override async run(ctx: CheckContext): Promise<CheckOutcome> {\n const schemas = await readJsonDir(join(ctx.cwd, SCHEMAS_DIR));\n if (schemas.length === 0) {\n return {\n name: this.name,\n status: \"warn\",\n message:\n `No schema files found in ${SCHEMAS_DIR} — this project predates editable ` +\n \"schema config or setup was interrupted. New projects scaffold editable \" +\n \"defaults via `zitadel setup`.\",\n path: this.path,\n };\n }\n return super.run(ctx);\n }\n\n protected async verify(ctx: CheckContext): Promise<void> {\n const schemas = await readJsonDir(join(ctx.cwd, SCHEMAS_DIR));\n for (const schema of schemas) {\n const result = schemaConfigSchema.safeParse(schema);\n if (!result.success) {\n throw new Error(\n result.error.issues\n .map((issue) => `${issue.path.join(\".\") || \"/\"} ${issue.message}`)\n .join(\"; \"),\n );\n }\n }\n }\n}\n","/**\n * Public surface for the doctor sanity checks. The `doctor` command imports\n * {@link SANITY_CHECKS} and runs every entry, aggregating the outcomes. Each\n * check is a small standalone class (see its own file); add a new diagnostic\n * by writing a class and appending an instance to the registry below.\n */\nimport type { SanityCheck } from \"./types\";\nimport { ConfigCheck } from \"./config\";\nimport { SecretCheck } from \"./secret\";\nimport { SecretPermissionsCheck } from \"./secret-permissions\";\nimport { GitignoreCheck } from \"./gitignore\";\nimport { EnvExampleCheck } from \"./env-example\";\nimport { FrameworkCheck } from \"./framework\";\nimport { DependencyCheck } from \"./dependency\";\nimport { ProjectMatchCheck } from \"./project-match\";\nimport { SchemaCheck } from \"./schema\";\n\nexport type { SanityCheck, CheckContext, CheckOutcome } from \"./types\";\nexport { AbstractSanityCheck } from \"./types\";\nexport { ConfigCheck } from \"./config\";\nexport { SecretCheck } from \"./secret\";\nexport { SecretPermissionsCheck } from \"./secret-permissions\";\nexport { GitignoreCheck } from \"./gitignore\";\nexport { EnvExampleCheck } from \"./env-example\";\nexport { FrameworkCheck } from \"./framework\";\nexport { SchemaCheck } from \"./schema\";\nexport { DependencyCheck } from \"./dependency\";\nexport { ProjectMatchCheck } from \"./project-match\";\n\n/** Every diagnostic the `doctor` command runs, in display order. */\nexport const SANITY_CHECKS: ReadonlyArray<SanityCheck> = [\n new ConfigCheck(),\n new SecretCheck(),\n new SecretPermissionsCheck(),\n new GitignoreCheck(),\n new EnvExampleCheck(),\n new FrameworkCheck(),\n new SchemaCheck(),\n new DependencyCheck(),\n new ProjectMatchCheck(),\n];\n","import { Flags } from \"@oclif/core\";\nimport consola from \"consola\";\n\nimport { ZitadelError } from \"../../lib/errors\";\nimport { assertServerPackageAvailable } from \"../../lib/local-server/binary\";\nimport { dockerAvailable, imageAvailable } from \"../../lib/local-server/docker\";\nimport {\n dockerRuntimeGuidance,\n dockerUnavailableMessage,\n} from \"../../lib/local-server/docker-guidance\";\nimport {\n discoverManagedRuntimeProcesses,\n type ManagedRuntimeProcess,\n} from \"../../lib/local-server/processes\";\nimport {\n DEFAULT_LOCAL_SERVER_PORT,\n assertLocalStateWritable,\n checkLocalServerHealth,\n defaultLocalServerImageForCliVersion,\n localServerUrl,\n readRuntimeMetadata,\n type RuntimeBackend,\n type RuntimeMetadata,\n} from \"../../lib/local-server/runtime\";\nimport { BaseCommand, type JsonEnvelope } from \"../../lib/oclif\";\nimport { createOrca } from \"../../lib/orca\";\nimport { hasZitadelConfig } from \"../../lib/project\";\nimport { listenersForPort } from \"../../lib/prober/ports\";\nimport { publicCliCommand } from \"../../lib/public-cli\";\nimport { SANITY_CHECKS, type CheckContext, type CheckOutcome } from \"./checks\";\n\nconst LOCAL_RUNTIME_CHECK_NAMES = new Set([\n \"server-binary\",\n \"docker-cli\",\n \"image\",\n \"state-dir\",\n \"port\",\n \"runtime\",\n]);\n\n/**\n * `zitadel doctor` — verify generated files and local state.\n *\n * Runs every registered {@link SANITY_CHECKS} entry and emits the aggregate\n * result; if any check fails it throws `E_VALIDATION` carrying the full check\n * details. With `--fix`, each failing check first attempts its own repair (a\n * no-op for checks with no safe automatic remedy), then the battery re-runs.\n *\n * The `--fix` loop is best-effort: a repair that throws (e.g. a missing\n * prerequisite file the check itself would also flag) is logged at debug\n * level and skipped, not propagated — the post-fix re-verify still reports\n * whatever remains broken.\n */\nexport default class Doctor extends BaseCommand {\n static override description = \"Verify local runtime and project state.\";\n static override flags = {\n fix: Flags.boolean({ description: \"Re-apply missing managed files.\" }),\n image: Flags.string({ description: \"Container image to check.\" }),\n port: Flags.integer({ description: \"Local HTTP port.\", default: DEFAULT_LOCAL_SERVER_PORT }),\n runtime: Flags.string({\n description: \"Local runtime backend.\",\n options: [\"binary\", \"docker\"],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Doctor);\n const port = flags.port ?? DEFAULT_LOCAL_SERVER_PORT;\n await this.toMeta(flags, { resolveServer: false, source: localServerUrl(port) });\n const { cwd, dryRun } = this.meta;\n const existingRuntime = await readRuntimeMetadata(cwd);\n const runtimeBackend = resolveRuntimeBackend({\n runtime: flags.runtime,\n image: flags.image,\n envImage: this.meta.env.ZITADEL_LOCAL_IMAGE,\n existingRuntime,\n });\n const image =\n flags.image ??\n this.meta.env.ZITADEL_LOCAL_IMAGE ??\n defaultLocalServerImageForCliVersion(this.meta.cliVersion);\n const runtimeChecks = await runLocalRuntimeChecks(cwd, runtimeBackend, image, port);\n const hasConfig = await hasZitadelConfig(cwd);\n const ctx: CheckContext = { cwd, orca: createOrca(), cliVersion: this.meta.cliVersion, dryRun };\n\n if (hasConfig && flags.fix) {\n const before = await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)));\n for (const [index, check] of SANITY_CHECKS.entries()) {\n if (before[index]?.status !== \"fail\") {\n continue;\n }\n try {\n await check.fix(ctx);\n } catch (error) {\n consola.debug(`doctor --fix: ${check.name} repair failed`, error);\n }\n }\n }\n\n const projectChecks = hasConfig\n ? await Promise.all(SANITY_CHECKS.map((check) => check.run(ctx)))\n : [];\n const checks = [...runtimeChecks, ...projectChecks];\n const failed = checks.filter((check) => check.status === \"fail\");\n const warnings = checks.filter((check) => check.status === \"warn\");\n const warningAdvice = advisoryForWarnings(warnings, this.meta.cliVersion);\n this.recordTelemetry({\n runtime: runtimeBackend,\n checks_total: checks.length,\n checks_failed: failed.length,\n checks_warn: warnings.length,\n failed_checks: failed.length > 0 ? failed.map((check) => check.name).join(\",\") : undefined,\n });\n const data = {\n title:\n failed.length > 0\n ? \"Zitadel doctor found issues.\"\n : warnings.length > 0\n ? \"Zitadel doctor passed with warnings.\"\n : \"Zitadel doctor passed.\",\n ok: failed.length === 0,\n runtime: runtimeBackend,\n ...(runtimeBackend === \"docker\" ? { image } : {}),\n port,\n project: {\n lifecycle: hasConfig ? \"configured\" : \"not-configured\",\n },\n checks,\n ...(warningAdvice\n ? {\n next_actions: warningAdvice.nextActions,\n next_commands: warningAdvice.nextCommands,\n }\n : {}),\n };\n\n if (failed.length > 0) {\n const advice = failureAdvice(failed, image, port, this.meta.cliVersion);\n const code = failed.some((check) => check.name === \"port\") ? \"E_PORT_IN_USE\" : \"E_VALIDATION\";\n throw new ZitadelError(code, \"Zitadel doctor found issues\", {\n hint: advice.hint,\n nextCommands: advice.nextCommands,\n details: data,\n });\n }\n\n return this.emit({\n status: \"ok\",\n data,\n warnings: warnings.map((warning) => `${warning.name}: ${warning.message}`),\n });\n }\n}\n\nfunction failureAdvice(\n failed: CheckOutcome[],\n image: string,\n port: number,\n cliVersion: string,\n): { hint: string; nextCommands: string[] } {\n const failedNames = new Set(failed.map((check) => check.name));\n\n if (failedNames.has(\"server-binary\")) {\n return {\n hint: \"The Zitadel server npm package is not available. Reinstall the CLI package, then retry.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"docker-cli\")) {\n const advice = dockerRuntimeGuidance(\"doctor\", cliVersion);\n return {\n hint: advice.hint,\n nextCommands: advice.nextCommands,\n };\n }\n\n if (failedNames.has(\"image\")) {\n return {\n hint: \"The local Zitadel image is not available. Check Docker registry access, build it locally, or pass --image / ZITADEL_LOCAL_IMAGE.\",\n nextCommands: [`docker pull ${image}`, publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"state-dir\")) {\n return {\n hint: \"The local Zitadel state directory is not writable. Fix directory permissions, then rerun `zitadel doctor`.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n }\n\n if (failedNames.has(\"port\")) {\n const fallbackPort = port === DEFAULT_LOCAL_SERVER_PORT ? port + 1 : DEFAULT_LOCAL_SERVER_PORT;\n const stopCommand = publicCliCommand(\"stop --all\", cliVersion);\n const retryCommand = publicCliCommand(\"doctor\", cliVersion);\n const alternatePortCommand = publicCliCommand(\n `doctor --port ${String(fallbackPort)}`,\n cliVersion,\n );\n return {\n hint:\n `Port ${String(port)} is already in use. Stop the process using it, ` +\n `run \\`${stopCommand}\\` for CLI-managed local runtimes, then rerun ` +\n `\\`${retryCommand}\\`; or choose another port with \\`${alternatePortCommand}\\`.`,\n nextCommands: [stopCommand, retryCommand, alternatePortCommand],\n };\n }\n\n if (failedNames.has(\"runtime\")) {\n return {\n hint: \"Existing local runtime metadata was found, but the local Zitadel server is not healthy. Start it again or reset stale local data.\",\n nextCommands: [\n publicCliCommand(\"start\", cliVersion),\n publicCliCommand(\"reset --force\", cliVersion),\n ],\n };\n }\n\n const hasProjectFailure = failed.some((check) => !LOCAL_RUNTIME_CHECK_NAMES.has(check.name));\n if (hasProjectFailure) {\n return {\n hint: `Run \\`${publicCliCommand(\"doctor --fix\", cliVersion)}\\` to re-apply missing managed files.`,\n nextCommands: [publicCliCommand(\"doctor --fix\", cliVersion)],\n };\n }\n\n return {\n hint: \"Fix the reported checks, then rerun `zitadel doctor`.\",\n nextCommands: [publicCliCommand(\"doctor\", cliVersion)],\n };\n}\n\nfunction advisoryForWarnings(\n warnings: CheckOutcome[],\n cliVersion: string,\n): { nextActions: string[]; nextCommands: string[] } | undefined {\n const nextActions: string[] = [];\n const nextCommands: string[] = [];\n if (warnings.some((check) => check.name === \"docker-cli\")) {\n const advice = dockerRuntimeGuidance(\"doctor\", cliVersion);\n nextActions.push(...advice.nextActions);\n nextCommands.push(...advice.nextCommands);\n }\n\n const managedRuntimeWarning = warnings.find((check) => check.name === \"managed-runtime-processes\");\n if (hasManagedRuntimeProcesses(managedRuntimeWarning)) {\n nextActions.push(\n \"Review other host-wide CLI-managed local Zitadel runtimes before starting a new one.\",\n );\n nextCommands.push(publicCliCommand(\"stop --all\", cliVersion));\n }\n\n if (nextActions.length === 0 && nextCommands.length === 0) {\n return undefined;\n }\n return { nextActions: unique(nextActions), nextCommands: unique(nextCommands) };\n}\n\nasync function runLocalRuntimeChecks(\n cwd: string,\n runtimeBackend: RuntimeBackend,\n image: string,\n port: number,\n): Promise<CheckOutcome[]> {\n const runtime = await readRuntimeMetadata(cwd);\n const managedRuntimeCheck = await checkManagedRuntimeProcesses(runtime);\n if (runtimeBackend === \"binary\") {\n return [\n await check(\"server-binary\", \"Server npm package is available\", async () => {\n const version = await assertServerPackageAvailable();\n return `@zitadel/server ${version} is available`;\n }),\n await check(\n \"state-dir\",\n \"Local state directory is writable\",\n async () => {\n const probe = await assertLocalStateWritable(cwd);\n return probe.checkedPath === probe.targetPath\n ? `${probe.targetPath} is writable`\n : `${probe.targetPath} can be created (${probe.checkedPath} is writable)`;\n },\n \"warn\",\n ),\n await check(\n \"port\",\n `Port ${String(port)} is available`,\n () => checkPortAvailability(runtime, port),\n ),\n await checkRuntime(runtime, runtimeBackend),\n managedRuntimeCheck,\n ];\n }\n\n const docker = await check(\n \"docker-cli\",\n \"Docker is reachable\",\n async () => {\n let result: Awaited<ReturnType<typeof dockerAvailable>>;\n try {\n result = await dockerAvailable();\n } catch (error) {\n throw new Error(dockerUnavailableMessage(error), { cause: error });\n }\n if (result.status !== 0) {\n throw new Error(dockerUnavailableMessage(result.stderr || \"docker version failed\"));\n }\n return `Docker engine ${result.stdout.trim() || \"available\"}`;\n },\n \"warn\",\n );\n\n const imageCheck =\n docker.status === \"pass\"\n ? await check(\n \"image\",\n `Image ${image} is available`,\n async () => {\n try {\n const source = await imageAvailable(image);\n return source === \"local\"\n ? `Image ${image} is available locally`\n : `Image ${image} is available from the registry`;\n } catch (error) {\n throw new Error(imageUnavailableMessage(image, error), { cause: error });\n }\n },\n \"warn\",\n )\n : ({\n name: \"image\",\n status: \"warn\",\n message: \"Skipped image check because Docker is not reachable.\",\n } satisfies CheckOutcome);\n\n return [\n docker,\n imageCheck,\n await check(\n \"state-dir\",\n \"Local state directory is writable\",\n async () => {\n const probe = await assertLocalStateWritable(cwd);\n return probe.checkedPath === probe.targetPath\n ? `${probe.targetPath} is writable`\n : `${probe.targetPath} can be created (${probe.checkedPath} is writable)`;\n },\n \"warn\",\n ),\n await check(\n \"port\",\n `Port ${String(port)} is available`,\n () => checkPortAvailability(runtime, port),\n ),\n await checkRuntime(runtime, runtimeBackend),\n managedRuntimeCheck,\n ];\n}\n\nasync function checkPortAvailability(\n runtime: RuntimeMetadata | undefined,\n port: number,\n): Promise<string> {\n if (runtime?.port === port && (await checkLocalServerHealth(runtime.server_url))) {\n return `${runtime.server_url} is already healthy`;\n }\n const listeners = await listenersForPort(port);\n if (listeners.length > 0) {\n throw new PortInUseCheckError(port, localServerUrl(port), listeners);\n }\n return `Port ${String(port)} is available`;\n}\n\nclass PortInUseCheckError extends Error {\n constructor(\n readonly port: number,\n readonly serverUrl: string,\n readonly listeners: Awaited<ReturnType<typeof listenersForPort>>,\n ) {\n super(`Port ${String(port)} is already in use by ${formatListeners(listeners)}`);\n }\n}\n\nasync function checkManagedRuntimeProcesses(\n runtime: RuntimeMetadata | undefined,\n): Promise<CheckOutcome> {\n const discovery = await discoverManagedRuntimeProcesses();\n if (!discovery.supported) {\n return {\n name: \"managed-runtime-processes\",\n status: \"warn\",\n message: \"Managed local runtime process discovery is unavailable.\",\n details: { supported: false, error: discovery.error },\n };\n }\n const processes = additionalManagedRuntimeProcesses(discovery.processes, runtime);\n if (processes.length === 0) {\n return {\n name: \"managed-runtime-processes\",\n status: \"pass\",\n message: \"No additional host-wide managed local runtime processes found.\",\n details: { supported: true, scope: \"host\", processes: [] },\n };\n }\n return {\n name: \"managed-runtime-processes\",\n status: \"warn\",\n message: `${String(processes.length)} other host-wide managed local runtime process${processes.length === 1 ? \"\" : \"es\"} found.`,\n details: { supported: true, scope: \"host\", processes },\n };\n}\n\nfunction additionalManagedRuntimeProcesses(\n processes: ReadonlyArray<ManagedRuntimeProcess>,\n runtime: RuntimeMetadata | undefined,\n): ReadonlyArray<ManagedRuntimeProcess> {\n if (runtime?.backend !== \"binary\") {\n return processes;\n }\n return processes.filter((processInfo) => processInfo.pid !== runtime.pid && processInfo.ppid !== runtime.pid);\n}\n\nasync function checkRuntime(\n runtime: { backend: RuntimeBackend; server_url: string } | undefined,\n runtimeBackend: RuntimeBackend,\n): Promise<CheckOutcome> {\n return check(\"runtime\", \"Existing local runtime is healthy\", async () => {\n if (!runtime) {\n return \"No existing runtime metadata\";\n }\n if (runtime.backend !== runtimeBackend) {\n throw new Error(\n `Existing local runtime uses ${runtime.backend}; run start --runtime ${runtimeBackend} to switch backends.`,\n );\n }\n if (!(await checkLocalServerHealth(runtime.server_url))) {\n throw new Error(`${runtime.server_url} did not respond to /healthz`);\n }\n return `${runtime.server_url} is healthy`;\n });\n}\n\nfunction formatListeners(listeners: Awaited<ReturnType<typeof listenersForPort>>): string {\n return listeners\n .map((listener) =>\n [listener.command ?? \"unknown\", listener.pid ? `pid ${String(listener.pid)}` : undefined]\n .filter(Boolean)\n .join(\" \"),\n )\n .join(\", \");\n}\n\nfunction hasManagedRuntimeProcesses(check: CheckOutcome | undefined): boolean {\n if (!check || check.status !== \"warn\") {\n return false;\n }\n const details = check.details;\n return (\n typeof details === \"object\" &&\n details !== null &&\n \"supported\" in details &&\n (details as { supported?: unknown }).supported === true &&\n Array.isArray((details as { processes?: unknown }).processes) &&\n ((details as { processes?: unknown[] }).processes?.length ?? 0) > 0\n );\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction resolveRuntimeBackend(input: {\n runtime: unknown;\n image: string | undefined;\n envImage: string | undefined;\n existingRuntime: { backend: RuntimeBackend } | undefined;\n}): RuntimeBackend {\n if (input.runtime === \"binary\" || input.runtime === \"docker\") {\n return input.runtime;\n }\n if (input.existingRuntime) {\n return input.existingRuntime.backend;\n }\n if (input.image || input.envImage) {\n return \"docker\";\n }\n return \"binary\";\n}\n\nasync function check(\n name: string,\n fallback: string,\n run: () => Promise<string>,\n failureStatus: \"warn\" | \"fail\" = \"fail\",\n): Promise<CheckOutcome> {\n try {\n return { name, status: \"pass\", message: await run() };\n } catch (error) {\n if (error instanceof PortInUseCheckError) {\n return {\n name,\n status: failureStatus,\n message: error.message,\n details: {\n port: error.port,\n server_url: error.serverUrl,\n listeners: error.listeners,\n },\n };\n }\n return {\n name,\n status: failureStatus,\n message: error instanceof Error ? error.message : fallback,\n };\n }\n}\n\nfunction imageUnavailableMessage(image: string, error: unknown): string {\n const detail = error instanceof Error ? error.message : String(error);\n const suffix = detail.trim() ? ` (${detail.trim()})` : \"\";\n return `Image ${image} is not available to Docker${suffix}; \\`zitadel start\\` may need a pull or a different image.`;\n}\n"],"mappings":"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"}
|
package/dist/commands/eject.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { E as ZitadelError, t as BaseCommand } from "../oclif-
|
|
2
|
-
import { t as createOrca } from "../orca-
|
|
3
|
-
import { a as readZitadelConfig, i as readRendererId } from "../project-
|
|
4
|
-
import { join } from "node:path";
|
|
1
|
+
import { E as ZitadelError, t as BaseCommand } from "../oclif-Bm-FkF6z.mjs";
|
|
2
|
+
import { t as createOrca } from "../orca-CpXj_XsA.mjs";
|
|
3
|
+
import { a as readZitadelConfig, i as readRendererId } from "../project-Dk7V0xka.mjs";
|
|
5
4
|
import { readFile, rename, rm, stat } from "node:fs/promises";
|
|
5
|
+
import { join } from "node:path";
|
|
6
6
|
//#region src/commands/eject.ts
|
|
7
7
|
/**
|
|
8
8
|
* Asks the framework patcher which artifacts it owns. Falls back to the
|
package/dist/commands/logs.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as ZitadelError, S as resolveCwd, b as publicCliCommand, m as readRuntimeMetadata, t as BaseCommand } from "../oclif-
|
|
2
|
-
import { a as followContainerLogs, f as binaryLogs, p as followBinaryLogs, t as containerLogs } from "../docker-
|
|
1
|
+
import { E as ZitadelError, S as resolveCwd, b as publicCliCommand, m as readRuntimeMetadata, t as BaseCommand } from "../oclif-Bm-FkF6z.mjs";
|
|
2
|
+
import { a as followContainerLogs, f as binaryLogs, p as followBinaryLogs, t as containerLogs } from "../docker-D7BSD5C9.mjs";
|
|
3
3
|
import { Flags } from "@oclif/core";
|
|
4
4
|
//#region src/commands/logs.ts
|
|
5
5
|
var Logs = class Logs extends BaseCommand {
|
package/dist/commands/plan.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { t as BaseCommand } from "../oclif-
|
|
2
|
-
import { o as readZitadelSecret } from "../project-
|
|
3
|
-
import {
|
|
1
|
+
import { t as BaseCommand } from "../oclif-Bm-FkF6z.mjs";
|
|
2
|
+
import { o as readZitadelSecret } from "../project-Dk7V0xka.mjs";
|
|
3
|
+
import { c as makeSyncers, n as summarizePlan, r as buildSyncPlan, t as renderPlan } from "../sync-CYuHVQT5.mjs";
|
|
4
|
+
import { t as environmentSchema } from "../environment-BQF7LeCz.mjs";
|
|
4
5
|
import { Flags } from "@oclif/core";
|
|
5
6
|
import { createZitadelClient } from "@zitadel/api/client";
|
|
6
7
|
import { consola as consola$1 } from "consola";
|
|
@@ -41,10 +42,11 @@ var Plan = class Plan extends BaseCommand {
|
|
|
41
42
|
this.recordTelemetry({
|
|
42
43
|
creates: summary.creates,
|
|
43
44
|
updates: summary.updates,
|
|
45
|
+
revisions: summary.revisions,
|
|
44
46
|
deletes: summary.deletes,
|
|
45
47
|
total: summary.total
|
|
46
48
|
});
|
|
47
|
-
consola$1.success(`Plan: ${summary.creates} create${summary.creates === 1 ? "" : "s"}, ${summary.updates} update${summary.updates === 1 ? "" : "s"}, ${summary.
|
|
49
|
+
consola$1.success(`Plan: ${summary.creates} create${summary.creates === 1 ? "" : "s"}, ${summary.updates} update${summary.updates === 1 ? "" : "s"}, ${summary.revisions} new revision${summary.revisions === 1 ? "" : "s"}, ${summary.deletes} delete${summary.deletes === 1 ? "" : "s"}, ${plan.length - summary.total} unchanged`);
|
|
48
50
|
return this.emit({
|
|
49
51
|
status: "ok",
|
|
50
52
|
data: summary,
|
|
@@ -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 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({
|
|
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({\n client,\n projectId: secret.project_id,\n env,\n });\n\n consola.start(\"Building plan\");\n const plan = await buildSyncPlan(cwd, syncers, true);\n const summary = summarizePlan(plan);\n this.recordTelemetry({\n creates: summary.creates,\n updates: summary.updates,\n revisions: summary.revisions,\n deletes: summary.deletes,\n total: summary.total,\n });\n consola.success(\n `Plan: ${summary.creates} create${summary.creates === 1 ? \"\" : \"s\"}, ` +\n `${summary.updates} update${summary.updates === 1 ? \"\" : \"s\"}, ` +\n `${summary.revisions} new revision${summary.revisions === 1 ? \"\" : \"s\"}, ` +\n `${summary.deletes} delete${summary.deletes === 1 ? \"\" : \"s\"}, ` +\n `${plan.length - summary.total} 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;GAC1B,QALa,oBAAoB;IACjC,SAAS;IACT,OAAO,OAAO;IACf,CAEO;GACN,WAAW,OAAO;GAClB;GACD,CAAC;AAEF,YAAQ,MAAM,gBAAgB;EAC9B,MAAM,OAAO,MAAM,cAAc,KAAK,SAAS,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK;AACnC,OAAK,gBAAgB;GACnB,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,WAAW,QAAQ;GACnB,SAAS,QAAQ;GACjB,OAAO,QAAQ;GAChB,CAAC;AACF,YAAQ,QACN,SAAS,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC9D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,UAAU,eAAe,QAAQ,cAAc,IAAI,KAAK,IAAI,IACpE,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,KAAK,SAAS,QAAQ,MAAM,YAClC;AACD,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;GACN,QAAQ,WAAW,MAAM,MAAM;GAChC,CAAC"}
|
package/dist/commands/reset.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as ZitadelError, S as resolveCwd, b as publicCliCommand, f as localContainerName, g as removeRuntimeMetadata, h as removeLocalData, m as readRuntimeMetadata, t as BaseCommand } from "../oclif-
|
|
2
|
-
import { g as stopBinaryRuntime, u as stopAndRemoveContainer } from "../docker-
|
|
1
|
+
import { E as ZitadelError, S as resolveCwd, b as publicCliCommand, f as localContainerName, g as removeRuntimeMetadata, h as removeLocalData, m as readRuntimeMetadata, t as BaseCommand } from "../oclif-Bm-FkF6z.mjs";
|
|
2
|
+
import { g as stopBinaryRuntime, u as stopAndRemoveContainer } from "../docker-D7BSD5C9.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 {
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { t as BaseCommand } from "../../oclif-Bm-FkF6z.mjs";
|
|
2
|
+
import { o as readZitadelSecret } from "../../project-Dk7V0xka.mjs";
|
|
3
|
+
import { t as environmentSchema } from "../../environment-BQF7LeCz.mjs";
|
|
4
|
+
import { cancel, isCancel, select, spinner } from "@clack/prompts";
|
|
5
|
+
import { Flags } from "@oclif/core";
|
|
6
|
+
import { createZitadelClient } from "@zitadel/api/client";
|
|
7
|
+
import { consola as consola$1 } from "consola";
|
|
8
|
+
//#region src/commands/schemas/list.ts
|
|
9
|
+
/**
|
|
10
|
+
* The `schemas list` topic command — inspect the revision history of a
|
|
11
|
+
* user-schema, filtered by `objectType`.
|
|
12
|
+
*
|
|
13
|
+
* Non-interactive: prints one row per revision (newest first) as a JSON payload
|
|
14
|
+
* or a plain-text table. Interactive: renders a `@clack/prompts` `select` menu
|
|
15
|
+
* of the same rows; on selection, fetches the full schema body via
|
|
16
|
+
* `getSchemaById` and pretty-prints it to stdout.
|
|
17
|
+
*/
|
|
18
|
+
var SchemasList = class SchemasList extends BaseCommand {
|
|
19
|
+
static description = "List revisions of a user-schema by objectType.";
|
|
20
|
+
static flags = {
|
|
21
|
+
"object-type": Flags.string({
|
|
22
|
+
char: "t",
|
|
23
|
+
required: true,
|
|
24
|
+
description: "Filter revisions by objectType (e.g. human-user)."
|
|
25
|
+
}),
|
|
26
|
+
environment: Flags.string({
|
|
27
|
+
char: "e",
|
|
28
|
+
description: "Target environment (default: development).",
|
|
29
|
+
options: [...environmentSchema.options]
|
|
30
|
+
})
|
|
31
|
+
};
|
|
32
|
+
async run() {
|
|
33
|
+
const { flags } = await this.parse(SchemasList);
|
|
34
|
+
await this.toMeta(flags);
|
|
35
|
+
const { cwd, source, nonInteractive } = this.meta;
|
|
36
|
+
const secret = await readZitadelSecret(cwd);
|
|
37
|
+
consola$1.info(`Project ${secret.project_id}`);
|
|
38
|
+
consola$1.info(`Server ${source}`);
|
|
39
|
+
const client = createZitadelClient({
|
|
40
|
+
baseUrl: source,
|
|
41
|
+
token: secret.project_secret
|
|
42
|
+
});
|
|
43
|
+
const objectType = flags["object-type"];
|
|
44
|
+
const revisions = await client.listSchemas({
|
|
45
|
+
project_id: secret.project_id,
|
|
46
|
+
object_type: objectType
|
|
47
|
+
});
|
|
48
|
+
if (revisions.length === 0) {
|
|
49
|
+
const message = `No revisions found for objectType "${objectType}".`;
|
|
50
|
+
consola$1.warn(message);
|
|
51
|
+
return this.emit({
|
|
52
|
+
status: "ok",
|
|
53
|
+
data: {
|
|
54
|
+
object_type: objectType,
|
|
55
|
+
revisions: [],
|
|
56
|
+
count: 0
|
|
57
|
+
},
|
|
58
|
+
pretty: message
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (nonInteractive) return this.emit({
|
|
62
|
+
status: "ok",
|
|
63
|
+
data: {
|
|
64
|
+
object_type: objectType,
|
|
65
|
+
revisions,
|
|
66
|
+
count: revisions.length
|
|
67
|
+
},
|
|
68
|
+
pretty: renderTable(objectType, revisions)
|
|
69
|
+
});
|
|
70
|
+
const picked = await select({
|
|
71
|
+
message: `Revisions of objectType "${objectType}" (newest first)`,
|
|
72
|
+
options: revisions.map((r, idx) => ({
|
|
73
|
+
value: r.id,
|
|
74
|
+
label: `${r.createdAt} ${r.id}${idx === 0 ? " (latest)" : ""}`
|
|
75
|
+
}))
|
|
76
|
+
});
|
|
77
|
+
if (isCancel(picked)) {
|
|
78
|
+
cancel("No revision selected.");
|
|
79
|
+
return this.emit({
|
|
80
|
+
status: "ok",
|
|
81
|
+
data: {
|
|
82
|
+
object_type: objectType,
|
|
83
|
+
revisions,
|
|
84
|
+
count: revisions.length
|
|
85
|
+
},
|
|
86
|
+
pretty: ""
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const s = spinner();
|
|
90
|
+
s.start(`Loading ${String(picked)}…`);
|
|
91
|
+
const body = await fetchSchemaRevision(client, String(picked), secret.project_id);
|
|
92
|
+
s.stop(`Loaded ${String(picked)}`);
|
|
93
|
+
const pretty = JSON.stringify(body, null, 2);
|
|
94
|
+
return this.emit({
|
|
95
|
+
status: "ok",
|
|
96
|
+
data: {
|
|
97
|
+
object_type: objectType,
|
|
98
|
+
revisions,
|
|
99
|
+
selected: {
|
|
100
|
+
id: picked,
|
|
101
|
+
body
|
|
102
|
+
},
|
|
103
|
+
count: revisions.length
|
|
104
|
+
},
|
|
105
|
+
pretty
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Fetch one schema revision body. The id is URL-encoded before it lands in
|
|
111
|
+
* the path: server-allocated ids are opaque today (`sch_…`), but ids can be
|
|
112
|
+
* full URLs when a schema carried an `$id` (the server-seeded defaults do),
|
|
113
|
+
* and an unencoded URL would break the `/schemas/:id` path. Mirrors the
|
|
114
|
+
* encoding the sync engine's schema syncer applies.
|
|
115
|
+
*/
|
|
116
|
+
async function fetchSchemaRevision(client, id, projectId) {
|
|
117
|
+
return client.getSchemaById(encodeURIComponent(id), { project_id: projectId });
|
|
118
|
+
}
|
|
119
|
+
function renderTable(objectType, revisions) {
|
|
120
|
+
const header = `Revisions of objectType "${objectType}" (${revisions.length}, newest first)`;
|
|
121
|
+
const idCol = Math.max(2, ...revisions.map((r) => r.id.length));
|
|
122
|
+
const createdCol = Math.max(9, ...revisions.map((r) => r.createdAt.length));
|
|
123
|
+
const rows = revisions.map((r) => `${r.createdAt.padEnd(createdCol)} ${r.id.padEnd(idCol)}`);
|
|
124
|
+
return [
|
|
125
|
+
header,
|
|
126
|
+
`${"createdAt".padEnd(createdCol)} ${"id".padEnd(idCol)}`,
|
|
127
|
+
`${"-".repeat(createdCol)} ${"-".repeat(idCol)}`,
|
|
128
|
+
...rows
|
|
129
|
+
].join("\n");
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
export { SchemasList as default, fetchSchemaRevision };
|
|
133
|
+
|
|
134
|
+
//# sourceMappingURL=list.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.mjs","names":[],"sources":["../../../src/commands/schemas/list.ts"],"sourcesContent":["import { cancel, isCancel, select, spinner } from \"@clack/prompts\";\nimport { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient, type ZitadelClient } from \"@zitadel/api/client\";\nimport type { ListSchemas200Item } from \"@zitadel/api/generated/model\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../../lib/oclif\";\nimport { environmentSchema } from \"../../lib/environment\";\nimport { readZitadelSecret } from \"../../lib/project\";\n\n/**\n * The `schemas list` topic command — inspect the revision history of a\n * user-schema, filtered by `objectType`.\n *\n * Non-interactive: prints one row per revision (newest first) as a JSON payload\n * or a plain-text table. Interactive: renders a `@clack/prompts` `select` menu\n * of the same rows; on selection, fetches the full schema body via\n * `getSchemaById` and pretty-prints it to stdout.\n */\nexport default class SchemasList extends BaseCommand {\n static override description = \"List revisions of a user-schema by objectType.\";\n static override flags = {\n \"object-type\": Flags.string({\n char: \"t\",\n required: true,\n description: \"Filter revisions by objectType (e.g. human-user).\",\n }),\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(SchemasList);\n await this.toMeta(flags);\n const { cwd, source, nonInteractive } = 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\n const objectType = flags[\"object-type\"];\n const revisions = await client.listSchemas({\n project_id: secret.project_id,\n object_type: objectType,\n });\n\n if (revisions.length === 0) {\n const message = `No revisions found for objectType \"${objectType}\".`;\n consola.warn(message);\n return this.emit({\n status: \"ok\",\n data: { object_type: objectType, revisions: [], count: 0 },\n pretty: message,\n });\n }\n\n // Server orders newest-first; the interactive picker inherits that order.\n if (nonInteractive) {\n return this.emit({\n status: \"ok\",\n data: {\n object_type: objectType,\n revisions,\n count: revisions.length,\n },\n pretty: renderTable(objectType, revisions),\n });\n }\n\n const picked = await select({\n message: `Revisions of objectType \"${objectType}\" (newest first)`,\n options: revisions.map((r, idx) => ({\n value: r.id,\n label: `${r.createdAt} ${r.id}${idx === 0 ? \" (latest)\" : \"\"}`,\n })),\n });\n if (isCancel(picked)) {\n cancel(\"No revision selected.\");\n return this.emit({\n status: \"ok\",\n data: { object_type: objectType, revisions, count: revisions.length },\n pretty: \"\",\n });\n }\n\n const s = spinner();\n s.start(`Loading ${String(picked)}…`);\n const body = await fetchSchemaRevision(client, String(picked), secret.project_id);\n s.stop(`Loaded ${String(picked)}`);\n\n const pretty = JSON.stringify(body, null, 2);\n\n return this.emit({\n status: \"ok\",\n data: {\n object_type: objectType,\n revisions,\n selected: { id: picked, body },\n count: revisions.length,\n },\n pretty,\n });\n }\n}\n\n/**\n * Fetch one schema revision body. The id is URL-encoded before it lands in\n * the path: server-allocated ids are opaque today (`sch_…`), but ids can be\n * full URLs when a schema carried an `$id` (the server-seeded defaults do),\n * and an unencoded URL would break the `/schemas/:id` path. Mirrors the\n * encoding the sync engine's schema syncer applies.\n */\nexport async function fetchSchemaRevision(\n client: ZitadelClient,\n id: string,\n projectId: string,\n): Promise<unknown> {\n return client.getSchemaById(encodeURIComponent(id), { project_id: projectId });\n}\n\nfunction renderTable(objectType: string, revisions: ReadonlyArray<ListSchemas200Item>): string {\n const header = `Revisions of objectType \"${objectType}\" (${revisions.length}, newest first)`;\n const idCol = Math.max(\"id\".length, ...revisions.map((r) => r.id.length));\n const createdCol = Math.max(\"createdAt\".length, ...revisions.map((r) => r.createdAt.length));\n const rows = revisions.map(\n (r) => `${r.createdAt.padEnd(createdCol)} ${r.id.padEnd(idCol)}`,\n );\n return [\n header,\n `${\"createdAt\".padEnd(createdCol)} ${\"id\".padEnd(idCol)}`,\n `${\"-\".repeat(createdCol)} ${\"-\".repeat(idCol)}`,\n ...rows,\n ].join(\"\\n\");\n}\n"],"mappings":"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"}
|