@zitadel/cli 0.1.0-alpha.18 → 0.1.0-alpha.19
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 +81 -33
- package/SKILLS.md +74 -8
- package/dist/{branding-BXj028-W.mjs → branding-cygSBPkV.mjs} +2 -2
- package/dist/{branding-BXj028-W.mjs.map → branding-cygSBPkV.mjs.map} +1 -1
- package/dist/{claim-state-BTGInAaN.mjs → claim-state-DlfD6Res.mjs} +2 -2
- package/dist/{claim-state-BTGInAaN.mjs.map → claim-state-DlfD6Res.mjs.map} +1 -1
- package/dist/commands/apply.mjs +4 -4
- package/dist/commands/branding/eject.mjs +11 -32
- package/dist/commands/branding/eject.mjs.map +1 -1
- package/dist/commands/claim.mjs +3 -3
- package/dist/commands/doctor.mjs +41 -18
- package/dist/commands/doctor.mjs.map +1 -1
- package/dist/commands/eject.mjs +4 -4
- package/dist/commands/eject.mjs.map +1 -1
- package/dist/commands/logs.mjs +2 -2
- package/dist/commands/plan.mjs +4 -4
- package/dist/commands/reset.mjs +2 -2
- package/dist/commands/schemas/list.mjs +6 -6
- package/dist/commands/schemas/list.mjs.map +1 -1
- package/dist/commands/setup.mjs +101 -143
- package/dist/commands/setup.mjs.map +1 -1
- package/dist/commands/start.mjs +3 -3
- package/dist/commands/status.mjs +5 -5
- package/dist/commands/stop.mjs +3 -3
- package/dist/designs-Ckz18Dpo.mjs +38 -0
- package/dist/designs-Ckz18Dpo.mjs.map +1 -0
- package/dist/{docker-Ciz9N6uI.mjs → docker-DcRGTOJa.mjs} +4 -3
- package/dist/docker-DcRGTOJa.mjs.map +1 -0
- package/dist/{environment-CuHKxtIO.mjs → environment-rjRVkJjW.mjs} +1 -1
- package/dist/{environment-CuHKxtIO.mjs.map → environment-rjRVkJjW.mjs.map} +1 -1
- package/dist/{journey-guidance-CtQUfWar.mjs → journey-guidance-BGrOX_gT.mjs} +2 -2
- package/dist/{journey-guidance-CtQUfWar.mjs.map → journey-guidance-BGrOX_gT.mjs.map} +1 -1
- package/dist/{oclif-CL6-M13m.mjs → oclif-CanO3zdt.mjs} +48 -2
- package/dist/oclif-CanO3zdt.mjs.map +1 -0
- package/dist/{orca-BWB4zOdw.mjs → orca-Cu0iW1mv.mjs} +167 -26
- package/dist/orca-Cu0iW1mv.mjs.map +1 -0
- package/dist/package-manager-DFdLcDx1.mjs +194 -0
- package/dist/package-manager-DFdLcDx1.mjs.map +1 -0
- package/dist/{ports-Cu2Y7aXQ.mjs → ports-BM20XIZb.mjs} +2 -2
- package/dist/{ports-Cu2Y7aXQ.mjs.map → ports-BM20XIZb.mjs.map} +1 -1
- package/dist/{processes-Bn2WngOi.mjs → processes-DKHPkU8O.mjs} +1 -1
- package/dist/{processes-Bn2WngOi.mjs.map → processes-DKHPkU8O.mjs.map} +1 -1
- package/dist/{project-yejJSfdJ.mjs → project-CHhot85s.mjs} +2 -2
- package/dist/{project-yejJSfdJ.mjs.map → project-CHhot85s.mjs.map} +1 -1
- package/dist/{sync-Cx2_4rXW.mjs → sync-Bd6vASgg.mjs} +456 -31
- package/dist/sync-Bd6vASgg.mjs.map +1 -0
- package/dist/{user-schema-W1OsXdpc.mjs → user-schema-DTuOsdKE.mjs} +1 -1
- package/dist/{user-schema-W1OsXdpc.mjs.map → user-schema-DTuOsdKE.mjs.map} +1 -1
- package/oclif.manifest.json +2 -2
- package/package.json +6 -5
- package/dist/docker-Ciz9N6uI.mjs.map +0 -1
- package/dist/oclif-CL6-M13m.mjs.map +0 -1
- package/dist/orca-BWB4zOdw.mjs.map +0 -1
- package/dist/scaffold-manifest-CKNFLX9T.mjs +0 -81
- package/dist/scaffold-manifest-CKNFLX9T.mjs.map +0 -1
- package/dist/sync-Cx2_4rXW.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.mjs","names":[],"sources":["../../../src/commands/schemas/list.ts"],"sourcesContent":["import { cancel, isCancel, select, spinner } from \"@clack/prompts\";\nimport { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient, type ZitadelClient } from \"@zitadel/api/client\";\nimport type { ListSchemas200Item } from \"@zitadel/api/generated/model\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../../lib/oclif\";\nimport { environmentSchema } from \"../../lib/environment\";\nimport { readZitadelSecret } from \"../../lib/project\";\n\n/**\n * The `schemas list` topic command — inspect the revision history of a\n * user-schema, filtered by `objectType`.\n *\n * Non-interactive: prints one row per revision (newest first) as a JSON payload\n * or a plain-text table. Interactive: renders a `@clack/prompts` `select` menu\n * of the same rows; on selection, fetches the full schema body via\n * `getSchemaById` and pretty-prints it to stdout.\n */\nexport default class SchemasList extends BaseCommand {\n static override description = \"List revisions of a user-schema by objectType.\";\n static override flags = {\n \"object-type\": Flags.string({\n char: \"t\",\n required: true,\n description: \"Filter revisions by objectType (e.g. human-user).\",\n }),\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(SchemasList);\n await this.toMeta(flags);\n const { cwd, source, nonInteractive } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n\n const objectType = flags[\"object-type\"];\n const revisions = await client.listSchemas({\n project_id: secret.project_id,\n object_type: objectType,\n });\n\n // The envelope's row shape is a contract; project it explicitly so a field\n // added to the API later cannot leak into stdout.\n const revisionRows = revisions.map((r) => ({ id: r.id, created_at: r.created_at }));\n\n if (revisions.length === 0) {\n const message = `No revisions found for objectType \"${objectType}\".`;\n consola.warn(message);\n return this.emit({\n status: \"ok\",\n data: { object_type: objectType, revisions: [], count: 0 },\n pretty: message,\n });\n }\n\n // Server orders newest-first; the interactive picker inherits that order.\n if (nonInteractive) {\n return this.emit({\n status: \"ok\",\n data: {\n object_type: objectType,\n revisions: revisionRows,\n count: revisions.length,\n },\n pretty: renderTable(objectType, revisions),\n });\n }\n\n const picked = await select({\n message: `Revisions of objectType \"${objectType}\" (newest first)`,\n options: revisions.map((r, idx) => ({\n value: r.id,\n label: `${r.created_at} ${r.id}${idx === 0 ? \" (latest)\" : \"\"}`,\n })),\n });\n if (isCancel(picked)) {\n cancel(\"No revision selected.\");\n return this.emit({\n status: \"ok\",\n data: { object_type: objectType, revisions: revisionRows, count: revisions.length },\n pretty: \"\",\n });\n }\n\n const s = spinner();\n s.start(`Loading ${String(picked)}…`);\n const body = await fetchSchemaRevision(client, String(picked)
|
|
1
|
+
{"version":3,"file":"list.mjs","names":[],"sources":["../../../src/commands/schemas/list.ts"],"sourcesContent":["import { cancel, isCancel, select, spinner } from \"@clack/prompts\";\nimport { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient, type ZitadelClient } from \"@zitadel/api/client\";\nimport type { ListSchemas200Item } from \"@zitadel/api/generated/model\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../../lib/oclif\";\nimport { environmentSchema } from \"../../lib/environment\";\nimport { readZitadelSecret } from \"../../lib/project\";\n\n/**\n * The `schemas list` topic command — inspect the revision history of a\n * user-schema, filtered by `objectType`.\n *\n * Non-interactive: prints one row per revision (newest first) as a JSON payload\n * or a plain-text table. Interactive: renders a `@clack/prompts` `select` menu\n * of the same rows; on selection, fetches the full schema body via\n * `getSchemaById` and pretty-prints it to stdout.\n */\nexport default class SchemasList extends BaseCommand {\n static override description = \"List revisions of a user-schema by objectType.\";\n static override flags = {\n \"object-type\": Flags.string({\n char: \"t\",\n required: true,\n description: \"Filter revisions by objectType (e.g. human-user).\",\n }),\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(SchemasList);\n await this.toMeta(flags);\n const { cwd, source, nonInteractive } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n\n const objectType = flags[\"object-type\"];\n const revisions = await client.listSchemas({\n project_id: secret.project_id,\n object_type: objectType,\n });\n\n // The envelope's row shape is a contract; project it explicitly so a field\n // added to the API later cannot leak into stdout.\n const revisionRows = revisions.map((r) => ({ id: r.id, created_at: r.created_at }));\n\n if (revisions.length === 0) {\n const message = `No revisions found for objectType \"${objectType}\".`;\n consola.warn(message);\n return this.emit({\n status: \"ok\",\n data: { object_type: objectType, revisions: [], count: 0 },\n pretty: message,\n });\n }\n\n // Server orders newest-first; the interactive picker inherits that order.\n if (nonInteractive) {\n return this.emit({\n status: \"ok\",\n data: {\n object_type: objectType,\n revisions: revisionRows,\n count: revisions.length,\n },\n pretty: renderTable(objectType, revisions),\n });\n }\n\n const picked = await select({\n message: `Revisions of objectType \"${objectType}\" (newest first)`,\n options: revisions.map((r, idx) => ({\n value: r.id,\n label: `${r.created_at} ${r.id}${idx === 0 ? \" (latest)\" : \"\"}`,\n })),\n });\n if (isCancel(picked)) {\n cancel(\"No revision selected.\");\n return this.emit({\n status: \"ok\",\n data: { object_type: objectType, revisions: revisionRows, count: revisions.length },\n pretty: \"\",\n });\n }\n\n const s = spinner();\n s.start(`Loading ${String(picked)}…`);\n const body = await fetchSchemaRevision(client, String(picked));\n s.stop(`Loaded ${String(picked)}`);\n\n const pretty = JSON.stringify(body, null, 2);\n\n return this.emit({\n status: \"ok\",\n data: {\n object_type: objectType,\n revisions: revisionRows,\n selected: { id: picked, body },\n count: revisions.length,\n },\n pretty,\n });\n }\n}\n\n/**\n * Fetch one schema revision body. The id is URL-encoded before it lands in\n * the path: server-allocated ids are opaque today (`sch_…`), but ids can be\n * full URLs when a schema carried an `$id` (the server-seeded defaults do),\n * and an unencoded URL would break the `/schemas/:id` path. Mirrors the\n * encoding the sync engine's schema syncer applies.\n */\nexport async function fetchSchemaRevision(client: ZitadelClient, id: string): Promise<unknown> {\n // Flat-by-id: authz resolves the project from RSI; no project_id query.\n return client.getSchemaById(encodeURIComponent(id));\n}\n\nfunction renderTable(objectType: string, revisions: ReadonlyArray<ListSchemas200Item>): string {\n const header = `Revisions of objectType \"${objectType}\" (${revisions.length}, newest first)`;\n const idCol = Math.max(\"id\".length, ...revisions.map((r) => r.id.length));\n const createdCol = Math.max(\"created_at\".length, ...revisions.map((r) => r.created_at.length));\n const rows = revisions.map(\n (r) => `${r.created_at.padEnd(createdCol)} ${r.id.padEnd(idCol)}`,\n );\n return [\n header,\n `${\"created_at\".padEnd(createdCol)} ${\"id\".padEnd(idCol)}`,\n `${\"-\".repeat(createdCol)} ${\"-\".repeat(idCol)}`,\n ...rows,\n ].join(\"\\n\");\n}\n"],"mappings":"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"}
|
package/dist/commands/setup.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { n as
|
|
4
|
-
import {
|
|
5
|
-
import { n as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { i as
|
|
9
|
-
import {
|
|
1
|
+
import { n as brandingDesignLabel, t as BRANDING_DESIGN_INFO } from "../designs-Ckz18Dpo.mjs";
|
|
2
|
+
import { D as toZitadelError, E as ZitadelError, T as stableStringify, j as publicCliCommand, k as normalizePublicCliProse, n as DEFAULT_SERVER, t as BaseCommand, u as detectHealthyLocalServer } from "../oclif-CanO3zdt.mjs";
|
|
3
|
+
import { n as claimCommand, r as claimState, t as claimAction } from "../claim-state-DlfD6Res.mjs";
|
|
4
|
+
import { n as customizeAndPublishActions, r as verifyLoginAction, t as brandingGuidanceAction } from "../journey-guidance-BGrOX_gT.mjs";
|
|
5
|
+
import { i as RENDERER_IDS, n as inspectScaffoldTarget, r as AVAILABLE_RENDERER_IDS, s as issuerFromPort, t as createOrca } from "../orca-Cu0iW1mv.mjs";
|
|
6
|
+
import { n as hasZitadelSecret, t as hasZitadelConfig } from "../project-CHhot85s.mjs";
|
|
7
|
+
import { a as updateState, t as SCHEMAS_DIR } from "../user-schema-DTuOsdKE.mjs";
|
|
8
|
+
import { a as runPackageCommand, c as writeScaffoldManifest, i as installCommandFor, n as detectPackageManager, r as devCommandFor } from "../package-manager-DFdLcDx1.mjs";
|
|
9
|
+
import { i as toBrandingWireBody, t as BRANDING_DIR } from "../branding-cygSBPkV.mjs";
|
|
10
|
+
import { c as writeBackResource, o as hashForState, u as FLOWS_DIR } from "../sync-Bd6vASgg.mjs";
|
|
10
11
|
import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
11
12
|
import { basename, dirname, join } from "node:path";
|
|
12
13
|
import { cancel, confirm, intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
|
|
@@ -15,7 +16,6 @@ import { createZitadelClient } from "@zitadel/api/client";
|
|
|
15
16
|
import { BRANDING_DESIGNS, DEFAULT_BRANDING_CONFIG_PATH, DEFAULT_BRANDING_TEMPLATE_PATH, DEFAULT_FLOW_CONFIG_PATH, DEFAULT_FLOW_SCHEMA_URI, DEFAULT_SCHEMA_CONFIG_PATH, DEFAULT_SETUP_PRESET, DEFAULT_SETUP_USE_CASE, SETUP_PRESETS, SETUP_USE_CASES, brandingReadmeContent, flowsReadmeContent, getDefaultBrandingConfig, getDefaultHumanUserSchema, getDefaultLoginFlow, schemasReadmeContent } from "@zitadel/config/defaults";
|
|
16
17
|
import { consola as consola$1 } from "consola";
|
|
17
18
|
import { BRANDING_FILE_SCHEMA_REF } from "@zitadel/config/meta-schemas";
|
|
18
|
-
import { spawn } from "node:child_process";
|
|
19
19
|
import { normalizeFlowBody, normalizeSchemaBody } from "@zitadel/config/normalize";
|
|
20
20
|
import pc from "picocolors";
|
|
21
21
|
//#region src/lib/orca/patchers/posture.ts
|
|
@@ -72,7 +72,7 @@ async function materializeSetupResources(opts) {
|
|
|
72
72
|
const schemaId = requiredString((await opts.client.createSchema(schemaBody, { project_id: opts.projectId })).id, "created schema id");
|
|
73
73
|
let schemaHash = hashForState({ normalize: normalizeSchemaBody }, schemaBody);
|
|
74
74
|
try {
|
|
75
|
-
const canonical = await opts.client.getSchemaById(encodeURIComponent(schemaId)
|
|
75
|
+
const canonical = await opts.client.getSchemaById(encodeURIComponent(schemaId));
|
|
76
76
|
schemaHash = (await writeBackResource(opts.cwd, DEFAULT_SCHEMA_CONFIG_PATH, { normalize: normalizeSchemaBody }, canonical)).hash;
|
|
77
77
|
} catch (err) {
|
|
78
78
|
consola$1.debug(`fetch created schema ${schemaId} during setup failed:`, err);
|
|
@@ -119,12 +119,12 @@ async function materializeSetupResources(opts) {
|
|
|
119
119
|
hash: hashForState({ normalize: brandingNormalize }, descriptor)
|
|
120
120
|
});
|
|
121
121
|
const brandingReadme = join(BRANDING_DIR, "README.md");
|
|
122
|
-
if (await writeReadmeFile(opts.cwd, brandingReadme, brandingReadmeContent())) filesWritten.push(join(opts.cwd, brandingReadme));
|
|
122
|
+
if (await writeReadmeFile(opts.cwd, brandingReadme, normalizePublicCliProse(brandingReadmeContent(), opts.cliVersion))) filesWritten.push(join(opts.cwd, brandingReadme));
|
|
123
123
|
}
|
|
124
124
|
const schemasReadme = join(SCHEMAS_DIR, "README.md");
|
|
125
125
|
const flowsReadme = join(FLOWS_DIR, "README.md");
|
|
126
|
-
if (await writeReadmeFile(opts.cwd, schemasReadme, schemasReadmeContent())) filesWritten.push(join(opts.cwd, schemasReadme));
|
|
127
|
-
if (await writeReadmeFile(opts.cwd, flowsReadme, flowsReadmeContent())) filesWritten.push(join(opts.cwd, flowsReadme));
|
|
126
|
+
if (await writeReadmeFile(opts.cwd, schemasReadme, normalizePublicCliProse(schemasReadmeContent(), opts.cliVersion))) filesWritten.push(join(opts.cwd, schemasReadme));
|
|
127
|
+
if (await writeReadmeFile(opts.cwd, flowsReadme, normalizePublicCliProse(flowsReadmeContent(), opts.cliVersion))) filesWritten.push(join(opts.cwd, flowsReadme));
|
|
128
128
|
return { filesWritten };
|
|
129
129
|
}
|
|
130
130
|
/**
|
|
@@ -177,88 +177,6 @@ function isErrno(error, code) {
|
|
|
177
177
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
178
178
|
}
|
|
179
179
|
//#endregion
|
|
180
|
-
//#region src/lib/package-manager.ts
|
|
181
|
-
async function detectPackageManager(cwd) {
|
|
182
|
-
const declared = await packageManagerFromManifest(cwd);
|
|
183
|
-
if (declared) return declared;
|
|
184
|
-
if (await exists(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
185
|
-
if (await exists(join(cwd, "yarn.lock"))) return "yarn";
|
|
186
|
-
if (await exists(join(cwd, "bun.lock"))) return "bun";
|
|
187
|
-
if (await exists(join(cwd, "bun.lockb"))) return "bun";
|
|
188
|
-
if (await exists(join(cwd, "package-lock.json"))) return "npm";
|
|
189
|
-
return "npm";
|
|
190
|
-
}
|
|
191
|
-
function installCommandFor(packageManager) {
|
|
192
|
-
return command(packageManager, ["install"]);
|
|
193
|
-
}
|
|
194
|
-
function devCommandFor(packageManager) {
|
|
195
|
-
switch (packageManager) {
|
|
196
|
-
case "npm": return command("npm", ["run", "dev"]);
|
|
197
|
-
case "pnpm": return command("pnpm", ["dev"]);
|
|
198
|
-
case "yarn": return command("yarn", ["dev"]);
|
|
199
|
-
case "bun": return command("bun", ["run", "dev"]);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
async function runPackageCommand(packageCommand, options) {
|
|
203
|
-
await new Promise((resolve, reject) => {
|
|
204
|
-
const child = spawn(packageCommand.command, packageCommand.args, {
|
|
205
|
-
cwd: options.cwd,
|
|
206
|
-
env: options.env ?? process.env,
|
|
207
|
-
stdio: options.redirectStdoutToStderr ? [
|
|
208
|
-
"ignore",
|
|
209
|
-
"pipe",
|
|
210
|
-
"pipe"
|
|
211
|
-
] : "inherit"
|
|
212
|
-
});
|
|
213
|
-
if (options.redirectStdoutToStderr) {
|
|
214
|
-
child.stdout?.on("data", (chunk) => process.stderr.write(chunk));
|
|
215
|
-
child.stderr?.on("data", (chunk) => process.stderr.write(chunk));
|
|
216
|
-
}
|
|
217
|
-
child.on("error", reject);
|
|
218
|
-
child.on("close", (code, signal) => {
|
|
219
|
-
if (code === 0) {
|
|
220
|
-
resolve();
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
const detail = signal ? `signal ${signal}` : `exit ${String(code ?? 1)}`;
|
|
224
|
-
const error = /* @__PURE__ */ new Error(`${packageCommand.display} failed with ${detail}`);
|
|
225
|
-
Object.assign(error, {
|
|
226
|
-
code: code ?? 1,
|
|
227
|
-
signal
|
|
228
|
-
});
|
|
229
|
-
reject(error);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
function command(packageManager, args) {
|
|
234
|
-
return {
|
|
235
|
-
command: packageManager,
|
|
236
|
-
args,
|
|
237
|
-
display: [packageManager, ...args].join(" ")
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
async function packageManagerFromManifest(cwd) {
|
|
241
|
-
try {
|
|
242
|
-
const raw = await readFile(join(cwd, "package.json"), "utf8");
|
|
243
|
-
const parsed = JSON.parse(raw);
|
|
244
|
-
return typeof parsed.packageManager === "string" ? packageManagerFromString(parsed.packageManager) : void 0;
|
|
245
|
-
} catch {
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
function packageManagerFromString(value) {
|
|
250
|
-
const name = value.split("@")[0];
|
|
251
|
-
return name === "npm" || name === "pnpm" || name === "yarn" || name === "bun" ? name : void 0;
|
|
252
|
-
}
|
|
253
|
-
async function exists(path) {
|
|
254
|
-
try {
|
|
255
|
-
await stat(path);
|
|
256
|
-
return true;
|
|
257
|
-
} catch {
|
|
258
|
-
return false;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
//#endregion
|
|
262
180
|
//#region src/commands/setup/install.ts
|
|
263
181
|
async function installDependenciesForSetup(input) {
|
|
264
182
|
const packageManager = await detectPackageManager(input.cwd);
|
|
@@ -391,38 +309,15 @@ var DesignPrompt = class {
|
|
|
391
309
|
const value = await select({
|
|
392
310
|
message: "How should the login look? A starter design adds its editable template to .zitadel/branding/.",
|
|
393
311
|
initialValue: answers.design ?? BUILT_IN,
|
|
394
|
-
options: [
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
hint: "card centred on the page"
|
|
404
|
-
},
|
|
405
|
-
{
|
|
406
|
-
value: "split",
|
|
407
|
-
label: "Split",
|
|
408
|
-
hint: "brand panel left, form right"
|
|
409
|
-
},
|
|
410
|
-
{
|
|
411
|
-
value: "split-right",
|
|
412
|
-
label: "Split (reversed)",
|
|
413
|
-
hint: "form left, brand panel right"
|
|
414
|
-
},
|
|
415
|
-
{
|
|
416
|
-
value: "hero",
|
|
417
|
-
label: "Hero",
|
|
418
|
-
hint: "landing-style brand pane left, form right"
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
value: "minimal",
|
|
422
|
-
label: "Minimal",
|
|
423
|
-
hint: "no card chrome, fields straight on the page"
|
|
424
|
-
}
|
|
425
|
-
]
|
|
312
|
+
options: [{
|
|
313
|
+
value: BUILT_IN,
|
|
314
|
+
label: "Built-in",
|
|
315
|
+
hint: "no files added; pick a design anytime later with `branding eject`"
|
|
316
|
+
}, ...BRANDING_DESIGNS.map((design) => ({
|
|
317
|
+
value: design,
|
|
318
|
+
label: BRANDING_DESIGN_INFO[design].label,
|
|
319
|
+
hint: BRANDING_DESIGN_INFO[design].hint
|
|
320
|
+
}))]
|
|
426
321
|
});
|
|
427
322
|
bail(value);
|
|
428
323
|
if (value === BUILT_IN) return {
|
|
@@ -675,6 +570,16 @@ const SETUP_PROMPTS = [
|
|
|
675
570
|
//#endregion
|
|
676
571
|
//#region src/commands/setup/summary.ts
|
|
677
572
|
/**
|
|
573
|
+
* Renders a path under `cwd` with stable POSIX separators. Setup's summary
|
|
574
|
+
* matches generated artifacts against repository-style suffixes such as
|
|
575
|
+
* `.zitadel/schemas/default-human-user.json`; normalizing here keeps those
|
|
576
|
+
* matches working when Node returns Windows paths with backslashes.
|
|
577
|
+
*/
|
|
578
|
+
function relativeDisplayPath(cwd, absolute) {
|
|
579
|
+
const boundary = absolute[cwd.length];
|
|
580
|
+
return (absolute.startsWith(cwd) && (boundary === "/" || boundary === "\\") ? absolute.slice(cwd.length + 1) : absolute).replaceAll("\\", "/");
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
678
583
|
* Renders the section list as a single multi-line string. Labels are
|
|
679
584
|
* padded to a common width per section so the `✓ label value` columns
|
|
680
585
|
* line up, the title prints in dim gray, and `✓` is green. Values come
|
|
@@ -765,6 +670,29 @@ function stripRange(range) {
|
|
|
765
670
|
function fileNameOf(p) {
|
|
766
671
|
return basename(p);
|
|
767
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Layout caveats for the chosen login design, shown to humans after the
|
|
675
|
+
* summary box and carried in the JSON envelope's `warnings`.
|
|
676
|
+
*
|
|
677
|
+
* The split family's brand pane is keyed to the **login's own container**
|
|
678
|
+
* width — a `@container (max-width: 48rem)` query on the widget's mount, not
|
|
679
|
+
* a viewport media query. Above that the pane renders; below it the pane is
|
|
680
|
+
* `display: none` and the compact brand mark takes its place — and the split
|
|
681
|
+
* template only emits that mark when `branding.json` names `logo_url` or
|
|
682
|
+
* `hero_url`, so without one the narrow layout loses the branding entirely.
|
|
683
|
+
*
|
|
684
|
+
* Independent of posture, because the container query is: a full-page login
|
|
685
|
+
* hits the same collapse on a phone that an embedded card hits in a sidebar.
|
|
686
|
+
* Gating on `widget` would have been a guess about the container, and a wrong
|
|
687
|
+
* one in both directions — the wrapper setup scaffolds for a widget is
|
|
688
|
+
* full-width (the pane renders there), and a page-posture login on a phone is
|
|
689
|
+
* exactly the narrow case the advice is for. `hero` stays quiet: its compact
|
|
690
|
+
* fallback is editable text, so a narrow container never leaves it blank.
|
|
691
|
+
*/
|
|
692
|
+
function designWarnings(design) {
|
|
693
|
+
if (design !== "split" && design !== "split-right") return [];
|
|
694
|
+
return [`The ${design} design shows its brand pane only when the login's container is wide; a narrow container — a card-width embed, or any phone-width viewport — collapses it to the compact brand mark. Set logo_url (or hero_url) in .zitadel/branding/branding.json so that mark isn't empty.`];
|
|
695
|
+
}
|
|
768
696
|
//#endregion
|
|
769
697
|
//#region src/commands/setup/index.ts
|
|
770
698
|
/**
|
|
@@ -819,7 +747,7 @@ var Setup = class Setup extends BaseCommand {
|
|
|
819
747
|
options: [...SETUP_USE_CASES]
|
|
820
748
|
}),
|
|
821
749
|
design: Flags.string({
|
|
822
|
-
description: "Login design to eject into .zitadel/branding/ and publish as branding revision 1. Skips the wizard's design question. When omitted in non-interactive runs, the login uses the built-in template; run the `branding eject` command later to customize.",
|
|
750
|
+
description: "Login design to eject into .zitadel/branding/ and publish as branding revision 1. Skips the wizard's design question. When omitted in non-interactive runs, the login uses the built-in template; run the `branding eject` command later to customize. Split-family designs (split, split-right, hero) collapse their brand pane by container width: narrow containers — including widget-posture embeds at card width — render the compact brand mark instead (logo_url, else hero_url, from .zitadel/branding/branding.json; hero falls back to editable text).",
|
|
823
751
|
options: [...BRANDING_DESIGNS]
|
|
824
752
|
})
|
|
825
753
|
};
|
|
@@ -938,10 +866,10 @@ var Setup = class Setup extends BaseCommand {
|
|
|
938
866
|
force
|
|
939
867
|
});
|
|
940
868
|
for (const file of result.filesWritten) {
|
|
941
|
-
const sentence = describeWrittenFile(
|
|
869
|
+
const sentence = describeWrittenFile(relativeDisplayPath(cwd, file), dryRun);
|
|
942
870
|
if (sentence) consola$1.info(sentence);
|
|
943
871
|
}
|
|
944
|
-
for (const file of result.filesSkipped) consola$1.info(`Left ${
|
|
872
|
+
for (const file of result.filesSkipped) consola$1.info(`Left ${relativeDisplayPath(cwd, file)} unchanged (already matches target)`);
|
|
945
873
|
let resourceResult;
|
|
946
874
|
try {
|
|
947
875
|
resourceResult = dryRun ? { filesWritten: [] } : await materializeSetupResources({
|
|
@@ -954,7 +882,8 @@ var Setup = class Setup extends BaseCommand {
|
|
|
954
882
|
force,
|
|
955
883
|
preset: answers.preset,
|
|
956
884
|
useCase: answers.useCase,
|
|
957
|
-
design: answers.design
|
|
885
|
+
design: answers.design,
|
|
886
|
+
cliVersion: this.meta.cliVersion
|
|
958
887
|
});
|
|
959
888
|
} catch (error) {
|
|
960
889
|
await rm(join(cwd, "zitadel.json"), { force: true });
|
|
@@ -967,7 +896,7 @@ var Setup = class Setup extends BaseCommand {
|
|
|
967
896
|
});
|
|
968
897
|
}
|
|
969
898
|
for (const file of resourceResult.filesWritten) {
|
|
970
|
-
const sentence = describeWrittenFile(
|
|
899
|
+
const sentence = describeWrittenFile(relativeDisplayPath(cwd, file), dryRun);
|
|
971
900
|
if (sentence) consola$1.info(sentence);
|
|
972
901
|
}
|
|
973
902
|
const allFilesWritten = [...result.filesWritten, ...resourceResult.filesWritten];
|
|
@@ -1006,7 +935,7 @@ var Setup = class Setup extends BaseCommand {
|
|
|
1006
935
|
step: "dependencies_installed",
|
|
1007
936
|
package_manager: installOutcome.install.package_manager
|
|
1008
937
|
});
|
|
1009
|
-
const writtenRel = allFilesWritten.map((file) =>
|
|
938
|
+
const writtenRel = allFilesWritten.map((file) => relativeDisplayPath(cwd, file));
|
|
1010
939
|
const claimNudge = claimState({
|
|
1011
940
|
secret: {},
|
|
1012
941
|
server: answers.server
|
|
@@ -1017,6 +946,7 @@ var Setup = class Setup extends BaseCommand {
|
|
|
1017
946
|
actions: [],
|
|
1018
947
|
commands: []
|
|
1019
948
|
};
|
|
949
|
+
const warnings = designWarnings(answers.design);
|
|
1020
950
|
if (!this.jsonEnabled()) {
|
|
1021
951
|
const sections = buildSummary({
|
|
1022
952
|
projectFacts: await detectProjectFacts(cwd, framework.id),
|
|
@@ -1040,9 +970,11 @@ var Setup = class Setup extends BaseCommand {
|
|
|
1040
970
|
borderColor: "green"
|
|
1041
971
|
}
|
|
1042
972
|
});
|
|
973
|
+
for (const warning of warnings) consola$1.warn(warning);
|
|
1043
974
|
}
|
|
1044
975
|
return this.emit({
|
|
1045
976
|
status: "ok",
|
|
977
|
+
warnings,
|
|
1046
978
|
pretty: "",
|
|
1047
979
|
data: {
|
|
1048
980
|
title: "Zitadel is ready.",
|
|
@@ -1052,13 +984,13 @@ var Setup = class Setup extends BaseCommand {
|
|
|
1052
984
|
},
|
|
1053
985
|
framework: framework.id,
|
|
1054
986
|
server: answers.server,
|
|
1055
|
-
files_written: allFilesWritten.map((file) =>
|
|
987
|
+
files_written: allFilesWritten.map((file) => relativeDisplayPath(cwd, file)),
|
|
1056
988
|
files: result.files.map((file) => ({
|
|
1057
|
-
path:
|
|
989
|
+
path: relativeDisplayPath(cwd, file.path),
|
|
1058
990
|
kind: file.kind,
|
|
1059
991
|
action: file.action
|
|
1060
992
|
})),
|
|
1061
|
-
files_skipped: result.filesSkipped.map((file) =>
|
|
993
|
+
files_skipped: result.filesSkipped.map((file) => relativeDisplayPath(cwd, file)),
|
|
1062
994
|
install: installOutcome.install,
|
|
1063
995
|
design: answers.design ?? null,
|
|
1064
996
|
next_actions: [
|
|
@@ -1169,10 +1101,6 @@ function localSetupHint(error, retry, cliVersion) {
|
|
|
1169
1101
|
details: normalized.details
|
|
1170
1102
|
});
|
|
1171
1103
|
}
|
|
1172
|
-
/** Renders an absolute path relative to `cwd` for human-readable output. */
|
|
1173
|
-
function relativeDisplay(cwd, path) {
|
|
1174
|
-
return path.startsWith(cwd) ? path.slice(cwd.length + 1) : path;
|
|
1175
|
-
}
|
|
1176
1104
|
/**
|
|
1177
1105
|
* Replaces the user's `$HOME` with `~` in a path for compact terminal output.
|
|
1178
1106
|
* Falls back to the raw path when `HOME` isn't set or doesn't match.
|
|
@@ -1225,6 +1153,10 @@ const SENTENCE_BY_PATH = {
|
|
|
1225
1153
|
".zitadel/meta/flow-definition.json": { subject: "the flow dialect spec (editor $schema)" },
|
|
1226
1154
|
".zitadel/meta/user-schema.json": { subject: "the user-schema dialect spec" },
|
|
1227
1155
|
".zitadel/meta/user-property.json": { subject: "the user-property dialect spec" },
|
|
1156
|
+
".zitadel/meta/branding.json": { subject: "the branding dialect spec" },
|
|
1157
|
+
".zitadel/branding/branding.json": { subject: "the branding descriptor (layout + asset URLs)" },
|
|
1158
|
+
".zitadel/branding/login.liquid": { subject: "the editable login template" },
|
|
1159
|
+
".zitadel/branding/README.md": { subject: "the branding folder README" },
|
|
1228
1160
|
"AGENTS.md": { subject: "the agent guidance (golden journey + config dialect)" },
|
|
1229
1161
|
"README.md": { subject: "the README's Zitadel section" },
|
|
1230
1162
|
"app/page.tsx": { subject: "the home page redirect" },
|
|
@@ -1270,6 +1202,28 @@ function buildSummary(opts) {
|
|
|
1270
1202
|
value: path(hit)
|
|
1271
1203
|
});
|
|
1272
1204
|
}
|
|
1205
|
+
const customizeRows = [];
|
|
1206
|
+
for (const [label, suffix, dir] of [
|
|
1207
|
+
[
|
|
1208
|
+
"User schema",
|
|
1209
|
+
".zitadel/schemas/default-human-user.json",
|
|
1210
|
+
".zitadel/schemas/"
|
|
1211
|
+
],
|
|
1212
|
+
[
|
|
1213
|
+
"Login flow",
|
|
1214
|
+
".zitadel/flows/default-login.json",
|
|
1215
|
+
".zitadel/flows/"
|
|
1216
|
+
],
|
|
1217
|
+
[
|
|
1218
|
+
"Login template",
|
|
1219
|
+
".zitadel/branding/login.liquid",
|
|
1220
|
+
".zitadel/branding/"
|
|
1221
|
+
]
|
|
1222
|
+
]) if (pickWrittenFile(writtenRel, suffix)) customizeRows.push({
|
|
1223
|
+
label,
|
|
1224
|
+
value: path(dir),
|
|
1225
|
+
secondary: "see its README.md"
|
|
1226
|
+
});
|
|
1273
1227
|
const projectRows = [
|
|
1274
1228
|
{
|
|
1275
1229
|
label: "Project id",
|
|
@@ -1285,8 +1239,8 @@ function buildSummary(opts) {
|
|
|
1285
1239
|
},
|
|
1286
1240
|
design ? {
|
|
1287
1241
|
label: "Login design",
|
|
1288
|
-
value: design,
|
|
1289
|
-
secondary: path(".zitadel/branding/")
|
|
1242
|
+
value: brandingDesignLabel(design),
|
|
1243
|
+
secondary: `${design} · ${path(".zitadel/branding/")}`
|
|
1290
1244
|
} : {
|
|
1291
1245
|
label: "Login design",
|
|
1292
1246
|
value: dim("built-in template")
|
|
@@ -1301,6 +1255,10 @@ function buildSummary(opts) {
|
|
|
1301
1255
|
title: "Installed",
|
|
1302
1256
|
rows: installedRows
|
|
1303
1257
|
},
|
|
1258
|
+
{
|
|
1259
|
+
title: "Customize",
|
|
1260
|
+
rows: customizeRows
|
|
1261
|
+
},
|
|
1304
1262
|
{
|
|
1305
1263
|
title: "Project",
|
|
1306
1264
|
rows: projectRows
|