@zitadel/cli 0.1.0-alpha.2 → 0.1.0-alpha.4
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 +75 -11
- package/SKILLS.md +11 -4
- package/dist/commands/apply.mjs +3 -4
- package/dist/commands/apply.mjs.map +1 -1
- package/dist/commands/doctor.mjs +6 -7
- package/dist/commands/doctor.mjs.map +1 -1
- package/dist/commands/eject.mjs +3 -3
- package/dist/commands/logs.mjs +3 -3
- package/dist/commands/logs.mjs.map +1 -1
- package/dist/commands/plan.mjs +3 -4
- package/dist/commands/plan.mjs.map +1 -1
- package/dist/commands/reset.mjs +3 -3
- package/dist/commands/reset.mjs.map +1 -1
- package/dist/commands/setup.mjs +23 -6
- package/dist/commands/setup.mjs.map +1 -1
- package/dist/commands/start.mjs +2 -2
- package/dist/commands/status.mjs +6 -7
- package/dist/commands/status.mjs.map +1 -1
- package/dist/commands/stop.mjs +3 -3
- package/dist/commands/stop.mjs.map +1 -1
- package/dist/{docker-DrOBycgG.mjs → docker-B4zvLujy.mjs} +2 -2
- package/dist/{docker-DrOBycgG.mjs.map → docker-B4zvLujy.mjs.map} +1 -1
- package/dist/{oclif-CqkWBQ7i.mjs → oclif-B3Qhw0cj.mjs} +24 -10
- package/dist/oclif-B3Qhw0cj.mjs.map +1 -0
- package/dist/{orca-S1tVnngd.mjs → orca-BGM8VCgQ.mjs} +139 -33
- package/dist/orca-BGM8VCgQ.mjs.map +1 -0
- package/dist/{project-B6YfSaZw.mjs → project-kWWyS7fS.mjs} +2 -2
- package/dist/{project-B6YfSaZw.mjs.map → project-kWWyS7fS.mjs.map} +1 -1
- package/dist/{sync-DN4oNLVH.mjs → sync-CHXZqYR7.mjs} +2 -2
- package/dist/{sync-DN4oNLVH.mjs.map → sync-CHXZqYR7.mjs.map} +1 -1
- package/oclif.manifest.json +1 -3
- package/package.json +4 -4
- package/dist/oclif-CqkWBQ7i.mjs.map +0 -1
- package/dist/orca-S1tVnngd.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oclif-B3Qhw0cj.mjs","names":[],"sources":["../src/lib/errors.ts","../src/lib/json.ts","../src/lib/paths.ts","../src/lib/public-cli.ts","../src/lib/local-server/runtime.ts","../src/lib/server.ts","../src/lib/oclif/base.ts"],"sourcesContent":["import { ApiError } from \"@zitadel/api/runtime/fetch\";\n\n/**\n * Closed set of failure categories the CLI can surface. Every error the\n * user sees is funnelled into one of these so messaging, exit codes, and\n * machine-readable output stay consistent regardless of where the failure\n * originated.\n */\nexport type ZitadelErrorCode =\n | \"E_ALREADY_INIT\"\n | \"E_FRAMEWORK_NOT_DETECTED\"\n | \"E_UNSUPPORTED_PROJECT_SHAPE\"\n | \"E_NETWORK\"\n | \"E_AUTH\"\n | \"E_CONFLICT\"\n | \"E_LOCAL_SERVER_NOT_RUNNING\"\n | \"E_VALIDATION\"\n | \"E_NOT_IMPLEMENTED\";\n\n/**\n * Maps each {@link ZitadelErrorCode} to the process exit code the CLI\n * returns. The table is the single source of truth for exit semantics so\n * scripts and CI can branch on stable, documented numbers.\n */\nexport const EXIT_CODES: Record<ZitadelErrorCode, number> = {\n E_ALREADY_INIT: 0,\n E_FRAMEWORK_NOT_DETECTED: 3,\n E_UNSUPPORTED_PROJECT_SHAPE: 3,\n E_NETWORK: 4,\n E_AUTH: 1,\n E_CONFLICT: 5,\n E_LOCAL_SERVER_NOT_RUNNING: 4,\n E_VALIDATION: 3,\n E_NOT_IMPLEMENTED: 2,\n};\n\n/**\n * Optional, user-facing extras attached to a {@link ZitadelError}. Kept\n * separate from the message so the renderer can present a hint, suggested\n * follow-up commands, and structured details independently (e.g. as JSON\n * fields) rather than concatenating everything into one string.\n */\nexport type ZitadelErrorOptions = {\n hint?: string;\n nextCommands?: string[];\n details?: unknown;\n};\n\n/**\n * The CLI's single error type. Carries a {@link ZitadelErrorCode} so the\n * top-level handler can derive an exit code and structured output without\n * pattern-matching on messages. Throwing this anywhere guarantees the user\n * gets a categorised, hint-bearing failure instead of a raw stack trace.\n */\nexport class ZitadelError extends Error {\n readonly code: ZitadelErrorCode;\n readonly hint?: string;\n readonly nextCommands?: string[];\n readonly details?: unknown;\n\n constructor(code: ZitadelErrorCode, message: string, opts: ZitadelErrorOptions = {}) {\n super(message);\n this.name = \"ZitadelError\";\n this.code = code;\n this.hint = opts.hint;\n this.nextCommands = opts.nextCommands;\n this.details = opts.details;\n }\n\n get exitCode(): number {\n return EXIT_CODES[this.code] ?? 1;\n }\n}\n\n/**\n * Normalises any thrown value into a {@link ZitadelError}. Inspection is\n * ordered most-specific-first (already-normalised, then errno/filesystem,\n * network, Zod-like, generic `Error`, then a catch-all) so the most\n * actionable category and hint win. This is the boundary that lets the rest\n * of the CLI `throw` plain errors yet still produce consistent, categorised\n * output. The original error shape is preserved under `details` for\n * debugging without leaking it into the user-facing message.\n */\nexport function toZitadelError(error: unknown): ZitadelError {\n if (error instanceof ZitadelError) {\n return error;\n }\n\n if (error instanceof ApiError) {\n // `401`/`403` → bad or missing project secret; `5xx` → transport or\n // server fault; everything else 4xx → the body the CLI sent was\n // rejected (validation, conflict, not-found, …).\n const code: ZitadelErrorCode =\n error.status === 401 || error.status === 403\n ? \"E_AUTH\"\n : error.status >= 500\n ? \"E_NETWORK\"\n : \"E_VALIDATION\";\n return new ZitadelError(code, error.message, {\n details: { status: error.status, url: error.url, body: error.body },\n });\n }\n\n if (isErrnoException(error)) {\n const details = { original: pickErrorShape(error) };\n if (error.code === \"EACCES\" || error.code === \"EPERM\") {\n return new ZitadelError(\"E_AUTH\", `Permission denied: ${error.message}`, {\n hint: \"Check file permissions or run with the right user.\",\n details,\n });\n }\n if (error.code === \"EEXIST\") {\n return new ZitadelError(\"E_CONFLICT\", error.message, {\n hint: \"A file already exists. Use --force to overwrite or remove it first.\",\n details,\n });\n }\n if (error.code === \"ENOENT\") {\n return new ZitadelError(\"E_VALIDATION\", error.message, {\n hint: \"A required file or directory is missing.\",\n details,\n });\n }\n }\n\n if (isNetworkError(error)) {\n return new ZitadelError(\"E_NETWORK\", errorMessage(error), {\n hint: \"Check your connection, ZITADEL_API_BASE, or the configured server URL.\",\n details: { original: pickErrorShape(error as Error) },\n });\n }\n\n if (isZodLikeError(error)) {\n return new ZitadelError(\"E_VALIDATION\", errorMessage(error), {\n details: { issues: (error as { issues: unknown }).issues },\n });\n }\n\n if (error instanceof Error) {\n return new ZitadelError(\"E_VALIDATION\", error.message, {\n details: { original: pickErrorShape(error) },\n });\n }\n\n return new ZitadelError(\"E_VALIDATION\", \"Unknown error\", { details: error });\n}\n\nfunction isErrnoException(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && typeof (error as NodeJS.ErrnoException).code === \"string\";\n}\n\nfunction isNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n if (\n error.name === \"TypeError\" &&\n /fetch failed|network|ECONNREFUSED|ENOTFOUND/i.test(error.message)\n ) {\n return true;\n }\n const cause = (error as { cause?: unknown }).cause;\n if (cause && typeof cause === \"object\" && \"code\" in cause) {\n const code = String((cause as { code: unknown }).code);\n return /^(ECONNREFUSED|ECONNRESET|ENOTFOUND|ETIMEDOUT|EAI_AGAIN|UND_ERR)/i.test(code);\n }\n return false;\n}\n\nfunction isZodLikeError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"issues\" in error &&\n Array.isArray((error as { issues: unknown }).issues)\n );\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === \"string\") {\n return error;\n }\n return String(error);\n}\n\nfunction pickErrorShape(error: Error): Record<string, unknown> {\n return {\n name: error.name,\n message: error.message,\n code: (error as NodeJS.ErrnoException).code,\n };\n}\n","import { stringify } from \"safe-stable-stringify\";\n\n/**\n * Serialise a value to pretty-printed JSON with object keys sorted at every\n * depth. Determinism is the point: managed files written by the CLI must be\n * byte-stable across runs so diffs stay clean and content hashes don't churn\n * when only key ordering would otherwise differ. Delegates the deterministic\n * sort to `safe-stable-stringify`, matching `JSON.stringify(value, null, 2)`\n * formatting. The `?? \"null\"` only applies to `undefined`/function inputs,\n * which the CLI never serialises.\n */\nexport function stableStringify(value: unknown): string {\n return stringify(value, null, 2) ?? \"null\";\n}\n\n/**\n * Parse `contents` as JSON and assert the root is a plain object (not an\n * array or scalar). The CLI's config and secret files are always objects, so\n * this guards callers from the `JSON.parse` return type of `any` and produces\n * a `path`-qualified error message pointing at the offending file.\n */\nexport function parseJsonObject(contents: string, path: string): Record<string, unknown> {\n const value = JSON.parse(contents) as unknown;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${path} must contain a JSON object`);\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Narrows an unknown value to a plain (non-array, non-null) object. Shared by\n * the commands and the file-writer that walk parsed JSON, so the predicate\n * isn't reimplemented per call site.\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { resolve } from \"node:path\";\n\n/**\n * Resolve the working directory the CLI should operate against, defaulting to\n * the process CWD when no `--cwd` override is given. Always returns an\n * absolute path so downstream `join`/`readFile` calls are unaffected by later\n * `process.chdir` or relative-path ambiguity.\n */\nexport function resolveCwd(cwd?: string): string {\n return resolve(cwd ?? process.cwd());\n}\n\n/**\n * Sentinel comment stamped at the top of every file the CLI generates and\n * owns. Commands like `doctor` and `eject` look for this marker to decide\n * whether a file is safe to touch; the trailing `v1` lets the format evolve\n * without mistaking newer managed files for hand-edited ones.\n */\nexport const MANAGED_MARKER = \"// zitadel-cli: managed-file v1\";\n","const CLI_PACKAGE_NAME = \"@zitadel/cli\";\n\nexport function npmDistTagForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n const match = normalized.match(/^\\d+\\.\\d+\\.\\d+-([0-9A-Za-z][0-9A-Za-z-]*)/);\n return match?.[1] ?? \"latest\";\n}\n\nexport function npmSelectorForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n if (/^\\d+\\.\\d+\\.\\d+-alpha\\.\\d+$/.test(normalized)) {\n return normalized;\n }\n return npmDistTagForCliVersion(normalized);\n}\n\nexport function publicCliCommand(args: string, cliVersion: string): string {\n const prefix = `npx ${CLI_PACKAGE_NAME}@${npmSelectorForCliVersion(cliVersion)}`;\n return args.length > 0 ? `${prefix} ${args}` : prefix;\n}\n\nexport function normalizePublicCliCommand(command: string, cliVersion: string): string {\n if (command === \"zitadel\") {\n return publicCliCommand(\"\", cliVersion);\n }\n if (command.startsWith(\"zitadel \")) {\n return publicCliCommand(command.slice(\"zitadel \".length), cliVersion);\n }\n return command;\n}\n\nexport function normalizePublicCliCommands(\n commands: ReadonlyArray<string> | undefined,\n cliVersion: string,\n): string[] | undefined {\n return commands?.map((command) => normalizePublicCliCommand(command, cliVersion));\n}\n","import { createHash } from \"node:crypto\";\nimport { access, mkdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { createServer } from \"node:net\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport { ZitadelError } from \"../errors\";\nimport { isObject, parseJsonObject } from \"../json\";\n\nexport const LOCAL_SERVER_IMAGE_NAME = \"ghcr.io/zitadel/nextgen\";\nexport const DEFAULT_LOCAL_SERVER_IMAGE = `${LOCAL_SERVER_IMAGE_NAME}:latest`;\nexport const DEFAULT_LOCAL_SERVER_PORT = 8080;\nexport const DEFAULT_LOCAL_SERVER_URL = \"http://localhost:8080\";\nexport const LOCAL_RUNTIME_DIR = \".zitadel/local\";\nexport const LOCAL_DATA_DIR = \".zitadel/local/nextgen-data\";\nexport const LOCAL_RUNTIME_FILE = \".zitadel/local/runtime.json\";\nexport const LOCAL_CONTAINER_PASSWD_FILE = \".zitadel/local/container-passwd\";\nexport const LOCAL_CONTAINER_GROUP_FILE = \".zitadel/local/container-group\";\nexport const CONTAINER_DATA_DIR = \"/var/lib/zitadel/nextgen-data\";\nexport const CONTAINER_HTTP_PORT = 8080;\n\nexport type RuntimeMetadata = {\n schema_version: 1;\n container_name: string;\n container_id: string;\n image: string;\n port: number;\n server_url: string;\n data_dir: string;\n created_at: string;\n cli_version: string;\n};\n\nexport type LocalRuntimePaths = {\n runtimeDir: string;\n dataDir: string;\n runtimeFile: string;\n containerPasswdFile: string;\n containerGroupFile: string;\n};\n\nexport type WritablePathProbe = {\n targetPath: string;\n checkedPath: string;\n};\n\nexport type ContainerIdentity = {\n uid: number;\n gid: number;\n passwdFile: string;\n groupFile: string;\n};\n\nexport function localRuntimePaths(cwd: string): LocalRuntimePaths {\n return {\n runtimeDir: join(cwd, LOCAL_RUNTIME_DIR),\n dataDir: join(cwd, LOCAL_DATA_DIR),\n runtimeFile: join(cwd, LOCAL_RUNTIME_FILE),\n containerPasswdFile: join(cwd, LOCAL_CONTAINER_PASSWD_FILE),\n containerGroupFile: join(cwd, LOCAL_CONTAINER_GROUP_FILE),\n };\n}\n\nexport function localContainerName(cwd: string): string {\n const hash = createHash(\"sha256\").update(resolve(cwd)).digest(\"hex\").slice(0, 12);\n return `zitadel-server-${hash}`;\n}\n\nexport function localServerUrl(port: number): string {\n return `http://localhost:${port}`;\n}\n\nexport function defaultLocalServerImageForCliVersion(cliVersion: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n if (/^\\d+\\.\\d+\\.\\d+-alpha\\.\\d+$/.test(normalized)) {\n return `${LOCAL_SERVER_IMAGE_NAME}:${normalized}`;\n }\n return DEFAULT_LOCAL_SERVER_IMAGE;\n}\n\nexport async function ensureLocalState(cwd: string): Promise<LocalRuntimePaths> {\n const paths = localRuntimePaths(cwd);\n await mkdir(paths.dataDir, { recursive: true, mode: 0o700 });\n await appendGitignoreEntry(cwd, `${LOCAL_RUNTIME_DIR}/`);\n return paths;\n}\n\nexport async function assertLocalStateWritable(cwd: string): Promise<WritablePathProbe> {\n const paths = localRuntimePaths(cwd);\n const checkedPath = await nearestExistingDirectory(paths.dataDir);\n await access(checkedPath, constants.W_OK);\n return { targetPath: paths.dataDir, checkedPath };\n}\n\nexport async function ensureContainerIdentity(\n cwd: string,\n user: { uid?: number; gid?: number },\n): Promise<ContainerIdentity | undefined> {\n if (user.uid === undefined || user.uid <= 0) {\n return undefined;\n }\n const gid = user.gid ?? user.uid;\n const paths = localRuntimePaths(cwd);\n await mkdir(paths.runtimeDir, { recursive: true, mode: 0o700 });\n await writeFile(\n paths.containerPasswdFile,\n [\n \"root:x:0:0:root:/root:/bin/sh\",\n \"nonroot:x:65532:65532:nonroot:/nonexistent:/usr/sbin/nologin\",\n `zitadel-local:x:${String(user.uid)}:${String(gid)}:Zitadel local user:/tmp:/usr/sbin/nologin`,\n \"\",\n ].join(\"\\n\"),\n { mode: 0o644 },\n );\n await writeFile(\n paths.containerGroupFile,\n [\n \"root:x:0:\",\n \"nonroot:x:65532:\",\n `zitadel-local:x:${String(gid)}:`,\n \"\",\n ].join(\"\\n\"),\n { mode: 0o644 },\n );\n return {\n uid: user.uid,\n gid,\n passwdFile: paths.containerPasswdFile,\n groupFile: paths.containerGroupFile,\n };\n}\n\nexport async function readRuntimeMetadata(cwd: string): Promise<RuntimeMetadata | undefined> {\n const paths = localRuntimePaths(cwd);\n let raw: string;\n try {\n raw = await readFile(paths.runtimeFile, \"utf8\");\n } catch (error) {\n if (isErrno(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n }\n\n const parsed = parseJsonObject(raw, LOCAL_RUNTIME_FILE);\n return normalizeRuntimeMetadata(parsed);\n}\n\nexport async function writeRuntimeMetadata(cwd: string, metadata: RuntimeMetadata): Promise<void> {\n const paths = localRuntimePaths(cwd);\n await mkdir(paths.runtimeDir, { recursive: true, mode: 0o700 });\n await writeFile(paths.runtimeFile, `${JSON.stringify(metadata, null, 2)}\\n`, { mode: 0o600 });\n}\n\nexport async function removeRuntimeMetadata(cwd: string): Promise<void> {\n await rm(localRuntimePaths(cwd).runtimeFile, { force: true });\n}\n\nexport async function removeLocalData(cwd: string): Promise<void> {\n await rm(localRuntimePaths(cwd).dataDir, { recursive: true, force: true });\n}\n\nexport async function checkLocalServerHealth(serverUrl: string, timeoutMs = 1500): Promise<boolean> {\n try {\n const healthUrl = new URL(\"/healthz\", serverUrl);\n const response = await fetch(healthUrl, { signal: AbortSignal.timeout(timeoutMs) });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport async function isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolvePort) => {\n const server = createServer();\n server.once(\"error\", () => resolvePort(false));\n server.once(\"listening\", () => {\n server.close(() => resolvePort(true));\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport async function resolveLocalServer(cwd: string): Promise<string> {\n const runtime = await readRuntimeMetadata(cwd);\n if (runtime) {\n if (await checkLocalServerHealth(runtime.server_url)) {\n return runtime.server_url;\n }\n throw localServerNotRunning(runtime.server_url);\n }\n\n if (await checkLocalServerHealth(DEFAULT_LOCAL_SERVER_URL)) {\n return DEFAULT_LOCAL_SERVER_URL;\n }\n throw localServerNotRunning(DEFAULT_LOCAL_SERVER_URL);\n}\n\nexport function localServerNotRunning(serverUrl: string): ZitadelError {\n return new ZitadelError(\"E_LOCAL_SERVER_NOT_RUNNING\", \"Local Zitadel server is not running\", {\n hint: `No healthy local server responded at ${serverUrl}.`,\n nextCommands: [\"zitadel start\"],\n details: { server_url: serverUrl },\n });\n}\n\nasync function appendGitignoreEntry(cwd: string, entry: string): Promise<void> {\n const path = join(cwd, \".gitignore\");\n let existing = \"\";\n try {\n existing = await readFile(path, \"utf8\");\n } catch (error) {\n if (!isErrno(error, \"ENOENT\")) {\n throw error;\n }\n }\n\n const lines = existing.split(/\\r?\\n/).map((line) => line.trim());\n if (lines.includes(entry)) {\n return;\n }\n const prefix = existing.length === 0 || existing.endsWith(\"\\n\") ? \"\" : \"\\n\";\n await writeFile(path, `${existing}${prefix}${entry}\\n`);\n}\n\nfunction normalizeRuntimeMetadata(input: Record<string, unknown>): RuntimeMetadata {\n if (\n input.schema_version !== 1 ||\n typeof input.container_name !== \"string\" ||\n typeof input.container_id !== \"string\" ||\n typeof input.image !== \"string\" ||\n typeof input.port !== \"number\" ||\n !isValidPort(input.port) ||\n typeof input.server_url !== \"string\" ||\n !isValidServerUrl(input.server_url, input.port) ||\n typeof input.data_dir !== \"string\" ||\n typeof input.created_at !== \"string\" ||\n typeof input.cli_version !== \"string\"\n ) {\n throw new ZitadelError(\"E_VALIDATION\", `${LOCAL_RUNTIME_FILE} is malformed`, {\n hint: \"Run `zitadel reset --force`, then `zitadel start`.\",\n nextCommands: [\"zitadel reset --force\", \"zitadel start\"],\n details: input,\n });\n }\n return {\n schema_version: 1,\n container_name: input.container_name,\n container_id: input.container_id,\n image: input.image,\n port: input.port,\n server_url: input.server_url,\n data_dir: input.data_dir,\n created_at: input.created_at,\n cli_version: input.cli_version,\n };\n}\n\nexport async function assertWritableDirectory(path: string): Promise<void> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n await access(path, constants.W_OK);\n}\n\nasync function nearestExistingDirectory(path: string): Promise<string> {\n let current = path;\n while (true) {\n try {\n const info = await stat(current);\n if (!info.isDirectory()) {\n throw new Error(`${current} exists but is not a directory`);\n }\n return current;\n } catch (error) {\n if (!isErrno(error, \"ENOENT\")) {\n throw error;\n }\n const parent = dirname(current);\n if (parent === current) {\n throw error;\n }\n current = parent;\n }\n }\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: unknown }).code === code\n );\n}\n\nexport function runtimeSummary(metadata: RuntimeMetadata | undefined): Record<string, unknown> {\n if (!metadata) {\n return { configured: false };\n }\n return {\n configured: true,\n container_name: metadata.container_name,\n container_id: metadata.container_id,\n image: metadata.image,\n port: metadata.port,\n server_url: metadata.server_url,\n data_dir: metadata.data_dir,\n created_at: metadata.created_at,\n };\n}\n\nexport function isRuntimeObject(value: unknown): value is RuntimeMetadata {\n return isObject(value) && value.schema_version === 1;\n}\n\nfunction isValidPort(value: number): boolean {\n return Number.isInteger(value) && value >= 1 && value <= 65_535;\n}\n\nfunction isValidServerUrl(value: string, port: number): boolean {\n try {\n const url = new URL(value);\n return (\n (url.protocol === \"http:\" || url.protocol === \"https:\") &&\n url.hostname.length > 0 &&\n explicitUrlPort(value) === port\n );\n } catch {\n return false;\n }\n}\n\nfunction explicitUrlPort(value: string): number | undefined {\n const match = value.match(/^[a-z][a-z\\d+\\-.]*:\\/\\/(?:\\[[^\\]]+\\]|[^/?#:]+):(\\d+)(?:[/?#]|$)/i);\n if (!match) {\n return undefined;\n }\n const port = Number(match[1]);\n return isValidPort(port) ? port : undefined;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ZitadelError } from \"./errors\";\nimport { resolveLocalServer } from \"./local-server/runtime\";\nimport { isObject, parseJsonObject } from \"./json\";\n\n/**\n * Server URL used when nothing else resolves. Also surfaced in hints and\n * the interactive setup prompt as the suggested value, so it is exported\n * rather than kept private.\n */\nexport const DEFAULT_SERVER = \"https://api.zitadel.cloud\";\n\n/**\n * The resolved target server plus the source it came from. `origin` is\n * retained (not just the value) so callers can report *why* a server was\n * chosen and so the precedence order stays auditable.\n */\nexport type ResolvedServer = {\n value: string;\n origin: \"flag\" | \"env\" | \"config-env\" | \"config-top\" | \"default\" | \"local\";\n};\n\n/**\n * Inputs to {@link resolveServer}. Passed explicitly (cwd, env) rather\n * than read from globals so resolution is pure and testable. `serverFlag`\n * and `environment` come from the parsed CLI invocation.\n */\nexport type ResolveServerInput = {\n cwd: string;\n env: NodeJS.ProcessEnv;\n serverFlag?: string;\n environment?: string;\n};\n\n/**\n * Resolves which server the CLI should target, applying a fixed\n * precedence: explicit `--server` flag, then `ZITADEL_API_BASE`, then the\n * selected environment block in `zitadel.json`, then the config's\n * top-level `server`, falling back to {@link DEFAULT_SERVER}. Every\n * candidate is validated to a normalised origin; an invalid URL throws a\n * `ZitadelError` rather than silently falling through.\n */\nexport async function resolveServer(input: ResolveServerInput): Promise<ResolvedServer> {\n if (input.serverFlag) {\n return validate(input.cwd, { value: input.serverFlag, origin: \"flag\" });\n }\n const envValue = input.env.ZITADEL_API_BASE;\n if (envValue) {\n return validate(input.cwd, { value: envValue, origin: \"env\" });\n }\n\n const config = await readConfig(input.cwd);\n if (config) {\n const envBranch = readEnvServer(config, input.environment);\n if (envBranch) {\n return validate(input.cwd, { value: envBranch, origin: \"config-env\" });\n }\n if (typeof config.server === \"string\") {\n return validate(input.cwd, { value: config.server, origin: \"config-top\" });\n }\n }\n\n return { value: DEFAULT_SERVER, origin: \"default\" };\n}\n\nasync function validate(cwd: string, resolved: ResolvedServer): Promise<ResolvedServer> {\n if (resolved.value === \"local\") {\n return { value: await resolveLocalServer(cwd), origin: \"local\" };\n }\n\n try {\n const url = new URL(resolved.value);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new ZitadelError(\"E_VALIDATION\", `Server URL must use http(s): ${resolved.value}`, {\n hint: `Set \"server\" in zitadel.json to a URL like ${DEFAULT_SERVER}.`,\n });\n }\n return { value: url.origin, origin: resolved.origin };\n } catch (error) {\n if (error instanceof ZitadelError) {\n throw error;\n }\n throw new ZitadelError(\"E_VALIDATION\", `Invalid server \"${resolved.value}\"`, {\n hint: `Use a URL like ${DEFAULT_SERVER}.`,\n details: { origin: resolved.origin },\n });\n }\n}\n\nasync function readConfig(cwd: string): Promise<Record<string, unknown> | undefined> {\n try {\n const contents = await readFile(join(cwd, \"zitadel.json\"), \"utf8\");\n return parseJsonObject(contents, \"zitadel.json\");\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: string }).code === \"ENOENT\"\n ) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction readEnvServer(\n config: Record<string, unknown>,\n environment: string | undefined,\n): string | undefined {\n if (!environment) {\n return undefined;\n }\n const envs = config.environments;\n if (!isObject(envs)) {\n return undefined;\n }\n const branch = envs[environment];\n if (!isObject(branch)) {\n return undefined;\n }\n return typeof branch.server === \"string\" ? branch.server : undefined;\n}\n","import { Command, Flags } from \"@oclif/core\";\nimport consola from \"consola\";\n\nimport { toZitadelError, type ZitadelError } from \"../errors\";\nimport { isObject } from \"../json\";\nimport { resolveCwd } from \"../paths\";\nimport { normalizePublicCliCommand, normalizePublicCliCommands } from \"../public-cli\";\nimport { resolveServer } from \"../server\";\nimport type {\n CommandResult,\n ErrorEnvelope,\n EnvelopeMeta,\n GlobalOptions,\n JsonEnvelope,\n} from \"./types\";\n\n/**\n * Base class for every oclif command. Owns the global flags, builds the\n * {@link GlobalOptions} context (including server `source` resolution) the\n * subclass's `run` reads via `this.meta`, and turns the {@link CommandResult}\n * it returns into the JSON envelope (oclif serialises it natively in `--json`\n * mode) or human-facing text. Errors are translated into the failure envelope\n * and the mapped process exit code. Subclasses stay thin: parse flags, call\n * {@link toMeta}, do their work, and `return this.emit(...)`. The agent\n * contract (ADR 004) is preserved — oclif only replaces parsing, dispatch,\n * help, and JSON emission.\n */\nexport abstract class BaseCommand extends Command {\n /** Opt into oclif's native `--json` flag and JSON serialisation of the result. */\n static override enableJsonFlag = true;\n\n /** Flags shared by every command, inherited via oclif `baseFlags`. */\n static override baseFlags = {\n cwd: Flags.string({ char: \"c\", description: \"Project directory to operate on.\" }),\n server: Flags.string({ char: \"s\", description: \"Override the resolved server URL.\" }),\n \"non-interactive\": Flags.boolean({\n char: \"n\",\n description: \"Disable prompts. Required when scripting or running as an agent.\",\n }),\n force: Flags.boolean({ char: \"f\", description: \"Overwrite protected files on conflict.\" }),\n \"dry-run\": Flags.boolean({ description: \"Preview without mutating files or the platform.\" }),\n verbose: Flags.boolean({ description: \"Verbose logging.\" }),\n debug: Flags.boolean({ description: \"Debug logging.\" }),\n };\n\n /** Resolved context for the current invocation; set by {@link toMeta}. */\n protected meta: GlobalOptions = this.fallbackMeta();\n\n /**\n * Builds {@link GlobalOptions} from parsed flags, resolving the server\n * `source` by the documented precedence and storing the result on\n * `this.meta` so the error handler can render a complete envelope.\n */\n protected async toMeta(\n flags: Record<string, unknown>,\n options: { resolveServer?: boolean; source?: string } = {},\n ): Promise<GlobalOptions> {\n const cwd = resolveCwd(typeof flags.cwd === \"string\" ? flags.cwd : undefined);\n const serverFlag = typeof flags.server === \"string\" ? flags.server : undefined;\n const environment = typeof flags.environment === \"string\" ? flags.environment : \"development\";\n const source =\n options.resolveServer === false\n ? { value: options.source ?? \"\", origin: \"default\" as const }\n : await resolveServer({ cwd, env: process.env, serverFlag, environment });\n const json = this.jsonEnabled();\n const isTTY = Boolean(process.stdout.isTTY && process.stdin.isTTY);\n const verbose = Boolean(flags.verbose);\n const debug = Boolean(flags.debug);\n // Default to `info` (3) so users see step-by-step narration (start/info/\n // success/box). `--json` silences consola entirely so the structured\n // envelope is the only thing on stdout. `--debug` raises to 4 (debug);\n // `--verbose` is reserved for richer per-step detail and currently maps\n // to the same level as default.\n consola.level = json ? -999 : debug ? 4 : 3;\n // Drop the right-aligned timestamp the FancyReporter adds by default.\n // Timestamps add no value in a one-off CLI run, wrap awkwardly on long\n // lines (e.g. created-schema URL), and clutter the visual rhythm of the\n // ◐/✔/ℹ glyphs that anchor each step.\n consola.options.formatOptions = {\n ...consola.options.formatOptions,\n date: false,\n colors: true,\n compact: true,\n };\n this.meta = {\n cwd,\n nonInteractive: Boolean(flags[\"non-interactive\"]) || !isTTY || json,\n dryRun: Boolean(flags[\"dry-run\"]),\n force: Boolean(flags.force),\n command: this.id ?? \"(default)\",\n cliVersion: this.config.version,\n source: source.value,\n serverFlag,\n verbose,\n debug,\n env: process.env,\n isTTY,\n };\n return this.meta;\n }\n\n /**\n * Final step of every command: in human mode it prints the rendered result\n * (oclif suppresses {@link Command.log} under `--json`); it returns the\n * envelope so oclif's `--json` path serialises it.\n */\n protected emit(result: CommandResult): JsonEnvelope {\n const normalized = normalizeCommandResult(result, this.meta);\n this.log(renderPretty(normalized, this.meta));\n return toEnvelope(normalized, this.meta);\n }\n\n /**\n * Renders any thrown error as the failure envelope and exits with its code.\n * A flag-parse error fires before {@link toMeta} runs, so the local `meta`\n * here refreshes `command` from the now-resolved command id to keep the\n * envelope's `command` field accurate.\n */\n protected override async catch(error: unknown): Promise<never> {\n const meta: GlobalOptions = { ...this.meta, command: this.id ?? this.meta.command };\n const zitadelError = toZitadelError(error);\n if (this.jsonEnabled()) {\n this.logJson(toErrorEnvelope(zitadelError, meta));\n } else {\n this.logToStderr(renderError(zitadelError, meta));\n }\n return this.exit(zitadelError.exitCode);\n }\n\n /**\n * Context used before {@link toMeta} runs, so an error thrown during flag\n * parsing still renders a complete envelope. Version comes from oclif's\n * resolved {@link Command.config}.\n */\n private fallbackMeta(): GlobalOptions {\n return {\n cwd: resolveCwd(undefined),\n nonInteractive: false,\n dryRun: false,\n force: false,\n command: \"(default)\",\n cliVersion: this.config.version,\n source: \"\",\n verbose: false,\n debug: false,\n env: process.env,\n isTTY: Boolean(process.stdout.isTTY && process.stdin.isTTY),\n };\n }\n}\n\nfunction normalizeCommandResult(result: CommandResult, meta: GlobalOptions): CommandResult {\n if (result.status === \"ok\") {\n return {\n ...result,\n data: normalizeDataNextCommands(result.data, meta),\n };\n }\n return {\n ...result,\n data: normalizeDataNextCommands(result.data, meta),\n nextCommands: normalizePublicCliCommands(result.nextCommands, meta.cliVersion),\n };\n}\n\nfunction normalizeDataNextCommands(data: unknown, meta: GlobalOptions): unknown {\n if (!isObject(data) || !Array.isArray(data.next_commands)) {\n return data;\n }\n return {\n ...data,\n next_commands: data.next_commands.map((command) =>\n typeof command === \"string\" ? normalizePublicCliCommand(command, meta.cliVersion) : command,\n ),\n };\n}\n\n/** Wraps a {@link CommandResult} with the invocation metadata into the final envelope. */\nfunction toEnvelope(result: CommandResult, meta: GlobalOptions): JsonEnvelope {\n const base: EnvelopeMeta = {\n cli_version: meta.cliVersion,\n command: meta.command,\n source: meta.source,\n };\n if (result.status === \"ok\") {\n return {\n ...base,\n status: \"ok\",\n data: result.data,\n warnings: result.warnings ? [...result.warnings] : [],\n };\n }\n return {\n ...base,\n status: \"skipped\",\n reason: result.reason,\n data: result.data,\n next_commands: result.nextCommands ? [...result.nextCommands] : undefined,\n };\n}\n\n/** Builds the failure envelope from a {@link ZitadelError} and the invocation metadata. */\nfunction toErrorEnvelope(error: ZitadelError, meta: GlobalOptions): ErrorEnvelope {\n return {\n status: \"error\",\n cli_version: meta.cliVersion,\n command: meta.command,\n source: meta.source,\n code: error.code,\n message: error.message,\n hint: error.hint,\n next_commands: normalizePublicCliCommands(error.nextCommands, meta.cliVersion),\n details: error.details,\n };\n}\n\n/**\n * Renders a {@link CommandResult} as human-facing text for non-JSON mode. A\n * command may supply a bespoke `pretty` string (e.g. the `apply` plan diff);\n * otherwise success payloads are summarised by {@link formatData} and skips are\n * shown with their reason and follow-up commands.\n */\nfunction renderPretty(result: CommandResult, meta: GlobalOptions): string {\n if (result.pretty !== undefined) {\n return result.pretty;\n }\n if (result.status === \"ok\") {\n return formatData(result.data, result.warnings ? [...result.warnings] : [], meta);\n }\n const lines = [`Skipped: ${result.reason}${suffixBlock(meta)}`];\n if (result.nextCommands && result.nextCommands.length > 0) {\n lines.push(\"Next:\");\n for (const cmd of result.nextCommands) {\n lines.push(` $ ${cmd}`);\n }\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Renders a {@link ZitadelError} as a human-readable block for stderr: the\n * coded message, an optional hint, and any suggested next commands.\n */\nfunction renderError(error: ZitadelError, meta: GlobalOptions): string {\n const lines = [`Error ${error.code}: ${error.message}`];\n if (error.hint) {\n lines.push(error.hint);\n }\n const nextCommands = normalizePublicCliCommands(error.nextCommands, meta.cliVersion);\n if (nextCommands && nextCommands.length > 0) {\n lines.push(\"Next:\");\n for (const cmd of nextCommands) {\n lines.push(` $ ${cmd}`);\n }\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatData(data: unknown, warnings: string[], opts: GlobalOptions): string {\n if (typeof data === \"string\") {\n const suffix = sourceSuffix(opts);\n return suffix ? `${data}\\n${suffix}` : data;\n }\n\n const lines: string[] = [];\n const titleLine =\n isObject(data) && typeof data.title === \"string\"\n ? String(data.title)\n : \"Zitadel command completed.\";\n lines.push(titleLine);\n const suffix = sourceSuffix(opts);\n if (suffix) {\n lines.push(suffix);\n }\n\n if (isObject(data)) {\n renderKnownSections(lines, data);\n\n if (Array.isArray(data.next_actions) && data.next_actions.length > 0) {\n lines.push(\"\");\n lines.push(\"Next:\");\n for (const action of data.next_actions) {\n lines.push(` ${String(action)}`);\n }\n }\n if (Array.isArray(data.next_commands) && data.next_commands.length > 0) {\n if (!Array.isArray(data.next_actions) || data.next_actions.length === 0) {\n lines.push(\"\");\n lines.push(\"Next:\");\n }\n for (const cmd of data.next_commands) {\n lines.push(` $ ${String(cmd)}`);\n }\n }\n }\n\n for (const warning of warnings.filter((warning) => !warningRenderedInChecks(data, warning))) {\n lines.push(`Warning: ${warning}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction warningRenderedInChecks(data: unknown, warning: string): boolean {\n if (!isObject(data) || !Array.isArray(data.checks)) {\n return false;\n }\n return data.checks.some((check) => {\n if (!isObject(check) || check.status !== \"warn\") {\n return false;\n }\n return warning === `${String(check.name ?? \"check\")}: ${String(check.message ?? \"\")}`;\n });\n}\n\nfunction renderKnownSections(lines: string[], data: Record<string, unknown>): void {\n if (isObject(data.project)) {\n const project = data.project;\n const segments: string[] = [];\n if (typeof project.project_id === \"string\") {\n segments.push(`project=${project.project_id}`);\n }\n if (typeof project.lifecycle === \"string\") {\n segments.push(`lifecycle=${project.lifecycle}`);\n }\n if (typeof project.issuer === \"string\") {\n segments.push(`issuer=${project.issuer}`);\n }\n if (segments.length > 0) {\n lines.push(`Project: ${segments.join(\" \")}`);\n }\n }\n\n if (typeof data.framework === \"string\") {\n lines.push(`framework=${data.framework}`);\n }\n\n if (Array.isArray(data.files_written) || Array.isArray(data.files_skipped)) {\n const written = Array.isArray(data.files_written) ? data.files_written.length : 0;\n const skippedCount = Array.isArray(data.files_skipped) ? data.files_skipped.length : 0;\n lines.push(`Files: ${written} written, ${skippedCount} unchanged`);\n }\n\n if (isObject(data.apply)) {\n const apply = data.apply;\n const bits: string[] = [];\n if (typeof apply.config_version === \"number\") {\n bits.push(`v${apply.config_version}`);\n }\n if (typeof apply.hash === \"string\") {\n bits.push(`hash=${String(apply.hash).slice(0, 12)}`);\n }\n if (typeof apply.environment === \"string\") {\n bits.push(`env=${apply.environment}`);\n }\n if (bits.length > 0) {\n lines.push(`Apply: ${bits.join(\" \")}`);\n }\n }\n\n if (Array.isArray(data.checks) && data.checks.length > 0) {\n lines.push(\"Checks:\");\n for (const check of data.checks) {\n if (!isObject(check)) {\n continue;\n }\n const status = check.status === \"pass\" ? \"ok\" : check.status === \"warn\" ? \"warn\" : \"fail\";\n lines.push(` [${status}] ${String(check.name ?? \"check\")}: ${String(check.message ?? \"\")}`);\n }\n }\n}\n\nfunction sourceSuffix(opts: GlobalOptions): string {\n try {\n const url = new URL(opts.source);\n if (url.host === \"api.zitadel.cloud\") {\n return \"\";\n }\n return `(server: ${url.host})`;\n } catch {\n return \"\";\n }\n}\n\nfunction suffixBlock(opts: GlobalOptions): string {\n const suffix = sourceSuffix(opts);\n return suffix ? ` ${suffix}` : \"\";\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as isObject, E as ZitadelError,
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { chmod, mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
|
|
1
|
+
import { C as isObject, E as ZitadelError, T as stableStringify, n as DEFAULT_SERVER, w as parseJsonObject, x as MANAGED_MARKER } from "./oclif-B3Qhw0cj.mjs";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { chmod, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
//#region src/lib/orca/detectors/package-json.ts
|
|
6
6
|
/**
|
|
@@ -19,6 +19,12 @@ async function readPackageJson(cwd) {
|
|
|
19
19
|
function hasDependency(pkg, name) {
|
|
20
20
|
return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]);
|
|
21
21
|
}
|
|
22
|
+
function dependencyVersionMajor(pkg, name) {
|
|
23
|
+
const spec = pkg.dependencies?.[name] ?? pkg.devDependencies?.[name];
|
|
24
|
+
if (!spec) return;
|
|
25
|
+
const match = spec.match(/\d+/);
|
|
26
|
+
return match ? Number(match[0]) : void 0;
|
|
27
|
+
}
|
|
22
28
|
//#endregion
|
|
23
29
|
//#region src/lib/orca/detectors/port.ts
|
|
24
30
|
/**
|
|
@@ -97,7 +103,8 @@ var NextDetector = class {
|
|
|
97
103
|
id: "next",
|
|
98
104
|
appDir,
|
|
99
105
|
devPort,
|
|
100
|
-
url: issuerFromPort(devPort)
|
|
106
|
+
url: issuerFromPort(devPort),
|
|
107
|
+
versionMajor: dependencyVersionMajor(pkg, "next")
|
|
101
108
|
};
|
|
102
109
|
}
|
|
103
110
|
};
|
|
@@ -551,7 +558,7 @@ export default function ${mode === "login" ? "LoginPage" : "RegisterPage"}() {
|
|
|
551
558
|
* The handle is passed as the `project` DOM property, which relies on React
|
|
552
559
|
* 19's custom-element property binding (the scaffold targets the latest Next /
|
|
553
560
|
* React). The backend URL never reaches the browser: the client talks to the
|
|
554
|
-
* same-origin `/__nextgen` proxy path, and the scaffolded
|
|
561
|
+
* same-origin `/__nextgen` proxy path, and the scaffolded Next request boundary
|
|
555
562
|
* forwards it to `ZITADEL_URL` server-side. `NEXT_PUBLIC_ZITADEL_PROJECT_ID` is
|
|
556
563
|
* public — the project id is not sensitive and the widget needs it to start a
|
|
557
564
|
* flow.
|
|
@@ -583,7 +590,7 @@ const ${elementName} = dynamic(
|
|
|
583
590
|
// \`project\` prop. The component reads config from this prop directly, so
|
|
584
591
|
// it works regardless of how the SDK packages are bundled. The backend URL
|
|
585
592
|
// stays server-side — requests go through the proxy path "/__nextgen",
|
|
586
|
-
// which the scaffolded
|
|
593
|
+
// which the scaffolded request boundary forwards to the Zitadel server.
|
|
587
594
|
const project = configureZitadel({
|
|
588
595
|
projectId: process.env.NEXT_PUBLIC_ZITADEL_PROJECT_ID ?? "",
|
|
589
596
|
proxyPath: "/__nextgen",
|
|
@@ -714,17 +721,18 @@ function getRenderer(id) {
|
|
|
714
721
|
//#endregion
|
|
715
722
|
//#region src/lib/orca/patchers/rule/next/index.ts
|
|
716
723
|
/**
|
|
717
|
-
* Next.js
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
724
|
+
* Next.js request-boundary file at the project root. Wires `nextgenMiddleware` so the
|
|
725
|
+
* generated project config's `/__nextgen` proxy path is same-origin proxied
|
|
726
|
+
* to `ZITADEL_URL` and `/profile` is gated. Next 16 renamed this convention to
|
|
727
|
+
* `proxy.ts`; older projects keep `middleware.ts`.
|
|
721
728
|
* Carries the managed marker so `doctor --fix` reclaims it and `eject` removes it.
|
|
722
729
|
*/
|
|
723
|
-
|
|
730
|
+
function requestBoundaryTemplate(functionName) {
|
|
731
|
+
return `${MANAGED_MARKER}
|
|
724
732
|
import { nextgenMiddleware } from "@zitadel/sdk-next/middleware";
|
|
725
733
|
import type { NextRequest } from "next/server";
|
|
726
734
|
|
|
727
|
-
export function
|
|
735
|
+
export function ${functionName}(req: NextRequest) {
|
|
728
736
|
return nextgenMiddleware(req, {
|
|
729
737
|
url: process.env.ZITADEL_URL,
|
|
730
738
|
protectedRoutes: ["/profile"],
|
|
@@ -736,10 +744,11 @@ export const config = {
|
|
|
736
744
|
matcher: ["/__nextgen/:path*", "/profile/:path*"],
|
|
737
745
|
};
|
|
738
746
|
`;
|
|
747
|
+
}
|
|
739
748
|
/**
|
|
740
749
|
* Rule-based patcher for the Next.js App Router. Inherits the shared
|
|
741
750
|
* `.zitadel/` base files from {@link AbstractRulePatcher} and contributes the
|
|
742
|
-
* Next routes
|
|
751
|
+
* Next routes and request boundary whose templates come from the chosen renderer.
|
|
743
752
|
*/
|
|
744
753
|
var NextPatcher = class extends AbstractRulePatcher {
|
|
745
754
|
/** Returns true for Next.js projects. */
|
|
@@ -750,7 +759,7 @@ var NextPatcher = class extends AbstractRulePatcher {
|
|
|
750
759
|
return nextCodeOps(ctx, getRenderer(ctx.rendererId));
|
|
751
760
|
}
|
|
752
761
|
routeFiles(view) {
|
|
753
|
-
return nextCodeFilePaths(view.framework
|
|
762
|
+
return nextCodeFilePaths(view.framework, getRenderer(view.rendererId));
|
|
754
763
|
}
|
|
755
764
|
routeDeps(view) {
|
|
756
765
|
return [getRenderer(view.rendererId).dependency.name];
|
|
@@ -768,15 +777,16 @@ var NextPatcher = class extends AbstractRulePatcher {
|
|
|
768
777
|
* and {@link NextPatcher.routeFiles} (which only needs the paths) so the two
|
|
769
778
|
* cannot drift.
|
|
770
779
|
*/
|
|
771
|
-
function nextCodeFilePaths(
|
|
780
|
+
function nextCodeFilePaths(framework, renderer) {
|
|
781
|
+
const appDir = framework.appDir;
|
|
772
782
|
const paths = [join(appDir, "login/page.tsx"), join(appDir, "register/page.tsx")];
|
|
773
783
|
if (renderer.templates.profilePage) paths.push(join(appDir, "profile/page.tsx"));
|
|
774
|
-
paths.push(join(appDir,
|
|
784
|
+
paths.push(join(appDir, `../${requestBoundaryFile(framework).filename}`));
|
|
775
785
|
if (renderer.templates.provider) paths.push(join(appDir, renderer.templates.provider.filename));
|
|
776
786
|
if (renderer.templates.customElementsDts) paths.push(join(appDir, "../custom-elements.d.ts"));
|
|
777
787
|
return paths;
|
|
778
788
|
}
|
|
779
|
-
/** The Next route/
|
|
789
|
+
/** The Next route/request-boundary write ops plus the SDK dependency. */
|
|
780
790
|
function nextCodeOps(ctx, renderer) {
|
|
781
791
|
const appDir = ctx.framework.appDir;
|
|
782
792
|
const ops = [{
|
|
@@ -794,10 +804,11 @@ function nextCodeOps(ctx, renderer) {
|
|
|
794
804
|
path: join(appDir, "profile/page.tsx"),
|
|
795
805
|
contents: profile.contents
|
|
796
806
|
});
|
|
807
|
+
const boundary = requestBoundaryFile(ctx.framework);
|
|
797
808
|
ops.push({
|
|
798
809
|
kind: "write",
|
|
799
|
-
path: join(appDir,
|
|
800
|
-
contents:
|
|
810
|
+
path: join(appDir, `../${boundary.filename}`),
|
|
811
|
+
contents: requestBoundaryTemplate(boundary.functionName)
|
|
801
812
|
});
|
|
802
813
|
const provider = renderer.templates.provider;
|
|
803
814
|
if (provider) ops.push({
|
|
@@ -818,6 +829,16 @@ function nextCodeOps(ctx, renderer) {
|
|
|
818
829
|
});
|
|
819
830
|
return ops;
|
|
820
831
|
}
|
|
832
|
+
function requestBoundaryFile(framework) {
|
|
833
|
+
if ((framework.versionMajor ?? 0) >= 16) return {
|
|
834
|
+
filename: "proxy.ts",
|
|
835
|
+
functionName: "proxy"
|
|
836
|
+
};
|
|
837
|
+
return {
|
|
838
|
+
filename: "middleware.ts",
|
|
839
|
+
functionName: "middleware"
|
|
840
|
+
};
|
|
841
|
+
}
|
|
821
842
|
function dependencyVersionForCli(cliVersion, fallback) {
|
|
822
843
|
const normalized = cliVersion.trim().replace(/^v/, "");
|
|
823
844
|
if (/^\d+\.\d+\.\d+-alpha\.\d+$/.test(normalized)) return normalized;
|
|
@@ -973,17 +994,9 @@ var Orca = class {
|
|
|
973
994
|
throw error;
|
|
974
995
|
}
|
|
975
996
|
}
|
|
976
|
-
/**
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
*/
|
|
980
|
-
async isEmpty(cwd) {
|
|
981
|
-
try {
|
|
982
|
-
await readFile(join(cwd, "package.json"), "utf8");
|
|
983
|
-
return false;
|
|
984
|
-
} catch {
|
|
985
|
-
return true;
|
|
986
|
-
}
|
|
997
|
+
/** Whether `cwd` is safe for an in-place framework scaffold. */
|
|
998
|
+
async isFreshScaffoldTarget(cwd) {
|
|
999
|
+
return (await inspectScaffoldTarget(cwd)).scaffoldable;
|
|
987
1000
|
}
|
|
988
1001
|
/**
|
|
989
1002
|
* Creates a new `framework` project in `cwd`, then re-detects it to return
|
|
@@ -992,8 +1005,17 @@ var Orca = class {
|
|
|
992
1005
|
* scaffolder supports the framework.
|
|
993
1006
|
*/
|
|
994
1007
|
async scaffold(cwd, framework) {
|
|
995
|
-
|
|
996
|
-
|
|
1008
|
+
const target = await inspectScaffoldTarget(cwd);
|
|
1009
|
+
if (!target.scaffoldable) throw new ZitadelError("E_CONFLICT", `Cannot scaffold: ${cwd} is not empty`, {
|
|
1010
|
+
hint: target.reason ?? "Run setup in an empty directory, or run setup from an existing supported app project.",
|
|
1011
|
+
details: { entries: target.entries }
|
|
1012
|
+
});
|
|
1013
|
+
const stash = target.hasRuntimeOnlyZitadel ? await stashRuntimeOnlyZitadel(cwd) : void 0;
|
|
1014
|
+
try {
|
|
1015
|
+
await this.scaffolderFor(framework).scaffold(cwd, framework);
|
|
1016
|
+
} finally {
|
|
1017
|
+
await restoreRuntimeOnlyZitadel(cwd, stash);
|
|
1018
|
+
}
|
|
997
1019
|
return this.detect(cwd, framework);
|
|
998
1020
|
}
|
|
999
1021
|
/**
|
|
@@ -1029,7 +1051,91 @@ var Orca = class {
|
|
|
1029
1051
|
function createOrca() {
|
|
1030
1052
|
return new Orca(detectors, scaffolders, patchers);
|
|
1031
1053
|
}
|
|
1054
|
+
async function inspectScaffoldTarget(cwd) {
|
|
1055
|
+
const entries = await readdir(cwd, { withFileTypes: true });
|
|
1056
|
+
const names = entries.map((entry) => entry.name).sort();
|
|
1057
|
+
let hasRuntimeOnlyZitadel = false;
|
|
1058
|
+
for (const entry of entries) {
|
|
1059
|
+
if (entry.name === ".gitignore") {
|
|
1060
|
+
if (!entry.isFile()) return {
|
|
1061
|
+
scaffoldable: false,
|
|
1062
|
+
hasRuntimeOnlyZitadel: false,
|
|
1063
|
+
reason: ".gitignore exists but is not a file.",
|
|
1064
|
+
entries: names
|
|
1065
|
+
};
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
if (entry.name === ".zitadel") {
|
|
1069
|
+
if (!entry.isDirectory() || !await isRuntimeOnlyZitadelDir(join(cwd, ".zitadel"))) return {
|
|
1070
|
+
scaffoldable: false,
|
|
1071
|
+
hasRuntimeOnlyZitadel: false,
|
|
1072
|
+
reason: ".zitadel contains project state. Move it aside or run setup from an empty app directory.",
|
|
1073
|
+
entries: names
|
|
1074
|
+
};
|
|
1075
|
+
hasRuntimeOnlyZitadel = true;
|
|
1076
|
+
continue;
|
|
1077
|
+
}
|
|
1078
|
+
return {
|
|
1079
|
+
scaffoldable: false,
|
|
1080
|
+
hasRuntimeOnlyZitadel: false,
|
|
1081
|
+
reason: `Directory contains ${entry.name}. Run setup from an empty directory to scaffold a new app.`,
|
|
1082
|
+
entries: names
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
return {
|
|
1086
|
+
scaffoldable: true,
|
|
1087
|
+
hasRuntimeOnlyZitadel,
|
|
1088
|
+
entries: names
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
async function isRuntimeOnlyZitadelDir(path) {
|
|
1092
|
+
const entries = await readdir(path, { withFileTypes: true });
|
|
1093
|
+
if (entries.length !== 1 || entries[0]?.name !== "local" || !entries[0].isDirectory()) return false;
|
|
1094
|
+
return true;
|
|
1095
|
+
}
|
|
1096
|
+
async function stashRuntimeOnlyZitadel(cwd) {
|
|
1097
|
+
const source = join(cwd, ".zitadel");
|
|
1098
|
+
const stash = join(dirname(cwd), `${`.${basename(cwd)}.zitadel-local-stash`}-${String(process.pid)}-${String(Date.now())}`);
|
|
1099
|
+
await rename(source, stash);
|
|
1100
|
+
return stash;
|
|
1101
|
+
}
|
|
1102
|
+
async function restoreRuntimeOnlyZitadel(cwd, stash) {
|
|
1103
|
+
if (!stash) return;
|
|
1104
|
+
const target = join(cwd, ".zitadel");
|
|
1105
|
+
try {
|
|
1106
|
+
await rename(stash, target);
|
|
1107
|
+
await appendGitignoreEntry(cwd, ".zitadel/local/");
|
|
1108
|
+
return;
|
|
1109
|
+
} catch (error) {
|
|
1110
|
+
if (!isErrno(error, "EEXIST")) throw error;
|
|
1111
|
+
}
|
|
1112
|
+
await mkdir(target, {
|
|
1113
|
+
recursive: true,
|
|
1114
|
+
mode: 448
|
|
1115
|
+
});
|
|
1116
|
+
await rename(join(stash, "local"), join(target, "local"));
|
|
1117
|
+
await rm(stash, {
|
|
1118
|
+
recursive: true,
|
|
1119
|
+
force: true
|
|
1120
|
+
});
|
|
1121
|
+
await appendGitignoreEntry(cwd, ".zitadel/local/");
|
|
1122
|
+
}
|
|
1123
|
+
async function appendGitignoreEntry(cwd, entry) {
|
|
1124
|
+
const path = join(cwd, ".gitignore");
|
|
1125
|
+
let existing = "";
|
|
1126
|
+
try {
|
|
1127
|
+
existing = await readFile(path, "utf8");
|
|
1128
|
+
} catch (error) {
|
|
1129
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
1130
|
+
}
|
|
1131
|
+
if (existing.split(/\r?\n/g).map((line) => line.trim()).includes(entry)) return;
|
|
1132
|
+
const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
|
|
1133
|
+
await writeFile(path, `${existing}${prefix}${entry}\n`);
|
|
1134
|
+
}
|
|
1135
|
+
function isErrno(error, code) {
|
|
1136
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
1137
|
+
}
|
|
1032
1138
|
//#endregion
|
|
1033
1139
|
export { RENDERER_IDS as n, issuerFromPort as r, createOrca as t };
|
|
1034
1140
|
|
|
1035
|
-
//# sourceMappingURL=orca-
|
|
1141
|
+
//# sourceMappingURL=orca-BGM8VCgQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orca-BGM8VCgQ.mjs","names":[],"sources":["../src/lib/orca/detectors/package-json.ts","../src/lib/orca/detectors/port.ts","../src/lib/orca/detectors/next.ts","../src/lib/orca/detectors/index.ts","../src/lib/orca/patchers/rule/file-writer/index.ts","../src/lib/orca/patchers/rule/reclaim.ts","../src/lib/orca/patchers/rule/base.ts","../src/lib/orca/patchers/rule/next/renderers/lit/index.ts","../src/lib/orca/patchers/rule/next/renderers/react/index.ts","../src/lib/orca/patchers/rule/next/renderers/registry.ts","../src/lib/orca/patchers/rule/next/index.ts","../src/lib/orca/patchers/index.ts","../src/lib/orca/scaffolders/cli.ts","../src/lib/orca/scaffolders/next.ts","../src/lib/orca/scaffolders/index.ts","../src/lib/orca/index.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\n/**\n * Minimal shape of the `package.json` fields detectors read. Intentionally\n * partial: only the keys detection logic depends on are modeled, all optional\n * since a project may omit any of them.\n */\nexport type PackageJson = {\n name?: string;\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n};\n\n/**\n * Reads and parses the `package.json` at `cwd`. Rejects if the file is absent\n * or malformed; callers that treat those as \"not a project\" are expected to\n * catch and fall back rather than have detection swallow the error here.\n */\nexport async function readPackageJson(cwd: string): Promise<PackageJson> {\n const contents = await readFile(join(cwd, \"package.json\"), \"utf8\");\n return JSON.parse(contents) as PackageJson;\n}\n\n/**\n * Reports whether `name` appears in either `dependencies` or `devDependencies`.\n * Both are checked because framework packages may legitimately live in either.\n */\nexport function hasDependency(pkg: PackageJson, name: string): boolean {\n return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]);\n}\n\nexport function dependencyVersionMajor(pkg: PackageJson, name: string): number | undefined {\n const spec = pkg.dependencies?.[name] ?? pkg.devDependencies?.[name];\n if (!spec) {\n return undefined;\n }\n const match = spec.match(/\\d+/);\n return match ? Number(match[0]) : undefined;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { PackageJson } from \"./package-json\";\n\n/**\n * Port assumed when no explicit dev port can be discovered. Matches Next.js's\n * own default so the inferred issuer URL lines up with `next dev`.\n */\nexport const DEFAULT_DEV_PORT = 3000;\n\n/**\n * Determines the local dev-server port for `cwd`. The `dev` script is the most\n * authoritative source, then a `PORT` declaration in an env file, falling back\n * to {@link DEFAULT_DEV_PORT}. Used to derive the local issuer URL.\n */\nexport async function detectDevPort(cwd: string, pkg: PackageJson): Promise<number> {\n const dev = pkg.scripts?.dev;\n const fromScript = typeof dev === \"string\" ? extractPort(dev) : undefined;\n if (fromScript) {\n return fromScript;\n }\n\n const fromEnvFile = await portFromEnvFile(cwd);\n if (fromEnvFile) {\n return fromEnvFile;\n }\n\n return DEFAULT_DEV_PORT;\n}\n\nasync function portFromEnvFile(cwd: string): Promise<number | undefined> {\n for (const candidate of [\".env.local\", \".env\"]) {\n try {\n const contents = await readFile(join(cwd, candidate), \"utf8\");\n const match = contents.match(/^\\s*PORT\\s*=\\s*(\\d+)/m);\n const rawPort = match?.[1];\n if (rawPort) {\n return Number.parseInt(rawPort, 10);\n }\n } catch {\n continue;\n }\n }\n return undefined;\n}\n\n/**\n * Parses a dev port out of an npm `dev` script string, recognizing both flag\n * forms (`-p`/`--port`) and a leading `PORT=` env assignment. Returns\n * `undefined` when no valid positive port is present so callers can fall back.\n */\nexport function extractPort(script: string): number | undefined {\n const inline = script.match(/-p\\s+(\\d+)|--port[=\\s]+(\\d+)/);\n if (inline) {\n const raw = inline[1] ?? inline[2];\n if (!raw) {\n return undefined;\n }\n const value = Number.parseInt(raw, 10);\n if (Number.isFinite(value) && value > 0) {\n return value;\n }\n }\n const env = script.match(/(?:^|\\s)PORT=(\\d+)/);\n const rawEnvPort = env?.[1];\n if (rawEnvPort) {\n return Number.parseInt(rawEnvPort, 10);\n }\n return undefined;\n}\n\n/**\n * Builds the local OIDC issuer URL for a given dev port. Centralized so the\n * `localhost` origin convention is defined in exactly one place.\n */\nexport function issuerFromPort(port: number): string {\n return `http://localhost:${port}`;\n}\n","import { stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ZitadelError } from \"../../errors\";\nimport { dependencyVersionMajor, hasDependency, readPackageJson } from \"./package-json\";\nimport { detectDevPort, issuerFromPort } from \"./port\";\nimport type { Detector, FrameworkFacts } from \"./types\";\n\n/**\n * Detects a Next.js App Router project and extracts its facts: the App Router\n * directory (`app` vs `src/app`), the dev-server port (parsed from the `dev`\n * script / env file, else 3000), and the derived local issuer URL. Owns every\n * Next-specific assumption so the orchestrator and commands stay generic.\n */\nexport class NextDetector implements Detector {\n readonly framework = \"next\";\n\n /**\n * Returns `null` when `cwd` is not a Next.js project (no `next` dependency),\n * so the orchestrator can try other detectors. Throws\n * `E_UNSUPPORTED_PROJECT_SHAPE` when it is Next.js but lacks an App Router\n * directory (e.g. a Pages Router project), which is a hard error rather than\n * an empty directory to scaffold.\n */\n async detect(cwd: string): Promise<FrameworkFacts | null> {\n const pkg = await readPackageJson(cwd).catch(() => undefined);\n if (!pkg || !hasDependency(pkg, \"next\")) {\n return null;\n }\n\n const appDir = (await dirExists(join(cwd, \"app\")))\n ? \"app\"\n : (await dirExists(join(cwd, \"src/app\")))\n ? \"src/app\"\n : undefined;\n if (!appDir) {\n throw new ZitadelError(\n \"E_UNSUPPORTED_PROJECT_SHAPE\",\n \"Next.js Pages Router projects are not supported in v1\",\n { hint: \"Create an App Router project with an app/ or src/app/ directory.\" },\n );\n }\n\n const devPort = await detectDevPort(cwd, pkg);\n return {\n id: \"next\",\n appDir,\n devPort,\n url: issuerFromPort(devPort),\n versionMajor: dependencyVersionMajor(pkg, \"next\"),\n };\n }\n}\n\nasync function dirExists(path: string): Promise<boolean> {\n try {\n return (await stat(path)).isDirectory();\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: string }).code === \"ENOENT\"\n ) {\n return false;\n }\n throw error;\n }\n}\n","import { NextDetector } from \"./next\";\nimport type { Detector } from \"./types\";\n\n/**\n * Active detectors, in probe order. The orchestrator tries each until one\n * recognises the project. Add a framework by appending its detector here — no\n * orchestrator changes needed.\n */\nexport const detectors = [new NextDetector()] as const satisfies ReadonlyArray<Detector>;\n","import { chmod, mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { ZitadelError } from \"../../../../errors\";\nimport { isObject, parseJsonObject, stableStringify } from \"../../../../json\";\nimport type { FileOp, ScaffoldPlan, ScaffoldResult } from \"./types\";\n\n/**\n * The executor's private, mutable accumulator. Handlers push into it as each\n * op is applied; {@link scaffold} returns it as the readonly\n * {@link ScaffoldResult} so the public result stays immutable.\n */\ntype ScaffoldAccumulator = {\n dryRun: boolean;\n filesWritten: string[];\n filesSkipped: string[];\n depsAdded: string[];\n};\n\n/**\n * Applies a {@link ScaffoldPlan} to disk, executing its operations in order.\n *\n * Operations are idempotent: writes whose target already matches the desired\n * contents are recorded as skipped rather than rewritten, so re-running setup\n * is safe. With `dryRun` no filesystem changes are made but the result still\n * reflects what would have been written. Existing files are only overwritten\n * when `force` is set; otherwise an `E_CONFLICT` is thrown to protect\n * user-authored content. Paths in the plan are resolved relative to `cwd`.\n */\nexport async function scaffold(\n plan: ScaffoldPlan,\n opts: { cwd: string; dryRun: boolean; force: boolean },\n): Promise<ScaffoldResult> {\n const result: ScaffoldAccumulator = {\n dryRun: opts.dryRun,\n filesWritten: [],\n filesSkipped: [],\n depsAdded: [],\n };\n\n for (const op of plan.ops) {\n await applyOp(op, opts, result);\n }\n\n return result;\n}\n\nasync function applyOp(\n op: FileOp,\n opts: { cwd: string; dryRun: boolean; force: boolean },\n result: ScaffoldAccumulator,\n): Promise<void> {\n switch (op.kind) {\n case \"mkdir\":\n await ensureDir(abs(opts.cwd, op.path), op.mode, opts.dryRun, result);\n break;\n case \"write\":\n await writeText(\n abs(opts.cwd, op.path),\n op.contents,\n { mode: op.mode, force: opts.force, dryRun: opts.dryRun },\n result,\n );\n break;\n case \"append\":\n await appendText(abs(opts.cwd, op.path), op.contents, op.ifMissing, opts.dryRun, result);\n break;\n case \"merge-env\":\n await mergeEnv(abs(opts.cwd, op.path), op.entries, opts.dryRun, result);\n break;\n case \"merge-json\":\n await mergeJson(abs(opts.cwd, op.path), op.patch, opts.dryRun, result);\n break;\n case \"append-gitignore\":\n await appendGitignore(abs(opts.cwd, \".gitignore\"), op.entries, opts.dryRun, result);\n break;\n case \"add-dep\":\n await addDependency(abs(opts.cwd, \"package.json\"), op, opts.dryRun, result);\n break;\n }\n}\n\nasync function ensureDir(\n path: string,\n mode: number | undefined,\n dryRun: boolean,\n result: ScaffoldAccumulator,\n): Promise<void> {\n if (dryRun) {\n result.filesWritten.push(path);\n return;\n }\n await mkdir(path, { recursive: true, mode });\n if (mode) {\n await chmod(path, mode).catch(() => undefined);\n }\n result.filesWritten.push(path);\n}\n\nasync function writeText(\n path: string,\n contents: string,\n opts: { mode?: number; force: boolean; dryRun: boolean },\n result: ScaffoldAccumulator,\n): Promise<void> {\n const existing = await readIfExists(path);\n if (existing === contents) {\n result.filesSkipped.push(path);\n return;\n }\n\n if (existing !== undefined && !opts.force) {\n throw new ZitadelError(\"E_CONFLICT\", `Refusing to overwrite ${path}`, {\n hint: \"Re-run with --force if you want the CLI to replace this file.\",\n details: { path },\n });\n }\n\n if (opts.dryRun) {\n result.filesWritten.push(path);\n return;\n }\n\n await mkdir(dirname(path), { recursive: true });\n const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;\n await writeFile(tmp, contents, { mode: opts.mode });\n if (opts.mode) {\n await chmod(tmp, opts.mode).catch(() => undefined);\n }\n await rename(tmp, path);\n result.filesWritten.push(path);\n}\n\nasync function appendText(\n path: string,\n contents: string,\n ifMissing: string | undefined,\n dryRun: boolean,\n result: ScaffoldAccumulator,\n): Promise<void> {\n const existing = (await readIfExists(path)) ?? \"\";\n if (ifMissing && existing.includes(ifMissing)) {\n result.filesSkipped.push(path);\n return;\n }\n\n const next = `${existing}${existing && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\"}${contents}`;\n if (next === existing) {\n result.filesSkipped.push(path);\n return;\n }\n\n if (dryRun) {\n result.filesWritten.push(path);\n return;\n }\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, next);\n result.filesWritten.push(path);\n}\n\nasync function mergeEnv(\n path: string,\n entries: Readonly<Record<string, string>>,\n dryRun: boolean,\n result: ScaffoldAccumulator,\n): Promise<void> {\n const existing = (await readIfExists(path)) ?? \"\";\n const present = new Set(\n existing\n .split(/\\r?\\n/g)\n .map((line) => line.match(/^\\s*([A-Za-z_][A-Za-z0-9_]*)=/)?.[1])\n .filter((value): value is string => Boolean(value)),\n );\n const additions = Object.entries(entries).filter(([key]) => !present.has(key));\n if (additions.length === 0) {\n result.filesSkipped.push(path);\n return;\n }\n\n const block = additions.map(([key, value]) => `${key}=${value}`).join(\"\\n\");\n const next = `${existing}${existing && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\"}${block}\\n`;\n if (dryRun) {\n result.filesWritten.push(path);\n return;\n }\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, next);\n result.filesWritten.push(path);\n}\n\nasync function mergeJson(\n path: string,\n patch: Readonly<Record<string, unknown>>,\n dryRun: boolean,\n result: ScaffoldAccumulator,\n): Promise<void> {\n const existing = await readIfExists(path);\n const current = existing ? parseJsonObject(existing, path) : {};\n const next = deepMerge(current, patch);\n const contents = `${stableStringify(next)}\\n`;\n if (existing === contents) {\n result.filesSkipped.push(path);\n return;\n }\n if (dryRun) {\n result.filesWritten.push(path);\n return;\n }\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, contents);\n result.filesWritten.push(path);\n}\n\nasync function appendGitignore(\n path: string,\n entries: ReadonlyArray<string>,\n dryRun: boolean,\n result: ScaffoldAccumulator,\n): Promise<void> {\n const existing = (await readIfExists(path)) ?? \"\";\n const lines = new Set(existing.split(/\\r?\\n/g).map((line) => line.trim()));\n const missing = entries.filter((entry) => !lines.has(entry));\n if (missing.length === 0) {\n result.filesSkipped.push(path);\n return;\n }\n const next = `${existing}${existing && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\"}${missing.join(\"\\n\")}\\n`;\n if (dryRun) {\n result.filesWritten.push(path);\n return;\n }\n await writeFile(path, next);\n result.filesWritten.push(path);\n}\n\nasync function addDependency(\n path: string,\n op: { name: string; version: string; dev?: boolean },\n dryRun: boolean,\n result: ScaffoldAccumulator,\n): Promise<void> {\n const existing = await readIfExists(path);\n if (!existing) {\n throw new ZitadelError(\"E_VALIDATION\", \"package.json is required to add Zitadel dependencies\");\n }\n const current = parseJsonObject(existing, path);\n const key = op.dev ? \"devDependencies\" : \"dependencies\";\n const deps = isObject(current[key]) ? (current[key] as Record<string, unknown>) : {};\n if (deps[op.name] === op.version) {\n result.filesSkipped.push(path);\n return;\n }\n current[key] = { ...deps, [op.name]: op.version };\n const contents = `${stableStringify(current)}\\n`;\n if (dryRun) {\n result.filesWritten.push(path);\n result.depsAdded.push(op.name);\n return;\n }\n await writeFile(path, contents);\n result.filesWritten.push(path);\n result.depsAdded.push(op.name);\n}\n\nasync function readIfExists(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction abs(cwd: string, path: string): string {\n return join(cwd, path);\n}\n\nfunction deepMerge(\n target: Record<string, unknown>,\n patch: Readonly<Record<string, unknown>>,\n): Record<string, unknown> {\n const out = { ...target };\n for (const [key, value] of Object.entries(patch)) {\n if (isObject(value) && isObject(out[key])) {\n out[key] = deepMerge(out[key] as Record<string, unknown>, value);\n } else {\n out[key] = value;\n }\n }\n return out;\n}\n","import { MANAGED_MARKER } from \"../../../paths\";\nimport type { FileOp, ScaffoldPlan } from \"./file-writer/types\";\n\n/**\n * The subset of a patcher plan's operations that `doctor --fix` re-applies:\n * env merges, gitignore entries, dependency additions, and marker-bearing\n * managed files (framework routes/middleware). Deliberately excludes the\n * unmarked `.zitadel/` resource writes and `zitadel.json` — those are\n * user-editable and synced by `apply`, so `--fix` must not clobber them.\n *\n * Pure: filters a freshly-allocated list; the input plan is not mutated.\n */\nexport function reclaimableOps(plan: ScaffoldPlan): FileOp[] {\n return plan.ops.filter(\n (op) =>\n op.kind === \"merge-env\" ||\n op.kind === \"append-gitignore\" ||\n op.kind === \"add-dep\" ||\n (op.kind === \"write\" && op.contents.includes(MANAGED_MARKER)),\n );\n}\n","import { stableStringify } from \"../../../json\";\nimport { DEFAULT_SERVER } from \"../../../server\";\nimport { scaffold } from \"./file-writer\";\nimport type { FileOp, ScaffoldPlan } from \"./file-writer/types\";\nimport type {\n EjectActions,\n Patcher,\n PatchContext,\n PatchExecOptions,\n PatchResult,\n PatchView,\n} from \"../types\";\nimport { reclaimableOps } from \"./reclaim\";\n\n/**\n * Base for rule-based (deterministic, template-driven) patchers, as opposed to\n * a future LLM-driven family. It applies the integration by building a\n * file-operation plan and running the file-writer — that strategy stays\n * entirely inside this family, so callers only ever see the family-neutral\n * {@link Patcher} surface. Owns the framework-agnostic `.zitadel/` base files\n * and the shared eject classification; subclasses contribute only their\n * framework-specific routes/middleware.\n */\nexport abstract class AbstractRulePatcher implements Patcher {\n abstract canPatch(framework: string): boolean;\n\n /** Apply the full plan (base `.zitadel/` files + framework routes). */\n async patch(ctx: PatchContext, opts: PatchExecOptions): Promise<PatchResult> {\n return scaffold(this.plan(ctx), opts);\n }\n\n /**\n * Re-apply only the reclaimable subset — env files, gitignore, the SDK\n * dependency, and marker-bearing routes — leaving the user-editable\n * `.zitadel/` resources untouched. Backs `doctor --fix`.\n */\n async repair(ctx: PatchContext, opts: PatchExecOptions): Promise<PatchResult> {\n const plan = this.plan(ctx);\n return scaffold({ ops: reclaimableOps(plan), summary: plan.summary }, opts);\n }\n\n /** Shared base artifacts plus the subclass's marker-bearing route files. */\n artifacts(view: PatchView): EjectActions {\n return {\n markedFiles: this.routeFiles(view),\n rootConfigFiles: [\"zitadel.json\"],\n directories: [\".zitadel\"],\n envBackups: [\".env.local\"],\n dependencies: this.routeDeps(view),\n };\n }\n\n /**\n * The full file-operation plan this patcher would apply. Public so rule-family\n * unit tests can assert the planned ops directly; the generic {@link Patcher}\n * interface deliberately does not expose it (an LLM patcher has no such plan).\n */\n plan(ctx: PatchContext): ScaffoldPlan {\n return {\n ops: [...this.baseOps(ctx), ...this.routeOps(ctx)],\n summary: [this.summary(ctx)],\n };\n }\n\n /**\n * The framework-agnostic `.zitadel/` base files every rule patcher writes:\n * the project secret, `zitadel.json`, env templates, and an empty sync\n * state. The `schemas/` and `flows/` directories are created empty — the\n * server provisions the default user schema and flow definition when the\n * project is created, so nothing is scaffolded into them here. Pure: no\n * filesystem or network.\n */\n private baseOps(ctx: PatchContext): ReadonlyArray<FileOp> {\n return [\n { kind: \"mkdir\", path: \".zitadel\", mode: 0o700 },\n { kind: \"mkdir\", path: \".zitadel/flows\" },\n { kind: \"mkdir\", path: \".zitadel/schemas\" },\n { kind: \"append-gitignore\", entries: [\".zitadel/secret\", \".env*\", \"!.env.example\"] },\n {\n kind: \"write\",\n path: \".zitadel/secret\",\n mode: 0o600,\n contents: `${stableStringify({\n project_id: ctx.project.id,\n project_secret: ctx.project.projectSecret,\n preview_secret: ctx.project.previewSecret,\n preview_origins: ctx.project.previewOrigins,\n created_at: ctx.project.createdAt,\n })}\\n`,\n },\n { kind: \"write\", path: \"zitadel.json\", contents: `${stableStringify(projectConfig(ctx))}\\n` },\n {\n kind: \"merge-env\",\n path: \".env.example\",\n entries: {\n ZITADEL_PROJECT_ID: \"\",\n ZITADEL_ENVIRONMENT: \"\",\n ZITADEL_ISSUER: \"\",\n ZITADEL_URL: \"\",\n NEXT_PUBLIC_ZITADEL_PROJECT_ID: \"\",\n },\n },\n {\n kind: \"merge-env\",\n path: \".env.local\",\n entries: {\n ZITADEL_PROJECT_ID: ctx.project.id,\n ZITADEL_ENVIRONMENT: \"development\",\n ZITADEL_ISSUER: ctx.issuer,\n ZITADEL_URL: ctx.server,\n NEXT_PUBLIC_ZITADEL_PROJECT_ID: ctx.project.id,\n },\n },\n {\n kind: \"write\",\n path: \".zitadel/state.json\",\n contents: `${stableStringify({ framework: ctx.framework.id, resources: {} })}\\n`,\n },\n ];\n }\n\n /** Framework-specific route/middleware write ops plus the SDK dependency. */\n protected abstract routeOps(ctx: PatchContext): ReadonlyArray<FileOp>;\n /** Framework-specific managed (marker-bearing) file paths, for ejection. */\n protected abstract routeFiles(view: PatchView): ReadonlyArray<string>;\n /**\n * The package-manager dependencies the integration added, surfaced in\n * `eject`'s `next_commands` so the user can uninstall them themselves.\n */\n protected abstract routeDeps(view: PatchView): ReadonlyArray<string>;\n /** One-line summary of what the integration scaffolded. */\n protected abstract summary(ctx: PatchContext): { title: string; detail: string };\n}\n\n/** Builds the `zitadel.json` body persisted at the project root. */\nfunction projectConfig(ctx: PatchContext): Record<string, unknown> {\n const environments: Record<string, unknown> = { development: { issuer: ctx.issuer } };\n if (ctx.project.previewOrigins.length > 0) {\n environments.preview = {\n issuer_pattern: ctx.project.previewOrigins.map((origin) => `https://${origin}`),\n };\n }\n return {\n $schema: \"https://schemas.zitadel.com/v2/project.schema.json\",\n project: ctx.project.id,\n server: resolveServerOrigin(ctx.server),\n framework: { id: ctx.framework.id },\n branding: { renderer: ctx.rendererId, attribution: \"visible\" },\n environments,\n };\n}\n\n/** Normalizes a server URL to its origin, falling back to {@link DEFAULT_SERVER}. */\nfunction resolveServerOrigin(source: string): string {\n try {\n return new URL(source).origin;\n } catch {\n return DEFAULT_SERVER;\n }\n}\n","import { MANAGED_MARKER } from \"../../../../../../paths\";\nimport type { RendererSpec } from \"../types\";\n\n/**\n * Placeholder renderer for the `<zitadel-flow>` Lit web component. Declared\n * so the `web-component` renderer id resolves and surfaces a clear\n * \"not yet published\" error, while reserving the integration shape for when\n * `@zitadel/ui-lit` ships. The `authPage` template emits an illustrative\n * page only; this renderer is never selected for real scaffolding because\n * `getRenderer` rejects any `status: \"not-implemented\"` spec.\n */\nexport const litRenderer: RendererSpec = {\n id: \"web-component\",\n displayName: \"Web component (<zitadel-flow>)\",\n status: \"not-implemented\",\n frameworks: [\"next\", \"astro\", \"remix\", \"sveltekit\", \"nuxt\", \"vanilla\"],\n dependency: { name: \"@zitadel/ui-lit\", version: \"workspace:*\" },\n templates: {\n authPage(mode) {\n const purpose = mode === \"login\" ? \"login\" : \"register\";\n return {\n mode,\n contents: `${MANAGED_MARKER}\n// The web component renderer ships a <zitadel-flow> element. Until\n// @zitadel/ui-lit is published, this template only declares the\n// intended integration point. See docs/design/cli/bdui-renderer.md.\nimport \"@zitadel/ui-lit\";\n\nconst environment =\n process.env.ZITADEL_ENVIRONMENT ??\n (process.env.NODE_ENV === \"production\" ? \"production\" : \"development\");\n\nexport default function ${mode === \"login\" ? \"LoginPage\" : \"RegisterPage\"}() {\n return (\n <zitadel-flow\n purpose=\"${purpose}\"\n project-id={process.env.ZITADEL_PROJECT_ID}\n issuer={process.env.ZITADEL_ISSUER}\n environment={environment}\n />\n );\n}\n`,\n };\n },\n },\n};\n","import { MANAGED_MARKER } from \"../../../../../../paths\";\nimport type { RendererSpec } from \"../types\";\n\n/**\n * The Next.js App Router renderer scaffolds `/login`, `/register`, and\n * `/profile` pages that drive the `<zitadel-login>` and `<zitadel-logout>`\n * Lit web components.\n *\n * Each page is a single client component (`\"use client\"`) that, inside a\n * `next/dynamic({ ssr: false })` loader, builds the SDK project handle with\n * `configureZitadel({ projectId, proxyPath: \"/__nextgen\" })` and passes it to\n * the widget via `project={...}`. It also imports\n * `@zitadel/sdk-next/client` for its `customElements.define`\n * side-effect — importing `@zitadel/components` directly would fail on\n * strict-resolution package managers (pnpm, yarn PnP) because the app only\n * declares `sdk-next` as a direct dep. SSR is disabled because Lit's element\n * registration needs a browser.\n *\n * The handle is passed as the `project` DOM property, which relies on React\n * 19's custom-element property binding (the scaffold targets the latest Next /\n * React). The backend URL never reaches the browser: the client talks to the\n * same-origin `/__nextgen` proxy path, and the scaffolded Next request boundary\n * forwards it to `ZITADEL_URL` server-side. `NEXT_PUBLIC_ZITADEL_PROJECT_ID` is\n * public — the project id is not sensitive and the widget needs it to start a\n * flow.\n */\nexport const reactRenderer: RendererSpec = {\n id: \"react\",\n displayName: \"React (Next.js App Router)\",\n status: \"available\",\n frameworks: [\"next\"],\n dependency: { name: \"@zitadel/sdk-next\", version: \"latest\" },\n templates: {\n authPage(mode) {\n const componentName = mode === \"login\" ? \"LoginPage\" : \"RegisterPage\";\n const elementName = mode === \"login\" ? \"ZitadelLogin\" : \"ZitadelRegister\";\n return {\n mode,\n contents: `${MANAGED_MARKER}\n\"use client\";\n\nimport dynamic from \"next/dynamic\";\n\nconst ${elementName} = dynamic(\n async () => {\n const { configureZitadel } = await import(\"@zitadel/sdk-next/client\");\n // Build the SDK project handle and pass it to the component via the\n // \\`project\\` prop. The component reads config from this prop directly, so\n // it works regardless of how the SDK packages are bundled. The backend URL\n // stays server-side — requests go through the proxy path \"/__nextgen\",\n // which the scaffolded request boundary forwards to the Zitadel server.\n const project = configureZitadel({\n projectId: process.env.NEXT_PUBLIC_ZITADEL_PROJECT_ID ?? \"\",\n proxyPath: \"/__nextgen\",\n });\n return function ${elementName}Element() {\n return (\n <zitadel-login\n project={project}\n purpose=\"${mode}\"\n post-sign-in-url=\"/profile\"\n />\n );\n };\n },\n { ssr: false },\n);\n\nexport default function ${componentName}() {\n return (\n <main style={{ minHeight: \"100vh\", display: \"flex\", alignItems: \"center\", justifyContent: \"center\" }}>\n <${elementName} />\n </main>\n );\n}\n`,\n };\n },\n profilePage() {\n return {\n contents: `${MANAGED_MARKER}\n\"use client\";\n\nimport dynamic from \"next/dynamic\";\n\nconst ZitadelLogout = dynamic(\n async () => {\n const { configureZitadel } = await import(\"@zitadel/sdk-next/client\");\n const project = configureZitadel({\n projectId: process.env.NEXT_PUBLIC_ZITADEL_PROJECT_ID ?? \"\",\n proxyPath: \"/__nextgen\",\n });\n return function ZitadelLogoutElement() {\n return (\n <zitadel-logout\n project={project}\n post-sign-out-url=\"/login\"\n />\n );\n };\n },\n { ssr: false },\n);\n\nexport default function ProfilePage() {\n return (\n <main style={{ padding: \"48px\", maxWidth: \"600px\", margin: \"0 auto\" }}>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", marginBottom: \"24px\" }}>\n <h1 style={{ fontSize: \"24px\", fontWeight: 700, margin: 0 }}>Signed in</h1>\n <ZitadelLogout />\n </div>\n <p style={{ color: \"#6b7280\" }}>You are signed in. Use the button above to log out.</p>\n </main>\n );\n}\n`,\n };\n },\n customElementsDts() {\n return {\n contents: `${MANAGED_MARKER}\nimport type React from \"react\";\nimport type { ZitadelProject } from \"@zitadel/sdk-next/client\";\n\ndeclare module \"react\" {\n namespace JSX {\n interface IntrinsicElements {\n \"zitadel-login\": React.HTMLAttributes<HTMLElement> & {\n project?: ZitadelProject;\n \"session-exchange-path\"?: string;\n \"post-sign-in-url\"?: string;\n purpose?: string;\n };\n \"zitadel-logout\": React.HTMLAttributes<HTMLElement> & {\n project?: ZitadelProject;\n \"post-sign-out-url\"?: string;\n };\n }\n }\n}\n`,\n };\n },\n },\n};\n","import { ZitadelError } from \"../../../../../errors\";\nimport { litRenderer } from \"./lit\";\nimport { reactRenderer } from \"./react\";\nimport type { RendererId, RendererSpec } from \"./types\";\n\n/**\n * Runtime mirror of the {@link RendererId} union, used by {@link isRendererId}\n * to validate untrusted strings (a TS union has no runtime presence). Must stay\n * in sync with the {@link RendererId} type.\n */\nexport const RENDERER_IDS: RendererId[] = [\"react\", \"web-component\"];\n\n/**\n * Type guard narrowing an arbitrary value to a {@link RendererId}, used to\n * validate renderer ids read from config before indexing {@link RENDERERS}.\n */\nexport function isRendererId(value: unknown): value is RendererId {\n return typeof value === \"string\" && (RENDERER_IDS as string[]).includes(value);\n}\n\n/**\n * The single source of truth mapping each {@link RendererId} to its spec.\n * Keyed by id so {@link getRenderer} can look up and validate a renderer\n * chosen from persisted config (an arbitrary string) at runtime.\n */\nexport const RENDERERS: Record<RendererId, RendererSpec> = {\n react: reactRenderer,\n \"web-component\": litRenderer,\n};\n\n/**\n * Resolves a renderer id (an untrusted string from config) to its spec,\n * throwing a typed {@link ZitadelError} rather than returning `undefined`\n * so callers get an actionable message. Rejects ids that are unknown\n * (`E_VALIDATION`) or declared-but-unpublished (`E_NOT_IMPLEMENTED`),\n * guaranteeing the returned spec is safe to scaffold from.\n */\nexport function getRenderer(id: string): RendererSpec {\n if (!isRendererId(id)) {\n throw new ZitadelError(\"E_VALIDATION\", `Unknown renderer \"${id}\"`, {\n hint: `Available renderers: ${Object.keys(RENDERERS).join(\", \")}`,\n });\n }\n const renderer = RENDERERS[id];\n if (renderer.status === \"not-implemented\") {\n throw new ZitadelError(\n \"E_NOT_IMPLEMENTED\",\n `Renderer \"${id}\" is declared but not yet published`,\n {\n hint: \"Use --renderer react for now; the <zitadel-flow> web component ships in a later package.\",\n },\n );\n }\n return renderer;\n}\n","import { join } from \"node:path\";\n\nimport { MANAGED_MARKER } from \"../../../../paths\";\nimport type { FileOp } from \"../file-writer/types\";\nimport type { PatchContext, PatchView } from \"../../types\";\nimport { AbstractRulePatcher } from \"../base\";\nimport { getRenderer } from \"./renderers/registry\";\nimport type { RendererSpec } from \"./renderers/types\";\n\n/**\n * Next.js request-boundary file at the project root. Wires `nextgenMiddleware` so the\n * generated project config's `/__nextgen` proxy path is same-origin proxied\n * to `ZITADEL_URL` and `/profile` is gated. Next 16 renamed this convention to\n * `proxy.ts`; older projects keep `middleware.ts`.\n * Carries the managed marker so `doctor --fix` reclaims it and `eject` removes it.\n */\nfunction requestBoundaryTemplate(functionName: \"middleware\" | \"proxy\"): string {\n return `${MANAGED_MARKER}\nimport { nextgenMiddleware } from \"@zitadel/sdk-next/middleware\";\nimport type { NextRequest } from \"next/server\";\n\nexport function ${functionName}(req: NextRequest) {\n return nextgenMiddleware(req, {\n url: process.env.ZITADEL_URL,\n protectedRoutes: [\"/profile\"],\n loginPath: \"/login\",\n });\n}\n\nexport const config = {\n matcher: [\"/__nextgen/:path*\", \"/profile/:path*\"],\n};\n`;\n}\n\n/**\n * Rule-based patcher for the Next.js App Router. Inherits the shared\n * `.zitadel/` base files from {@link AbstractRulePatcher} and contributes the\n * Next routes and request boundary whose templates come from the chosen renderer.\n */\nexport class NextPatcher extends AbstractRulePatcher {\n /** Returns true for Next.js projects. */\n canPatch(framework: string): boolean {\n return framework === \"next\";\n }\n\n protected routeOps(ctx: PatchContext): FileOp[] {\n return nextCodeOps(ctx, getRenderer(ctx.rendererId));\n }\n\n protected routeFiles(view: PatchView): ReadonlyArray<string> {\n return nextCodeFilePaths(view.framework, getRenderer(view.rendererId));\n }\n\n protected routeDeps(view: PatchView): ReadonlyArray<string> {\n return [getRenderer(view.rendererId).dependency.name];\n }\n\n protected summary(ctx: PatchContext): { title: string; detail: string } {\n return {\n title: \"Next.js integration\",\n detail: `Scaffolded login/register/profile routes with renderer \"${ctx.rendererId}\".`,\n };\n }\n}\n\n/**\n * Ordered paths of the framework code files the patcher writes. All carry the\n * managed marker. Shared by {@link NextPatcher.routeOps} (which adds contents)\n * and {@link NextPatcher.routeFiles} (which only needs the paths) so the two\n * cannot drift.\n */\nfunction nextCodeFilePaths(\n framework: PatchView[\"framework\"],\n renderer: RendererSpec,\n): ReadonlyArray<string> {\n const appDir = framework.appDir;\n const paths = [join(appDir, \"login/page.tsx\"), join(appDir, \"register/page.tsx\")];\n if (renderer.templates.profilePage) {\n paths.push(join(appDir, \"profile/page.tsx\"));\n }\n paths.push(join(appDir, `../${requestBoundaryFile(framework).filename}`));\n if (renderer.templates.provider) {\n paths.push(join(appDir, renderer.templates.provider.filename));\n }\n if (renderer.templates.customElementsDts) {\n paths.push(join(appDir, \"../custom-elements.d.ts\"));\n }\n return paths;\n}\n\n/** The Next route/request-boundary write ops plus the SDK dependency. */\nfunction nextCodeOps(ctx: PatchContext, renderer: RendererSpec): FileOp[] {\n const appDir = ctx.framework.appDir;\n const ops: FileOp[] = [\n {\n kind: \"write\",\n path: join(appDir, \"login/page.tsx\"),\n contents: renderer.templates.authPage(\"login\").contents,\n },\n {\n kind: \"write\",\n path: join(appDir, \"register/page.tsx\"),\n contents: renderer.templates.authPage(\"register\").contents,\n },\n ];\n const profile = renderer.templates.profilePage?.();\n if (profile) {\n ops.push({ kind: \"write\", path: join(appDir, \"profile/page.tsx\"), contents: profile.contents });\n }\n const boundary = requestBoundaryFile(ctx.framework);\n ops.push({\n kind: \"write\",\n path: join(appDir, `../${boundary.filename}`),\n contents: requestBoundaryTemplate(boundary.functionName),\n });\n const provider = renderer.templates.provider;\n if (provider) {\n ops.push({ kind: \"write\", path: join(appDir, provider.filename), contents: provider.contents });\n }\n const dts = renderer.templates.customElementsDts?.();\n if (dts) {\n ops.push({\n kind: \"write\",\n path: join(appDir, \"../custom-elements.d.ts\"),\n contents: dts.contents,\n });\n }\n ops.push({\n kind: \"add-dep\",\n name: renderer.dependency.name,\n version: dependencyVersionForCli(ctx.cliVersion, renderer.dependency.version),\n });\n return ops;\n}\n\nfunction requestBoundaryFile(framework: PatchContext[\"framework\"]): {\n filename: \"middleware.ts\" | \"proxy.ts\";\n functionName: \"middleware\" | \"proxy\";\n} {\n if ((framework.versionMajor ?? 0) >= 16) {\n return { filename: \"proxy.ts\", functionName: \"proxy\" };\n }\n return { filename: \"middleware.ts\", functionName: \"middleware\" };\n}\n\nfunction dependencyVersionForCli(cliVersion: string, fallback: string): string {\n const normalized = cliVersion.trim().replace(/^v/, \"\");\n if (/^\\d+\\.\\d+\\.\\d+-alpha\\.\\d+$/.test(normalized)) {\n return normalized;\n }\n const prerelease = normalized.match(/^\\d+\\.\\d+\\.\\d+-([0-9A-Za-z]+)(?:[.-]|$)/)?.[1];\n return prerelease ?? fallback;\n}\n","import { NextPatcher } from \"./rule/next\";\nimport type { Patcher } from \"./types\";\n\n/**\n * Active patchers, in priority order; the first whose `canPatch` matches wins.\n *\n * Patchers are grouped by family under subdirectories: `rule/` holds the\n * deterministic, template-driven patchers (extending\n * {@link import(\"./rule/base\").AbstractRulePatcher}). A future LLM-driven\n * family lives under `llm/` and registers its concrete patchers here — no\n * orchestrator or command changes needed. Only Next.js is supported today.\n */\nexport const patchers = [new NextPatcher()] as const satisfies ReadonlyArray<Patcher>;\n","import { spawnSync } from \"node:child_process\";\n\nimport { ZitadelError } from \"../../errors\";\nimport type { Scaffolder } from \"./types\";\n\n/**\n * Base for scaffolders that delegate to an external CLI (e.g. create-next-app).\n * Subclasses implement {@link scaffold} and call {@link runCommand}.\n */\nexport abstract class AbstractCLIScaffolder implements Scaffolder {\n abstract readonly displayName: string;\n abstract readonly supportedFrameworks: ReadonlyArray<string>;\n\n /** True when the requested framework is in {@link supportedFrameworks}. */\n canScaffold(framework: string): boolean {\n return this.supportedFrameworks.includes(framework);\n }\n\n abstract scaffold(cwd: string, framework: string): Promise<void>;\n\n /**\n * Runs an external command in `cwd`, throwing a typed {@link ZitadelError} on\n * failure so the cause surfaces as a categorized CLI error. Distinguishes\n * \"binary not on PATH\" (`ENOENT` from the spawn itself) from \"binary ran but\n * exited non-zero\" — the former previously got masked as a generic\n * `exited with status 1`, leaving users to guess. Tests stub\n * `node:child_process` to assert the command without spawning.\n */\n protected runCommand(command: string, args: ReadonlyArray<string>, cwd: string): void {\n const result = spawnSync(command, [...args], { cwd, encoding: \"utf8\" });\n if (result.error) {\n const err = result.error as NodeJS.ErrnoException;\n const notFound = err.code === \"ENOENT\";\n throw new ZitadelError(\n \"E_VALIDATION\",\n notFound ? `Command not found: ${command}` : `Failed to spawn \"${command}\": ${err.message}`,\n {\n hint: notFound ? `Ensure '${command}' is installed and on PATH.` : undefined,\n details: { command, args: [...args], code: err.code },\n },\n );\n }\n const status = result.status ?? 1;\n if (status !== 0) {\n const stdout = String(result.stdout ?? \"\");\n const stderr = String(result.stderr ?? \"\");\n const output = truncateCommandOutput([stderr, stdout].filter(Boolean).join(\"\\n\").trim());\n throw new ZitadelError(\n \"E_VALIDATION\",\n `Command \"${command} ${args.join(\" \")}\" exited with status ${String(status)}`,\n {\n hint: output ? `Command output:\\n${output}` : \"Run the command directly for more detail.\",\n details: { command, args: [...args], cwd, stdout, stderr },\n },\n );\n }\n }\n}\n\nfunction truncateCommandOutput(output: string): string {\n const limit = 4000;\n if (output.length <= limit) {\n return output;\n }\n return `${output.slice(0, limit)}\\n... output truncated ...`;\n}\n","import { AbstractCLIScaffolder } from \"./cli\";\n\nconst CREATE_NEXT_APP_VERSION = \"16.2.4\";\n\n/** Scaffolds a new Next.js App Router project with `create-next-app`. */\nexport class NextScaffolder extends AbstractCLIScaffolder {\n readonly displayName = \"Next.js\";\n readonly supportedFrameworks: ReadonlyArray<string> = [\"next\"];\n\n /**\n * Runs the pinned `create-next-app` version in `cwd`, creating a TypeScript\n * App Router project in place. `--yes` accepts all defaults so the command\n * runs unattended, and `--skip-install` leaves dependency installation to the\n * setup command's explicit next step after Zitadel patches package.json.\n */\n async scaffold(cwd: string, _framework: string): Promise<void> {\n this.runCommand(\n \"npx\",\n [\n \"--yes\",\n `create-next-app@${CREATE_NEXT_APP_VERSION}`,\n \".\",\n \"--ts\",\n \"--app\",\n \"--use-npm\",\n \"--disable-git\",\n \"--yes\",\n \"--skip-install\",\n ],\n cwd,\n );\n }\n}\n","import { NextScaffolder } from \"./next\";\nimport type { Scaffolder } from \"./types\";\n\n/**\n * Active scaffolders, in priority order. The framework picker derives its\n * choices from this list. Add a new framework by appending its scaffolder\n * here — no orchestrator changes needed.\n */\nexport const scaffolders = [new NextScaffolder()] as const satisfies ReadonlyArray<Scaffolder>;\n","import { mkdir, readdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport { ZitadelError } from \"../errors\";\nimport { detectors } from \"./detectors\";\nimport type { Detector, FrameworkFacts } from \"./detectors/types\";\nimport { patchers } from \"./patchers\";\nimport type { Patcher } from \"./patchers/types\";\nimport { scaffolders } from \"./scaffolders\";\nimport type { Scaffolder } from \"./scaffolders/types\";\n\nexport type { Detector, FrameworkFacts } from \"./detectors/types\";\nexport { issuerFromPort } from \"./detectors/port\";\n\n/** One framework the CLI can scaffold from scratch, surfaced to the picker. */\nexport type FrameworkChoice = Readonly<{ id: string; displayName: string }>;\n\nexport type ScaffoldTarget = Readonly<{\n scaffoldable: boolean;\n hasRuntimeOnlyZitadel: boolean;\n reason?: string;\n entries: ReadonlyArray<string>;\n}>;\n\n/**\n * Orchestrates the three per-framework strategies — detectors (recognise an\n * existing project and extract its facts), scaffolders (create a project), and\n * patchers (integrate Zitadel) — over their respective registries. It resolves\n * the right strategy for a framework and drives the detect/scaffold lifecycle;\n * how a patcher applies its work (file operations vs an LLM agent) stays\n * internal to that patcher. Registries are injected so tests can supply fakes.\n */\nexport class Orca {\n constructor(\n private readonly detectors: ReadonlyArray<Detector>,\n private readonly scaffolders: ReadonlyArray<Scaffolder>,\n private readonly patchers: ReadonlyArray<Patcher>,\n ) {}\n\n /**\n * Detects the framework in `cwd` and extracts its {@link FrameworkFacts},\n * honouring an explicit `requested` framework. Throws\n * `E_FRAMEWORK_NOT_DETECTED` when nothing matches; a detector's\n * `E_UNSUPPORTED_PROJECT_SHAPE` (recognised but unsupported) propagates.\n */\n async detect(cwd: string, requested?: string): Promise<FrameworkFacts> {\n const candidates = requested\n ? this.detectors.filter((detector) => detector.framework === requested)\n : this.detectors;\n if (requested && candidates.length === 0) {\n throw new ZitadelError(\"E_FRAMEWORK_NOT_DETECTED\", `Unsupported framework \"${requested}\"`, {\n hint: `Supported frameworks: ${this.frameworkIds().join(\", \")}.`,\n });\n }\n for (const detector of candidates) {\n const facts = await detector.detect(cwd);\n if (facts) {\n return facts;\n }\n }\n throw new ZitadelError(\n \"E_FRAMEWORK_NOT_DETECTED\",\n \"Could not detect a supported app framework\",\n {\n hint: \"Run setup from your app project directory, pass --cwd <path-to-app>, or run setup from an empty directory to scaffold a new app.\",\n },\n );\n }\n\n /**\n * Non-throwing detection: returns `undefined` instead of raising for a\n * project that is absent, unrecognised, or recognised-but-unsupported, so\n * callers (e.g. `eject`) can probe and degrade gracefully.\n */\n async tryDetect(cwd: string): Promise<FrameworkFacts | undefined> {\n try {\n return await this.detect(cwd);\n } catch (error) {\n if (\n error instanceof ZitadelError &&\n (error.code === \"E_FRAMEWORK_NOT_DETECTED\" || error.code === \"E_UNSUPPORTED_PROJECT_SHAPE\")\n ) {\n return undefined;\n }\n throw error;\n }\n }\n\n /** Whether `cwd` is safe for an in-place framework scaffold. */\n async isFreshScaffoldTarget(cwd: string): Promise<boolean> {\n return (await inspectScaffoldTarget(cwd)).scaffoldable;\n }\n\n /**\n * Creates a new `framework` project in `cwd`, then re-detects it to return\n * the resulting {@link FrameworkFacts}. Throws `E_CONFLICT` when the directory\n * already contains a project (\"already scaffolded\") and `E_VALIDATION` when no\n * scaffolder supports the framework.\n */\n async scaffold(cwd: string, framework: string): Promise<FrameworkFacts> {\n const target = await inspectScaffoldTarget(cwd);\n if (!target.scaffoldable) {\n throw new ZitadelError(\"E_CONFLICT\", `Cannot scaffold: ${cwd} is not empty`, {\n hint:\n target.reason ??\n \"Run setup in an empty directory, or run setup from an existing supported app project.\",\n details: { entries: target.entries },\n });\n }\n const stash = target.hasRuntimeOnlyZitadel ? await stashRuntimeOnlyZitadel(cwd) : undefined;\n try {\n await this.scaffolderFor(framework).scaffold(cwd, framework);\n } finally {\n await restoreRuntimeOnlyZitadel(cwd, stash);\n }\n return this.detect(cwd, framework);\n }\n\n /**\n * Resolves the scaffolder for a framework, throwing `E_VALIDATION` (with the\n * available list) when none matches.\n */\n scaffolderFor(framework: string): Scaffolder {\n const scaffolder = this.scaffolders.find((candidate) => candidate.canScaffold(framework));\n if (!scaffolder) {\n throw new ZitadelError(\"E_VALIDATION\", `No scaffolder supports \"${framework}\"`, {\n hint: `Available frameworks: ${this.availableFrameworks()\n .map((f) => f.id)\n .join(\", \")}.`,\n });\n }\n return scaffolder;\n }\n\n /**\n * Resolves the patcher for a framework, throwing `E_VALIDATION` when none\n * matches (e.g. a framework that can be scaffolded but not yet integrated).\n */\n patcherFor(framework: string): Patcher {\n const patcher = this.patchers.find((candidate) => candidate.canPatch(framework));\n if (!patcher) {\n throw new ZitadelError(\"E_VALIDATION\", `No patcher supports \"${framework}\"`, {\n hint: \"Zitadel integration currently supports Next.js.\",\n });\n }\n return patcher;\n }\n\n /** The frameworks that can be scaffolded, derived from the scaffolder registry. */\n availableFrameworks(): ReadonlyArray<FrameworkChoice> {\n return this.scaffolders.map((scaffolder) => ({\n id: scaffolder.supportedFrameworks[0] ?? scaffolder.displayName,\n displayName: scaffolder.displayName,\n }));\n }\n\n private frameworkIds(): ReadonlyArray<string> {\n return this.detectors.map((detector) => detector.framework);\n }\n}\n\n/** {@link Orca} wired with the default detector, scaffolder, and patcher registries. */\nexport function createOrca(): Orca {\n return new Orca(detectors, scaffolders, patchers);\n}\n\nexport async function inspectScaffoldTarget(cwd: string): Promise<ScaffoldTarget> {\n const entries = await readdir(cwd, { withFileTypes: true });\n const names = entries.map((entry) => entry.name).sort();\n let hasRuntimeOnlyZitadel = false;\n\n for (const entry of entries) {\n if (entry.name === \".gitignore\") {\n if (!entry.isFile()) {\n return {\n scaffoldable: false,\n hasRuntimeOnlyZitadel: false,\n reason: \".gitignore exists but is not a file.\",\n entries: names,\n };\n }\n continue;\n }\n\n if (entry.name === \".zitadel\") {\n if (!entry.isDirectory() || !(await isRuntimeOnlyZitadelDir(join(cwd, \".zitadel\")))) {\n return {\n scaffoldable: false,\n hasRuntimeOnlyZitadel: false,\n reason:\n \".zitadel contains project state. Move it aside or run setup from an empty app directory.\",\n entries: names,\n };\n }\n hasRuntimeOnlyZitadel = true;\n continue;\n }\n\n return {\n scaffoldable: false,\n hasRuntimeOnlyZitadel: false,\n reason: `Directory contains ${entry.name}. Run setup from an empty directory to scaffold a new app.`,\n entries: names,\n };\n }\n\n return { scaffoldable: true, hasRuntimeOnlyZitadel, entries: names };\n}\n\nasync function isRuntimeOnlyZitadelDir(path: string): Promise<boolean> {\n const entries = await readdir(path, { withFileTypes: true });\n if (entries.length !== 1 || entries[0]?.name !== \"local\" || !entries[0].isDirectory()) {\n return false;\n }\n return true;\n}\n\nasync function stashRuntimeOnlyZitadel(cwd: string): Promise<string> {\n const source = join(cwd, \".zitadel\");\n const parent = dirname(cwd);\n const prefix = `.${basename(cwd)}.zitadel-local-stash`;\n const stash = join(parent, `${prefix}-${String(process.pid)}-${String(Date.now())}`);\n await rename(source, stash);\n return stash;\n}\n\nasync function restoreRuntimeOnlyZitadel(cwd: string, stash: string | undefined): Promise<void> {\n if (!stash) {\n return;\n }\n const target = join(cwd, \".zitadel\");\n try {\n await rename(stash, target);\n await appendGitignoreEntry(cwd, \".zitadel/local/\");\n return;\n } catch (error) {\n if (!isErrno(error, \"EEXIST\")) {\n throw error;\n }\n }\n\n await mkdir(target, { recursive: true, mode: 0o700 });\n await rename(join(stash, \"local\"), join(target, \"local\"));\n await rm(stash, { recursive: true, force: true });\n await appendGitignoreEntry(cwd, \".zitadel/local/\");\n}\n\nasync function appendGitignoreEntry(cwd: string, entry: string): Promise<void> {\n const path = join(cwd, \".gitignore\");\n let existing = \"\";\n try {\n existing = await readFile(path, \"utf8\");\n } catch (error) {\n if (!isErrno(error, \"ENOENT\")) {\n throw error;\n }\n }\n\n const lines = existing.split(/\\r?\\n/g).map((line) => line.trim());\n if (lines.includes(entry)) {\n return;\n }\n const prefix = existing.length === 0 || existing.endsWith(\"\\n\") ? \"\" : \"\\n\";\n await writeFile(path, `${existing}${prefix}${entry}\\n`);\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: unknown }).code === code\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as isObject, E as ZitadelError, w as parseJsonObject } from "./oclif-
|
|
1
|
+
import { C as isObject, E as ZitadelError, w as parseJsonObject } from "./oclif-B3Qhw0cj.mjs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { readFile, stat } from "node:fs/promises";
|
|
4
4
|
//#region src/lib/project.ts
|
|
@@ -84,4 +84,4 @@ function isNotFound(error) {
|
|
|
84
84
|
//#endregion
|
|
85
85
|
export { readZitadelConfig as a, readRendererId as i, hasZitadelSecret as n, readZitadelSecret as o, readDevelopmentIssuer as r, hasZitadelConfig as t };
|
|
86
86
|
|
|
87
|
-
//# sourceMappingURL=project-
|
|
87
|
+
//# sourceMappingURL=project-kWWyS7fS.mjs.map
|