@zitadel/cli 0.1.0-alpha.4 → 0.1.0-alpha.8
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 +70 -63
- package/SKILLS.md +60 -18
- package/dist/commands/apply.mjs +3 -3
- package/dist/commands/doctor.mjs +75 -20
- package/dist/commands/doctor.mjs.map +1 -1
- package/dist/commands/eject.mjs +13 -6
- package/dist/commands/eject.mjs.map +1 -1
- package/dist/commands/logs.mjs +13 -5
- package/dist/commands/logs.mjs.map +1 -1
- package/dist/commands/plan.mjs +3 -3
- package/dist/commands/reset.mjs +16 -7
- package/dist/commands/reset.mjs.map +1 -1
- package/dist/commands/setup.mjs +56 -17
- package/dist/commands/setup.mjs.map +1 -1
- package/dist/commands/start.mjs +104 -11
- package/dist/commands/start.mjs.map +1 -1
- package/dist/commands/status.mjs +26 -7
- package/dist/commands/status.mjs.map +1 -1
- package/dist/commands/stop.mjs +15 -6
- package/dist/commands/stop.mjs.map +1 -1
- package/dist/docker-BA78SdC2.mjs +383 -0
- package/dist/docker-BA78SdC2.mjs.map +1 -0
- package/dist/docker-guidance-BvfpmsDj.mjs +21 -0
- package/dist/docker-guidance-BvfpmsDj.mjs.map +1 -0
- package/dist/{oclif-B3Qhw0cj.mjs → oclif-VkCTGIEk.mjs} +50 -15
- package/dist/oclif-VkCTGIEk.mjs.map +1 -0
- package/dist/orca-CfKDQRop.mjs +2556 -0
- package/dist/orca-CfKDQRop.mjs.map +1 -0
- package/dist/{project-kWWyS7fS.mjs → project-CKAHtHML.mjs} +2 -2
- package/dist/{project-kWWyS7fS.mjs.map → project-CKAHtHML.mjs.map} +1 -1
- package/dist/{sync-CHXZqYR7.mjs → sync-B5lqgQO3.mjs} +2 -2
- package/dist/{sync-CHXZqYR7.mjs.map → sync-B5lqgQO3.mjs.map} +1 -1
- package/oclif.manifest.json +37 -3
- package/package.json +8 -41
- package/dist/docker-B4zvLujy.mjs +0 -210
- package/dist/docker-B4zvLujy.mjs.map +0 -1
- package/dist/oclif-B3Qhw0cj.mjs.map +0 -1
- package/dist/orca-BGM8VCgQ.mjs +0 -1141
- package/dist/orca-BGM8VCgQ.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-CHXZqYR7.mjs","names":["createSchemaBodySchema"],"sources":["../src/lib/environment.ts","../src/lib/flows/validate.ts","../src/lib/flows/env-refs.ts","../src/lib/flows/index.ts","../src/lib/user-schema/index.ts","../src/lib/sync/syncers.ts","../src/lib/sync/state.ts","../src/lib/sync/loop.ts","../src/lib/sync/plan-renderer.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * CLI-side deployment environment. Not an API model — it gates which\n * `zitadel.json` environment block and server the commands target.\n * Project request/response shapes live in `@zitadel/api`\n * (generated from the OpenAPI spec).\n */\nexport const environmentSchema = z.enum([\"development\", \"preview\", \"production\"]);\n","import type { CreateFlowDefinitionBodyFlowDefinition } from \"@zitadel/api/generated/model\";\nimport { CreateFlowDefinitionBody } from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\n\nimport { ZitadelError } from \"../errors\";\n\n/**\n * The generated `CreateFlowDefinitionBody` Zod schema describes the\n * full envelope (`{project_id, flow_definition, schema_uri?}`); the\n * on-disk flow body is just the inner `flow_definition` shape. Pull\n * that out via `.shape` so on-disk validation runs against exactly the\n * same schema the wire request validates against.\n */\nconst flowDefinitionBodySchema = CreateFlowDefinitionBody.shape.flow_definition;\n\n/**\n * Validate raw JSON bodies against the generated flow-definition Zod\n * schema (the orval-emitted equivalent of\n * `api/openapi/components/flows/flow-definition.yaml`). Errors from\n * every input are collected and rethrown as a single `E_VALIDATION`\n * `ZitadelError` so callers see the full picture at once rather than\n * failing on the first malformed entry.\n *\n * Pure: does not touch the filesystem or network. The input array\n * is read-only; the returned array is freshly allocated.\n *\n * @param flows - Raw values to validate. Unknown-typed so callers\n * can pass freshly-parsed JSON without first asserting a shape.\n */\nexport function validateFlows(\n flows: ReadonlyArray<unknown>,\n): ReadonlyArray<CreateFlowDefinitionBodyFlowDefinition> {\n const issues: Array<{ index: number; issues: unknown }> = [];\n const parsed: CreateFlowDefinitionBodyFlowDefinition[] = [];\n for (let i = 0; i < flows.length; i += 1) {\n const result = flowDefinitionBodySchema.safeParse(flows[i]);\n if (!result.success) {\n issues.push({ index: i, issues: result.error.issues });\n continue;\n }\n parsed.push(result.data as CreateFlowDefinitionBodyFlowDefinition);\n }\n if (issues.length > 0) {\n throw new ZitadelError(\"E_VALIDATION\", \"One or more flow definitions are invalid\", {\n details: { issues },\n });\n }\n return parsed;\n}\n","import { isObject } from \"../json\";\n\n/**\n * Collects the environment variables a flows document depends on, sorted and\n * de-duplicated. Recognises two reference styles: inline `${VAR}` interpolations\n * inside string values, and keys ending in `_env` whose value names a single\n * variable. `apply`/`plan` use this to fail before contacting the platform when\n * a required variable is absent.\n */\nexport function flowEnvRefs(value: unknown): string[] {\n const refs = new Set<string>();\n const visit = (node: unknown): void => {\n if (typeof node === \"string\") {\n for (const match of node.matchAll(/\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g)) {\n const ref = match[1];\n if (ref) {\n refs.add(ref);\n }\n }\n } else if (Array.isArray(node)) {\n node.forEach(visit);\n } else if (isObject(node)) {\n for (const [key, child] of Object.entries(node)) {\n if (key.endsWith(\"_env\") && typeof child === \"string\" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(child)) {\n refs.add(child);\n } else {\n visit(child);\n }\n }\n }\n };\n visit(value);\n return [...refs].sort();\n}\n","/**\n * Public surface for the flow domain. Every caller outside this module\n * imports from here (not from individual files) so the package\n * boundary stays observable.\n *\n * **Source of truth.** The wire shape lives in\n * `@zitadel/api/generated/model` (orval-generated from the\n * OpenAPI spec). Callers that need the type import\n * `CreateFlowDefinitionBodyFlowDefinition` from there directly;\n * callers that need the runtime validator import\n * `CreateFlowDefinitionBody` from\n * `@zitadel/api/generated/endpoints/zitadelNextGen.zod`. This\n * module owns only the CLI-specific concerns: the password-flow\n * builder, env-var reference scanning, and the file-level\n * `validateFlows` helper that surfaces `E_VALIDATION` errors against\n * the generated Zod.\n *\n * **Dependency rule.** No upward imports (`commands/`, `sync/`, etc.)\n * and no filesystem I/O. It depends sideways only on shared utilities\n * under `apps/cli/src/lib/` — today `lib/errors` (`ZitadelError`).\n */\nexport { buildFlow } from \"./build\";\nexport { validateFlows } from \"./validate\";\nexport { flowEnvRefs } from \"./env-refs\";\n\n/**\n * Relative directory (from the project root) where local flow files\n * live. Owned here so callers (`commands/*`, `sync/syncers.ts`) and\n * tests share a single source of truth for the path; the runtime\n * never depends on it directly because `lib/flows` does not touch\n * the filesystem.\n */\nexport const FLOWS_DIR = \".zitadel/flows\";\n","/**\n * Public surface for the user-schema domain. Every caller outside this\n * module imports from here (not from individual files), the same\n * discipline as `lib/flows/`.\n *\n * **Source of truth.** The wire shape lives in\n * `@zitadel/api/generated/model` (orval-generated from the\n * OpenAPI spec). Callers that need the type import `CreateSchemaBody`\n * from there directly; callers that need the runtime validator import\n * the matching Zod schema from\n * `@zitadel/api/generated/endpoints/zitadelNextGen.zod`. This\n * module owns only CLI-specific concerns: the builder, the per-field\n * preset catalog, and the two `DEFAULT_*` URI constants.\n *\n * **Dependency rule.** No upward imports (`commands/`, `sync/`, etc.)\n * and no filesystem I/O. Reading and writing local files is the\n * caller's responsibility, served by `apps/cli/src/lib/json-dir.ts`\n * plus this module's {@link SCHEMAS_DIR} constant.\n */\nexport {\n DEFAULT_USER_META_SCHEMA,\n DEFAULT_USER_SCHEMA_ID,\n buildUserSchema,\n} from \"./build\";\n\n/**\n * Relative directory (from the project root) where local user-schema\n * files live. Owned here so callers (`commands/*`, `sync/syncers.ts`)\n * and tests share a single source of truth for the path; the runtime\n * never depends on it directly because `lib/user-schema` does not touch\n * the filesystem. The counterpart of `lib/flows`' `FLOWS_DIR`.\n */\nexport const SCHEMAS_DIR = \".zitadel/schemas\";\n","import type {\n CreateFlowDefinitionBodyFlowDefinition,\n CreateSchemaBody,\n GetSchemaById200,\n GetFlowDefinition200,\n} from \"@zitadel/api/generated/model\";\nimport type { ZitadelClient } from \"@zitadel/api/client\";\nimport { CreateSchemaBody as createSchemaBodySchema } from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\n\nimport { FLOWS_DIR, flowEnvRefs, validateFlows } from \"../flows\";\nimport { SCHEMAS_DIR } from \"../user-schema\";\nimport { ZitadelError } from \"../errors\";\nimport type { ResourceSyncer } from \"./types.js\";\n\n/** Runtime environment lookup used to resolve `${VAR}` / `*_env` references. */\ntype EnvLookup = Record<string, string | undefined>;\n\n/**\n * Build the syncer list with the context every syncer needs: the\n * `project_id` flow creates carry, and the runtime `env` against which\n * each file's `${VAR}` / `*_env` references are checked. Callers\n * (apply / plan / setup) read `project_id` from `.zitadel/secret` and\n * pass the process environment. The returned array is treated as\n * read-only by the sync loop.\n */\nexport function makeSyncers(opts: {\n client: ZitadelClient;\n projectId: string;\n env: EnvLookup;\n}): ReadonlyArray<ResourceSyncer> {\n return [\n new SchemaSyncer(opts.client, opts.projectId, opts.env),\n new FlowDefinitionSyncer(opts.client, opts.projectId, opts.env),\n ];\n}\n\n/**\n * Assert that every env var a resource references — `${VAR}` placeholders and\n * the `*_env` convention — is present in `env`, throwing `E_VALIDATION` listing\n * the missing names. Shared by every syncer so the check is identical for\n * schemas and flows, and runs in the sync engine before any platform call.\n */\nfunction assertEnvRefs(data: object, env: EnvLookup): void {\n const missing = flowEnvRefs(data).filter((name) => !env[name]);\n if (missing.length > 0) {\n throw new ZitadelError(\"E_VALIDATION\", `Missing environment variables: ${missing.join(\", \")}`);\n }\n}\n\nclass SchemaSyncer implements ResourceSyncer {\n readonly kind = \"schema\";\n readonly directory = SCHEMAS_DIR;\n readonly mutable = false;\n\n constructor(\n private readonly client: ZitadelClient,\n private readonly projectId: string,\n private readonly env: EnvLookup,\n ) {}\n\n /**\n * Parse against the generated `CreateSchemaBody` Zod (the orval-emitted\n * equivalent of `api/openapi/endpoints/schemas/user-schema.yaml`). The\n * generated schema is a union of `user-schema` and `schema-url`\n * discriminated on `kind`; both are valid on-disk bodies.\n */\n validate(data: object): void {\n const result = createSchemaBodySchema.safeParse(data);\n if (!result.success) {\n throw new ZitadelError(\"E_VALIDATION\", \"Schema file is not a valid Zitadel schema body\", {\n details: { issues: result.error.issues },\n });\n }\n assertEnvRefs(data, this.env);\n }\n\n async create(data: object): Promise<string> {\n const result = await this.client.createSchema(data as CreateSchemaBody, {\n project_id: this.projectId,\n });\n return result.id;\n }\n\n /** Never called — schemas are immutable on the platform, so `mutable = false`. */\n async update(_id: string, _data: object): Promise<void> {\n return;\n }\n\n async delete(id: string): Promise<void> {\n // Schemas are immutable on the platform: no PATCH, no DELETE in the\n // generated client. The sync loop's delete branch (`loop.ts`) still\n // schedules a delete action when a state entry exists and the\n // on-disk file is gone — `mutable` only gates updates, not deletes.\n // We deliberately fail loud here so the user notices that removing\n // a schema file is not a supported way to retire it.\n throw new ZitadelError(\"E_NOT_IMPLEMENTED\", `schema delete is not supported (${id})`);\n }\n\n async fetch(id: string): Promise<object> {\n const body = await this.client.getSchemaById(id, { project_id: this.projectId });\n return body as unknown as GetSchemaById200;\n }\n}\n\nclass FlowDefinitionSyncer implements ResourceSyncer {\n readonly kind = \"flow\";\n readonly directory = FLOWS_DIR;\n readonly mutable = true;\n\n constructor(\n private readonly client: ZitadelClient,\n private readonly projectId: string,\n private readonly env: EnvLookup,\n ) {}\n\n /**\n * Validates one flow file. `validateFlows` takes a batch and throws\n * `E_VALIDATION` on the first invalid entry; passing a single-element array\n * lets us reuse the batch validator for one file.\n */\n validate(data: object): void {\n validateFlows([data]);\n assertEnvRefs(data, this.env);\n }\n\n /**\n * Wraps the bare on-disk flow body in the spec's create-envelope\n * (`api/openapi/components/flows/flow-definition-create-request.yaml`)\n * before sending. The file on disk stays bare so it is human-editable;\n * only the wire request carries `project_id` and the surrounding\n * envelope.\n */\n async create(data: object): Promise<string> {\n const result = await this.client.createFlowDefinition({\n project_id: this.projectId,\n flow_definition: data as CreateFlowDefinitionBodyFlowDefinition,\n });\n return result.id;\n }\n\n /** PATCH body is the bare partial flow per `flow-definition-update-request` — no envelope. */\n async update(id: string, data: object): Promise<void> {\n await this.client.updateFlowDefinition(\n id,\n data as Partial<CreateFlowDefinitionBodyFlowDefinition>,\n );\n }\n\n async delete(id: string): Promise<void> {\n await this.client.deleteFlowDefinition(id);\n }\n\n /**\n * `GET /flow_definitions/:id` wraps the bare flow body in a detail envelope\n * (`id`, `project_id`, `schema_uri`, `status`, `created_at`, `updated_at`).\n * Strip those envelope fields here so the diff renderer compares\n * apples-to-apples against the on-disk file, which stores only the bare\n * body.\n */\n async fetch(id: string): Promise<object> {\n const envelope = (await this.client.getFlowDefinition(id)) as GetFlowDefinition200;\n const {\n id: _id,\n project_id: _projectId,\n schema_uri: _schemaUri,\n status: _status,\n created_at: _createdAt,\n updated_at: _updatedAt,\n ...body\n } = envelope;\n return body;\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { ResourceEntry, ZitadelState } from \"./types.js\";\n\n/**\n * Read and parse `.zitadel/state.json`. Throws if the file is\n * missing or malformed; callers run `zitadel setup` first to bring\n * the file into existence.\n */\nexport async function readState(cwd: string): Promise<ZitadelState> {\n const raw = await readFile(join(cwd, \".zitadel/state.json\"), \"utf8\");\n return JSON.parse(raw) as ZitadelState;\n}\n\n/**\n * Merge an entry into the state file under `key`, preserving any\n * fields the caller did not override. Reads the file, writes it back\n * with sorted keys disabled (state is engine-managed, not human-\n * authored, so deterministic ordering isn't required here).\n */\nexport async function updateState(\n cwd: string,\n key: string,\n entry: ResourceEntry,\n): Promise<void> {\n const current = await readState(cwd);\n const updated: ZitadelState = {\n ...current,\n resources: {\n ...current.resources,\n [key]: { ...current.resources[key], ...entry },\n },\n };\n await writeFile(join(cwd, \".zitadel/state.json\"), JSON.stringify(updated, null, 2));\n}\n\n/**\n * Remove an entry from the state file. No-op if the key is absent.\n */\nexport async function removeFromState(cwd: string, key: string): Promise<void> {\n const current = await readState(cwd);\n const { [key]: _removed, ...rest } = current.resources;\n const updated: ZitadelState = { ...current, resources: rest };\n await writeFile(join(cwd, \".zitadel/state.json\"), JSON.stringify(updated, null, 2));\n}\n","import { createHash } from \"node:crypto\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { consola } from \"consola\";\n\nimport { readState, removeFromState, updateState } from \"./state.js\";\nimport type { ResourceSyncer, SyncAction } from \"./types.js\";\n\n/**\n * Compute the sync plan for `cwd` against the state file and (when\n * `fetchOld` is true) the platform API. The plan is read-only: it\n * decides what create/update/delete operations need to happen but\n * performs none of them. Pass it to {@link runSyncLoop} to execute.\n *\n * Validates every on-disk file (via `syncer.validate`) before planning any\n * work — a single malformed schema or flow aborts the whole run with\n * `E_VALIDATION` before any platform mutation. Both `plan` and `apply`\n * reach this code path.\n *\n * Bearer auth + base URL live in the api package's runtime registries\n * (`runtime/{auth,base-url}`). Callers set them once at command boot;\n * the sync engine doesn't carry a client.\n *\n * @param cwd - Project root.\n * @param syncers - Per-resource adapters. Order is preserved in the output.\n * @param fetchOld - When true, the planner fetches each delete/update target\n * from the platform to populate `oldContent` for diff rendering.\n */\nexport async function buildSyncPlan(\n cwd: string,\n syncers: ReadonlyArray<ResourceSyncer>,\n fetchOld = false,\n): Promise<ReadonlyArray<SyncAction>> {\n const state = await readState(cwd);\n const actions: SyncAction[] = [];\n\n for (const syncer of syncers) {\n const dirPath = join(cwd, syncer.directory);\n consola.debug(`scanning ${syncer.directory}`);\n const onDisk = await readJsonDir(dirPath);\n\n for (const content of onDisk.values()) {\n syncer.validate(content);\n }\n\n for (const [filePath, entry] of Object.entries(state.resources)) {\n if (!filePath.startsWith(syncer.directory)) {\n continue;\n }\n if (onDisk.has(join(cwd, filePath)) || !entry.id) {\n continue;\n }\n\n let oldContent: object | null = null;\n if (fetchOld && syncer.fetch) {\n try {\n oldContent = await syncer.fetch(entry.id);\n } catch (err) {\n consola.debug(`fetch ${syncer.kind} ${entry.id} failed:`, err);\n }\n }\n actions.push({ kind: \"delete\", path: filePath, syncer, id: entry.id, oldContent });\n }\n\n for (const [absPath, content] of onDisk.entries()) {\n const relPath = absPath.slice(cwd.length + 1);\n const entry = state.resources[relPath];\n const hash = sha256(content);\n\n if (!entry?.id) {\n actions.push({ kind: \"create\", path: relPath, syncer, content, hash });\n continue;\n }\n\n if (!syncer.mutable) {\n actions.push({ kind: \"skip\", path: relPath, reason: \"immutable\" });\n continue;\n }\n\n if (entry.hash === hash) {\n actions.push({ kind: \"skip\", path: relPath, reason: \"no-change\" });\n continue;\n }\n\n let oldContent: object | null = null;\n if (fetchOld && syncer.fetch) {\n try {\n oldContent = await syncer.fetch(entry.id);\n } catch (err) {\n consola.debug(`fetch ${syncer.kind} ${entry.id} failed:`, err);\n }\n }\n actions.push({\n kind: \"update\",\n path: relPath,\n syncer,\n id: entry.id,\n content,\n hash,\n oldContent,\n });\n }\n }\n\n return actions;\n}\n\n/**\n * Execute every action returned by {@link buildSyncPlan} against the\n * platform. Updates the local state file (`.zitadel/state.json`) as\n * each action completes so an interrupted run can resume.\n *\n * The platform target (base URL + bearer auth) lives in the api\n * package's runtime registries; callers set them before invoking this.\n *\n * @param cwd - Project root.\n * @param syncers - Per-resource adapters; same list passed to\n * `buildSyncPlan`.\n */\nexport async function runSyncLoop(\n cwd: string,\n syncers: ReadonlyArray<ResourceSyncer>,\n): Promise<void> {\n const actions = await buildSyncPlan(cwd, syncers);\n\n for (const action of actions) {\n switch (action.kind) {\n case \"create\": {\n const id = await action.syncer.create(action.content);\n await updateState(cwd, action.path, { id, hash: action.hash });\n consola.info(\n `Created a new ${action.syncer.kind} on Zitadel from ${action.path} (id ${id})`,\n );\n break;\n }\n case \"update\": {\n await action.syncer.update(action.id, action.content);\n await updateState(cwd, action.path, { hash: action.hash });\n consola.info(`Updated the ${action.syncer.kind} on Zitadel from ${action.path}`);\n break;\n }\n case \"delete\": {\n await action.syncer.delete(action.id);\n await removeFromState(cwd, action.path);\n consola.info(\n `Deleted the ${action.syncer.kind} on Zitadel because ${action.path} was removed locally`,\n );\n break;\n }\n case \"skip\": {\n consola.debug(`Skipped ${action.path} (${action.reason})`);\n break;\n }\n }\n }\n}\n\nasync function readJsonDir(dirPath: string): Promise<Map<string, object>> {\n const result = new Map<string, object>();\n let entries: string[];\n try {\n entries = await readdir(dirPath);\n } catch (err) {\n if (typeof err === \"object\" && err !== null && \"code\" in err && err.code === \"ENOENT\") {\n return result;\n }\n throw err;\n }\n for (const entry of entries.filter((e) => e.endsWith(\".json\"))) {\n const filePath = join(dirPath, entry);\n const raw = await readFile(filePath, \"utf8\");\n result.set(filePath, JSON.parse(raw) as object);\n }\n return result;\n}\n\nfunction sha256(data: object): string {\n return createHash(\"sha256\").update(JSON.stringify(data)).digest(\"hex\");\n}\n","import type { SyncAction, SyncPlanSummary } from \"./types.js\";\n\n/**\n * Count the non-`skip` actions in a {@link buildSyncPlan} result. Pure; the\n * single source of truth for the plan counts shared by the `plan` /\n * `apply --dry-run` JSON payload and {@link renderPlan}'s summary line.\n */\nexport function summarizePlan(actions: ReadonlyArray<SyncAction>): SyncPlanSummary {\n const active = actions.filter((a) => a.kind !== \"skip\");\n return {\n creates: active.filter((a) => a.kind === \"create\").length,\n updates: active.filter((a) => a.kind === \"update\").length,\n deletes: active.filter((a) => a.kind === \"delete\").length,\n total: active.length,\n };\n}\n\n/**\n * Render a {@link buildSyncPlan} result as a human-readable Terraform-style\n * plan. TTY-aware: colors and bold are emitted only when `tty` is true.\n * Returns the empty-state message when every action is `skip`.\n *\n * @param actions - The action list produced by `buildSyncPlan`. Read-only;\n * the function never mutates the input.\n * @param tty - True when stdout is a TTY; controls ANSI emission.\n */\nexport function renderPlan(actions: ReadonlyArray<SyncAction>, tty: boolean): string {\n const active = actions.filter((a) => a.kind !== \"skip\");\n\n if (active.length === 0) {\n return paint(\n \"No changes. Your Zitadel configuration matches the current state.\",\n A.bold,\n tty,\n );\n }\n\n const out: string[] = [];\n out.push(paint(\"Zitadel will perform the following actions:\", A.bold, tty));\n\n for (const action of active) {\n out.push(\"\");\n out.push(...renderBlock(action, tty));\n }\n\n out.push(\"\");\n\n const { creates, updates, deletes } = summarizePlan(actions);\n\n const parts: string[] = [];\n if (creates > 0) {\n parts.push(`${creates} to add`);\n }\n if (updates > 0) {\n parts.push(`${updates} to change`);\n }\n if (deletes > 0) {\n parts.push(`${deletes} to destroy`);\n }\n\n out.push(paint(`Plan: ${parts.join(\", \")}.`, A.bold, tty));\n return out.join(\"\\n\");\n}\n\nconst A = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n green: \"\\x1b[32m\",\n red: \"\\x1b[31m\",\n yellow: \"\\x1b[33m\",\n} as const;\n\nfunction paint(text: string, code: string, tty: boolean): string {\n return tty ? `${code}${text}${A.reset}` : text;\n}\n\nfunction isPrimitive(v: unknown): v is string | number | boolean | null {\n return v === null || typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\";\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nconst KNOWN_AFTER_APPLY = \"(known after apply)\";\n\nfunction escapeString(s: string): string {\n return s\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\t/g, \"\\\\t\");\n}\n\nfunction fmtPrimitive(v: string | number | boolean | null): string {\n if (v === null) {\n return \"null\";\n }\n if (typeof v === \"string\" && v === KNOWN_AFTER_APPLY) {\n return KNOWN_AFTER_APPLY;\n }\n if (typeof v === \"string\") {\n return `\"${escapeString(v)}\"`;\n }\n return String(v);\n}\n\n/**\n * Indentation contract (matches Terraform exactly):\n * prefixCol = column index of the +/-/~ character\n * field content starts at prefixCol + 2 (one space gap after prefix)\n * nested object/array content: prefixCol + 4 for the child prefixCol\n * closing } or ] : prefixCol + 2 columns of plain spaces, no prefix\n */\ntype ChangePrefix = \"+\" | \"-\" | \"~\" | \" \";\n\nfunction prefixAnsi(p: ChangePrefix): string {\n if (p === \"+\") {\n return A.green;\n }\n if (p === \"-\") {\n return A.red;\n }\n if (p === \"~\") {\n return A.yellow;\n }\n return \"\";\n}\n\ninterface RenderCtx {\n tty: boolean;\n deleteMode: boolean;\n}\n\nfunction renderFields(\n obj: Record<string, unknown>,\n prefix: ChangePrefix,\n prefixCol: number,\n ctx: RenderCtx,\n lines: string[],\n): void {\n const pad = \" \".repeat(prefixCol);\n const ansi = prefixAnsi(prefix);\n const col = (s: string) => paint(s, ansi, ctx.tty);\n\n const keys = Object.keys(obj).sort();\n const maxLen = keys.reduce((m, k) => Math.max(m, k.length), 0);\n\n for (const key of keys) {\n const val = obj[key];\n const pk = key.padEnd(maxLen);\n\n if (isPrimitive(val)) {\n const formatted = fmtPrimitive(val);\n const suffix = ctx.deleteMode ? \" -> null\" : \"\";\n lines.push(col(`${pad}${prefix} ${pk} = ${formatted}${suffix}`));\n } else if (Array.isArray(val)) {\n if (val.length === 0) {\n lines.push(col(`${pad}${prefix} ${pk} = []`));\n } else {\n lines.push(col(`${pad}${prefix} ${pk} = [`));\n renderArrayItems(val, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}]`));\n }\n } else if (isPlainObject(val)) {\n if (Object.keys(val).length === 0) {\n lines.push(col(`${pad}${prefix} ${pk} = {}`));\n } else {\n lines.push(col(`${pad}${prefix} ${pk} = {`));\n renderFields(val, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n }\n }\n }\n}\n\n/**\n * Renders the items of an array. Unlike {@link renderFields}, primitive\n * elements never get a trailing ` -> null` suffix even under `deleteMode` —\n * Terraform only annotates scalar object-field removals that way, not array\n * items.\n */\nfunction renderArrayItems(\n arr: ReadonlyArray<unknown>,\n prefix: ChangePrefix,\n prefixCol: number,\n ctx: RenderCtx,\n lines: string[],\n): void {\n const pad = \" \".repeat(prefixCol);\n const ansi = prefixAnsi(prefix);\n const col = (s: string) => paint(s, ansi, ctx.tty);\n\n for (const item of arr) {\n if (isPrimitive(item)) {\n const formatted = fmtPrimitive(item);\n lines.push(col(`${pad}${prefix} ${formatted},`));\n } else if (Array.isArray(item)) {\n if (item.length === 0) {\n lines.push(col(`${pad}${prefix} [],`));\n } else {\n lines.push(col(`${pad}${prefix} [`));\n renderArrayItems(item, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}],`));\n }\n } else if (isPlainObject(item)) {\n if (Object.keys(item).length === 0) {\n lines.push(col(`${pad}${prefix} {},`));\n } else {\n lines.push(col(`${pad}${prefix} {`));\n renderFields(item, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}},`));\n }\n }\n }\n}\n\n/**\n * Walks both old and new objects, emitting Terraform-style change lines.\n * Returns true if any actual change line (+ / - / ~) was emitted.\n *\n * Edge cases:\n * - Changed arrays render as a full remove + full add (no LCS diff).\n * - Nested objects recurse, and the outer key is only marked `~` if a child\n * actually changed; unchanged children render with the neutral prefix.\n * - A value whose type changed (e.g. string → object) also renders as a\n * remove + add pair.\n */\nfunction renderDiff(\n oldObj: Record<string, unknown>,\n newObj: Record<string, unknown>,\n prefixCol: number,\n tty: boolean,\n lines: string[],\n): boolean {\n const allKeys = [...new Set([...Object.keys(oldObj), ...Object.keys(newObj)])].sort();\n const maxLen = allKeys.reduce((m, k) => Math.max(m, k.length), 0);\n const pad = \" \".repeat(prefixCol);\n let hasChanges = false;\n\n for (const key of allKeys) {\n const pk = key.padEnd(maxLen);\n const hasOld = Object.prototype.hasOwnProperty.call(oldObj, key);\n const hasNew = Object.prototype.hasOwnProperty.call(newObj, key);\n const oldVal = oldObj[key];\n const newVal = newObj[key];\n\n if (!hasOld) {\n hasChanges = true;\n const col = (s: string) => paint(s, A.green, tty);\n if (isPrimitive(newVal)) {\n lines.push(col(`${pad}+ ${pk} = ${fmtPrimitive(newVal)}`));\n } else if (Array.isArray(newVal)) {\n lines.push(col(`${pad}+ ${pk} = [`));\n renderArrayItems(newVal, \"+\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}]`));\n } else if (isPlainObject(newVal)) {\n lines.push(col(`${pad}+ ${pk} = {`));\n renderFields(newVal, \"+\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n }\n } else if (!hasNew) {\n hasChanges = true;\n const col = (s: string) => paint(s, A.red, tty);\n if (isPrimitive(oldVal)) {\n lines.push(col(`${pad}- ${pk} = ${fmtPrimitive(oldVal)} -> null`));\n } else if (Array.isArray(oldVal)) {\n lines.push(col(`${pad}- ${pk} = [`));\n renderArrayItems(oldVal, \"-\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}]`));\n } else if (isPlainObject(oldVal)) {\n lines.push(col(`${pad}- ${pk} = {`));\n renderFields(oldVal, \"-\", prefixCol + 4, { tty, deleteMode: true }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n }\n } else if (isPrimitive(oldVal) && isPrimitive(newVal)) {\n if (oldVal === newVal) {\n lines.push(`${pad} ${pk} = ${fmtPrimitive(newVal)}`);\n } else {\n hasChanges = true;\n const col = (s: string) => paint(s, A.yellow, tty);\n lines.push(col(`${pad}~ ${pk} = ${fmtPrimitive(oldVal)} -> ${fmtPrimitive(newVal)}`));\n }\n } else if (Array.isArray(oldVal) && Array.isArray(newVal)) {\n if (JSON.stringify(oldVal) === JSON.stringify(newVal)) {\n if (newVal.length === 0) {\n lines.push(`${pad} ${pk} = []`);\n } else {\n lines.push(`${pad} ${pk} = [`);\n renderArrayItems(newVal, \" \", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(`${\" \".repeat(prefixCol + 2)}]`);\n }\n } else {\n hasChanges = true;\n const colR = (s: string) => paint(s, A.red, tty);\n const colA = (s: string) => paint(s, A.green, tty);\n if (oldVal.length === 0) {\n lines.push(colR(`${pad}- ${pk} = []`));\n } else {\n lines.push(colR(`${pad}- ${pk} = [`));\n renderArrayItems(oldVal, \"-\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(colR(`${\" \".repeat(prefixCol + 2)}]`));\n }\n if (newVal.length === 0) {\n lines.push(colA(`${pad}+ ${pk} = []`));\n } else {\n lines.push(colA(`${pad}+ ${pk} = [`));\n renderArrayItems(newVal, \"+\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(colA(`${\" \".repeat(prefixCol + 2)}]`));\n }\n }\n } else if (isPlainObject(oldVal) && isPlainObject(newVal)) {\n const childLines: string[] = [];\n const childHasChanges = renderDiff(oldVal, newVal, prefixCol + 4, tty, childLines);\n if (childHasChanges) {\n hasChanges = true;\n const col = (s: string) => paint(s, A.yellow, tty);\n lines.push(col(`${pad}~ ${pk} = {`));\n lines.push(...childLines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n } else if (childLines.length > 0) {\n lines.push(`${pad} ${pk} = {`);\n lines.push(...childLines);\n lines.push(`${\" \".repeat(prefixCol + 2)}}`);\n } else {\n lines.push(`${pad} ${pk} = {}`);\n }\n } else {\n hasChanges = true;\n const colR = (s: string) => paint(s, A.red, tty);\n const colA = (s: string) => paint(s, A.green, tty);\n if (isPrimitive(oldVal)) {\n lines.push(colR(`${pad}- ${pk} = ${fmtPrimitive(oldVal)} -> null`));\n }\n if (isPrimitive(newVal)) {\n lines.push(colA(`${pad}+ ${pk} = ${fmtPrimitive(newVal)}`));\n }\n }\n }\n\n return hasChanges;\n}\n\n/**\n * Column layout (matches Terraform's per-block format):\n * BLOCK_COL = 2 — where the +/-/~ sits on the resource opening line\n * FIELD_COL = 6 — where the +/-/~ sits on first-level field lines\n * closing } — at BLOCK_COL + 2 = 4, no prefix\n */\nconst BLOCK_COL = 2;\nconst FIELD_COL = 6;\n\nfunction resourceName(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\n/**\n * Renders one Terraform-style resource block for a single `SyncAction`.\n *\n * Per-case notes:\n * - **create**: a synthetic `id = (known after apply)` is injected into the\n * rendered fields so it sorts alphabetically alongside the real keys.\n * - **delete**: when `oldContent` is null (the fetch failed), the body\n * collapses to a single `- id = \"<id>\" -> null` line.\n * - **update**: when `oldContent` is null (no read endpoint for this\n * resource kind), the field diff is replaced with a placeholder\n * \"field diff unavailable\" line.\n * - **skip**: omitted from the output entirely, matching Terraform's\n * default of not showing no-change resources.\n */\nfunction renderBlock(action: SyncAction, tty: boolean): string[] {\n const lines: string[] = [];\n const blkPad = \" \".repeat(BLOCK_COL);\n const closePad = \" \".repeat(BLOCK_COL + 2);\n\n switch (action.kind) {\n case \"create\": {\n const header = `${blkPad}# ${action.path} will be created`;\n const opening = `${blkPad}+ resource \"${action.syncer.kind}\" \"${resourceName(action.path)}\" {`;\n lines.push(paint(header, A.bold, tty));\n lines.push(paint(opening, A.green, tty));\n\n const display: Record<string, unknown> = {\n id: KNOWN_AFTER_APPLY,\n ...(action.content as Record<string, unknown>),\n };\n renderFields(display, \"+\", FIELD_COL, { tty, deleteMode: false }, lines);\n lines.push(`${closePad}}`);\n break;\n }\n\n case \"delete\": {\n const header = `${blkPad}# ${action.path} will be destroyed`;\n const opening = `${blkPad}- resource \"${action.syncer.kind}\" \"${resourceName(action.path)}\" {`;\n lines.push(paint(header, A.bold, tty));\n lines.push(paint(opening, A.red, tty));\n\n if (action.oldContent) {\n const display: Record<string, unknown> = {\n id: action.id,\n ...(action.oldContent as Record<string, unknown>),\n };\n renderFields(display, \"-\", FIELD_COL, { tty, deleteMode: true }, lines);\n } else {\n lines.push(paint(`${\" \".repeat(FIELD_COL)}- id = \"${action.id}\" -> null`, A.red, tty));\n }\n lines.push(`${closePad}}`);\n break;\n }\n\n case \"update\": {\n const header = `${blkPad}# ${action.path} will be updated in-place`;\n const opening = `${blkPad}~ resource \"${action.syncer.kind}\" \"${resourceName(action.path)}\" {`;\n lines.push(paint(header, A.bold, tty));\n lines.push(paint(opening, A.yellow, tty));\n\n if (action.oldContent) {\n renderDiff(\n action.oldContent as Record<string, unknown>,\n action.content as Record<string, unknown>,\n FIELD_COL,\n tty,\n lines,\n );\n } else {\n lines.push(\n `${\" \".repeat(FIELD_COL)} # (field diff unavailable — no read endpoint for ${action.syncer.kind})`,\n );\n }\n lines.push(`${closePad}}`);\n break;\n }\n\n case \"skip\":\n break;\n }\n\n return lines;\n}\n"],"mappings":";;;;;;;;;;;;;;AAQA,MAAa,oBAAoB,EAAE,KAAK;CAAC;CAAe;CAAW;CAAa,CAAC;;;;;;;;;;ACIjF,MAAM,2BAA2B,yBAAyB,MAAM;;;;;;;;;;;;;;;AAgBhE,SAAgB,cACd,OACuD;CACvD,MAAM,SAAoD,EAAE;CAC5D,MAAM,SAAmD,EAAE;AAC3D,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,SAAS,yBAAyB,UAAU,MAAM,GAAG;AAC3D,MAAI,CAAC,OAAO,SAAS;AACnB,UAAO,KAAK;IAAE,OAAO;IAAG,QAAQ,OAAO,MAAM;IAAQ,CAAC;AACtD;;AAEF,SAAO,KAAK,OAAO,KAA+C;;AAEpE,KAAI,OAAO,SAAS,EAClB,OAAM,IAAI,aAAa,gBAAgB,4CAA4C,EACjF,SAAS,EAAE,QAAQ,EACpB,CAAC;AAEJ,QAAO;;;;;;;;;;;ACrCT,SAAgB,YAAY,OAA0B;CACpD,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,SAAS,SAAwB;AACrC,MAAI,OAAO,SAAS,SAClB,MAAK,MAAM,SAAS,KAAK,SAAS,kCAAkC,EAAE;GACpE,MAAM,MAAM,MAAM;AAClB,OAAI,IACF,MAAK,IAAI,IAAI;;WAGR,MAAM,QAAQ,KAAK,CAC5B,MAAK,QAAQ,MAAM;WACV,SAAS,KAAK,CACvB,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,CAC7C,KAAI,IAAI,SAAS,OAAO,IAAI,OAAO,UAAU,YAAY,2BAA2B,KAAK,MAAM,CAC7F,MAAK,IAAI,MAAM;MAEf,OAAM,MAAM;;AAKpB,OAAM,MAAM;AACZ,QAAO,CAAC,GAAG,KAAK,CAAC,MAAM;;;;;;;;;;;ACAzB,MAAa,YAAY;;;;;;;;;;ACAzB,MAAa,cAAc;;;;;;;;;;;ACP3B,SAAgB,YAAY,MAIM;AAChC,QAAO,CACL,IAAI,aAAa,KAAK,QAAQ,KAAK,WAAW,KAAK,IAAI,EACvD,IAAI,qBAAqB,KAAK,QAAQ,KAAK,WAAW,KAAK,IAAI,CAChE;;;;;;;;AASH,SAAS,cAAc,MAAc,KAAsB;CACzD,MAAM,UAAU,YAAY,KAAK,CAAC,QAAQ,SAAS,CAAC,IAAI,MAAM;AAC9D,KAAI,QAAQ,SAAS,EACnB,OAAM,IAAI,aAAa,gBAAgB,kCAAkC,QAAQ,KAAK,KAAK,GAAG;;AAIlG,IAAM,eAAN,MAA6C;CAC3C,OAAgB;CAChB,YAAqB;CACrB,UAAmB;CAEnB,YACE,QACA,WACA,KACA;AAHiB,OAAA,SAAA;AACA,OAAA,YAAA;AACA,OAAA,MAAA;;;;;;;;CASnB,SAAS,MAAoB;EAC3B,MAAM,SAASA,iBAAuB,UAAU,KAAK;AACrD,MAAI,CAAC,OAAO,QACV,OAAM,IAAI,aAAa,gBAAgB,kDAAkD,EACvF,SAAS,EAAE,QAAQ,OAAO,MAAM,QAAQ,EACzC,CAAC;AAEJ,gBAAc,MAAM,KAAK,IAAI;;CAG/B,MAAM,OAAO,MAA+B;AAI1C,UAAO,MAHc,KAAK,OAAO,aAAa,MAA0B,EACtE,YAAY,KAAK,WAClB,CAAC,EACY;;;CAIhB,MAAM,OAAO,KAAa,OAA8B;CAIxD,MAAM,OAAO,IAA2B;AAOtC,QAAM,IAAI,aAAa,qBAAqB,mCAAmC,GAAG,GAAG;;CAGvF,MAAM,MAAM,IAA6B;AAEvC,SAAO,MADY,KAAK,OAAO,cAAc,IAAI,EAAE,YAAY,KAAK,WAAW,CAAC;;;AAKpF,IAAM,uBAAN,MAAqD;CACnD,OAAgB;CAChB,YAAqB;CACrB,UAAmB;CAEnB,YACE,QACA,WACA,KACA;AAHiB,OAAA,SAAA;AACA,OAAA,YAAA;AACA,OAAA,MAAA;;;;;;;CAQnB,SAAS,MAAoB;AAC3B,gBAAc,CAAC,KAAK,CAAC;AACrB,gBAAc,MAAM,KAAK,IAAI;;;;;;;;;CAU/B,MAAM,OAAO,MAA+B;AAK1C,UAAO,MAJc,KAAK,OAAO,qBAAqB;GACpD,YAAY,KAAK;GACjB,iBAAiB;GAClB,CAAC,EACY;;;CAIhB,MAAM,OAAO,IAAY,MAA6B;AACpD,QAAM,KAAK,OAAO,qBAChB,IACA,KACD;;CAGH,MAAM,OAAO,IAA2B;AACtC,QAAM,KAAK,OAAO,qBAAqB,GAAG;;;;;;;;;CAU5C,MAAM,MAAM,IAA6B;EAEvC,MAAM,EACJ,IAAI,KACJ,YAAY,YACZ,YAAY,YACZ,QAAQ,SACR,YAAY,YACZ,YAAY,YACZ,GAAG,SACD,MAToB,KAAK,OAAO,kBAAkB,GAAG;AAUzD,SAAO;;;;;;;;;;AChKX,eAAsB,UAAU,KAAoC;CAClE,MAAM,MAAM,MAAM,SAAS,KAAK,KAAK,sBAAsB,EAAE,OAAO;AACpE,QAAO,KAAK,MAAM,IAAI;;;;;;;;AASxB,eAAsB,YACpB,KACA,KACA,OACe;CACf,MAAM,UAAU,MAAM,UAAU,IAAI;CACpC,MAAM,UAAwB;EAC5B,GAAG;EACH,WAAW;GACT,GAAG,QAAQ;IACV,MAAM;IAAE,GAAG,QAAQ,UAAU;IAAM,GAAG;IAAO;GAC/C;EACF;AACD,OAAM,UAAU,KAAK,KAAK,sBAAsB,EAAE,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;;;;;AAMrF,eAAsB,gBAAgB,KAAa,KAA4B;CAC7E,MAAM,UAAU,MAAM,UAAU,IAAI;CACpC,MAAM,GAAG,MAAM,UAAU,GAAG,SAAS,QAAQ;CAC7C,MAAM,UAAwB;EAAE,GAAG;EAAS,WAAW;EAAM;AAC7D,OAAM,UAAU,KAAK,KAAK,sBAAsB,EAAE,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;ACfrF,eAAsB,cACpB,KACA,SACA,WAAW,OACyB;CACpC,MAAM,QAAQ,MAAM,UAAU,IAAI;CAClC,MAAM,UAAwB,EAAE;AAEhC,MAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,UAAU,KAAK,KAAK,OAAO,UAAU;AAC3C,YAAQ,MAAM,YAAY,OAAO,YAAY;EAC7C,MAAM,SAAS,MAAM,YAAY,QAAQ;AAEzC,OAAK,MAAM,WAAW,OAAO,QAAQ,CACnC,QAAO,SAAS,QAAQ;AAG1B,OAAK,MAAM,CAAC,UAAU,UAAU,OAAO,QAAQ,MAAM,UAAU,EAAE;AAC/D,OAAI,CAAC,SAAS,WAAW,OAAO,UAAU,CACxC;AAEF,OAAI,OAAO,IAAI,KAAK,KAAK,SAAS,CAAC,IAAI,CAAC,MAAM,GAC5C;GAGF,IAAI,aAA4B;AAChC,OAAI,YAAY,OAAO,MACrB,KAAI;AACF,iBAAa,MAAM,OAAO,MAAM,MAAM,GAAG;YAClC,KAAK;AACZ,cAAQ,MAAM,SAAS,OAAO,KAAK,GAAG,MAAM,GAAG,WAAW,IAAI;;AAGlE,WAAQ,KAAK;IAAE,MAAM;IAAU,MAAM;IAAU;IAAQ,IAAI,MAAM;IAAI;IAAY,CAAC;;AAGpF,OAAK,MAAM,CAAC,SAAS,YAAY,OAAO,SAAS,EAAE;GACjD,MAAM,UAAU,QAAQ,MAAM,IAAI,SAAS,EAAE;GAC7C,MAAM,QAAQ,MAAM,UAAU;GAC9B,MAAM,OAAO,OAAO,QAAQ;AAE5B,OAAI,CAAC,OAAO,IAAI;AACd,YAAQ,KAAK;KAAE,MAAM;KAAU,MAAM;KAAS;KAAQ;KAAS;KAAM,CAAC;AACtE;;AAGF,OAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,KAAK;KAAE,MAAM;KAAQ,MAAM;KAAS,QAAQ;KAAa,CAAC;AAClE;;AAGF,OAAI,MAAM,SAAS,MAAM;AACvB,YAAQ,KAAK;KAAE,MAAM;KAAQ,MAAM;KAAS,QAAQ;KAAa,CAAC;AAClE;;GAGF,IAAI,aAA4B;AAChC,OAAI,YAAY,OAAO,MACrB,KAAI;AACF,iBAAa,MAAM,OAAO,MAAM,MAAM,GAAG;YAClC,KAAK;AACZ,cAAQ,MAAM,SAAS,OAAO,KAAK,GAAG,MAAM,GAAG,WAAW,IAAI;;AAGlE,WAAQ,KAAK;IACX,MAAM;IACN,MAAM;IACN;IACA,IAAI,MAAM;IACV;IACA;IACA;IACD,CAAC;;;AAIN,QAAO;;;;;;;;;;;;;;AAeT,eAAsB,YACpB,KACA,SACe;CACf,MAAM,UAAU,MAAM,cAAc,KAAK,QAAQ;AAEjD,MAAK,MAAM,UAAU,QACnB,SAAQ,OAAO,MAAf;EACE,KAAK,UAAU;GACb,MAAM,KAAK,MAAM,OAAO,OAAO,OAAO,OAAO,QAAQ;AACrD,SAAM,YAAY,KAAK,OAAO,MAAM;IAAE;IAAI,MAAM,OAAO;IAAM,CAAC;AAC9D,aAAQ,KACN,iBAAiB,OAAO,OAAO,KAAK,mBAAmB,OAAO,KAAK,OAAO,GAAG,GAC9E;AACD;;EAEF,KAAK;AACH,SAAM,OAAO,OAAO,OAAO,OAAO,IAAI,OAAO,QAAQ;AACrD,SAAM,YAAY,KAAK,OAAO,MAAM,EAAE,MAAM,OAAO,MAAM,CAAC;AAC1D,aAAQ,KAAK,eAAe,OAAO,OAAO,KAAK,mBAAmB,OAAO,OAAO;AAChF;EAEF,KAAK;AACH,SAAM,OAAO,OAAO,OAAO,OAAO,GAAG;AACrC,SAAM,gBAAgB,KAAK,OAAO,KAAK;AACvC,aAAQ,KACN,eAAe,OAAO,OAAO,KAAK,sBAAsB,OAAO,KAAK,sBACrE;AACD;EAEF,KAAK;AACH,aAAQ,MAAM,WAAW,OAAO,KAAK,IAAI,OAAO,OAAO,GAAG;AAC1D;;;AAMR,eAAe,YAAY,SAA+C;CACxE,MAAM,yBAAS,IAAI,KAAqB;CACxC,IAAI;AACJ,KAAI;AACF,YAAU,MAAM,QAAQ,QAAQ;UACzB,KAAK;AACZ,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU,OAAO,IAAI,SAAS,SAC3E,QAAO;AAET,QAAM;;AAER,MAAK,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,EAAE;EAC9D,MAAM,WAAW,KAAK,SAAS,MAAM;EACrC,MAAM,MAAM,MAAM,SAAS,UAAU,OAAO;AAC5C,SAAO,IAAI,UAAU,KAAK,MAAM,IAAI,CAAW;;AAEjD,QAAO;;AAGT,SAAS,OAAO,MAAsB;AACpC,QAAO,WAAW,SAAS,CAAC,OAAO,KAAK,UAAU,KAAK,CAAC,CAAC,OAAO,MAAM;;;;;;;;;AC3KxE,SAAgB,cAAc,SAAqD;CACjF,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,SAAS,OAAO;AACvD,QAAO;EACL,SAAS,OAAO,QAAQ,MAAM,EAAE,SAAS,SAAS,CAAC;EACnD,SAAS,OAAO,QAAQ,MAAM,EAAE,SAAS,SAAS,CAAC;EACnD,SAAS,OAAO,QAAQ,MAAM,EAAE,SAAS,SAAS,CAAC;EACnD,OAAO,OAAO;EACf;;;;;;;;;;;AAYH,SAAgB,WAAW,SAAoC,KAAsB;CACnF,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,SAAS,OAAO;AAEvD,KAAI,OAAO,WAAW,EACpB,QAAO,MACL,qEACA,EAAE,MACF,IACD;CAGH,MAAM,MAAgB,EAAE;AACxB,KAAI,KAAK,MAAM,+CAA+C,EAAE,MAAM,IAAI,CAAC;AAE3E,MAAK,MAAM,UAAU,QAAQ;AAC3B,MAAI,KAAK,GAAG;AACZ,MAAI,KAAK,GAAG,YAAY,QAAQ,IAAI,CAAC;;AAGvC,KAAI,KAAK,GAAG;CAEZ,MAAM,EAAE,SAAS,SAAS,YAAY,cAAc,QAAQ;CAE5D,MAAM,QAAkB,EAAE;AAC1B,KAAI,UAAU,EACZ,OAAM,KAAK,GAAG,QAAQ,SAAS;AAEjC,KAAI,UAAU,EACZ,OAAM,KAAK,GAAG,QAAQ,YAAY;AAEpC,KAAI,UAAU,EACZ,OAAM,KAAK,GAAG,QAAQ,aAAa;AAGrC,KAAI,KAAK,MAAM,SAAS,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1D,QAAO,IAAI,KAAK,KAAK;;AAGvB,MAAM,IAAI;CACR,OAAO;CACP,MAAM;CACN,OAAO;CACP,KAAK;CACL,QAAQ;CACT;AAED,SAAS,MAAM,MAAc,MAAc,KAAsB;AAC/D,QAAO,MAAM,GAAG,OAAO,OAAO,EAAE,UAAU;;AAG5C,SAAS,YAAY,GAAmD;AACtE,QAAO,MAAM,QAAQ,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,OAAO,MAAM;;AAGtF,SAAS,cAAc,GAA0C;AAC/D,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,EAAE;;AAGjE,MAAM,oBAAoB;AAE1B,SAAS,aAAa,GAAmB;AACvC,QAAO,EACJ,QAAQ,OAAO,OAAO,CACtB,QAAQ,MAAM,OAAM,CACpB,QAAQ,OAAO,MAAM,CACrB,QAAQ,OAAO,MAAM,CACrB,QAAQ,OAAO,MAAM;;AAG1B,SAAS,aAAa,GAA6C;AACjE,KAAI,MAAM,KACR,QAAO;AAET,KAAI,OAAO,MAAM,YAAY,MAAM,kBACjC,QAAO;AAET,KAAI,OAAO,MAAM,SACf,QAAO,IAAI,aAAa,EAAE,CAAC;AAE7B,QAAO,OAAO,EAAE;;AAYlB,SAAS,WAAW,GAAyB;AAC3C,KAAI,MAAM,IACR,QAAO,EAAE;AAEX,KAAI,MAAM,IACR,QAAO,EAAE;AAEX,KAAI,MAAM,IACR,QAAO,EAAE;AAEX,QAAO;;AAQT,SAAS,aACP,KACA,QACA,WACA,KACA,OACM;CACN,MAAM,MAAM,IAAI,OAAO,UAAU;CACjC,MAAM,OAAO,WAAW,OAAO;CAC/B,MAAM,OAAO,MAAc,MAAM,GAAG,MAAM,IAAI,IAAI;CAElD,MAAM,OAAO,OAAO,KAAK,IAAI,CAAC,MAAM;CACpC,MAAM,SAAS,KAAK,QAAQ,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,OAAO,EAAE,EAAE;AAE9D,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,MAAM,IAAI;EAChB,MAAM,KAAK,IAAI,OAAO,OAAO;AAE7B,MAAI,YAAY,IAAI,EAAE;GACpB,MAAM,YAAY,aAAa,IAAI;GACnC,MAAM,SAAS,IAAI,aAAa,aAAa;AAC7C,SAAM,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,GAAG,KAAK,YAAY,SAAS,CAAC;aACvD,MAAM,QAAQ,IAAI,CAC3B,KAAI,IAAI,WAAW,EACjB,OAAM,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC;OACxC;AACL,SAAM,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC;AAC5C,oBAAiB,KAAK,QAAQ,YAAY,GAAG,KAAK,MAAM;AACxD,SAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;;WAEzC,cAAc,IAAI,CAC3B,KAAI,OAAO,KAAK,IAAI,CAAC,WAAW,EAC9B,OAAM,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC;OACxC;AACL,SAAM,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC;AAC5C,gBAAa,KAAK,QAAQ,YAAY,GAAG,KAAK,MAAM;AACpD,SAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;;;;;;;;;;AAYxD,SAAS,iBACP,KACA,QACA,WACA,KACA,OACM;CACN,MAAM,MAAM,IAAI,OAAO,UAAU;CACjC,MAAM,OAAO,WAAW,OAAO;CAC/B,MAAM,OAAO,MAAc,MAAM,GAAG,MAAM,IAAI,IAAI;AAElD,MAAK,MAAM,QAAQ,IACjB,KAAI,YAAY,KAAK,EAAE;EACrB,MAAM,YAAY,aAAa,KAAK;AACpC,QAAM,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,UAAU,GAAG,CAAC;YACvC,MAAM,QAAQ,KAAK,CAC5B,KAAI,KAAK,WAAW,EAClB,OAAM,KAAK,IAAI,GAAG,MAAM,OAAO,MAAM,CAAC;MACjC;AACL,QAAM,KAAK,IAAI,GAAG,MAAM,OAAO,IAAI,CAAC;AACpC,mBAAiB,MAAM,QAAQ,YAAY,GAAG,KAAK,MAAM;AACzD,QAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,IAAI,CAAC;;UAE1C,cAAc,KAAK,CAC5B,KAAI,OAAO,KAAK,KAAK,CAAC,WAAW,EAC/B,OAAM,KAAK,IAAI,GAAG,MAAM,OAAO,MAAM,CAAC;MACjC;AACL,QAAM,KAAK,IAAI,GAAG,MAAM,OAAO,IAAI,CAAC;AACpC,eAAa,MAAM,QAAQ,YAAY,GAAG,KAAK,MAAM;AACrD,QAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;AAiBzD,SAAS,WACP,QACA,QACA,WACA,KACA,OACS;CACT,MAAM,UAAU,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,OAAO,EAAE,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM;CACrF,MAAM,SAAS,QAAQ,QAAQ,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,OAAO,EAAE,EAAE;CACjE,MAAM,MAAM,IAAI,OAAO,UAAU;CACjC,IAAI,aAAa;AAEjB,MAAK,MAAM,OAAO,SAAS;EACzB,MAAM,KAAK,IAAI,OAAO,OAAO;EAC7B,MAAM,SAAS,OAAO,UAAU,eAAe,KAAK,QAAQ,IAAI;EAChE,MAAM,SAAS,OAAO,UAAU,eAAe,KAAK,QAAQ,IAAI;EAChE,MAAM,SAAS,OAAO;EACtB,MAAM,SAAS,OAAO;AAEtB,MAAI,CAAC,QAAQ;AACX,gBAAa;GACb,MAAM,OAAO,MAAc,MAAM,GAAG,EAAE,OAAO,IAAI;AACjD,OAAI,YAAY,OAAO,CACrB,OAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK,aAAa,OAAO,GAAG,CAAC;YACjD,MAAM,QAAQ,OAAO,EAAE;AAChC,UAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,MAAM,CAAC;AACpC,qBAAiB,QAAQ,KAAK,YAAY,GAAG;KAAE;KAAK,YAAY;KAAO,EAAE,MAAM;AAC/E,UAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;cACvC,cAAc,OAAO,EAAE;AAChC,UAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,MAAM,CAAC;AACpC,iBAAa,QAAQ,KAAK,YAAY,GAAG;KAAE;KAAK,YAAY;KAAO,EAAE,MAAM;AAC3E,UAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;;aAEzC,CAAC,QAAQ;AAClB,gBAAa;GACb,MAAM,OAAO,MAAc,MAAM,GAAG,EAAE,KAAK,IAAI;AAC/C,OAAI,YAAY,OAAO,CACrB,OAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK,aAAa,OAAO,CAAC,UAAU,CAAC;YACzD,MAAM,QAAQ,OAAO,EAAE;AAChC,UAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,MAAM,CAAC;AACpC,qBAAiB,QAAQ,KAAK,YAAY,GAAG;KAAE;KAAK,YAAY;KAAO,EAAE,MAAM;AAC/E,UAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;cACvC,cAAc,OAAO,EAAE;AAChC,UAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,MAAM,CAAC;AACpC,iBAAa,QAAQ,KAAK,YAAY,GAAG;KAAE;KAAK,YAAY;KAAM,EAAE,MAAM;AAC1E,UAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;;aAEzC,YAAY,OAAO,IAAI,YAAY,OAAO,CACnD,KAAI,WAAW,OACb,OAAM,KAAK,GAAG,IAAI,IAAI,GAAG,KAAK,aAAa,OAAO,GAAG;OAChD;AACL,gBAAa;GACb,MAAM,OAAO,MAAc,MAAM,GAAG,EAAE,QAAQ,IAAI;AAClD,SAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK,aAAa,OAAO,CAAC,MAAM,aAAa,OAAO,GAAG,CAAC;;WAE9E,MAAM,QAAQ,OAAO,IAAI,MAAM,QAAQ,OAAO,CACvD,KAAI,KAAK,UAAU,OAAO,KAAK,KAAK,UAAU,OAAO,CACnD,KAAI,OAAO,WAAW,EACpB,OAAM,KAAK,GAAG,IAAI,IAAI,GAAG,OAAO;OAC3B;AACL,SAAM,KAAK,GAAG,IAAI,IAAI,GAAG,MAAM;AAC/B,oBAAiB,QAAQ,KAAK,YAAY,GAAG;IAAE;IAAK,YAAY;IAAO,EAAE,MAAM;AAC/E,SAAM,KAAK,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG;;OAExC;AACL,gBAAa;GACb,MAAM,QAAQ,MAAc,MAAM,GAAG,EAAE,KAAK,IAAI;GAChD,MAAM,QAAQ,MAAc,MAAM,GAAG,EAAE,OAAO,IAAI;AAClD,OAAI,OAAO,WAAW,EACpB,OAAM,KAAK,KAAK,GAAG,IAAI,IAAI,GAAG,OAAO,CAAC;QACjC;AACL,UAAM,KAAK,KAAK,GAAG,IAAI,IAAI,GAAG,MAAM,CAAC;AACrC,qBAAiB,QAAQ,KAAK,YAAY,GAAG;KAAE;KAAK,YAAY;KAAO,EAAE,MAAM;AAC/E,UAAM,KAAK,KAAK,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;;AAEnD,OAAI,OAAO,WAAW,EACpB,OAAM,KAAK,KAAK,GAAG,IAAI,IAAI,GAAG,OAAO,CAAC;QACjC;AACL,UAAM,KAAK,KAAK,GAAG,IAAI,IAAI,GAAG,MAAM,CAAC;AACrC,qBAAiB,QAAQ,KAAK,YAAY,GAAG;KAAE;KAAK,YAAY;KAAO,EAAE,MAAM;AAC/E,UAAM,KAAK,KAAK,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;;;WAG5C,cAAc,OAAO,IAAI,cAAc,OAAO,EAAE;GACzD,MAAM,aAAuB,EAAE;AAE/B,OADwB,WAAW,QAAQ,QAAQ,YAAY,GAAG,KAAK,WACpD,EAAE;AACnB,iBAAa;IACb,MAAM,OAAO,MAAc,MAAM,GAAG,EAAE,QAAQ,IAAI;AAClD,UAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,MAAM,CAAC;AACpC,UAAM,KAAK,GAAG,WAAW;AACzB,UAAM,KAAK,IAAI,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG,CAAC;cACvC,WAAW,SAAS,GAAG;AAChC,UAAM,KAAK,GAAG,IAAI,IAAI,GAAG,MAAM;AAC/B,UAAM,KAAK,GAAG,WAAW;AACzB,UAAM,KAAK,GAAG,IAAI,OAAO,YAAY,EAAE,CAAC,GAAG;SAE3C,OAAM,KAAK,GAAG,IAAI,IAAI,GAAG,OAAO;SAE7B;AACL,gBAAa;GACb,MAAM,QAAQ,MAAc,MAAM,GAAG,EAAE,KAAK,IAAI;GAChD,MAAM,QAAQ,MAAc,MAAM,GAAG,EAAE,OAAO,IAAI;AAClD,OAAI,YAAY,OAAO,CACrB,OAAM,KAAK,KAAK,GAAG,IAAI,IAAI,GAAG,KAAK,aAAa,OAAO,CAAC,UAAU,CAAC;AAErE,OAAI,YAAY,OAAO,CACrB,OAAM,KAAK,KAAK,GAAG,IAAI,IAAI,GAAG,KAAK,aAAa,OAAO,GAAG,CAAC;;;AAKjE,QAAO;;;;;;;;AAST,MAAM,YAAY;AAClB,MAAM,YAAY;AAElB,SAAS,aAAa,MAAsB;AAC1C,QAAO,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;;AAiBlC,SAAS,YAAY,QAAoB,KAAwB;CAC/D,MAAM,QAAkB,EAAE;CAC1B,MAAM,SAAS,IAAI,OAAO,UAAU;CACpC,MAAM,WAAW,IAAI,OAAO,YAAY,EAAE;AAE1C,SAAQ,OAAO,MAAf;EACE,KAAK,UAAU;GACb,MAAM,SAAS,GAAG,OAAO,IAAI,OAAO,KAAK;GACzC,MAAM,UAAU,GAAG,OAAO,cAAc,OAAO,OAAO,KAAK,KAAK,aAAa,OAAO,KAAK,CAAC;AAC1F,SAAM,KAAK,MAAM,QAAQ,EAAE,MAAM,IAAI,CAAC;AACtC,SAAM,KAAK,MAAM,SAAS,EAAE,OAAO,IAAI,CAAC;AAMxC,gBAAa;IAHX,IAAI;IACJ,GAAI,OAAO;IAEO,EAAE,KAAK,WAAW;IAAE;IAAK,YAAY;IAAO,EAAE,MAAM;AACxE,SAAM,KAAK,GAAG,SAAS,GAAG;AAC1B;;EAGF,KAAK,UAAU;GACb,MAAM,SAAS,GAAG,OAAO,IAAI,OAAO,KAAK;GACzC,MAAM,UAAU,GAAG,OAAO,cAAc,OAAO,OAAO,KAAK,KAAK,aAAa,OAAO,KAAK,CAAC;AAC1F,SAAM,KAAK,MAAM,QAAQ,EAAE,MAAM,IAAI,CAAC;AACtC,SAAM,KAAK,MAAM,SAAS,EAAE,KAAK,IAAI,CAAC;AAEtC,OAAI,OAAO,WAKT,cAAa;IAHX,IAAI,OAAO;IACX,GAAI,OAAO;IAEO,EAAE,KAAK,WAAW;IAAE;IAAK,YAAY;IAAM,EAAE,MAAM;OAEvE,OAAM,KAAK,MAAM,GAAG,IAAI,OAAO,UAAU,CAAC,UAAU,OAAO,GAAG,YAAY,EAAE,KAAK,IAAI,CAAC;AAExF,SAAM,KAAK,GAAG,SAAS,GAAG;AAC1B;;EAGF,KAAK,UAAU;GACb,MAAM,SAAS,GAAG,OAAO,IAAI,OAAO,KAAK;GACzC,MAAM,UAAU,GAAG,OAAO,cAAc,OAAO,OAAO,KAAK,KAAK,aAAa,OAAO,KAAK,CAAC;AAC1F,SAAM,KAAK,MAAM,QAAQ,EAAE,MAAM,IAAI,CAAC;AACtC,SAAM,KAAK,MAAM,SAAS,EAAE,QAAQ,IAAI,CAAC;AAEzC,OAAI,OAAO,WACT,YACE,OAAO,YACP,OAAO,SACP,WACA,KACA,MACD;OAED,OAAM,KACJ,GAAG,IAAI,OAAO,UAAU,CAAC,qDAAqD,OAAO,OAAO,KAAK,GAClG;AAEH,SAAM,KAAK,GAAG,SAAS,GAAG;AAC1B;;EAGF,KAAK,OACH;;AAGJ,QAAO"}
|
|
1
|
+
{"version":3,"file":"sync-B5lqgQO3.mjs","names":["createSchemaBodySchema"],"sources":["../src/lib/environment.ts","../src/lib/flows/validate.ts","../src/lib/flows/env-refs.ts","../src/lib/flows/index.ts","../src/lib/user-schema/index.ts","../src/lib/sync/syncers.ts","../src/lib/sync/state.ts","../src/lib/sync/loop.ts","../src/lib/sync/plan-renderer.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * CLI-side deployment environment. Not an API model — it gates which\n * `zitadel.json` environment block and server the commands target.\n * Project request/response shapes live in `@zitadel/api`\n * (generated from the OpenAPI spec).\n */\nexport const environmentSchema = z.enum([\"development\", \"preview\", \"production\"]);\n","import type { CreateFlowDefinitionBodyFlowDefinition } from \"@zitadel/api/generated/model\";\nimport { CreateFlowDefinitionBody } from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\n\nimport { ZitadelError } from \"../errors\";\n\n/**\n * The generated `CreateFlowDefinitionBody` Zod schema describes the\n * full envelope (`{project_id, flow_definition, schema_uri?}`); the\n * on-disk flow body is just the inner `flow_definition` shape. Pull\n * that out via `.shape` so on-disk validation runs against exactly the\n * same schema the wire request validates against.\n */\nconst flowDefinitionBodySchema = CreateFlowDefinitionBody.shape.flow_definition;\n\n/**\n * Validate raw JSON bodies against the generated flow-definition Zod\n * schema (the orval-emitted equivalent of\n * `api/openapi/components/flows/flow-definition.yaml`). Errors from\n * every input are collected and rethrown as a single `E_VALIDATION`\n * `ZitadelError` so callers see the full picture at once rather than\n * failing on the first malformed entry.\n *\n * Pure: does not touch the filesystem or network. The input array\n * is read-only; the returned array is freshly allocated.\n *\n * @param flows - Raw values to validate. Unknown-typed so callers\n * can pass freshly-parsed JSON without first asserting a shape.\n */\nexport function validateFlows(\n flows: ReadonlyArray<unknown>,\n): ReadonlyArray<CreateFlowDefinitionBodyFlowDefinition> {\n const issues: Array<{ index: number; issues: unknown }> = [];\n const parsed: CreateFlowDefinitionBodyFlowDefinition[] = [];\n for (let i = 0; i < flows.length; i += 1) {\n const result = flowDefinitionBodySchema.safeParse(flows[i]);\n if (!result.success) {\n issues.push({ index: i, issues: result.error.issues });\n continue;\n }\n parsed.push(result.data as CreateFlowDefinitionBodyFlowDefinition);\n }\n if (issues.length > 0) {\n throw new ZitadelError(\"E_VALIDATION\", \"One or more flow definitions are invalid\", {\n details: { issues },\n });\n }\n return parsed;\n}\n","import { isObject } from \"../json\";\n\n/**\n * Collects the environment variables a flows document depends on, sorted and\n * de-duplicated. Recognises two reference styles: inline `${VAR}` interpolations\n * inside string values, and keys ending in `_env` whose value names a single\n * variable. `apply`/`plan` use this to fail before contacting the platform when\n * a required variable is absent.\n */\nexport function flowEnvRefs(value: unknown): string[] {\n const refs = new Set<string>();\n const visit = (node: unknown): void => {\n if (typeof node === \"string\") {\n for (const match of node.matchAll(/\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g)) {\n const ref = match[1];\n if (ref) {\n refs.add(ref);\n }\n }\n } else if (Array.isArray(node)) {\n node.forEach(visit);\n } else if (isObject(node)) {\n for (const [key, child] of Object.entries(node)) {\n if (key.endsWith(\"_env\") && typeof child === \"string\" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(child)) {\n refs.add(child);\n } else {\n visit(child);\n }\n }\n }\n };\n visit(value);\n return [...refs].sort();\n}\n","/**\n * Public surface for the flow domain. Every caller outside this module\n * imports from here (not from individual files) so the package\n * boundary stays observable.\n *\n * **Source of truth.** The wire shape lives in\n * `@zitadel/api/generated/model` (orval-generated from the\n * OpenAPI spec). Callers that need the type import\n * `CreateFlowDefinitionBodyFlowDefinition` from there directly;\n * callers that need the runtime validator import\n * `CreateFlowDefinitionBody` from\n * `@zitadel/api/generated/endpoints/zitadelNextGen.zod`. This\n * module owns only the CLI-specific concerns: the password-flow\n * builder, env-var reference scanning, and the file-level\n * `validateFlows` helper that surfaces `E_VALIDATION` errors against\n * the generated Zod.\n *\n * **Dependency rule.** No upward imports (`commands/`, `sync/`, etc.)\n * and no filesystem I/O. It depends sideways only on shared utilities\n * under `apps/cli/src/lib/` — today `lib/errors` (`ZitadelError`).\n */\nexport { buildFlow } from \"./build\";\nexport { validateFlows } from \"./validate\";\nexport { flowEnvRefs } from \"./env-refs\";\n\n/**\n * Relative directory (from the project root) where local flow files\n * live. Owned here so callers (`commands/*`, `sync/syncers.ts`) and\n * tests share a single source of truth for the path; the runtime\n * never depends on it directly because `lib/flows` does not touch\n * the filesystem.\n */\nexport const FLOWS_DIR = \".zitadel/flows\";\n","/**\n * Public surface for the user-schema domain. Every caller outside this\n * module imports from here (not from individual files), the same\n * discipline as `lib/flows/`.\n *\n * **Source of truth.** The wire shape lives in\n * `@zitadel/api/generated/model` (orval-generated from the\n * OpenAPI spec). Callers that need the type import `CreateSchemaBody`\n * from there directly; callers that need the runtime validator import\n * the matching Zod schema from\n * `@zitadel/api/generated/endpoints/zitadelNextGen.zod`. This\n * module owns only CLI-specific concerns: the builder, the per-field\n * preset catalog, and the two `DEFAULT_*` URI constants.\n *\n * **Dependency rule.** No upward imports (`commands/`, `sync/`, etc.)\n * and no filesystem I/O. Reading and writing local files is the\n * caller's responsibility, served by `apps/cli/src/lib/json-dir.ts`\n * plus this module's {@link SCHEMAS_DIR} constant.\n */\nexport {\n DEFAULT_USER_META_SCHEMA,\n DEFAULT_USER_SCHEMA_ID,\n buildUserSchema,\n} from \"./build\";\n\n/**\n * Relative directory (from the project root) where local user-schema\n * files live. Owned here so callers (`commands/*`, `sync/syncers.ts`)\n * and tests share a single source of truth for the path; the runtime\n * never depends on it directly because `lib/user-schema` does not touch\n * the filesystem. The counterpart of `lib/flows`' `FLOWS_DIR`.\n */\nexport const SCHEMAS_DIR = \".zitadel/schemas\";\n","import type {\n CreateFlowDefinitionBodyFlowDefinition,\n CreateSchemaBody,\n GetSchemaById200,\n GetFlowDefinition200,\n} from \"@zitadel/api/generated/model\";\nimport type { ZitadelClient } from \"@zitadel/api/client\";\nimport { CreateSchemaBody as createSchemaBodySchema } from \"@zitadel/api/generated/endpoints/zitadelNextGen.zod\";\n\nimport { FLOWS_DIR, flowEnvRefs, validateFlows } from \"../flows\";\nimport { SCHEMAS_DIR } from \"../user-schema\";\nimport { ZitadelError } from \"../errors\";\nimport type { ResourceSyncer } from \"./types.js\";\n\n/** Runtime environment lookup used to resolve `${VAR}` / `*_env` references. */\ntype EnvLookup = Record<string, string | undefined>;\n\n/**\n * Build the syncer list with the context every syncer needs: the\n * `project_id` flow creates carry, and the runtime `env` against which\n * each file's `${VAR}` / `*_env` references are checked. Callers\n * (apply / plan / setup) read `project_id` from `.zitadel/secret` and\n * pass the process environment. The returned array is treated as\n * read-only by the sync loop.\n */\nexport function makeSyncers(opts: {\n client: ZitadelClient;\n projectId: string;\n env: EnvLookup;\n}): ReadonlyArray<ResourceSyncer> {\n return [\n new SchemaSyncer(opts.client, opts.projectId, opts.env),\n new FlowDefinitionSyncer(opts.client, opts.projectId, opts.env),\n ];\n}\n\n/**\n * Assert that every env var a resource references — `${VAR}` placeholders and\n * the `*_env` convention — is present in `env`, throwing `E_VALIDATION` listing\n * the missing names. Shared by every syncer so the check is identical for\n * schemas and flows, and runs in the sync engine before any platform call.\n */\nfunction assertEnvRefs(data: object, env: EnvLookup): void {\n const missing = flowEnvRefs(data).filter((name) => !env[name]);\n if (missing.length > 0) {\n throw new ZitadelError(\"E_VALIDATION\", `Missing environment variables: ${missing.join(\", \")}`);\n }\n}\n\nclass SchemaSyncer implements ResourceSyncer {\n readonly kind = \"schema\";\n readonly directory = SCHEMAS_DIR;\n readonly mutable = false;\n\n constructor(\n private readonly client: ZitadelClient,\n private readonly projectId: string,\n private readonly env: EnvLookup,\n ) {}\n\n /**\n * Parse against the generated `CreateSchemaBody` Zod (the orval-emitted\n * equivalent of `api/openapi/endpoints/schemas/user-schema.yaml`). The\n * generated schema is a union of `user-schema` and `schema-url`\n * discriminated on `kind`; both are valid on-disk bodies.\n */\n validate(data: object): void {\n const result = createSchemaBodySchema.safeParse(data);\n if (!result.success) {\n throw new ZitadelError(\"E_VALIDATION\", \"Schema file is not a valid Zitadel schema body\", {\n details: { issues: result.error.issues },\n });\n }\n assertEnvRefs(data, this.env);\n }\n\n async create(data: object): Promise<string> {\n const result = await this.client.createSchema(data as CreateSchemaBody, {\n project_id: this.projectId,\n });\n return result.id;\n }\n\n /** Never called — schemas are immutable on the platform, so `mutable = false`. */\n async update(_id: string, _data: object): Promise<void> {\n return;\n }\n\n async delete(id: string): Promise<void> {\n // Schemas are immutable on the platform: no PATCH, no DELETE in the\n // generated client. The sync loop's delete branch (`loop.ts`) still\n // schedules a delete action when a state entry exists and the\n // on-disk file is gone — `mutable` only gates updates, not deletes.\n // We deliberately fail loud here so the user notices that removing\n // a schema file is not a supported way to retire it.\n throw new ZitadelError(\"E_NOT_IMPLEMENTED\", `schema delete is not supported (${id})`);\n }\n\n async fetch(id: string): Promise<object> {\n const body = await this.client.getSchemaById(id, { project_id: this.projectId });\n return body as unknown as GetSchemaById200;\n }\n}\n\nclass FlowDefinitionSyncer implements ResourceSyncer {\n readonly kind = \"flow\";\n readonly directory = FLOWS_DIR;\n readonly mutable = true;\n\n constructor(\n private readonly client: ZitadelClient,\n private readonly projectId: string,\n private readonly env: EnvLookup,\n ) {}\n\n /**\n * Validates one flow file. `validateFlows` takes a batch and throws\n * `E_VALIDATION` on the first invalid entry; passing a single-element array\n * lets us reuse the batch validator for one file.\n */\n validate(data: object): void {\n validateFlows([data]);\n assertEnvRefs(data, this.env);\n }\n\n /**\n * Wraps the bare on-disk flow body in the spec's create-envelope\n * (`api/openapi/components/flows/flow-definition-create-request.yaml`)\n * before sending. The file on disk stays bare so it is human-editable;\n * only the wire request carries `project_id` and the surrounding\n * envelope.\n */\n async create(data: object): Promise<string> {\n const result = await this.client.createFlowDefinition({\n project_id: this.projectId,\n flow_definition: data as CreateFlowDefinitionBodyFlowDefinition,\n });\n return result.id;\n }\n\n /** PATCH body is the bare partial flow per `flow-definition-update-request` — no envelope. */\n async update(id: string, data: object): Promise<void> {\n await this.client.updateFlowDefinition(\n id,\n data as Partial<CreateFlowDefinitionBodyFlowDefinition>,\n );\n }\n\n async delete(id: string): Promise<void> {\n await this.client.deleteFlowDefinition(id);\n }\n\n /**\n * `GET /flow_definitions/:id` wraps the bare flow body in a detail envelope\n * (`id`, `project_id`, `schema_uri`, `status`, `created_at`, `updated_at`).\n * Strip those envelope fields here so the diff renderer compares\n * apples-to-apples against the on-disk file, which stores only the bare\n * body.\n */\n async fetch(id: string): Promise<object> {\n const envelope = (await this.client.getFlowDefinition(id)) as GetFlowDefinition200;\n const {\n id: _id,\n project_id: _projectId,\n schema_uri: _schemaUri,\n status: _status,\n created_at: _createdAt,\n updated_at: _updatedAt,\n ...body\n } = envelope;\n return body;\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { ResourceEntry, ZitadelState } from \"./types.js\";\n\n/**\n * Read and parse `.zitadel/state.json`. Throws if the file is\n * missing or malformed; callers run `zitadel setup` first to bring\n * the file into existence.\n */\nexport async function readState(cwd: string): Promise<ZitadelState> {\n const raw = await readFile(join(cwd, \".zitadel/state.json\"), \"utf8\");\n return JSON.parse(raw) as ZitadelState;\n}\n\n/**\n * Merge an entry into the state file under `key`, preserving any\n * fields the caller did not override. Reads the file, writes it back\n * with sorted keys disabled (state is engine-managed, not human-\n * authored, so deterministic ordering isn't required here).\n */\nexport async function updateState(\n cwd: string,\n key: string,\n entry: ResourceEntry,\n): Promise<void> {\n const current = await readState(cwd);\n const updated: ZitadelState = {\n ...current,\n resources: {\n ...current.resources,\n [key]: { ...current.resources[key], ...entry },\n },\n };\n await writeFile(join(cwd, \".zitadel/state.json\"), JSON.stringify(updated, null, 2));\n}\n\n/**\n * Remove an entry from the state file. No-op if the key is absent.\n */\nexport async function removeFromState(cwd: string, key: string): Promise<void> {\n const current = await readState(cwd);\n const { [key]: _removed, ...rest } = current.resources;\n const updated: ZitadelState = { ...current, resources: rest };\n await writeFile(join(cwd, \".zitadel/state.json\"), JSON.stringify(updated, null, 2));\n}\n","import { createHash } from \"node:crypto\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { consola } from \"consola\";\n\nimport { readState, removeFromState, updateState } from \"./state.js\";\nimport type { ResourceSyncer, SyncAction } from \"./types.js\";\n\n/**\n * Compute the sync plan for `cwd` against the state file and (when\n * `fetchOld` is true) the platform API. The plan is read-only: it\n * decides what create/update/delete operations need to happen but\n * performs none of them. Pass it to {@link runSyncLoop} to execute.\n *\n * Validates every on-disk file (via `syncer.validate`) before planning any\n * work — a single malformed schema or flow aborts the whole run with\n * `E_VALIDATION` before any platform mutation. Both `plan` and `apply`\n * reach this code path.\n *\n * Bearer auth + base URL live in the api package's runtime registries\n * (`runtime/{auth,base-url}`). Callers set them once at command boot;\n * the sync engine doesn't carry a client.\n *\n * @param cwd - Project root.\n * @param syncers - Per-resource adapters. Order is preserved in the output.\n * @param fetchOld - When true, the planner fetches each delete/update target\n * from the platform to populate `oldContent` for diff rendering.\n */\nexport async function buildSyncPlan(\n cwd: string,\n syncers: ReadonlyArray<ResourceSyncer>,\n fetchOld = false,\n): Promise<ReadonlyArray<SyncAction>> {\n const state = await readState(cwd);\n const actions: SyncAction[] = [];\n\n for (const syncer of syncers) {\n const dirPath = join(cwd, syncer.directory);\n consola.debug(`scanning ${syncer.directory}`);\n const onDisk = await readJsonDir(dirPath);\n\n for (const content of onDisk.values()) {\n syncer.validate(content);\n }\n\n for (const [filePath, entry] of Object.entries(state.resources)) {\n if (!filePath.startsWith(syncer.directory)) {\n continue;\n }\n if (onDisk.has(join(cwd, filePath)) || !entry.id) {\n continue;\n }\n\n let oldContent: object | null = null;\n if (fetchOld && syncer.fetch) {\n try {\n oldContent = await syncer.fetch(entry.id);\n } catch (err) {\n consola.debug(`fetch ${syncer.kind} ${entry.id} failed:`, err);\n }\n }\n actions.push({ kind: \"delete\", path: filePath, syncer, id: entry.id, oldContent });\n }\n\n for (const [absPath, content] of onDisk.entries()) {\n const relPath = absPath.slice(cwd.length + 1);\n const entry = state.resources[relPath];\n const hash = sha256(content);\n\n if (!entry?.id) {\n actions.push({ kind: \"create\", path: relPath, syncer, content, hash });\n continue;\n }\n\n if (!syncer.mutable) {\n actions.push({ kind: \"skip\", path: relPath, reason: \"immutable\" });\n continue;\n }\n\n if (entry.hash === hash) {\n actions.push({ kind: \"skip\", path: relPath, reason: \"no-change\" });\n continue;\n }\n\n let oldContent: object | null = null;\n if (fetchOld && syncer.fetch) {\n try {\n oldContent = await syncer.fetch(entry.id);\n } catch (err) {\n consola.debug(`fetch ${syncer.kind} ${entry.id} failed:`, err);\n }\n }\n actions.push({\n kind: \"update\",\n path: relPath,\n syncer,\n id: entry.id,\n content,\n hash,\n oldContent,\n });\n }\n }\n\n return actions;\n}\n\n/**\n * Execute every action returned by {@link buildSyncPlan} against the\n * platform. Updates the local state file (`.zitadel/state.json`) as\n * each action completes so an interrupted run can resume.\n *\n * The platform target (base URL + bearer auth) lives in the api\n * package's runtime registries; callers set them before invoking this.\n *\n * @param cwd - Project root.\n * @param syncers - Per-resource adapters; same list passed to\n * `buildSyncPlan`.\n */\nexport async function runSyncLoop(\n cwd: string,\n syncers: ReadonlyArray<ResourceSyncer>,\n): Promise<void> {\n const actions = await buildSyncPlan(cwd, syncers);\n\n for (const action of actions) {\n switch (action.kind) {\n case \"create\": {\n const id = await action.syncer.create(action.content);\n await updateState(cwd, action.path, { id, hash: action.hash });\n consola.info(\n `Created a new ${action.syncer.kind} on Zitadel from ${action.path} (id ${id})`,\n );\n break;\n }\n case \"update\": {\n await action.syncer.update(action.id, action.content);\n await updateState(cwd, action.path, { hash: action.hash });\n consola.info(`Updated the ${action.syncer.kind} on Zitadel from ${action.path}`);\n break;\n }\n case \"delete\": {\n await action.syncer.delete(action.id);\n await removeFromState(cwd, action.path);\n consola.info(\n `Deleted the ${action.syncer.kind} on Zitadel because ${action.path} was removed locally`,\n );\n break;\n }\n case \"skip\": {\n consola.debug(`Skipped ${action.path} (${action.reason})`);\n break;\n }\n }\n }\n}\n\nasync function readJsonDir(dirPath: string): Promise<Map<string, object>> {\n const result = new Map<string, object>();\n let entries: string[];\n try {\n entries = await readdir(dirPath);\n } catch (err) {\n if (typeof err === \"object\" && err !== null && \"code\" in err && err.code === \"ENOENT\") {\n return result;\n }\n throw err;\n }\n for (const entry of entries.filter((e) => e.endsWith(\".json\"))) {\n const filePath = join(dirPath, entry);\n const raw = await readFile(filePath, \"utf8\");\n result.set(filePath, JSON.parse(raw) as object);\n }\n return result;\n}\n\nfunction sha256(data: object): string {\n return createHash(\"sha256\").update(JSON.stringify(data)).digest(\"hex\");\n}\n","import type { SyncAction, SyncPlanSummary } from \"./types.js\";\n\n/**\n * Count the non-`skip` actions in a {@link buildSyncPlan} result. Pure; the\n * single source of truth for the plan counts shared by the `plan` /\n * `apply --dry-run` JSON payload and {@link renderPlan}'s summary line.\n */\nexport function summarizePlan(actions: ReadonlyArray<SyncAction>): SyncPlanSummary {\n const active = actions.filter((a) => a.kind !== \"skip\");\n return {\n creates: active.filter((a) => a.kind === \"create\").length,\n updates: active.filter((a) => a.kind === \"update\").length,\n deletes: active.filter((a) => a.kind === \"delete\").length,\n total: active.length,\n };\n}\n\n/**\n * Render a {@link buildSyncPlan} result as a human-readable Terraform-style\n * plan. TTY-aware: colors and bold are emitted only when `tty` is true.\n * Returns the empty-state message when every action is `skip`.\n *\n * @param actions - The action list produced by `buildSyncPlan`. Read-only;\n * the function never mutates the input.\n * @param tty - True when stdout is a TTY; controls ANSI emission.\n */\nexport function renderPlan(actions: ReadonlyArray<SyncAction>, tty: boolean): string {\n const active = actions.filter((a) => a.kind !== \"skip\");\n\n if (active.length === 0) {\n return paint(\n \"No changes. Your Zitadel configuration matches the current state.\",\n A.bold,\n tty,\n );\n }\n\n const out: string[] = [];\n out.push(paint(\"Zitadel will perform the following actions:\", A.bold, tty));\n\n for (const action of active) {\n out.push(\"\");\n out.push(...renderBlock(action, tty));\n }\n\n out.push(\"\");\n\n const { creates, updates, deletes } = summarizePlan(actions);\n\n const parts: string[] = [];\n if (creates > 0) {\n parts.push(`${creates} to add`);\n }\n if (updates > 0) {\n parts.push(`${updates} to change`);\n }\n if (deletes > 0) {\n parts.push(`${deletes} to destroy`);\n }\n\n out.push(paint(`Plan: ${parts.join(\", \")}.`, A.bold, tty));\n return out.join(\"\\n\");\n}\n\nconst A = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n green: \"\\x1b[32m\",\n red: \"\\x1b[31m\",\n yellow: \"\\x1b[33m\",\n} as const;\n\nfunction paint(text: string, code: string, tty: boolean): string {\n return tty ? `${code}${text}${A.reset}` : text;\n}\n\nfunction isPrimitive(v: unknown): v is string | number | boolean | null {\n return v === null || typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\";\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nconst KNOWN_AFTER_APPLY = \"(known after apply)\";\n\nfunction escapeString(s: string): string {\n return s\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\t/g, \"\\\\t\");\n}\n\nfunction fmtPrimitive(v: string | number | boolean | null): string {\n if (v === null) {\n return \"null\";\n }\n if (typeof v === \"string\" && v === KNOWN_AFTER_APPLY) {\n return KNOWN_AFTER_APPLY;\n }\n if (typeof v === \"string\") {\n return `\"${escapeString(v)}\"`;\n }\n return String(v);\n}\n\n/**\n * Indentation contract (matches Terraform exactly):\n * prefixCol = column index of the +/-/~ character\n * field content starts at prefixCol + 2 (one space gap after prefix)\n * nested object/array content: prefixCol + 4 for the child prefixCol\n * closing } or ] : prefixCol + 2 columns of plain spaces, no prefix\n */\ntype ChangePrefix = \"+\" | \"-\" | \"~\" | \" \";\n\nfunction prefixAnsi(p: ChangePrefix): string {\n if (p === \"+\") {\n return A.green;\n }\n if (p === \"-\") {\n return A.red;\n }\n if (p === \"~\") {\n return A.yellow;\n }\n return \"\";\n}\n\ninterface RenderCtx {\n tty: boolean;\n deleteMode: boolean;\n}\n\nfunction renderFields(\n obj: Record<string, unknown>,\n prefix: ChangePrefix,\n prefixCol: number,\n ctx: RenderCtx,\n lines: string[],\n): void {\n const pad = \" \".repeat(prefixCol);\n const ansi = prefixAnsi(prefix);\n const col = (s: string) => paint(s, ansi, ctx.tty);\n\n const keys = Object.keys(obj).sort();\n const maxLen = keys.reduce((m, k) => Math.max(m, k.length), 0);\n\n for (const key of keys) {\n const val = obj[key];\n const pk = key.padEnd(maxLen);\n\n if (isPrimitive(val)) {\n const formatted = fmtPrimitive(val);\n const suffix = ctx.deleteMode ? \" -> null\" : \"\";\n lines.push(col(`${pad}${prefix} ${pk} = ${formatted}${suffix}`));\n } else if (Array.isArray(val)) {\n if (val.length === 0) {\n lines.push(col(`${pad}${prefix} ${pk} = []`));\n } else {\n lines.push(col(`${pad}${prefix} ${pk} = [`));\n renderArrayItems(val, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}]`));\n }\n } else if (isPlainObject(val)) {\n if (Object.keys(val).length === 0) {\n lines.push(col(`${pad}${prefix} ${pk} = {}`));\n } else {\n lines.push(col(`${pad}${prefix} ${pk} = {`));\n renderFields(val, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n }\n }\n }\n}\n\n/**\n * Renders the items of an array. Unlike {@link renderFields}, primitive\n * elements never get a trailing ` -> null` suffix even under `deleteMode` —\n * Terraform only annotates scalar object-field removals that way, not array\n * items.\n */\nfunction renderArrayItems(\n arr: ReadonlyArray<unknown>,\n prefix: ChangePrefix,\n prefixCol: number,\n ctx: RenderCtx,\n lines: string[],\n): void {\n const pad = \" \".repeat(prefixCol);\n const ansi = prefixAnsi(prefix);\n const col = (s: string) => paint(s, ansi, ctx.tty);\n\n for (const item of arr) {\n if (isPrimitive(item)) {\n const formatted = fmtPrimitive(item);\n lines.push(col(`${pad}${prefix} ${formatted},`));\n } else if (Array.isArray(item)) {\n if (item.length === 0) {\n lines.push(col(`${pad}${prefix} [],`));\n } else {\n lines.push(col(`${pad}${prefix} [`));\n renderArrayItems(item, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}],`));\n }\n } else if (isPlainObject(item)) {\n if (Object.keys(item).length === 0) {\n lines.push(col(`${pad}${prefix} {},`));\n } else {\n lines.push(col(`${pad}${prefix} {`));\n renderFields(item, prefix, prefixCol + 4, ctx, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}},`));\n }\n }\n }\n}\n\n/**\n * Walks both old and new objects, emitting Terraform-style change lines.\n * Returns true if any actual change line (+ / - / ~) was emitted.\n *\n * Edge cases:\n * - Changed arrays render as a full remove + full add (no LCS diff).\n * - Nested objects recurse, and the outer key is only marked `~` if a child\n * actually changed; unchanged children render with the neutral prefix.\n * - A value whose type changed (e.g. string → object) also renders as a\n * remove + add pair.\n */\nfunction renderDiff(\n oldObj: Record<string, unknown>,\n newObj: Record<string, unknown>,\n prefixCol: number,\n tty: boolean,\n lines: string[],\n): boolean {\n const allKeys = [...new Set([...Object.keys(oldObj), ...Object.keys(newObj)])].sort();\n const maxLen = allKeys.reduce((m, k) => Math.max(m, k.length), 0);\n const pad = \" \".repeat(prefixCol);\n let hasChanges = false;\n\n for (const key of allKeys) {\n const pk = key.padEnd(maxLen);\n const hasOld = Object.prototype.hasOwnProperty.call(oldObj, key);\n const hasNew = Object.prototype.hasOwnProperty.call(newObj, key);\n const oldVal = oldObj[key];\n const newVal = newObj[key];\n\n if (!hasOld) {\n hasChanges = true;\n const col = (s: string) => paint(s, A.green, tty);\n if (isPrimitive(newVal)) {\n lines.push(col(`${pad}+ ${pk} = ${fmtPrimitive(newVal)}`));\n } else if (Array.isArray(newVal)) {\n lines.push(col(`${pad}+ ${pk} = [`));\n renderArrayItems(newVal, \"+\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}]`));\n } else if (isPlainObject(newVal)) {\n lines.push(col(`${pad}+ ${pk} = {`));\n renderFields(newVal, \"+\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n }\n } else if (!hasNew) {\n hasChanges = true;\n const col = (s: string) => paint(s, A.red, tty);\n if (isPrimitive(oldVal)) {\n lines.push(col(`${pad}- ${pk} = ${fmtPrimitive(oldVal)} -> null`));\n } else if (Array.isArray(oldVal)) {\n lines.push(col(`${pad}- ${pk} = [`));\n renderArrayItems(oldVal, \"-\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}]`));\n } else if (isPlainObject(oldVal)) {\n lines.push(col(`${pad}- ${pk} = {`));\n renderFields(oldVal, \"-\", prefixCol + 4, { tty, deleteMode: true }, lines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n }\n } else if (isPrimitive(oldVal) && isPrimitive(newVal)) {\n if (oldVal === newVal) {\n lines.push(`${pad} ${pk} = ${fmtPrimitive(newVal)}`);\n } else {\n hasChanges = true;\n const col = (s: string) => paint(s, A.yellow, tty);\n lines.push(col(`${pad}~ ${pk} = ${fmtPrimitive(oldVal)} -> ${fmtPrimitive(newVal)}`));\n }\n } else if (Array.isArray(oldVal) && Array.isArray(newVal)) {\n if (JSON.stringify(oldVal) === JSON.stringify(newVal)) {\n if (newVal.length === 0) {\n lines.push(`${pad} ${pk} = []`);\n } else {\n lines.push(`${pad} ${pk} = [`);\n renderArrayItems(newVal, \" \", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(`${\" \".repeat(prefixCol + 2)}]`);\n }\n } else {\n hasChanges = true;\n const colR = (s: string) => paint(s, A.red, tty);\n const colA = (s: string) => paint(s, A.green, tty);\n if (oldVal.length === 0) {\n lines.push(colR(`${pad}- ${pk} = []`));\n } else {\n lines.push(colR(`${pad}- ${pk} = [`));\n renderArrayItems(oldVal, \"-\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(colR(`${\" \".repeat(prefixCol + 2)}]`));\n }\n if (newVal.length === 0) {\n lines.push(colA(`${pad}+ ${pk} = []`));\n } else {\n lines.push(colA(`${pad}+ ${pk} = [`));\n renderArrayItems(newVal, \"+\", prefixCol + 4, { tty, deleteMode: false }, lines);\n lines.push(colA(`${\" \".repeat(prefixCol + 2)}]`));\n }\n }\n } else if (isPlainObject(oldVal) && isPlainObject(newVal)) {\n const childLines: string[] = [];\n const childHasChanges = renderDiff(oldVal, newVal, prefixCol + 4, tty, childLines);\n if (childHasChanges) {\n hasChanges = true;\n const col = (s: string) => paint(s, A.yellow, tty);\n lines.push(col(`${pad}~ ${pk} = {`));\n lines.push(...childLines);\n lines.push(col(`${\" \".repeat(prefixCol + 2)}}`));\n } else if (childLines.length > 0) {\n lines.push(`${pad} ${pk} = {`);\n lines.push(...childLines);\n lines.push(`${\" \".repeat(prefixCol + 2)}}`);\n } else {\n lines.push(`${pad} ${pk} = {}`);\n }\n } else {\n hasChanges = true;\n const colR = (s: string) => paint(s, A.red, tty);\n const colA = (s: string) => paint(s, A.green, tty);\n if (isPrimitive(oldVal)) {\n lines.push(colR(`${pad}- ${pk} = ${fmtPrimitive(oldVal)} -> null`));\n }\n if (isPrimitive(newVal)) {\n lines.push(colA(`${pad}+ ${pk} = ${fmtPrimitive(newVal)}`));\n }\n }\n }\n\n return hasChanges;\n}\n\n/**\n * Column layout (matches Terraform's per-block format):\n * BLOCK_COL = 2 — where the +/-/~ sits on the resource opening line\n * FIELD_COL = 6 — where the +/-/~ sits on first-level field lines\n * closing } — at BLOCK_COL + 2 = 4, no prefix\n */\nconst BLOCK_COL = 2;\nconst FIELD_COL = 6;\n\nfunction resourceName(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\n/**\n * Renders one Terraform-style resource block for a single `SyncAction`.\n *\n * Per-case notes:\n * - **create**: a synthetic `id = (known after apply)` is injected into the\n * rendered fields so it sorts alphabetically alongside the real keys.\n * - **delete**: when `oldContent` is null (the fetch failed), the body\n * collapses to a single `- id = \"<id>\" -> null` line.\n * - **update**: when `oldContent` is null (no read endpoint for this\n * resource kind), the field diff is replaced with a placeholder\n * \"field diff unavailable\" line.\n * - **skip**: omitted from the output entirely, matching Terraform's\n * default of not showing no-change resources.\n */\nfunction renderBlock(action: SyncAction, tty: boolean): string[] {\n const lines: string[] = [];\n const blkPad = \" \".repeat(BLOCK_COL);\n const closePad = \" \".repeat(BLOCK_COL + 2);\n\n switch (action.kind) {\n case \"create\": {\n const header = `${blkPad}# ${action.path} will be created`;\n const opening = `${blkPad}+ resource \"${action.syncer.kind}\" \"${resourceName(action.path)}\" {`;\n lines.push(paint(header, A.bold, tty));\n lines.push(paint(opening, A.green, tty));\n\n const display: Record<string, unknown> = {\n id: KNOWN_AFTER_APPLY,\n ...(action.content as Record<string, unknown>),\n };\n renderFields(display, \"+\", FIELD_COL, { tty, deleteMode: false }, lines);\n lines.push(`${closePad}}`);\n break;\n }\n\n case \"delete\": {\n const header = `${blkPad}# ${action.path} will be destroyed`;\n const opening = `${blkPad}- resource \"${action.syncer.kind}\" \"${resourceName(action.path)}\" {`;\n lines.push(paint(header, A.bold, tty));\n lines.push(paint(opening, A.red, tty));\n\n if (action.oldContent) {\n const display: Record<string, unknown> = {\n id: action.id,\n ...(action.oldContent as Record<string, unknown>),\n };\n renderFields(display, \"-\", FIELD_COL, { tty, deleteMode: true }, lines);\n } else {\n lines.push(paint(`${\" \".repeat(FIELD_COL)}- id = \"${action.id}\" -> null`, A.red, tty));\n }\n lines.push(`${closePad}}`);\n break;\n }\n\n case \"update\": {\n const header = `${blkPad}# ${action.path} will be updated in-place`;\n const opening = `${blkPad}~ resource \"${action.syncer.kind}\" \"${resourceName(action.path)}\" {`;\n lines.push(paint(header, A.bold, tty));\n lines.push(paint(opening, A.yellow, tty));\n\n if (action.oldContent) {\n renderDiff(\n action.oldContent as Record<string, unknown>,\n action.content as Record<string, unknown>,\n FIELD_COL,\n tty,\n lines,\n );\n } else {\n lines.push(\n `${\" \".repeat(FIELD_COL)} # (field diff unavailable — no read endpoint for ${action.syncer.kind})`,\n );\n }\n lines.push(`${closePad}}`);\n break;\n }\n\n case \"skip\":\n break;\n }\n\n return lines;\n}\n"],"mappings":"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"}
|
package/oclif.manifest.json
CHANGED
|
@@ -169,6 +169,17 @@
|
|
|
169
169
|
"hasDynamicHelp": false,
|
|
170
170
|
"multiple": false,
|
|
171
171
|
"type": "option"
|
|
172
|
+
},
|
|
173
|
+
"runtime": {
|
|
174
|
+
"description": "Local runtime backend.",
|
|
175
|
+
"name": "runtime",
|
|
176
|
+
"hasDynamicHelp": false,
|
|
177
|
+
"multiple": false,
|
|
178
|
+
"options": [
|
|
179
|
+
"binary",
|
|
180
|
+
"docker"
|
|
181
|
+
],
|
|
182
|
+
"type": "option"
|
|
172
183
|
}
|
|
173
184
|
},
|
|
174
185
|
"hasDynamicHelp": false,
|
|
@@ -524,7 +535,8 @@
|
|
|
524
535
|
"args": {},
|
|
525
536
|
"description": "Create a Zitadel project and scaffold local auth.",
|
|
526
537
|
"examples": [
|
|
527
|
-
"<%= config.bin %> setup --framework next"
|
|
538
|
+
"<%= config.bin %> setup --framework next",
|
|
539
|
+
"<%= config.bin %> setup --framework react --dev-port 3000"
|
|
528
540
|
],
|
|
529
541
|
"flags": {
|
|
530
542
|
"json": {
|
|
@@ -588,7 +600,11 @@
|
|
|
588
600
|
"hasDynamicHelp": false,
|
|
589
601
|
"multiple": false,
|
|
590
602
|
"options": [
|
|
591
|
-
"next"
|
|
603
|
+
"next",
|
|
604
|
+
"nuxt",
|
|
605
|
+
"react",
|
|
606
|
+
"vue",
|
|
607
|
+
"angular"
|
|
592
608
|
],
|
|
593
609
|
"type": "option"
|
|
594
610
|
},
|
|
@@ -603,6 +619,13 @@
|
|
|
603
619
|
],
|
|
604
620
|
"type": "option"
|
|
605
621
|
},
|
|
622
|
+
"dev-port": {
|
|
623
|
+
"description": "Dev-server port; also the issuer origin registered with Zitadel. Defaults to the detected port. Use distinct ports to run several scaffolded apps side by side.",
|
|
624
|
+
"name": "dev-port",
|
|
625
|
+
"hasDynamicHelp": false,
|
|
626
|
+
"multiple": false,
|
|
627
|
+
"type": "option"
|
|
628
|
+
},
|
|
606
629
|
"skip-install": {
|
|
607
630
|
"description": "Do not install dependencies after setup updates package.json.",
|
|
608
631
|
"name": "skip-install",
|
|
@@ -699,6 +722,17 @@
|
|
|
699
722
|
"hasDynamicHelp": false,
|
|
700
723
|
"multiple": false,
|
|
701
724
|
"type": "option"
|
|
725
|
+
},
|
|
726
|
+
"runtime": {
|
|
727
|
+
"description": "Local runtime backend.",
|
|
728
|
+
"name": "runtime",
|
|
729
|
+
"hasDynamicHelp": false,
|
|
730
|
+
"multiple": false,
|
|
731
|
+
"options": [
|
|
732
|
+
"binary",
|
|
733
|
+
"docker"
|
|
734
|
+
],
|
|
735
|
+
"type": "option"
|
|
702
736
|
}
|
|
703
737
|
},
|
|
704
738
|
"hasDynamicHelp": false,
|
|
@@ -869,5 +903,5 @@
|
|
|
869
903
|
]
|
|
870
904
|
}
|
|
871
905
|
},
|
|
872
|
-
"version": "0.1.0-alpha.
|
|
906
|
+
"version": "0.1.0-alpha.8"
|
|
873
907
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zitadel/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.8",
|
|
4
4
|
"description": "Agent-friendly Zitadel CLI",
|
|
5
5
|
"homepage": "https://github.com/zitadel/nextgen/tree/main/apps/cli#readme",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/zitadel/nextgen/issues"
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=24"
|
|
12
|
+
},
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
15
|
"url": "git+https://github.com/zitadel/nextgen.git",
|
|
@@ -52,10 +55,12 @@
|
|
|
52
55
|
"@oclif/plugin-which": "^3.2.55",
|
|
53
56
|
"ajv": "^8.20.0",
|
|
54
57
|
"consola": "^3.4.2",
|
|
58
|
+
"magicast": "^0.5.3",
|
|
55
59
|
"safe-stable-stringify": "^2.5.0",
|
|
56
60
|
"zod": "^4.3.6",
|
|
57
61
|
"picocolors": "^1.1.1",
|
|
58
|
-
"@zitadel/
|
|
62
|
+
"@zitadel/server": "0.1.0-alpha.8",
|
|
63
|
+
"@zitadel/api": "0.1.0-alpha.8"
|
|
59
64
|
},
|
|
60
65
|
"devDependencies": {
|
|
61
66
|
"@types/node": "^25.6.0",
|
|
@@ -63,47 +68,9 @@
|
|
|
63
68
|
"oclif": "^4.17.46",
|
|
64
69
|
"tsdown": "^0.21.10",
|
|
65
70
|
"vitest": "^3.0.0",
|
|
66
|
-
"@zitadel/sdk-next": "0.1.0-alpha.
|
|
71
|
+
"@zitadel/sdk-next": "0.1.0-alpha.8",
|
|
67
72
|
"@zitadel/api-mock": "0.0.0"
|
|
68
73
|
},
|
|
69
|
-
"nx": {
|
|
70
|
-
"targets": {
|
|
71
|
-
"build": {
|
|
72
|
-
"options": {
|
|
73
|
-
"cache": true
|
|
74
|
-
},
|
|
75
|
-
"inputs": [
|
|
76
|
-
"production",
|
|
77
|
-
"^production",
|
|
78
|
-
{
|
|
79
|
-
"externalDependencies": [
|
|
80
|
-
"tsdown"
|
|
81
|
-
]
|
|
82
|
-
}
|
|
83
|
-
],
|
|
84
|
-
"outputs": [
|
|
85
|
-
"{projectRoot}/dist/**/*.mjs",
|
|
86
|
-
"{projectRoot}/dist/**/*.mjs.map"
|
|
87
|
-
],
|
|
88
|
-
"dependsOn": [
|
|
89
|
-
"^build",
|
|
90
|
-
"^typecheck"
|
|
91
|
-
]
|
|
92
|
-
},
|
|
93
|
-
"readme": {
|
|
94
|
-
"dependsOn": [
|
|
95
|
-
"build"
|
|
96
|
-
],
|
|
97
|
-
"inputs": [
|
|
98
|
-
"{projectRoot}/dist/**/*.mjs",
|
|
99
|
-
"{projectRoot}/README.md"
|
|
100
|
-
],
|
|
101
|
-
"outputs": [
|
|
102
|
-
"{projectRoot}/README.md"
|
|
103
|
-
]
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
74
|
"scripts": {
|
|
108
75
|
"build": "tsdown",
|
|
109
76
|
"typecheck": "tsc --noEmit",
|
package/dist/docker-B4zvLujy.mjs
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { E as ZitadelError, i as CONTAINER_HTTP_PORT, r as CONTAINER_DATA_DIR } from "./oclif-B3Qhw0cj.mjs";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
//#region src/lib/local-server/docker.ts
|
|
4
|
-
function dockerRunArgs(spec) {
|
|
5
|
-
const args = [
|
|
6
|
-
"run",
|
|
7
|
-
"--detach",
|
|
8
|
-
"--name",
|
|
9
|
-
spec.containerName,
|
|
10
|
-
"--publish",
|
|
11
|
-
`127.0.0.1:${spec.port}:${CONTAINER_HTTP_PORT}`,
|
|
12
|
-
"--volume",
|
|
13
|
-
`${spec.dataDir}:${CONTAINER_DATA_DIR}`,
|
|
14
|
-
"--env",
|
|
15
|
-
`NEXTGEN_SERVER_ADDRESS=:${CONTAINER_HTTP_PORT}`,
|
|
16
|
-
"--env",
|
|
17
|
-
`NEXTGEN_SERVER_DATA_DIR=${CONTAINER_DATA_DIR}`
|
|
18
|
-
];
|
|
19
|
-
if (spec.identity) args.push("--volume", `${spec.identity.passwdFile}:/etc/passwd:ro`, "--volume", `${spec.identity.groupFile}:/etc/group:ro`, "--user", `${spec.identity.uid}:${spec.identity.gid}`);
|
|
20
|
-
args.push(spec.image);
|
|
21
|
-
return args;
|
|
22
|
-
}
|
|
23
|
-
async function runDocker(args) {
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
const child = spawn("docker", args, {
|
|
26
|
-
stdio: [
|
|
27
|
-
"ignore",
|
|
28
|
-
"pipe",
|
|
29
|
-
"pipe"
|
|
30
|
-
],
|
|
31
|
-
env: process.env
|
|
32
|
-
});
|
|
33
|
-
let stdout = "";
|
|
34
|
-
let stderr = "";
|
|
35
|
-
child.stdout?.setEncoding("utf8");
|
|
36
|
-
child.stderr?.setEncoding("utf8");
|
|
37
|
-
child.stdout?.on("data", (chunk) => {
|
|
38
|
-
stdout += chunk;
|
|
39
|
-
});
|
|
40
|
-
child.stderr?.on("data", (chunk) => {
|
|
41
|
-
stderr += chunk;
|
|
42
|
-
});
|
|
43
|
-
child.on("error", reject);
|
|
44
|
-
child.on("close", (code) => {
|
|
45
|
-
resolve({
|
|
46
|
-
status: code ?? 1,
|
|
47
|
-
stdout,
|
|
48
|
-
stderr
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
async function streamDocker(args) {
|
|
54
|
-
await new Promise((resolve, reject) => {
|
|
55
|
-
const child = spawn("docker", args, {
|
|
56
|
-
stdio: "inherit",
|
|
57
|
-
env: process.env
|
|
58
|
-
});
|
|
59
|
-
child.on("error", reject);
|
|
60
|
-
child.on("close", (code) => {
|
|
61
|
-
if (code === 0) resolve();
|
|
62
|
-
else reject(/* @__PURE__ */ new Error(`docker ${args.join(" ")} exited with status ${code ?? 1}`));
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
async function dockerAvailable() {
|
|
67
|
-
return runDocker([
|
|
68
|
-
"version",
|
|
69
|
-
"--format",
|
|
70
|
-
"{{.Server.Version}}"
|
|
71
|
-
]);
|
|
72
|
-
}
|
|
73
|
-
async function pullImage(image) {
|
|
74
|
-
await requireDocker([
|
|
75
|
-
"pull",
|
|
76
|
-
"--quiet",
|
|
77
|
-
image
|
|
78
|
-
], `Pull Docker image ${image}`);
|
|
79
|
-
}
|
|
80
|
-
async function imageExists(image) {
|
|
81
|
-
let result;
|
|
82
|
-
const args = [
|
|
83
|
-
"image",
|
|
84
|
-
"inspect",
|
|
85
|
-
image
|
|
86
|
-
];
|
|
87
|
-
try {
|
|
88
|
-
result = await runDocker(args);
|
|
89
|
-
} catch (error) {
|
|
90
|
-
throw dockerError(`Inspect Docker image ${image}`, args, error);
|
|
91
|
-
}
|
|
92
|
-
return result.status === 0;
|
|
93
|
-
}
|
|
94
|
-
async function imageAvailable(image) {
|
|
95
|
-
if (await imageExists(image)) return "local";
|
|
96
|
-
const args = [
|
|
97
|
-
"manifest",
|
|
98
|
-
"inspect",
|
|
99
|
-
image
|
|
100
|
-
];
|
|
101
|
-
let result;
|
|
102
|
-
try {
|
|
103
|
-
result = await runDocker(args);
|
|
104
|
-
} catch (error) {
|
|
105
|
-
throw dockerError(`Inspect Docker image ${image}`, args, error);
|
|
106
|
-
}
|
|
107
|
-
if (result.status === 0) return "remote";
|
|
108
|
-
throw dockerError(`Inspect Docker image ${image}`, args, result);
|
|
109
|
-
}
|
|
110
|
-
async function ensureImage(image) {
|
|
111
|
-
if (await imageExists(image)) return "local";
|
|
112
|
-
await pullImage(image);
|
|
113
|
-
return "pulled";
|
|
114
|
-
}
|
|
115
|
-
async function inspectContainer(containerName) {
|
|
116
|
-
const result = await runDocker([
|
|
117
|
-
"inspect",
|
|
118
|
-
"--format",
|
|
119
|
-
"{{.Id}} {{.State.Running}} {{.Config.Image}}",
|
|
120
|
-
containerName
|
|
121
|
-
]);
|
|
122
|
-
if (result.status !== 0) return {
|
|
123
|
-
exists: false,
|
|
124
|
-
running: false
|
|
125
|
-
};
|
|
126
|
-
const [id, running, ...imageParts] = result.stdout.trim().split(/\s+/);
|
|
127
|
-
return {
|
|
128
|
-
exists: true,
|
|
129
|
-
running: running === "true",
|
|
130
|
-
id,
|
|
131
|
-
image: imageParts.join(" ")
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
async function startContainer(spec) {
|
|
135
|
-
return (await requireDocker(dockerRunArgs(spec), "Start local Zitadel container")).stdout.trim();
|
|
136
|
-
}
|
|
137
|
-
async function stopAndRemoveContainer(containerName) {
|
|
138
|
-
const inspect = await inspectContainer(containerName);
|
|
139
|
-
if (!inspect.exists) return;
|
|
140
|
-
if (inspect.running) await requireDocker(["stop", containerName], `Stop ${containerName}`);
|
|
141
|
-
await requireDocker(["rm", containerName], `Remove ${containerName}`);
|
|
142
|
-
}
|
|
143
|
-
async function containerLogs(containerName, tail) {
|
|
144
|
-
return (await requireDocker([
|
|
145
|
-
"logs",
|
|
146
|
-
"--tail",
|
|
147
|
-
String(tail),
|
|
148
|
-
containerName
|
|
149
|
-
], "Read logs")).stdout;
|
|
150
|
-
}
|
|
151
|
-
async function followContainerLogs(containerName, tail) {
|
|
152
|
-
await streamDocker([
|
|
153
|
-
"logs",
|
|
154
|
-
"--tail",
|
|
155
|
-
String(tail),
|
|
156
|
-
"--follow",
|
|
157
|
-
containerName
|
|
158
|
-
]);
|
|
159
|
-
}
|
|
160
|
-
function currentUser() {
|
|
161
|
-
const getuid = process.getuid;
|
|
162
|
-
const getgid = process.getgid;
|
|
163
|
-
if (typeof getuid !== "function") return {};
|
|
164
|
-
const uid = getuid();
|
|
165
|
-
return {
|
|
166
|
-
uid,
|
|
167
|
-
gid: typeof getgid === "function" ? getgid() : uid
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
function metadataFromStart(input) {
|
|
171
|
-
return {
|
|
172
|
-
schema_version: 1,
|
|
173
|
-
container_name: input.containerName,
|
|
174
|
-
container_id: input.containerId,
|
|
175
|
-
image: input.image,
|
|
176
|
-
port: input.port,
|
|
177
|
-
server_url: input.serverUrl,
|
|
178
|
-
data_dir: input.cwdDataDir,
|
|
179
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
180
|
-
cli_version: input.cliVersion
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
async function requireDocker(args, action) {
|
|
184
|
-
let result;
|
|
185
|
-
try {
|
|
186
|
-
result = await runDocker(args);
|
|
187
|
-
} catch (error) {
|
|
188
|
-
throw dockerError(action, args, error);
|
|
189
|
-
}
|
|
190
|
-
if (result.status !== 0) throw dockerError(action, args, result);
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
|
-
function dockerError(action, args, cause) {
|
|
194
|
-
const details = cause && typeof cause === "object" && "stderr" in cause ? {
|
|
195
|
-
command: ["docker", ...args],
|
|
196
|
-
stderr: String(cause.stderr)
|
|
197
|
-
} : {
|
|
198
|
-
command: ["docker", ...args],
|
|
199
|
-
cause
|
|
200
|
-
};
|
|
201
|
-
return new ZitadelError("E_VALIDATION", `${action} failed`, {
|
|
202
|
-
hint: "Check that Docker is installed, running, and reachable from this shell.",
|
|
203
|
-
nextCommands: ["zitadel doctor"],
|
|
204
|
-
details
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
//#endregion
|
|
208
|
-
export { followContainerLogs as a, metadataFromStart as c, ensureImage as i, startContainer as l, currentUser as n, imageAvailable as o, dockerAvailable as r, inspectContainer as s, containerLogs as t, stopAndRemoveContainer as u };
|
|
209
|
-
|
|
210
|
-
//# sourceMappingURL=docker-B4zvLujy.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docker-B4zvLujy.mjs","names":[],"sources":["../src/lib/local-server/docker.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\n\nimport { ZitadelError } from \"../errors\";\nimport {\n CONTAINER_DATA_DIR,\n CONTAINER_HTTP_PORT,\n type ContainerIdentity,\n type RuntimeMetadata,\n} from \"./runtime\";\n\nexport type DockerResult = {\n status: number;\n stdout: string;\n stderr: string;\n};\n\nexport type DockerRunSpec = {\n containerName: string;\n image: string;\n port: number;\n dataDir: string;\n identity?: ContainerIdentity;\n};\n\nexport function dockerRunArgs(spec: DockerRunSpec): string[] {\n const args = [\n \"run\",\n \"--detach\",\n \"--name\",\n spec.containerName,\n \"--publish\",\n `127.0.0.1:${spec.port}:${CONTAINER_HTTP_PORT}`,\n \"--volume\",\n `${spec.dataDir}:${CONTAINER_DATA_DIR}`,\n \"--env\",\n `NEXTGEN_SERVER_ADDRESS=:${CONTAINER_HTTP_PORT}`,\n \"--env\",\n `NEXTGEN_SERVER_DATA_DIR=${CONTAINER_DATA_DIR}`,\n ];\n\n if (spec.identity) {\n args.push(\n \"--volume\",\n `${spec.identity.passwdFile}:/etc/passwd:ro`,\n \"--volume\",\n `${spec.identity.groupFile}:/etc/group:ro`,\n \"--user\",\n `${spec.identity.uid}:${spec.identity.gid}`,\n );\n }\n\n args.push(spec.image);\n return args;\n}\n\nexport async function runDocker(args: string[]): Promise<DockerResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"docker\", args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.setEncoding(\"utf8\");\n child.stderr?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (chunk: string) => {\n stdout += chunk;\n });\n child.stderr?.on(\"data\", (chunk: string) => {\n stderr += chunk;\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n resolve({ status: code ?? 1, stdout, stderr });\n });\n });\n}\n\nexport async function streamDocker(args: string[]): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(\"docker\", args, {\n stdio: \"inherit\",\n env: process.env,\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`docker ${args.join(\" \")} exited with status ${code ?? 1}`));\n }\n });\n });\n}\n\nexport async function dockerAvailable(): Promise<DockerResult> {\n return runDocker([\"version\", \"--format\", \"{{.Server.Version}}\"]);\n}\n\nexport async function pullImage(image: string): Promise<void> {\n await requireDocker([\"pull\", \"--quiet\", image], `Pull Docker image ${image}`);\n}\n\nexport async function imageExists(image: string): Promise<boolean> {\n let result: DockerResult;\n const args = [\"image\", \"inspect\", image];\n try {\n result = await runDocker(args);\n } catch (error) {\n throw dockerError(`Inspect Docker image ${image}`, args, error);\n }\n return result.status === 0;\n}\n\nexport async function imageAvailable(image: string): Promise<\"local\" | \"remote\"> {\n if (await imageExists(image)) {\n return \"local\";\n }\n\n const args = [\"manifest\", \"inspect\", image];\n let result: DockerResult;\n try {\n result = await runDocker(args);\n } catch (error) {\n throw dockerError(`Inspect Docker image ${image}`, args, error);\n }\n if (result.status === 0) {\n return \"remote\";\n }\n throw dockerError(`Inspect Docker image ${image}`, args, result);\n}\n\nexport async function ensureImage(image: string): Promise<\"local\" | \"pulled\"> {\n if (await imageExists(image)) {\n return \"local\";\n }\n await pullImage(image);\n return \"pulled\";\n}\n\nexport async function inspectContainer(containerName: string): Promise<{\n exists: boolean;\n running: boolean;\n id?: string;\n image?: string;\n}> {\n const result = await runDocker([\n \"inspect\",\n \"--format\",\n \"{{.Id}} {{.State.Running}} {{.Config.Image}}\",\n containerName,\n ]);\n if (result.status !== 0) {\n return { exists: false, running: false };\n }\n const [id, running, ...imageParts] = result.stdout.trim().split(/\\s+/);\n return { exists: true, running: running === \"true\", id, image: imageParts.join(\" \") };\n}\n\nexport async function startContainer(spec: DockerRunSpec): Promise<string> {\n const args = dockerRunArgs(spec);\n const result = await requireDocker(args, \"Start local Zitadel container\");\n return result.stdout.trim();\n}\n\nexport async function stopAndRemoveContainer(containerName: string): Promise<void> {\n const inspect = await inspectContainer(containerName);\n if (!inspect.exists) {\n return;\n }\n if (inspect.running) {\n await requireDocker([\"stop\", containerName], `Stop ${containerName}`);\n }\n await requireDocker([\"rm\", containerName], `Remove ${containerName}`);\n}\n\nexport async function containerLogs(containerName: string, tail: number): Promise<string> {\n const result = await requireDocker([\"logs\", \"--tail\", String(tail), containerName], \"Read logs\");\n return result.stdout;\n}\n\nexport async function followContainerLogs(containerName: string, tail: number): Promise<void> {\n await streamDocker([\"logs\", \"--tail\", String(tail), \"--follow\", containerName]);\n}\n\nexport function currentUser(): { uid?: number; gid?: number } {\n const getuid = process.getuid;\n const getgid = process.getgid;\n if (typeof getuid !== \"function\") {\n return {};\n }\n const uid = getuid();\n const gid = typeof getgid === \"function\" ? getgid() : uid;\n return { uid, gid };\n}\n\nexport function metadataFromStart(input: {\n cwdDataDir: string;\n cliVersion: string;\n containerName: string;\n containerId: string;\n image: string;\n port: number;\n serverUrl: string;\n}): RuntimeMetadata {\n return {\n schema_version: 1,\n container_name: input.containerName,\n container_id: input.containerId,\n image: input.image,\n port: input.port,\n server_url: input.serverUrl,\n data_dir: input.cwdDataDir,\n created_at: new Date().toISOString(),\n cli_version: input.cliVersion,\n };\n}\n\nexport async function requireDocker(args: string[], action: string): Promise<DockerResult> {\n let result: DockerResult;\n try {\n result = await runDocker(args);\n } catch (error) {\n throw dockerError(action, args, error);\n }\n if (result.status !== 0) {\n throw dockerError(action, args, result);\n }\n return result;\n}\n\nfunction dockerError(action: string, args: string[], cause: unknown): ZitadelError {\n const details =\n cause && typeof cause === \"object\" && \"stderr\" in cause\n ? { command: [\"docker\", ...args], stderr: String((cause as { stderr?: unknown }).stderr) }\n : { command: [\"docker\", ...args], cause };\n return new ZitadelError(\"E_VALIDATION\", `${action} failed`, {\n hint: \"Check that Docker is installed, running, and reachable from this shell.\",\n nextCommands: [\"zitadel doctor\"],\n details,\n });\n}\n"],"mappings":"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"}
|