@zitadel/cli 0.1.0-alpha.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +4043 -229
  2. package/bin/run.js +8 -0
  3. package/dist/index.mjs +24173 -0
  4. package/dist/index.mjs.map +1 -0
  5. package/dist/lib/oclif/help.mjs +117 -0
  6. package/dist/lib/oclif/help.mjs.map +1 -0
  7. package/dist/skills-hint-CBoak9HL.mjs +4348 -0
  8. package/dist/skills-hint-CBoak9HL.mjs.map +1 -0
  9. package/oclif.manifest.json +8635 -253
  10. package/package.json +106 -15
  11. package/skills/zitadel-cli/SKILL.md +538 -0
  12. package/skills/zitadel-cli/references/driving-login-ui.md +109 -0
  13. package/SKILLS.md +0 -157
  14. package/dist/commands/apply.mjs +0 -62
  15. package/dist/commands/apply.mjs.map +0 -1
  16. package/dist/commands/doctor.mjs +0 -569
  17. package/dist/commands/doctor.mjs.map +0 -1
  18. package/dist/commands/eject.mjs +0 -145
  19. package/dist/commands/eject.mjs.map +0 -1
  20. package/dist/commands/logs.mjs +0 -58
  21. package/dist/commands/logs.mjs.map +0 -1
  22. package/dist/commands/plan.mjs +0 -52
  23. package/dist/commands/plan.mjs.map +0 -1
  24. package/dist/commands/reset.mjs +0 -79
  25. package/dist/commands/reset.mjs.map +0 -1
  26. package/dist/commands/setup.mjs +0 -856
  27. package/dist/commands/setup.mjs.map +0 -1
  28. package/dist/commands/start.mjs +0 -288
  29. package/dist/commands/start.mjs.map +0 -1
  30. package/dist/commands/status.mjs +0 -112
  31. package/dist/commands/status.mjs.map +0 -1
  32. package/dist/commands/stop.mjs +0 -105
  33. package/dist/commands/stop.mjs.map +0 -1
  34. package/dist/docker-CnGQK3ZK.mjs +0 -432
  35. package/dist/docker-CnGQK3ZK.mjs.map +0 -1
  36. package/dist/docker-guidance-ypN3IM3o.mjs +0 -21
  37. package/dist/docker-guidance-ypN3IM3o.mjs.map +0 -1
  38. package/dist/oclif-B7lBzh3R.mjs +0 -808
  39. package/dist/oclif-B7lBzh3R.mjs.map +0 -1
  40. package/dist/orca-U142Wrau.mjs +0 -2556
  41. package/dist/orca-U142Wrau.mjs.map +0 -1
  42. package/dist/ports-B09RjuHx.mjs +0 -111
  43. package/dist/ports-B09RjuHx.mjs.map +0 -1
  44. package/dist/processes-Cw8TO1SY.mjs +0 -120
  45. package/dist/processes-Cw8TO1SY.mjs.map +0 -1
  46. package/dist/project-Cd0L3PtM.mjs +0 -87
  47. package/dist/project-Cd0L3PtM.mjs.map +0 -1
  48. package/dist/sync-BojoQm2P.mjs +0 -733
  49. package/dist/sync-BojoQm2P.mjs.map +0 -1
@@ -1,120 +0,0 @@
1
- import { basename } from "node:path";
2
- import { execFile } from "node:child_process";
3
- //#region src/lib/local-server/processes.ts
4
- async function discoverManagedRuntimeProcesses(opts) {
5
- if (process.platform === "win32") return {
6
- supported: false,
7
- processes: [],
8
- error: "process sweep is not available on Windows"
9
- };
10
- let rows;
11
- try {
12
- rows = parsePsRows(await runPs(["axo", "pid=,ppid=,command="], opts?.timeoutMs ?? 1e3));
13
- } catch (error) {
14
- return {
15
- supported: false,
16
- processes: [],
17
- error: errorMessage(error)
18
- };
19
- }
20
- const candidates = rows.filter((row) => isRuntimeCandidate(row.command));
21
- return {
22
- supported: true,
23
- processes: uniqueByPid((await Promise.all(candidates.map(async (row) => ({
24
- ...row,
25
- command: await hydrateCommand(row.pid, row.command, opts?.timeoutMs ?? 1e3)
26
- })))).map(toManagedRuntimeProcess).filter((candidate) => candidate !== void 0))
27
- };
28
- }
29
- function runPs(args, timeoutMs) {
30
- return new Promise((resolve, reject) => {
31
- execFile("ps", args, {
32
- timeout: timeoutMs,
33
- encoding: "utf8"
34
- }, (err, stdout) => {
35
- if (err) {
36
- reject(err);
37
- return;
38
- }
39
- resolve(stdout);
40
- });
41
- });
42
- }
43
- async function hydrateCommand(pid, fallback, timeoutMs) {
44
- try {
45
- return (await runPs([
46
- "eww",
47
- "-p",
48
- String(pid),
49
- "-o",
50
- "command="
51
- ], timeoutMs)).trim() || fallback;
52
- } catch {
53
- return fallback;
54
- }
55
- }
56
- function parsePsRows(stdout) {
57
- const rows = [];
58
- for (const line of stdout.split(/\r?\n/)) {
59
- const trimmed = line.trim();
60
- if (!trimmed) continue;
61
- const match = trimmed.match(/^(\d+)\s+(\d+)\s+(.+)$/);
62
- if (!match) continue;
63
- rows.push({
64
- pid: Number(match[1]),
65
- ppid: Number(match[2]),
66
- command: match[3] ?? ""
67
- });
68
- }
69
- return rows;
70
- }
71
- function toManagedRuntimeProcess(row) {
72
- const dataDir = extractDataDir(row.command);
73
- const wrapper = isServerWrapper(row.command);
74
- const binary = isServerBinary(row.command);
75
- if (!wrapper && !binary) return;
76
- if (!wrapper && !isCliLocalDataDir(dataDir)) return;
77
- return {
78
- pid: row.pid,
79
- ppid: row.ppid,
80
- command: stripEnvironmentNoise(row.command),
81
- kind: wrapper ? "server-wrapper" : "server-binary",
82
- ...dataDir ? { data_dir: dataDir } : {}
83
- };
84
- }
85
- function isRuntimeCandidate(command) {
86
- return isServerWrapper(command) || isServerBinary(command) || command.includes("NEXTGEN_SERVER_DATA_DIR=") || basename(command.split(/\s+/)[0] ?? "") === "nextgen";
87
- }
88
- function isServerWrapper(command) {
89
- return command.includes("zitadel-server.js");
90
- }
91
- function isServerBinary(command) {
92
- if (/@zitadel\/server-[^/\s]+\/bin\/nextgen(?:\.exe)?(?:\s|$)/.test(command)) return true;
93
- return isCliLocalDataDir(extractDataDir(command)) && commandTokens(command).some((token) => basename(token) === "nextgen");
94
- }
95
- function extractDataDir(command) {
96
- const value = command.match(/NEXTGEN_SERVER_DATA_DIR=("[^"]+"|'[^']+'|[^\s]+)/)?.[1];
97
- if (!value) return;
98
- return value.replace(/^["']|["']$/g, "");
99
- }
100
- function isCliLocalDataDir(path) {
101
- return Boolean(path && /(?:^|\/)\.zitadel\/local\/nextgen-data\/?$/.test(path));
102
- }
103
- function stripEnvironmentNoise(command) {
104
- return command.replace(/(^|\s)[A-Z_][A-Z0-9_]*=(?:"[^"]+"|'[^']+'|[^\s]+)/g, " ").replace(/\s{2,}/g, " ").trim();
105
- }
106
- function commandTokens(command) {
107
- return command.split(/\s+/).filter((token) => !/^[A-Z_][A-Z0-9_]*=/.test(token));
108
- }
109
- function uniqueByPid(processes) {
110
- const byPid = /* @__PURE__ */ new Map();
111
- for (const processInfo of processes) byPid.set(processInfo.pid, processInfo);
112
- return [...byPid.values()].sort((a, b) => a.pid - b.pid);
113
- }
114
- function errorMessage(error) {
115
- return error instanceof Error ? error.message : String(error);
116
- }
117
- //#endregion
118
- export { discoverManagedRuntimeProcesses as t };
119
-
120
- //# sourceMappingURL=processes-Cw8TO1SY.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"processes-Cw8TO1SY.mjs","names":[],"sources":["../src/lib/local-server/processes.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { basename } from \"node:path\";\n\nexport type ManagedRuntimeProcess = Readonly<{\n command: string;\n data_dir?: string;\n kind: \"server-binary\" | \"server-wrapper\";\n pid: number;\n ppid?: number;\n}>;\n\nexport type ManagedRuntimeDiscovery = Readonly<{\n error?: string;\n processes: ReadonlyArray<ManagedRuntimeProcess>;\n supported: boolean;\n}>;\n\ntype ProcessRow = Readonly<{\n command: string;\n pid: number;\n ppid?: number;\n}>;\n\nexport async function discoverManagedRuntimeProcesses(opts?: {\n readonly timeoutMs?: number;\n}): Promise<ManagedRuntimeDiscovery> {\n if (process.platform === \"win32\") {\n return { supported: false, processes: [], error: \"process sweep is not available on Windows\" };\n }\n\n let rows: ReadonlyArray<ProcessRow>;\n try {\n rows = parsePsRows(await runPs([\"axo\", \"pid=,ppid=,command=\"], opts?.timeoutMs ?? 1000));\n } catch (error) {\n return { supported: false, processes: [], error: errorMessage(error) };\n }\n\n const candidates = rows.filter((row) => isRuntimeCandidate(row.command));\n const hydrated = await Promise.all(\n candidates.map(async (row) => ({\n ...row,\n command: await hydrateCommand(row.pid, row.command, opts?.timeoutMs ?? 1000),\n })),\n );\n const processes = hydrated\n .map(toManagedRuntimeProcess)\n .filter((candidate): candidate is ManagedRuntimeProcess => candidate !== undefined);\n return { supported: true, processes: uniqueByPid(processes) };\n}\n\nfunction runPs(args: string[], timeoutMs: number): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n execFile(\"ps\", args, { timeout: timeoutMs, encoding: \"utf8\" }, (err, stdout) => {\n if (err) {\n reject(err);\n return;\n }\n resolve(stdout);\n });\n });\n}\n\nasync function hydrateCommand(pid: number, fallback: string, timeoutMs: number): Promise<string> {\n try {\n const hydrated = await runPs([\"eww\", \"-p\", String(pid), \"-o\", \"command=\"], timeoutMs);\n return hydrated.trim() || fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction parsePsRows(stdout: string): ReadonlyArray<ProcessRow> {\n const rows: ProcessRow[] = [];\n for (const line of stdout.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) {\n continue;\n }\n const match = trimmed.match(/^(\\d+)\\s+(\\d+)\\s+(.+)$/);\n if (!match) {\n continue;\n }\n rows.push({\n pid: Number(match[1]),\n ppid: Number(match[2]),\n command: match[3] ?? \"\",\n });\n }\n return rows;\n}\n\nfunction toManagedRuntimeProcess(row: ProcessRow): ManagedRuntimeProcess | undefined {\n const dataDir = extractDataDir(row.command);\n const wrapper = isServerWrapper(row.command);\n const binary = isServerBinary(row.command);\n if (!wrapper && !binary) {\n return undefined;\n }\n if (!wrapper && !isCliLocalDataDir(dataDir)) {\n return undefined;\n }\n return {\n pid: row.pid,\n ppid: row.ppid,\n command: stripEnvironmentNoise(row.command),\n kind: wrapper ? \"server-wrapper\" : \"server-binary\",\n ...(dataDir ? { data_dir: dataDir } : {}),\n };\n}\n\nfunction isRuntimeCandidate(command: string): boolean {\n return (\n isServerWrapper(command) ||\n isServerBinary(command) ||\n command.includes(\"NEXTGEN_SERVER_DATA_DIR=\") ||\n basename(command.split(/\\s+/)[0] ?? \"\") === \"nextgen\"\n );\n}\n\nfunction isServerWrapper(command: string): boolean {\n return command.includes(\"zitadel-server.js\");\n}\n\nfunction isServerBinary(command: string): boolean {\n if (/@zitadel\\/server-[^/\\s]+\\/bin\\/nextgen(?:\\.exe)?(?:\\s|$)/.test(command)) {\n return true;\n }\n return (\n isCliLocalDataDir(extractDataDir(command)) &&\n commandTokens(command).some((token) => basename(token) === \"nextgen\")\n );\n}\n\nfunction extractDataDir(command: string): string | undefined {\n const match = command.match(/NEXTGEN_SERVER_DATA_DIR=(\"[^\"]+\"|'[^']+'|[^\\s]+)/);\n const value = match?.[1];\n if (!value) {\n return undefined;\n }\n return value.replace(/^[\"']|[\"']$/g, \"\");\n}\n\nfunction isCliLocalDataDir(path: string | undefined): boolean {\n return Boolean(path && /(?:^|\\/)\\.zitadel\\/local\\/nextgen-data\\/?$/.test(path));\n}\n\nfunction stripEnvironmentNoise(command: string): string {\n return command\n .replace(/(^|\\s)[A-Z_][A-Z0-9_]*=(?:\"[^\"]+\"|'[^']+'|[^\\s]+)/g, \" \")\n .replace(/\\s{2,}/g, \" \")\n .trim();\n}\n\nfunction commandTokens(command: string): string[] {\n return command.split(/\\s+/).filter((token) => !/^[A-Z_][A-Z0-9_]*=/.test(token));\n}\n\nfunction uniqueByPid(\n processes: ReadonlyArray<ManagedRuntimeProcess>,\n): ReadonlyArray<ManagedRuntimeProcess> {\n const byPid = new Map<number, ManagedRuntimeProcess>();\n for (const processInfo of processes) {\n byPid.set(processInfo.pid, processInfo);\n }\n return [...byPid.values()].sort((a, b) => a.pid - b.pid);\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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"}
@@ -1,87 +0,0 @@
1
- import { C as isObject, E as ZitadelError, w as parseJsonObject } from "./oclif-B7lBzh3R.mjs";
2
- import { join } from "node:path";
3
- import { readFile, stat } from "node:fs/promises";
4
- //#region src/lib/project.ts
5
- /**
6
- * Reports whether `cwd` has already been initialized, i.e. a committed
7
- * `zitadel.json` exists. Used to decide whether setup should run or skip.
8
- */
9
- async function hasZitadelConfig(cwd) {
10
- return exists(join(cwd, "zitadel.json"));
11
- }
12
- /**
13
- * Reports whether local secret material (`.zitadel/secret`) is present. Gates
14
- * commands that need credentials, and signals that secrets were already pulled.
15
- */
16
- async function hasZitadelSecret(cwd) {
17
- return exists(join(cwd, ".zitadel/secret"));
18
- }
19
- async function exists(path) {
20
- try {
21
- await stat(path);
22
- return true;
23
- } catch (error) {
24
- if (isNotFound(error)) return false;
25
- throw error;
26
- }
27
- }
28
- /**
29
- * Reads and parses `zitadel.json` into a plain object. Translates a missing
30
- * file into an actionable `E_VALIDATION` error pointing at `zitadel setup`;
31
- * other errors (e.g. malformed JSON) propagate unchanged.
32
- */
33
- async function readZitadelConfig(cwd) {
34
- try {
35
- return parseJsonObject(await readFile(join(cwd, "zitadel.json"), "utf8"), "zitadel.json");
36
- } catch (error) {
37
- if (isNotFound(error)) throw new ZitadelError("E_VALIDATION", "zitadel.json was not found", {
38
- hint: "Run `zitadel setup` first.",
39
- nextCommands: ["zitadel setup"]
40
- });
41
- throw error;
42
- }
43
- }
44
- /**
45
- * Reads, parses, and structurally validates `.zitadel/secret`, returning it
46
- * as a {@link ZitadelSecret}. A missing file becomes an actionable
47
- * `E_VALIDATION` error pointing at `zitadel setup` / `zitadel doctor --fix`;
48
- * a present-but-incomplete file throws so callers never proceed with partial
49
- * credentials.
50
- */
51
- async function readZitadelSecret(cwd) {
52
- try {
53
- const secret = parseJsonObject(await readFile(join(cwd, ".zitadel/secret"), "utf8"), ".zitadel/secret");
54
- if (typeof secret.project_id !== "string" || typeof secret.project_secret !== "string" || typeof secret.preview_secret !== "string" || !Array.isArray(secret.preview_origins)) throw new Error(".zitadel/secret is missing required fields");
55
- return secret;
56
- } catch (error) {
57
- if (isNotFound(error)) throw new ZitadelError("E_VALIDATION", ".zitadel/secret was not found", {
58
- hint: "Run `zitadel setup` first, or restore the project secret with `zitadel doctor --fix`.",
59
- nextCommands: ["zitadel setup", "zitadel doctor --fix"]
60
- });
61
- throw error;
62
- }
63
- }
64
- /**
65
- * Reads the configured renderer id from a parsed `zitadel.json`, normalising the
66
- * legacy `default` alias to `react` and falling back to `react` when unset. The
67
- * value is validated downstream by `getRenderer`, so callers need not re-check.
68
- */
69
- function readRendererId(config) {
70
- const branding = isObject(config.branding) ? config.branding : void 0;
71
- const value = branding && typeof branding.renderer === "string" ? branding.renderer : "react";
72
- return value === "default" ? "react" : value;
73
- }
74
- /** Reads `environments.development.issuer` from a parsed `zitadel.json`, if present. */
75
- function readDevelopmentIssuer(config) {
76
- if (isObject(config.environments) && isObject(config.environments.development)) {
77
- const issuer = config.environments.development.issuer;
78
- return typeof issuer === "string" ? issuer : void 0;
79
- }
80
- }
81
- function isNotFound(error) {
82
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
83
- }
84
- //#endregion
85
- export { readZitadelConfig as a, readRendererId as i, hasZitadelSecret as n, readZitadelSecret as o, readDevelopmentIssuer as r, hasZitadelConfig as t };
86
-
87
- //# sourceMappingURL=project-Cd0L3PtM.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-Cd0L3PtM.mjs","names":[],"sources":["../src/lib/project.ts"],"sourcesContent":["import { readFile, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ZitadelError } from \"./errors\";\nimport { isObject, parseJsonObject } from \"./json\";\n\n/**\n * Reports whether `cwd` has already been initialized, i.e. a committed\n * `zitadel.json` exists. Used to decide whether setup should run or skip.\n */\nexport async function hasZitadelConfig(cwd: string): Promise<boolean> {\n return exists(join(cwd, \"zitadel.json\"));\n}\n\n/**\n * Reports whether local secret material (`.zitadel/secret`) is present. Gates\n * commands that need credentials, and signals that secrets were already pulled.\n */\nexport async function hasZitadelSecret(cwd: string): Promise<boolean> {\n return exists(join(cwd, \".zitadel/secret\"));\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch (error) {\n if (isNotFound(error)) {\n return false;\n }\n throw error;\n }\n}\n\n/**\n * Shape of the project secret persisted at `.zitadel/secret`. Holds the\n * project identity plus the credentials used to talk to the platform in\n * preview and production. Validated structurally by {@link readZitadelSecret}.\n */\nexport type ZitadelSecret = {\n project_id: string;\n project_secret: string;\n preview_secret: string;\n preview_origins: string[];\n created_at: string;\n};\n\n/**\n * Reads and parses `zitadel.json` into a plain object. Translates a missing\n * file into an actionable `E_VALIDATION` error pointing at `zitadel setup`;\n * other errors (e.g. malformed JSON) propagate unchanged.\n */\nexport async function readZitadelConfig(cwd: string): Promise<Record<string, unknown>> {\n try {\n return parseJsonObject(await readFile(join(cwd, \"zitadel.json\"), \"utf8\"), \"zitadel.json\");\n } catch (error) {\n if (isNotFound(error)) {\n throw new ZitadelError(\"E_VALIDATION\", \"zitadel.json was not found\", {\n hint: \"Run `zitadel setup` first.\",\n nextCommands: [\"zitadel setup\"],\n });\n }\n throw error;\n }\n}\n\n/**\n * Reads, parses, and structurally validates `.zitadel/secret`, returning it\n * as a {@link ZitadelSecret}. A missing file becomes an actionable\n * `E_VALIDATION` error pointing at `zitadel setup` / `zitadel doctor --fix`;\n * a present-but-incomplete file throws so callers never proceed with partial\n * credentials.\n */\nexport async function readZitadelSecret(cwd: string): Promise<ZitadelSecret> {\n try {\n const secret = parseJsonObject(\n await readFile(join(cwd, \".zitadel/secret\"), \"utf8\"),\n \".zitadel/secret\",\n );\n if (\n typeof secret.project_id !== \"string\" ||\n typeof secret.project_secret !== \"string\" ||\n typeof secret.preview_secret !== \"string\" ||\n !Array.isArray(secret.preview_origins)\n ) {\n throw new Error(\".zitadel/secret is missing required fields\");\n }\n return secret as ZitadelSecret;\n } catch (error) {\n if (isNotFound(error)) {\n throw new ZitadelError(\"E_VALIDATION\", \".zitadel/secret was not found\", {\n hint: \"Run `zitadel setup` first, or restore the project secret with `zitadel doctor --fix`.\",\n nextCommands: [\"zitadel setup\", \"zitadel doctor --fix\"],\n });\n }\n throw error;\n }\n}\n\n/**\n * Reads the configured renderer id from a parsed `zitadel.json`, normalising the\n * legacy `default` alias to `react` and falling back to `react` when unset. The\n * value is validated downstream by `getRenderer`, so callers need not re-check.\n */\nexport function readRendererId(config: Record<string, unknown>): string {\n const branding = isObject(config.branding) ? config.branding : undefined;\n const value = branding && typeof branding.renderer === \"string\" ? branding.renderer : \"react\";\n return value === \"default\" ? \"react\" : value;\n}\n\n/** Reads `environments.development.issuer` from a parsed `zitadel.json`, if present. */\nexport function readDevelopmentIssuer(config: Record<string, unknown>): string | undefined {\n if (isObject(config.environments) && isObject(config.environments.development)) {\n const issuer = config.environments.development.issuer;\n return typeof issuer === \"string\" ? issuer : undefined;\n }\n return undefined;\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: string }).code === \"ENOENT\"\n );\n}\n"],"mappings":";;;;;;;;AAUA,eAAsB,iBAAiB,KAA+B;AACpE,QAAO,OAAO,KAAK,KAAK,eAAe,CAAC;;;;;;AAO1C,eAAsB,iBAAiB,KAA+B;AACpE,QAAO,OAAO,KAAK,KAAK,kBAAkB,CAAC;;AAG7C,eAAe,OAAO,MAAgC;AACpD,KAAI;AACF,QAAM,KAAK,KAAK;AAChB,SAAO;UACA,OAAO;AACd,MAAI,WAAW,MAAM,CACnB,QAAO;AAET,QAAM;;;;;;;;AAsBV,eAAsB,kBAAkB,KAA+C;AACrF,KAAI;AACF,SAAO,gBAAgB,MAAM,SAAS,KAAK,KAAK,eAAe,EAAE,OAAO,EAAE,eAAe;UAClF,OAAO;AACd,MAAI,WAAW,MAAM,CACnB,OAAM,IAAI,aAAa,gBAAgB,8BAA8B;GACnE,MAAM;GACN,cAAc,CAAC,gBAAgB;GAChC,CAAC;AAEJ,QAAM;;;;;;;;;;AAWV,eAAsB,kBAAkB,KAAqC;AAC3E,KAAI;EACF,MAAM,SAAS,gBACb,MAAM,SAAS,KAAK,KAAK,kBAAkB,EAAE,OAAO,EACpD,kBACD;AACD,MACE,OAAO,OAAO,eAAe,YAC7B,OAAO,OAAO,mBAAmB,YACjC,OAAO,OAAO,mBAAmB,YACjC,CAAC,MAAM,QAAQ,OAAO,gBAAgB,CAEtC,OAAM,IAAI,MAAM,6CAA6C;AAE/D,SAAO;UACA,OAAO;AACd,MAAI,WAAW,MAAM,CACnB,OAAM,IAAI,aAAa,gBAAgB,iCAAiC;GACtE,MAAM;GACN,cAAc,CAAC,iBAAiB,uBAAuB;GACxD,CAAC;AAEJ,QAAM;;;;;;;;AASV,SAAgB,eAAe,QAAyC;CACtE,MAAM,WAAW,SAAS,OAAO,SAAS,GAAG,OAAO,WAAW,KAAA;CAC/D,MAAM,QAAQ,YAAY,OAAO,SAAS,aAAa,WAAW,SAAS,WAAW;AACtF,QAAO,UAAU,YAAY,UAAU;;;AAIzC,SAAgB,sBAAsB,QAAqD;AACzF,KAAI,SAAS,OAAO,aAAa,IAAI,SAAS,OAAO,aAAa,YAAY,EAAE;EAC9E,MAAM,SAAS,OAAO,aAAa,YAAY;AAC/C,SAAO,OAAO,WAAW,WAAW,SAAS,KAAA;;;AAKjD,SAAS,WAAW,OAAyB;AAC3C,QACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAA4B,SAAS"}