@plenary/cli 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1062,14 +1062,57 @@ call.`
1062
1062
  if (flags.publish) entry = await publish(ctx, entry.id, "publish");
1063
1063
  report(ctx, entry, "updated");
1064
1064
  });
1065
- entries.command("delete").description("Delete an entry (recoverable from history while the model tracks revisions)").argument("<id>").option("--note <text>", "revision note").option("-y, --yes", "do not ask").action(async (id, flags, cmd) => {
1065
+ entries.command("archive").description("Archive an entry (restorable from the console's Archived view while the model tracks revisions)").argument("<id>").option("--note <text>", "revision note").option("-y, --yes", "do not ask").action(async (id, flags, cmd) => {
1066
1066
  const ctx = resolveContext(cmd.optsWithGlobals(), io);
1067
- await confirm(io, `Delete entry ${id}?`, Boolean(flags.yes));
1067
+ await confirm(io, `Archive entry ${id}?`, Boolean(flags.yes));
1068
1068
  await request(ctx, "DELETE", `content/${encodeURIComponent(id)}`, { query: { note: flags.note } });
1069
+ if (ctx.json) io.stdout.write(toJson({ id, archived: true }) + "\n");
1070
+ else io.stdout.write(`archived ${id}
1071
+ `);
1072
+ });
1073
+ entries.command("delete").description("Permanently delete an entry and its revision history (a live or an archived one); cannot be undone").argument("<id>").option("--permanent", "required this release: delete used to archive, which is now 'entries archive'").option("-y, --yes", "do not ask").action(async (id, flags, cmd) => {
1074
+ const ctx = resolveContext(cmd.optsWithGlobals(), io);
1075
+ if (!flags.permanent) {
1076
+ throw usageError(
1077
+ "entries delete now deletes permanently: pass --permanent, or use 'plenary entries archive' for what delete did before"
1078
+ );
1079
+ }
1080
+ await confirm(io, `Permanently delete entry ${id} and its history? This cannot be undone.`, Boolean(flags.yes));
1081
+ await request(ctx, "DELETE", `content/${encodeURIComponent(id)}`, { query: { permanent: "true" } });
1069
1082
  if (ctx.json) io.stdout.write(toJson({ id, deleted: true }) + "\n");
1070
1083
  else io.stdout.write(`deleted ${id}
1071
1084
  `);
1072
1085
  });
1086
+ entries.command("archived").description("List a model's archived entries, newest first").argument("<model>").option("--limit <n>", "page size (max 200)").option("--offset <n>", "rows to skip").action(async (model, flags, cmd) => {
1087
+ const ctx = resolveContext(cmd.optsWithGlobals(), io);
1088
+ const siteKey = requireSiteKey(ctx);
1089
+ const res = await request(ctx, "GET", `content/${encodeURIComponent(model)}/entries/archived`, {
1090
+ query: { site_key: siteKey, limit: flags.limit, offset: flags.offset }
1091
+ });
1092
+ if (ctx.json) {
1093
+ io.stdout.write(toJson(res.data) + "\n");
1094
+ return;
1095
+ }
1096
+ const rows = res.data.map((r) => [r.id, r.slug ?? "", r.title ?? "", r.archived_at, r.actor.label]);
1097
+ io.stdout.write(formatTable(rows, ["ID", "SLUG", "TITLE", "ARCHIVED", "BY"]) + "\n");
1098
+ const total = res.headers.get("X-Total-Count");
1099
+ if (total !== null) io.stdout.write(`${res.data.length} of ${total}
1100
+ `);
1101
+ });
1102
+ entries.command("restore").description("Restore an archived entry; it comes back as a draft under its original id").argument("<id>").option("--note <text>", "revision note").action(async (id, flags, cmd) => {
1103
+ const ctx = resolveContext(cmd.optsWithGlobals(), io);
1104
+ const [newest] = (await request(ctx, "GET", `content/${encodeURIComponent(id)}/revisions`, {
1105
+ query: { limit: "1" }
1106
+ })).data;
1107
+ if (!newest) throw usageError(`entry ${id} has no history to restore from`);
1108
+ if (newest.action !== "delete") {
1109
+ throw usageError(`entry ${id} is not archived: its newest revision is a ${newest.action}`);
1110
+ }
1111
+ const entry = (await request(ctx, "POST", `revisions/${encodeURIComponent(newest.id)}/restore`, {
1112
+ body: flags.note === void 0 ? {} : { note: flags.note }
1113
+ })).data;
1114
+ report(ctx, entry, "restored");
1115
+ });
1073
1116
  entries.command("publish").description("Publish an entry now; on a published entry, make its pending changes live").argument("<id>").action(async (id, _flags, cmd) => {
1074
1117
  const ctx = resolveContext(cmd.optsWithGlobals(), io);
1075
1118
  report(ctx, await publish(ctx, id, "publish"), "published");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/output.ts","../src/errors.ts","../src/config.ts","../src/api/http.ts","../src/session.ts","../src/input.ts","../src/entries/client.ts","../src/commands/admin.ts","../src/commands/api.ts","../src/commands/auth.ts","../src/commands/catalog.ts","../src/commands/entries.ts","../src/entries/query.ts","../src/commands/folders.ts","../src/commands/formentries.ts","../src/commands/media.ts","../src/commands/metadata.ts","../src/metadata/dir.ts","../src/metadata/plan.ts","../src/commands/init.ts","../src/commands/status.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { Command, CommanderError } from \"commander\";\nimport type { Io } from \"./config.js\";\nimport { describeError, exitCodeFor } from \"./output.js\";\nimport { registerAdmin } from \"./commands/admin.js\";\nimport { registerApi } from \"./commands/api.js\";\nimport { registerAuth } from \"./commands/auth.js\";\nimport { registerCatalog } from \"./commands/catalog.js\";\nimport { registerEntries } from \"./commands/entries.js\";\nimport { registerContentFolders } from \"./commands/folders.js\";\nimport { registerFormEntries } from \"./commands/formentries.js\";\nimport { registerMedia } from \"./commands/media.js\";\nimport { registerMetadata } from \"./commands/metadata.js\";\nimport { registerInit } from \"./commands/init.js\";\nimport { registerStatus } from \"./commands/status.js\";\n\nfunction version(): string {\n try {\n const pkg = JSON.parse(readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\")) as { version: string };\n return pkg.version;\n } catch {\n return \"0.0.0\";\n }\n}\n\nexport function createProgram(io: Io): Command {\n const program = new Command(\"plenary\")\n .description(\"Command-line client for the Plenary API\")\n .version(version(), \"-v, --version\")\n .option(\"--base-url <url>\", \"instance URL (PLENARY_BASE_URL)\")\n .option(\"--api-key <key>\", \"API key (PLENARY_CLI_API_KEY)\")\n .option(\"--site <key>\", \"site key (PLENARY_SITE_KEY)\")\n .option(\"--locale <code>\", \"locale (PLENARY_LOCALE)\")\n .option(\"--config <path>\", \"plenary.json to use (default: nearest, searching upward)\")\n .option(\"--json\", \"print machine-readable JSON\")\n .option(\"--debug\", \"print requests and stack traces to stderr\")\n .showHelpAfterError(\"(run with --help for usage)\")\n .exitOverride()\n .configureOutput({\n writeOut: (s) => io.stdout.write(s),\n writeErr: (s) => io.stderr.write(s),\n });\n\n registerInit(program, io);\n registerAuth(program, io);\n registerStatus(program, io);\n registerMetadata(program, io);\n registerCatalog(program, io, \"models\");\n registerFormEntries(registerCatalog(program, io, \"forms\"), io);\n registerEntries(program, io);\n registerContentFolders(program, io);\n registerMedia(program, io);\n registerAdmin(program, io);\n registerApi(program, io);\n return program;\n}\n\n/** Runs one invocation and returns the exit code; never throws. */\nexport async function run(argv: string[], io: Io): Promise<number> {\n const program = createProgram(io);\n try {\n await program.parseAsync(argv, { from: \"user\" });\n return 0;\n } catch (err) {\n if (err instanceof CommanderError) {\n // Commander has already written help or its own message.\n return exitCodeFor(err);\n }\n const debug = Boolean(program.opts<{ debug?: boolean }>().debug);\n const message = describeError(err, debug);\n if (message !== \"plenary: \") io.stderr.write(message + \"\\n\");\n return exitCodeFor(err);\n }\n}\n","import { PlenaryError } from \"@plenary/client\";\nimport { CommanderError } from \"commander\";\nimport { CliError } from \"./errors.js\";\n\n/** Renders rows as aligned columns; the first row is the header when `header` is set. */\nexport function formatTable(rows: string[][], header?: string[]): string {\n const all = header ? [header, ...rows] : rows;\n if (all.length === 0) return \"\";\n const widths: number[] = [];\n for (const row of all) {\n row.forEach((cell, i) => {\n widths[i] = Math.max(widths[i] ?? 0, cell.length);\n });\n }\n return all\n .map((row) =>\n row\n .map((cell, i) => (i === row.length - 1 ? cell : cell.padEnd(widths[i] ?? 0)))\n .join(\" \")\n .trimEnd(),\n )\n .join(\"\\n\");\n}\n\nexport function toJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\n/** One line for stderr describing why a command failed. */\nexport function describeError(err: unknown, debug = false): string {\n if (err instanceof PlenaryError) {\n let line = `plenary: ${err.code} (HTTP ${err.status})`;\n if (err.vars && Object.keys(err.vars).length > 0) {\n line += \"\\n\" + Object.entries(err.vars).map(([k, v]) => ` ${k}: ${fmtVar(v)}`).join(\"\\n\");\n }\n return line;\n }\n if (err instanceof CliError) return `plenary: ${err.message}`;\n if (err instanceof Error) {\n const cause = err.cause instanceof Error ? `: ${err.cause.message}` : \"\";\n return debug && err.stack ? err.stack : `plenary: ${err.message}${cause}`;\n }\n return `plenary: ${String(err)}`;\n}\n\nexport function exitCodeFor(err: unknown): number {\n if (err instanceof CliError) return err.exitCode;\n if (err instanceof CommanderError) return err.exitCode === 0 ? 0 : 2;\n return 1;\n}\n\nfunction fmtVar(v: unknown): string {\n return typeof v === \"string\" ? v : JSON.stringify(v);\n}\n","/**\n * An error the CLI raised itself (as opposed to one the server returned).\n * exitCode 2 is a usage problem — a missing credential, a malformed flag —\n * and 1 is everything else.\n */\nexport class CliError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode = 1) {\n super(message);\n this.name = \"CliError\";\n this.exitCode = exitCode;\n }\n}\n\nexport function usageError(message: string): CliError {\n return new CliError(message, 2);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { usageError } from \"./errors.js\";\n\n/** The streams and environment a run reads and writes — injected so tests can capture them. */\nexport interface Io {\n stdout: NodeJS.WritableStream;\n stderr: NodeJS.WritableStream;\n stdin: NodeJS.ReadableStream;\n env: NodeJS.ProcessEnv;\n cwd: string;\n fetch: typeof globalThis.fetch;\n /** Whether stdin is a terminal: prompts are only ever issued when it is. */\n isTTY: boolean;\n}\n\n/** The global options every command accepts (declared on the root program). */\nexport interface GlobalOptions {\n baseUrl?: string;\n apiKey?: string;\n site?: string;\n locale?: string;\n config?: string;\n json?: boolean;\n debug?: boolean;\n}\n\n/** The shape of `plenary.json`. Never holds a credential. */\nexport interface ProjectConfig {\n baseUrl?: string;\n siteKey?: string;\n locale?: string;\n metadataDir?: string;\n}\n\n/** Everything a command needs, resolved once per invocation. */\nexport interface Context {\n io: Io;\n baseUrl?: string;\n apiKey?: string;\n siteKey?: string;\n locale?: string;\n metadataDir: string;\n /** The directory holding plenary.json, or the cwd when there is none. */\n projectRoot: string;\n configPath?: string;\n json: boolean;\n debug: boolean;\n /** The access token minted from a stored session, once this run has one. */\n sessionToken?: string;\n}\n\nexport const CONFIG_FILE = \"plenary.json\";\nexport const DEFAULT_METADATA_DIR = \"plenary\";\n\n/** Walks up from `from` and returns the first plenary.json found, if any. */\nexport function findConfigFile(from: string): string | undefined {\n let dir = path.resolve(from);\n for (;;) {\n const candidate = path.join(dir, CONFIG_FILE);\n if (existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n\nconst CONFIG_KEYS: ReadonlyArray<keyof ProjectConfig> = [\"baseUrl\", \"siteKey\", \"locale\", \"metadataDir\"];\n\nexport function readProjectConfig(file: string): ProjectConfig {\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(file, \"utf8\"));\n } catch (err) {\n throw usageError(`${file}: ${(err as Error).message}`);\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw usageError(`${file}: expected a JSON object`);\n }\n const out: ProjectConfig = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (!(CONFIG_KEYS as readonly string[]).includes(key)) {\n throw usageError(`${file}: unknown key \"${key}\"`);\n }\n if (typeof value !== \"string\") {\n throw usageError(`${file}: \"${key}\" must be a string`);\n }\n out[key as keyof ProjectConfig] = value;\n }\n return out;\n}\n\n/**\n * Reads the PLENARY_* lines of a .env file. Deliberately minimal — `KEY=value`,\n * optional surrounding quotes, `#` comments — because a project that needs\n * more has a real env loader already.\n */\nexport function readDotEnv(file: string): Record<string, string> {\n const out: Record<string, string> = {};\n let text: string;\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return out;\n }\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (line === \"\" || line.startsWith(\"#\")) continue;\n const m = /^(?:export\\s+)?(PLENARY_[A-Z0-9_]+)=(.*)$/.exec(line);\n if (!m) continue;\n let value = (m[2] ?? \"\").trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[m[1] as string] = value;\n }\n return out;\n}\n\n/**\n * Resolves the run context. Precedence, highest first: flag, process\n * environment, `.env` beside plenary.json (or in the cwd), plenary.json,\n * default.\n */\nexport function resolveContext(opts: GlobalOptions, io: Io): Context {\n const configPath = opts.config ? path.resolve(io.cwd, opts.config) : findConfigFile(io.cwd);\n if (opts.config && !existsSync(configPath as string)) {\n throw usageError(`config file not found: ${configPath}`);\n }\n const file = configPath ? readProjectConfig(configPath) : {};\n const projectRoot = configPath ? path.dirname(configPath) : io.cwd;\n const env = { ...readDotEnv(path.join(projectRoot, \".env\")), ...pick(io.env) };\n\n const baseUrl = opts.baseUrl ?? env.PLENARY_BASE_URL ?? file.baseUrl;\n return {\n io,\n baseUrl: baseUrl ? baseUrl.replace(/\\/+$/, \"\") : undefined,\n apiKey: opts.apiKey ?? env.PLENARY_CLI_API_KEY,\n siteKey: opts.site ?? env.PLENARY_SITE_KEY ?? file.siteKey,\n locale: opts.locale ?? env.PLENARY_LOCALE ?? file.locale,\n metadataDir: env.PLENARY_METADATA_DIR ?? file.metadataDir ?? DEFAULT_METADATA_DIR,\n projectRoot,\n configPath,\n json: opts.json ?? false,\n debug: opts.debug ?? false,\n };\n}\n\n/** Only the PLENARY_* variables, and only those actually set. */\nfunction pick(env: NodeJS.ProcessEnv): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n if (k.startsWith(\"PLENARY_\") && v !== undefined && v !== \"\") out[k] = v;\n }\n return out;\n}\n\nexport function requireBaseUrl(ctx: Context): string {\n if (!ctx.baseUrl) {\n throw usageError(\n \"no base URL: pass --base-url, set PLENARY_BASE_URL, or run `plenary init`\",\n );\n }\n return ctx.baseUrl;\n}\n","import { errorFromResponse } from \"@plenary/client\";\nimport { requireBaseUrl, type Context } from \"../config.js\";\nimport { usageError } from \"../errors.js\";\nimport { sessionAccessToken } from \"../session.js\";\n\n/**\n * Which credential a request carries. A configured API key wins over a\n * stored session for content work, so a person's login never silently\n * becomes the actor of a deploy job that also has a key; a session is what\n * admin work needs, since a key can never hold admin:* capabilities.\n */\nexport type AuthMode = \"required\" | \"optional\" | \"none\" | \"session\";\n\nexport async function credentialHeaders(ctx: Context, mode: AuthMode): Promise<Record<string, string>> {\n if (mode === \"none\") return {};\n if (mode === \"session\") {\n const token = await sessionAccessToken(ctx);\n if (!token) throw usageError(\"this command needs a user session: run `plenary login`\");\n return { Authorization: `Bearer ${token}` };\n }\n if (ctx.apiKey) return { \"X-API-KEY\": ctx.apiKey };\n const token = await sessionAccessToken(ctx);\n if (token) return { Authorization: `Bearer ${token}` };\n if (mode === \"required\") {\n throw usageError(\"no credential: pass --api-key, set PLENARY_CLI_API_KEY, or run `plenary login`\");\n }\n return {};\n}\n\nexport interface RequestOptions {\n /** Query parameters; undefined values are dropped. */\n query?: Record<string, string | undefined>;\n /** A JSON body. */\n body?: unknown;\n /** A multipart body; wins over `body`. */\n form?: FormData;\n headers?: Record<string, string>;\n /**\n * \"required\" (default) refuses to run without a credential; \"optional\"\n * sends one when there is one; \"none\" never does (the health check);\n * \"session\" insists on a user login (admin routes).\n */\n auth?: AuthMode;\n /** Return a non-2xx response instead of throwing its PlenaryError. */\n allowError?: boolean;\n}\n\nexport interface ApiResponse<T = unknown> {\n status: number;\n ok: boolean;\n headers: Headers;\n /** The parsed JSON body, the text body for non-JSON responses, or null for 204. */\n data: T;\n}\n\n/** Turns `models` into `/api/v1/models`; a path that already starts with `/` is kept. */\nexport function apiPath(p: string): string {\n return p.startsWith(\"/\") ? p : `/api/v1/${p}`;\n}\n\nexport async function request<T = unknown>(\n ctx: Context,\n method: string,\n path: string,\n opts: RequestOptions = {},\n): Promise<ApiResponse<T>> {\n const base = requireBaseUrl(ctx);\n const headers: Record<string, string> = { ...opts.headers, ...(await credentialHeaders(ctx, opts.auth ?? \"required\")) };\n\n const url = new URL(base + apiPath(path));\n for (const [k, v] of Object.entries(opts.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, v);\n }\n\n let body: RequestInit[\"body\"];\n if (opts.form) {\n body = opts.form;\n } else if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(opts.body);\n }\n\n if (ctx.debug) ctx.io.stderr.write(`> ${method} ${url}\\n`);\n const response = await ctx.io.fetch(url, { method, headers, body });\n const data = await parseBody(response);\n if (ctx.debug) ctx.io.stderr.write(`< ${response.status}\\n`);\n\n if (!response.ok && !opts.allowError) {\n throw errorFromResponse(response.status, data);\n }\n return { status: response.status, ok: response.ok, headers: response.headers, data: data as T };\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n if (response.status === 204) return null;\n const text = await response.text();\n if (text === \"\") return null;\n const type = response.headers.get(\"content-type\") ?? \"\";\n if (type.includes(\"json\")) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return text;\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport type { Context, Io } from \"./config.js\";\nimport { usageError } from \"./errors.js\";\n\n/** What login stores: never an access token, only the refresh token that mints one. */\nexport interface StoredSession {\n refresh_token: string;\n identifier?: string;\n updated_at: string;\n}\n\ntype Store = Record<string, StoredSession>;\n\n/** `$XDG_CONFIG_HOME/plenary/credentials.json`, `~/.config` by default. */\nexport function credentialsPath(io: Io): string {\n const base = io.env.XDG_CONFIG_HOME || path.join(io.env.HOME || homedir(), \".config\");\n return path.join(base, \"plenary\", \"credentials.json\");\n}\n\nfunction readStore(io: Io): Store {\n const file = credentialsPath(io);\n if (!existsSync(file)) return {};\n try {\n const parsed = JSON.parse(readFileSync(file, \"utf8\")) as unknown;\n return typeof parsed === \"object\" && parsed !== null ? (parsed as Store) : {};\n } catch {\n return {};\n }\n}\n\nfunction writeStore(io: Io, store: Store): void {\n const file = credentialsPath(io);\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n // Written whole and renamed into place, so a crash mid-write never leaves\n // a half file where a refresh token used to be.\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(store, null, 2) + \"\\n\", { mode: 0o600 });\n chmodSync(tmp, 0o600);\n renameSync(tmp, file);\n}\n\nexport function loadSession(io: Io, baseUrl: string): StoredSession | undefined {\n return readStore(io)[baseUrl];\n}\n\nexport function saveSession(io: Io, baseUrl: string, session: Omit<StoredSession, \"updated_at\">): void {\n const store = readStore(io);\n store[baseUrl] = { ...session, updated_at: new Date().toISOString() };\n writeStore(io, store);\n}\n\nexport function clearSession(io: Io, baseUrl: string): boolean {\n const store = readStore(io);\n if (!(baseUrl in store)) return false;\n delete store[baseUrl];\n writeStore(io, store);\n return true;\n}\n\ninterface RefreshResponse {\n status: string;\n access_token: string;\n refresh_token: string;\n}\n\n/**\n * The access token for this run, minted from the stored refresh token. The\n * rotated refresh token is written back before the access token is used for\n * anything, because presenting the old one again would revoke the family.\n * Undefined when there is no session for this instance.\n */\nexport async function sessionAccessToken(ctx: Context): Promise<string | undefined> {\n if (ctx.sessionToken) return ctx.sessionToken;\n const baseUrl = ctx.baseUrl;\n if (!baseUrl) return undefined;\n const stored = loadSession(ctx.io, baseUrl);\n if (!stored) return undefined;\n\n const response = await ctx.io.fetch(`${baseUrl}/api/v1/auth/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: stored.refresh_token }),\n });\n const body = (await response.json().catch(() => null)) as RefreshResponse | { error?: { code?: string } } | null;\n if (!response.ok || !body || !(\"access_token\" in body)) {\n const code = (body as { error?: { code?: string } } | null)?.error?.code ?? `http_${response.status}`;\n if (response.status === 401) {\n clearSession(ctx.io, baseUrl);\n throw usageError(`session for ${baseUrl} is no longer valid (${code}): run \\`plenary login\\``);\n }\n throw usageError(`could not refresh the session for ${baseUrl} (${code})`);\n }\n saveSession(ctx.io, baseUrl, { refresh_token: body.refresh_token, identifier: stored.identifier });\n ctx.sessionToken = body.access_token;\n return body.access_token;\n}\n","import { readFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline/promises\";\nimport type { Io } from \"./config.js\";\nimport { usageError } from \"./errors.js\";\n\n/** `k=v` pairs → object; a repeated key keeps the last value. */\nexport function parsePairs(pairs: string[], sep: string, what: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const pair of pairs) {\n const i = pair.indexOf(sep);\n if (i <= 0) throw usageError(`invalid ${what} \"${pair}\": expected key${sep}value`);\n out[pair.slice(0, i).trim()] = pair.slice(i + 1).trim();\n }\n return out;\n}\n\n/** Inline text, `@file`, or `-` for stdin. */\nexport async function readText(data: string, stdin: NodeJS.ReadableStream): Promise<string> {\n if (data === \"-\") return readStream(stdin);\n if (data.startsWith(\"@\")) {\n try {\n return readFileSync(data.slice(1), \"utf8\");\n } catch (err) {\n throw usageError(`cannot read ${data.slice(1)}: ${(err as Error).message}`);\n }\n }\n return data;\n}\n\n/** Inline JSON, `@file`, or `-` for stdin; returns the parsed value. */\nexport async function readData(data: string, stdin: NodeJS.ReadableStream, flag = \"--data\"): Promise<unknown> {\n const text = await readText(data, stdin);\n try {\n return JSON.parse(text);\n } catch (err) {\n throw usageError(`${flag} is not valid JSON: ${(err as Error).message}`);\n }\n}\n\n/** Like readData, but insists on a JSON object. */\nexport async function readObject(\n data: string,\n stdin: NodeJS.ReadableStream,\n flag = \"--data\",\n): Promise<Record<string, unknown>> {\n const value = await readData(data, stdin, flag);\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw usageError(`${flag} must be a JSON object`);\n }\n return value as Record<string, unknown>;\n}\n\nexport async function readStream(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) chunks.push(Buffer.from(chunk as Buffer | string));\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\n/**\n * Asks before something destructive. `yes` (from -y) skips the question; a\n * run with no terminal and no -y is refused rather than silently answered.\n */\nexport async function confirm(io: Io, question: string, yes: boolean): Promise<void> {\n if (yes) return;\n if (!io.isTTY) throw usageError(`${question} — pass -y to confirm without a terminal`);\n const rl = createInterface({ input: io.stdin, output: io.stderr });\n try {\n const answer = (await rl.question(`${question} [y/N] `)).trim().toLowerCase();\n if (answer !== \"y\" && answer !== \"yes\") throw usageError(\"aborted\");\n } finally {\n rl.close();\n }\n}\n\n/** Prompts for one line on a terminal; without one, reads a line from stdin. */\nexport async function readLine(io: Io, prompt: string): Promise<string> {\n const rl = createInterface({ input: io.stdin, output: io.isTTY ? io.stderr : undefined, terminal: io.isTTY });\n try {\n if (!io.isTTY) {\n const it = rl[Symbol.asyncIterator]();\n const { value } = await it.next();\n return (value ?? \"\").trim();\n }\n return (await rl.question(prompt)).trim();\n } finally {\n rl.close();\n }\n}\n\n/**\n * Prompts for a secret without echoing it. On a terminal the input is put in\n * raw mode and read a key at a time; otherwise a line is read from stdin, so\n * a script can pipe a password in.\n */\nexport async function readSecret(io: Io, prompt: string): Promise<string> {\n const stdin = io.stdin as NodeJS.ReadableStream & { setRawMode?: (raw: boolean) => void };\n if (!io.isTTY || typeof stdin.setRawMode !== \"function\") return readLine(io, prompt);\n io.stderr.write(prompt);\n stdin.setRawMode(true);\n stdin.resume();\n try {\n return await new Promise<string>((resolve, reject) => {\n let value = \"\";\n const onData = (chunk: Buffer | string) => {\n for (const ch of String(chunk)) {\n const code = ch.charCodeAt(0);\n if (code === 3) {\n cleanup();\n reject(usageError(\"aborted\"));\n return;\n }\n if (code === 13 || code === 10) {\n cleanup();\n io.stderr.write(\"\\n\");\n resolve(value);\n return;\n }\n if (code === 127 || code === 8) value = value.slice(0, -1);\n else value += ch;\n }\n };\n const cleanup = () => {\n stdin.off(\"data\", onData);\n stdin.setRawMode?.(false);\n stdin.pause();\n };\n stdin.on(\"data\", onData);\n });\n } finally {\n stdin.setRawMode?.(false);\n }\n}\n","import { createClient, type PlenaryClient } from \"@plenary/client\";\nimport { requireBaseUrl, type Context } from \"../config.js\";\nimport { credentialHeaders, request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\n\ninterface Site {\n key: string;\n default_locale: string;\n}\n\nexport function requireSiteKey(ctx: Context): string {\n if (!ctx.siteKey) {\n throw usageError(\"no site key: pass --site, set PLENARY_SITE_KEY, or set siteKey in plenary.json\");\n }\n return ctx.siteKey;\n}\n\n/**\n * The locale every content read states. When none is configured it is the\n * site's default, which every authenticated principal may look up.\n */\nexport async function resolveLocale(ctx: Context, siteKey: string): Promise<string> {\n if (ctx.locale) return ctx.locale;\n const sites = await request<Site[]>(ctx, \"GET\", \"sites\");\n const site = sites.data.find((s) => s.key === siteKey);\n if (!site) throw usageError(`site \"${siteKey}\" not found on the instance`);\n return site.default_locale;\n}\n\n/**\n * A @plenary/client for this run: the content reads go through it. The\n * client only knows how to send an API key, so with a session instead the\n * fetch it is given swaps the key header for the bearer token.\n */\nexport async function contentClient(ctx: Context): Promise<PlenaryClient> {\n const siteKey = requireSiteKey(ctx);\n const baseUrl = requireBaseUrl(ctx);\n const auth = await credentialHeaders(ctx, \"required\");\n const apiKey = auth[\"X-API-KEY\"] ?? \"\";\n const fetch: typeof globalThis.fetch = apiKey\n ? ctx.io.fetch\n : (input, init = {}) => {\n const headers = new Headers(init.headers);\n headers.delete(\"X-API-KEY\");\n for (const [k, v] of Object.entries(auth)) headers.set(k, v);\n return ctx.io.fetch(input, { ...init, headers });\n };\n return createClient({ baseUrl, siteKey, apiKey, locale: await resolveLocale(ctx, siteKey), fetch });\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { confirm } from \"../input.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { requireSiteKey } from \"../entries/client.js\";\n\ninterface Site {\n key: string;\n name: string;\n is_active: boolean;\n default_locale: string;\n locales: string[];\n timezone: string;\n}\n\ninterface RoleItem {\n site_key: string;\n key: string;\n name: string;\n description: string | null;\n is_system: boolean;\n grant_count: number;\n assigned_user_count: number;\n}\n\ninterface Grant {\n key: string;\n site_key?: string;\n content_model_key?: string;\n}\n\ninterface Role extends Omit<RoleItem, \"grant_count\" | \"assigned_user_count\"> {\n grants: Grant[];\n}\n\ninterface ApiKeyItem {\n id: string;\n name: string;\n key_type: string;\n is_active: boolean;\n last_used_at: string | null;\n expires_at: string | null;\n revoked_at: string | null;\n}\n\ninterface ApiKeyCreated extends ApiKeyItem {\n key: string;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/** `content:entries:read`, optionally `,site=<key>` and `,model=<key>`. */\nexport function parseGrant(spec: string): Grant {\n const [key, ...filters] = spec.split(\",\").map((s) => s.trim());\n if (!key) throw usageError(`invalid --grant \"${spec}\"`);\n const grant: Grant = { key };\n for (const f of filters) {\n const [name, value] = f.split(\"=\");\n if (name === \"site\" && value) grant.site_key = value;\n else if (name === \"model\" && value) grant.content_model_key = value;\n else throw usageError(`invalid --grant \"${spec}\": expected key[,site=<key>][,model=<key>]`);\n }\n return grant;\n}\n\nexport function registerAdmin(program: Command, io: Io): void {\n program\n .command(\"sites\")\n .description(\"Sites\")\n .command(\"list\")\n .description(\"List sites\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<Site[]>(ctx, \"GET\", \"sites\");\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((s) => [\n s.key,\n s.name,\n s.default_locale,\n s.locales.join(\",\"),\n s.timezone,\n s.is_active ? \"\" : \"inactive\",\n ]);\n io.stdout.write(formatTable(rows, [\"KEY\", \"NAME\", \"DEFAULT\", \"LOCALES\", \"TIMEZONE\", \"\"]) + \"\\n\");\n });\n\n // A role belongs to a site, so both commands take the configured one\n // (--site, PLENARY_SITE_KEY or siteKey in plenary.json).\n const roles = program.command(\"roles\").description(\"The configured site's roles (needs a super user session)\");\n roles\n .command(\"list\")\n .description(\"List the site's roles\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const site = requireSiteKey(ctx);\n const res = await request<RoleItem[]>(ctx, \"GET\", `sites/${encodeURIComponent(site)}/roles`, { auth: \"session\" });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((r) => [\n r.key,\n r.name,\n String(r.grant_count),\n String(r.assigned_user_count),\n r.is_system ? \"system\" : \"\",\n ]);\n io.stdout.write(formatTable(rows, [\"KEY\", \"NAME\", \"GRANTS\", \"USERS\", \"\"]) + \"\\n\");\n });\n roles\n .command(\"get\")\n .description(\"Show one of the site's roles and its grants\")\n .argument(\"<key>\")\n .action(async (key: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const site = requireSiteKey(ctx);\n const res = await request<Role>(ctx, \"GET\", `sites/${encodeURIComponent(site)}/roles/${encodeURIComponent(key)}`, {\n auth: \"session\",\n });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const r = res.data;\n const head = [\n [\"Site\", r.site_key],\n [\"Key\", r.key],\n [\"Name\", r.name],\n [\"System\", r.is_system ? \"yes\" : \"no\"],\n ];\n if (r.description) head.push([\"Description\", r.description]);\n const grants = r.grants.map((g) => [g.key, g.site_key ?? \"\", g.content_model_key ?? \"\"]);\n io.stdout.write(formatTable(head) + \"\\n\\n\" + formatTable(grants, [\"GRANT\", \"SITE\", \"MODEL\"]) + \"\\n\");\n });\n\n const keys = program.command(\"api-keys\").description(\"API keys (needs a user session)\");\n keys\n .command(\"list\")\n .description(\"List API keys\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<ApiKeyItem[]>(ctx, \"GET\", \"api-keys\", { auth: \"session\" });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((k) => [\n k.id,\n k.name,\n k.key_type,\n k.revoked_at ? \"revoked\" : k.is_active ? \"active\" : \"inactive\",\n k.last_used_at ?? \"never\",\n k.expires_at ?? \"\",\n ]);\n io.stdout.write(formatTable(rows, [\"ID\", \"NAME\", \"TYPE\", \"STATE\", \"LAST USED\", \"EXPIRES\"]) + \"\\n\");\n });\n keys\n .command(\"get\")\n .description(\"Show one API key (never its secret)\")\n .argument(\"<id>\")\n .action(async (id: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request(ctx, \"GET\", `api-keys/${encodeURIComponent(id)}`, { auth: \"session\" });\n io.stdout.write(toJson(res.data) + \"\\n\");\n });\n keys\n .command(\"create\")\n // --site is the global option: a subcommand option of the same name never\n // receives a value, because the program-level one consumes it first.\n .description(\n \"Create an API key; the secret is printed once, alone on stdout. --site names the site the key belongs to: \" +\n \"a public key reads it (default: the configured site), a private key's grants are held to it\",\n )\n .requiredOption(\"-n, --name <name>\")\n .option(\"-t, --type <private|public>\", \"key type\", \"private\")\n .option(\"--description <text>\")\n .option(\"-g, --grant <spec>\", \"private keys: key[,site=<key>][,model=<model key>] (repeatable)\", collect, [])\n .option(\"--expires <iso>\", \"expiry timestamp\")\n .option(\"--origin <origin>\", \"an allowed browser origin (repeatable)\", collect, [])\n .option(\"--rate-limit <n>\", \"requests per minute, 0 = unlimited\", \"0\")\n .option(\"--include-drafts\", \"public keys: read drafts too\")\n .action(\n async (\n flags: {\n name: string;\n type: string;\n description?: string;\n grant: string[];\n expires?: string;\n origin: string[];\n rateLimit: string;\n includeDrafts?: boolean;\n },\n cmd: Command,\n ) => {\n const globals = cmd.optsWithGlobals<GlobalOptions>();\n const ctx = resolveContext(globals, io);\n if (flags.type !== \"private\" && flags.type !== \"public\") throw usageError(\"--type must be private or public\");\n // Only an explicit --site binds a private key; a public key can't exist\n // without a site, so it falls back to the configured one.\n const site = globals.site ?? (flags.type === \"public\" ? ctx.siteKey : undefined);\n const body = {\n name: flags.name,\n description: flags.description ?? null,\n key_type: flags.type,\n is_active: true,\n expires_at: flags.expires ?? null,\n grants: flags.grant.map(parseGrant),\n ...(site ? { site_key: site } : {}),\n allowed_origins: flags.origin,\n rate_limit_per_minute: Number(flags.rateLimit),\n include_drafts: Boolean(flags.includeDrafts),\n };\n const res = await request<ApiKeyCreated>(ctx, \"POST\", \"api-keys\", { auth: \"session\", body });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n io.stderr.write(\n `created ${flags.type} key \"${flags.name}\" (${res.data.id}); the secret follows and is not shown again\\n`,\n );\n io.stdout.write(res.data.key + \"\\n\");\n },\n );\n keys\n .command(\"delete\")\n .description(\"Delete an API key\")\n .argument(\"<id>\")\n .option(\"-y, --yes\", \"do not ask\")\n .action(async (id: string, flags: { yes?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await confirm(io, `Delete API key ${id}?`, Boolean(flags.yes));\n await request(ctx, \"DELETE\", `api-keys/${encodeURIComponent(id)}`, { auth: \"session\" });\n io.stdout.write(`deleted ${id}\\n`);\n });\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { CliError, usageError } from \"../errors.js\";\nimport { parsePairs, readData } from \"../input.js\";\nimport { describeError, toJson } from \"../output.js\";\nimport { errorFromResponse } from \"@plenary/client\";\n\nconst METHODS = new Set([\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"HEAD\"]);\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nexport function registerApi(program: Command, io: Io): void {\n program\n .command(\"api\")\n .description(\"Call any API endpoint and print the response body\")\n .argument(\"<method>\", \"GET, POST, PUT, PATCH, DELETE, or HEAD\")\n .argument(\"<path>\", \"a path such as models or /api/v1/models\")\n .option(\"-d, --data <json>\", \"request body: inline JSON, @file, or - for stdin\")\n .option(\"-q, --query <key=value>\", \"query parameter (repeatable)\", collect, [])\n .option(\"-H, --header <key:value>\", \"request header (repeatable)\", collect, [])\n .option(\"-i, --include\", \"print the status line and response headers to stderr\")\n .addHelpText(\n \"after\",\n `\nExamples:\n plenary api GET models\n plenary api GET content/post -q site_key=main -q limit=5\n plenary api POST content/post -q site_key=main -d '{\"fields\":{\"title\":\"Hello\"}}'\n plenary api PUT models/<uuid> -d @model.json`,\n )\n .action(\n async (\n methodArg: string,\n path: string,\n opts: { data?: string; query: string[]; header: string[]; include?: boolean },\n cmd: Command,\n ) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const method = methodArg.toUpperCase();\n if (!METHODS.has(method)) throw usageError(`unsupported method \"${methodArg}\"`);\n\n const body = opts.data !== undefined ? await readData(opts.data, io.stdin) : undefined;\n const res = await request(ctx, method, path, {\n query: parsePairs(opts.query, \"=\", \"query parameter\"),\n headers: parsePairs(opts.header, \":\", \"header\"),\n body,\n auth: \"optional\",\n allowError: true,\n });\n\n if (opts.include) {\n io.stderr.write(`HTTP ${res.status}\\n`);\n res.headers.forEach((v: string, k: string) => io.stderr.write(`${k}: ${v}\\n`));\n io.stderr.write(\"\\n\");\n }\n if (res.data !== null) {\n io.stdout.write((typeof res.data === \"string\" ? res.data : toJson(res.data)) + \"\\n\");\n }\n if (!res.ok) {\n io.stderr.write(describeError(errorFromResponse(res.status, res.data)) + \"\\n\");\n throw new CliError(\"\", 1);\n }\n },\n );\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, requireBaseUrl, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { credentialHeaders, request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { readLine, readSecret } from \"../input.js\";\nimport { toJson } from \"../output.js\";\nimport { clearSession, credentialsPath, loadSession, saveSession } from \"../session.js\";\n\ntype LoginResponse =\n | { status: \"success\"; access_token: string; refresh_token: string }\n | { status: \"otp_sent\" | \"otp_required\"; challenge_id: string; otp_methods: Record<string, string> };\n\ninterface Tokens {\n access_token: string;\n refresh_token: string;\n}\n\ninterface MeUser {\n principal: \"user\";\n is_super_user: boolean;\n grants: { site_key?: string; role_key?: string }[];\n}\n\n/** \"super user\", or the site roles a session's grants come from. */\nexport function describeUser(me: MeUser): string {\n if (me.is_super_user) return \"super user\";\n const roles = new Set<string>();\n for (const g of me.grants) if (g.role_key && g.site_key) roles.add(`${g.role_key} on ${g.site_key}`);\n return roles.size ? [...roles].join(\", \") : \"no site roles\";\n}\n\n/** The password, then OTP, then tokens conversation, prompting only where needed. */\nasync function login(ctx: Context, identifier: string, password: string, otpMethod?: string): Promise<Tokens> {\n const io = ctx.io;\n const first = await request<LoginResponse>(ctx, \"POST\", \"auth/login\", {\n auth: \"none\",\n body: { identifier, password },\n });\n const res = first.data;\n if (res.status === \"success\") return res;\n\n const challengeId = res.challenge_id;\n const methods = Object.keys(res.otp_methods);\n if (res.status === \"otp_required\") {\n let method = otpMethod ?? (methods.length === 1 ? methods[0] : undefined);\n if (!method) {\n if (!io.isTTY) throw usageError(`2FA needs a delivery method: pass --otp-method ${methods.join(\"|\")}`);\n const shown = methods.map((m) => `${m} (${res.otp_methods[m]})`).join(\", \");\n method = await readLine(io, `Send the code by ${shown}? [${methods[0]}] `);\n if (method === \"\") method = methods[0];\n }\n if (!methods.includes(method as string)) throw usageError(`--otp-method must be one of ${methods.join(\", \")}`);\n await request(ctx, \"POST\", \"auth/login/otp/send\", {\n auth: \"none\",\n body: { challenge_id: challengeId, otp_method: method },\n });\n io.stderr.write(`code sent by ${method}\\n`);\n } else {\n io.stderr.write(`code sent to ${Object.values(res.otp_methods).join(\", \")}\\n`);\n }\n\n if (!io.isTTY) throw usageError(\"2FA needs a terminal to enter the code\");\n const code = await readLine(io, \"Code: \");\n const verified = await request<Tokens & { status: string }>(ctx, \"POST\", \"auth/login/otp/verify\", {\n auth: \"none\",\n body: { challenge_id: challengeId, otp_code: code },\n });\n return verified.data;\n}\n\nexport function registerAuth(program: Command, io: Io): void {\n program\n .command(\"login\")\n .description(\"Sign in as a user and keep the session for admin commands\")\n .option(\"-u, --identifier <email-or-username>\", \"or PLENARY_USERNAME\")\n .option(\"--otp-method <email|sms>\", \"how to receive a 2FA code when more than one way is offered\")\n .addHelpText(\n \"after\",\n `\nThe password is prompted for (never a flag); PLENARY_PASSWORD supplies it\nwithout a terminal. Only the refresh token is stored, in\n$XDG_CONFIG_HOME/plenary/credentials.json, keyed by instance.`,\n )\n .action(async (flags: { identifier?: string; otpMethod?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const baseUrl = requireBaseUrl(ctx);\n let identifier = flags.identifier ?? io.env.PLENARY_USERNAME;\n if (!identifier) {\n if (!io.isTTY) throw usageError(\"no identifier: pass --identifier or set PLENARY_USERNAME\");\n identifier = await readLine(io, \"Email or username: \");\n }\n let password = io.env.PLENARY_PASSWORD;\n if (!password) {\n if (!io.isTTY) throw usageError(\"no password: set PLENARY_PASSWORD or run on a terminal\");\n password = await readSecret(io, \"Password: \");\n }\n const tokens = await login(ctx, identifier, password, flags.otpMethod);\n saveSession(io, baseUrl, { refresh_token: tokens.refresh_token, identifier });\n ctx.sessionToken = tokens.access_token;\n\n const me = await request<MeUser>(ctx, \"GET\", \"auth/me\", { auth: \"session\" });\n if (ctx.json) {\n io.stdout.write(\n toJson({ base_url: baseUrl, identifier, is_super_user: me.data.is_super_user, credentials: credentialsPath(io) }) + \"\\n\",\n );\n return;\n }\n io.stdout.write(`logged in to ${baseUrl} as ${identifier} (${describeUser(me.data)})\\n`);\n });\n\n program\n .command(\"logout\")\n .description(\"Revoke the stored session for this instance\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const baseUrl = requireBaseUrl(ctx);\n const stored = loadSession(io, baseUrl);\n if (!stored) {\n io.stdout.write(`no session for ${baseUrl}\\n`);\n return;\n }\n // Logout is idempotent server-side; a failure there must not keep a\n // token on disk the person asked to be rid of.\n try {\n await request(ctx, \"POST\", \"auth/logout\", { auth: \"none\", body: { refresh_token: stored.refresh_token } });\n } finally {\n clearSession(io, baseUrl);\n }\n io.stdout.write(`logged out of ${baseUrl}\\n`);\n });\n\n program\n .command(\"whoami\")\n .description(\"Show the credentials this run would use\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const baseUrl = requireBaseUrl(ctx);\n const stored = loadSession(io, baseUrl);\n const out: Record<string, unknown> = { base_url: baseUrl, api_key: null, session: null };\n const lines: string[] = [];\n if (ctx.apiKey) {\n const me = await request<{ key_type?: string; name?: string; grants?: unknown[] }>(ctx, \"GET\", \"auth/me\", {\n auth: \"none\",\n headers: { \"X-API-KEY\": ctx.apiKey },\n allowError: true,\n });\n out.api_key = me.ok ? me.data : { error: (me.data as { error?: unknown } | null)?.error ?? me.status };\n if (me.ok && me.data.key_type) {\n lines.push(\n `API key ${me.data.key_type} \"${me.data.name}\" (${me.data.grants?.length ?? 0} grants), used for content commands`,\n );\n } else if (me.status === 403) {\n lines.push(\"API key accepted (this server cannot describe keys), used for content commands\");\n } else {\n lines.push(`API key rejected (HTTP ${me.status})`);\n }\n }\n if (stored) {\n const headers = await credentialHeaders(ctx, \"session\");\n const me = await request<MeUser>(ctx, \"GET\", \"auth/me\", { auth: \"none\", headers });\n out.session = { identifier: stored.identifier ?? null, is_super_user: me.data.is_super_user };\n lines.push(\n `Session ${stored.identifier ?? \"user\"} (${describeUser(me.data)}), used for admin commands${\n ctx.apiKey ? \"\" : \" and content\"\n }`,\n );\n }\n if (lines.length === 0) lines.push(\"no credentials: set PLENARY_CLI_API_KEY or run `plenary login`\");\n io.stdout.write((ctx.json ? toJson(out) : lines.join(\"\\n\")) + \"\\n\");\n });\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { formatTable, toJson } from \"../output.js\";\n\ninterface CatalogItem {\n id: string;\n key: string;\n kind: string;\n name_singular: string;\n active: boolean;\n fields_count: number;\n site_key?: string;\n}\n\ninterface CatalogField {\n key: string;\n name: string;\n type: string;\n required: boolean;\n localized: boolean;\n}\n\ninterface CatalogDetail extends CatalogItem {\n name_plural: string;\n description?: string;\n private: boolean;\n fields: CatalogField[];\n transformers?: unknown[];\n entry_count?: number;\n}\n\n/**\n * A model key is unique within its site only, so the configured site, when\n * there is one, narrows a list and says which model a key names.\n */\nfunction siteQuery(siteKey: string | undefined) {\n return siteKey ? { query: { site_key: siteKey } } : undefined;\n}\n\n/** `models` and `forms` are the same surface at two paths. */\nexport function registerCatalog(program: Command, io: Io, name: \"models\" | \"forms\"): Command {\n const group = program.command(name).description(name === \"models\" ? \"Content models and objects\" : \"Forms\");\n\n group\n .command(\"list\")\n .description(`List ${name}`)\n .action(async (_opts: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<CatalogItem[]>(ctx, \"GET\", name, siteQuery(ctx.siteKey));\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((m) => [\n m.key,\n m.kind,\n m.name_singular,\n String(m.fields_count),\n m.active ? \"\" : \"inactive\",\n ]);\n io.stdout.write(formatTable(rows, [\"KEY\", \"KIND\", \"NAME\", \"FIELDS\", \"\"]) + \"\\n\");\n });\n\n group\n .command(\"get\")\n .description(`Show one of the ${name} by key or id`)\n .argument(\"<key>\")\n .option(\"--yaml\", \"print the YAML file the metadata commands use\")\n .action(async (key: string, opts: { yaml?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<CatalogDetail>(ctx, \"GET\", `${name}/${encodeURIComponent(key)}`, siteQuery(ctx.siteKey));\n const m = res.data;\n if (opts.yaml) {\n const yaml = await request<string>(ctx, \"GET\", `${name}/${m.id}/yaml`);\n io.stdout.write(yaml.data.endsWith(\"\\n\") ? yaml.data : yaml.data + \"\\n\");\n return;\n }\n if (ctx.json) {\n io.stdout.write(toJson(m) + \"\\n\");\n return;\n }\n const head = [\n [\"Key\", m.key],\n [\"Kind\", m.kind],\n [\"Name\", `${m.name_singular} / ${m.name_plural}`],\n [\"Id\", m.id],\n [\"Site\", m.site_key || \"-\"],\n [\"Active\", m.active ? \"yes\" : \"no\"],\n ];\n if (m.description) head.push([\"Description\", m.description]);\n if (m.entry_count !== undefined) head.push([\"Entries\", String(m.entry_count)]);\n const fields = m.fields.map((f) => [\n f.key,\n f.type,\n f.name,\n [f.required ? \"required\" : \"\", f.localized ? \"localized\" : \"\"].filter(Boolean).join(\", \"),\n ]);\n io.stdout.write(\n formatTable(head) + \"\\n\\n\" + formatTable(fields, [\"FIELD\", \"TYPE\", \"NAME\", \"\"]) + \"\\n\",\n );\n });\n\n return group;\n}\n","import type { Command } from \"commander\";\nimport { PlenaryNotFoundError, type Entry, type ListOptions, type PlenaryClient } from \"@plenary/client\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { CliError, usageError } from \"../errors.js\";\nimport { confirm, readObject, readText } from \"../input.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { contentClient, requireSiteKey } from \"../entries/client.js\";\nimport { toListOptions, toReadOptions, type ListFlags } from \"../entries/query.js\";\nimport { contentFolders, folderIdAt } from \"./folders.js\";\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/** The flags every listing command shares, declared once. */\nfunction withListFlags(cmd: Command): Command {\n return cmd\n .option(\"-w, --where <field=value>\", \"filter: field=value or field=$op:value (repeatable)\", collect, [])\n .option(\"--filters <json>\", \"a filter tree (inline JSON, @file, or -); excludes --where\")\n .option(\"-s, --sort <field[:dir]>\", \"sort field, asc unless :desc (repeatable, in precedence order)\", collect, [])\n .option(\"--limit <n>\", \"page size\")\n .option(\"--offset <n>\", \"rows to skip\")\n .option(\"--include <fields>\", \"comma-separated data fields to return\")\n .option(\"--exclude <fields>\", \"comma-separated data fields to omit\")\n .option(\"--hydrate <field[=subfields]>\", \"hydrate a reference field (repeatable)\", collect, [])\n .option(\"--count\", \"ask for the total and show it\");\n}\n\n/** The intrinsic flags a create or update accepts beside --data. */\ninterface WriteFlags {\n data?: string;\n slug?: string;\n folder?: string;\n folderPath?: string;\n note?: string;\n publishAt?: string;\n unpublishAt?: string;\n}\n\nfunction withWriteFlags(cmd: Command): Command {\n return cmd\n .option(\"-d, --data <json>\", \"the field values as a JSON object (inline, @file, or -)\")\n .option(\"--slug <slug>\")\n .option(\"--folder <id>\", \"content folder id\")\n .option(\"--folder-path <path>\", \"content folder path, such as /company (instead of --folder; / is the root)\")\n .option(\"--note <text>\", \"revision note (required by models with Require Change Notes)\")\n .option(\"--publish-at <iso>\", \"schedule a publish\")\n .option(\"--unpublish-at <iso>\", \"schedule an unpublish\");\n}\n\n/** The write body the Content API takes. */\ninterface EntryBody {\n fields: Record<string, unknown>;\n slug?: string;\n locale?: string;\n folder_id?: string | null;\n publish_at?: string | null;\n unpublish_at?: string | null;\n note?: string;\n}\n\n// --include narrows the response to the fields it names, so any column may be\n// missing from a row and prints blank.\nfunction entryRow(e: Partial<Entry>): string[] {\n return [e.id ?? \"\", statusLabel(e), e.slug ?? \"\", e.title ?? \"\", e.updated_at ?? \"\"];\n}\n\n/** The status column: a published entry with changes pending is `published*`. */\nfunction statusLabel(e: Partial<Entry>): string {\n return `${e.status ?? \"\"}${e.draft ? \"*\" : \"\"}`;\n}\n\nconst ENTRY_HEADER = [\"ID\", \"STATUS\", \"SLUG\", \"TITLE\", \"UPDATED\"];\n\nconst PAGE = 100;\n\n/** Every entry matching the options, one page at a time. */\nasync function* pageAll(client: PlenaryClient, model: string, opts: ListOptions): AsyncGenerator<Entry> {\n const limit = opts.limit ?? PAGE;\n let offset = opts.offset ?? 0;\n for (;;) {\n const { items } = await client.listEntries(model, { ...opts, limit, offset, count: false });\n for (const e of items) yield e;\n if (items.length < limit) return;\n offset += items.length;\n }\n}\n\nasync function publish(ctx: Context, id: string, action: \"publish\" | \"unpublish\"): Promise<Entry> {\n return (await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(id)}/${action}`)).data;\n}\n\nexport function registerEntries(program: Command, io: Io): void {\n const entries = program.command(\"entries\").description(\"Content entries\");\n\n withListFlags(entries.command(\"list\").description(\"List a model's entries\").argument(\"<model>\")).action(\n async (model: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n const result = await client.listEntries(model, await toListOptions(flags, io.stdin));\n // A singleton model's collection route answers with its one entry, not a list.\n if (!Array.isArray(result.items)) {\n throw usageError(`${model} is a singleton; use 'plenary entries get ${model}'`);\n }\n if (ctx.json) {\n io.stdout.write(toJson(result) + \"\\n\");\n return;\n }\n io.stdout.write(formatTable(result.items.map(entryRow), ENTRY_HEADER) + \"\\n\");\n if (result.total !== undefined) io.stdout.write(`${result.items.length} of ${result.total}\\n`);\n },\n );\n\n entries\n .command(\"get\")\n .description(\"Print one entry as JSON; omit the slug for a singleton\")\n .argument(\"<model>\")\n .argument(\"[slug-or-id]\")\n .option(\"--include <fields>\")\n .option(\"--exclude <fields>\")\n .option(\"--hydrate <field[=subfields]>\", \"hydrate a reference field (repeatable)\", collect, [])\n .action(async (model: string, slug: string | undefined, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n const opts = await toReadOptions(flags);\n const entry = slug === undefined ? await client.getSingleton(model, opts) : await client.getEntry(model, slug, opts);\n io.stdout.write(toJson(entry) + \"\\n\");\n });\n\n withWriteFlags(entries.command(\"create\").description(\"Create a draft entry\").argument(\"<model>\"))\n .option(\"--publish\", \"publish it right after creating\")\n .action(async (model: string, flags: WriteFlags & { publish?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const siteKey = requireSiteKey(ctx);\n if (flags.data === undefined) throw usageError(\"--data is required\");\n const body: EntryBody = { fields: await readObject(flags.data, io.stdin) };\n if (ctx.locale) body.locale = ctx.locale;\n applyWriteFlags(body, flags);\n await applyFolderPath(ctx, model, body, flags);\n let entry = (\n await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(model)}`, { query: { site_key: siteKey }, body })\n ).data;\n if (flags.publish) entry = await publish(ctx, entry.id, \"publish\");\n report(ctx, entry, \"created\");\n });\n\n withWriteFlags(\n entries\n .command(\"update\")\n .description(\"Update an entry: --data is merged into its fields (a null removes one)\")\n .argument(\"<model>\")\n .argument(\"<slug-or-id>\"),\n )\n .option(\"--publish\", \"publish it right after updating (on a published entry, publish the pending changes)\")\n .addHelpText(\n \"after\",\n `\nOn a published entry the update is saved as pending changes and the live\ncopy stays as it was until the entry is published again; --data is then\nmerged into the pending copy. --publish makes the change live in a second\ncall.`,\n )\n .action(async (model: string, slug: string, flags: WriteFlags & { publish?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n const current = await client.getEntry(model, slug);\n // Pending changes are what the editor last saved, so they are what --data\n // merges into; carrying the live copy forward would silently drop them.\n const working = current.draft ?? current;\n const fields: Record<string, unknown> = { ...working.data };\n if (flags.data !== undefined) {\n for (const [k, v] of Object.entries(await readObject(flags.data, io.stdin))) {\n if (v === null) delete fields[k];\n else fields[k] = v;\n }\n }\n // PUT replaces the whole entry, so everything not being changed is carried.\n const body: EntryBody = {\n fields,\n slug: working.slug ?? undefined,\n locale: current.locale ?? undefined,\n folder_id: current.folder_id,\n publish_at: current.publish_at,\n unpublish_at: current.unpublish_at,\n };\n applyWriteFlags(body, flags);\n await applyFolderPath(ctx, model, body, flags);\n let entry = (await request<Entry>(ctx, \"PUT\", `content/${encodeURIComponent(current.id)}`, { body })).data;\n if (flags.publish) entry = await publish(ctx, entry.id, \"publish\");\n report(ctx, entry, \"updated\");\n });\n\n entries\n .command(\"delete\")\n .description(\"Delete an entry (recoverable from history while the model tracks revisions)\")\n .argument(\"<id>\")\n .option(\"--note <text>\", \"revision note\")\n .option(\"-y, --yes\", \"do not ask\")\n .action(async (id: string, flags: { note?: string; yes?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await confirm(io, `Delete entry ${id}?`, Boolean(flags.yes));\n await request(ctx, \"DELETE\", `content/${encodeURIComponent(id)}`, { query: { note: flags.note } });\n if (ctx.json) io.stdout.write(toJson({ id, deleted: true }) + \"\\n\");\n else io.stdout.write(`deleted ${id}\\n`);\n });\n\n entries\n .command(\"publish\")\n .description(\"Publish an entry now; on a published entry, make its pending changes live\")\n .argument(\"<id>\")\n .action(async (id: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n report(ctx, await publish(ctx, id, \"publish\"), \"published\");\n });\n\n entries\n .command(\"unpublish\")\n .description(\"Unpublish an entry now\")\n .argument(\"<id>\")\n .option(\"--draft <merge|discard>\", \"with changes pending: keep them as the draft's content (merge) or drop them (discard)\")\n .action(async (id: string, flags: { draft?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const entry = (\n await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(id)}/unpublish`, { query: { draft: flags.draft } })\n ).data;\n report(ctx, entry, \"unpublished\");\n });\n\n entries\n .command(\"discard\")\n .description(\"Drop the pending changes on a published entry, leaving the live copy as it is\")\n .argument(\"<id>\")\n .option(\"--note <text>\", \"revision note\")\n .action(async (id: string, flags: { note?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const entry = (\n await request<Entry>(ctx, \"DELETE\", `content/${encodeURIComponent(id)}/draft`, { query: { note: flags.note } })\n ).data;\n report(ctx, entry, \"discarded\");\n });\n\n withListFlags(\n entries.command(\"export\").description(\"Write every matching entry to stdout as NDJSON\").argument(\"<model>\"),\n ).action(async (model: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n for await (const e of pageAll(client, model, await toListOptions(flags, io.stdin))) {\n io.stdout.write(JSON.stringify(e) + \"\\n\");\n }\n });\n\n entries\n .command(\"import\")\n .description(\"Create one entry per NDJSON line (exported entries or {fields, slug, …} bodies)\")\n .argument(\"<model>\")\n .argument(\"<file>\", \"a file, or - for stdin\")\n .option(\"--publish\", \"publish each entry after writing it\")\n .option(\"--upsert\", \"update the entry with the line's slug when it exists, instead of failing\")\n .addHelpText(\n \"after\",\n `\nEvery line is tried; a line that fails is reported with its number and the\nrun continues, exiting 1 at the end if any failed.\n\nWith --upsert a line is matched by its slug (unique per site, model and\nlocale), so a seed file can be imported again. A match has its fields\nreplaced by the line's; the slug, folder and schedule it doesn't state are\nkept. A line without a slug fails.`,\n )\n .action(async (model: string, file: string, flags: { publish?: boolean; upsert?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const siteKey = requireSiteKey(ctx);\n const client = flags.upsert ? await contentClient(ctx) : undefined;\n const text = await readText(file === \"-\" ? \"-\" : `@${file}`, io.stdin);\n let failed = 0;\n let updated = 0;\n let n = 0;\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (line === \"\") continue;\n n++;\n try {\n const body = importBody(JSON.parse(line) as Record<string, unknown>, ctx);\n const current = client && (await findBySlug(client, model, body));\n let entry = current\n ? (\n await request<Entry>(ctx, \"PUT\", `content/${encodeURIComponent(current.id)}`, {\n body: {\n slug: current.slug ?? undefined,\n locale: current.locale ?? undefined,\n folder_id: current.folder_id,\n publish_at: current.publish_at,\n unpublish_at: current.unpublish_at,\n ...body,\n },\n })\n ).data\n : (\n await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(model)}`, {\n query: { site_key: siteKey },\n body,\n })\n ).data;\n if (current) updated++;\n if (flags.publish) entry = await publish(ctx, entry.id, \"publish\");\n io.stdout.write(`ok ${entry.id}${entry.slug ? ` ${entry.slug}` : \"\"}${current ? \" (updated)\" : \"\"}\\n`);\n } catch (err) {\n failed++;\n const why = err instanceof Error ? (err as { code?: string }).code ?? err.message : String(err);\n io.stdout.write(`fail line ${n}: ${why}\\n`);\n }\n }\n io.stderr.write(`${n - failed - updated} created, ${updated ? `${updated} updated, ` : \"\"}${failed} failed\\n`);\n if (failed) throw new CliError(\"\", 1);\n });\n}\n\nfunction applyWriteFlags(body: EntryBody, flags: WriteFlags): void {\n if (flags.slug !== undefined) body.slug = flags.slug;\n if (flags.folder !== undefined) body.folder_id = flags.folder;\n if (flags.publishAt !== undefined) body.publish_at = flags.publishAt;\n if (flags.unpublishAt !== undefined) body.unpublish_at = flags.unpublishAt;\n if (flags.note !== undefined) body.note = flags.note;\n}\n\n/** --folder-path resolved against the model's folders; \"/\" moves the entry to the root. */\nasync function applyFolderPath(ctx: Context, model: string, body: EntryBody, flags: WriteFlags): Promise<void> {\n if (flags.folderPath === undefined) return;\n if (flags.folder !== undefined) throw usageError(\"pass --folder or --folder-path, not both\");\n body.folder_id = await folderIdAt(ctx, contentFolders(ctx, model), flags.folderPath);\n}\n\n/** An exported entry (`data`) or a bare write body (`fields`) → the write body. */\nfunction importBody(line: Record<string, unknown>, ctx: Context): EntryBody {\n if (\"fields\" in line) return line as unknown as EntryBody;\n if (!(\"data\" in line)) throw usageError(\"expected an object with fields or data\");\n const e = line as Partial<Entry>;\n const body: EntryBody = { fields: (e.data ?? {}) as Record<string, unknown> };\n if (e.slug) body.slug = e.slug;\n if (e.locale ?? ctx.locale) body.locale = e.locale ?? ctx.locale;\n if (e.folder_id) body.folder_id = e.folder_id;\n if (e.publish_at) body.publish_at = e.publish_at;\n if (e.unpublish_at) body.unpublish_at = e.unpublish_at;\n return body;\n}\n\n/** The entry an upserted line names by slug, or undefined when there is none yet. */\nasync function findBySlug(client: PlenaryClient, model: string, body: EntryBody): Promise<Entry | undefined> {\n if (!body.slug) throw usageError(\"--upsert needs a slug on every line\");\n try {\n return await client.getEntry(model, body.slug, body.locale ? { locale: body.locale } : {});\n } catch (err) {\n if (err instanceof PlenaryNotFoundError) return undefined;\n throw err;\n }\n}\n\nfunction report(ctx: Context, entry: Entry, verb: string): void {\n if (ctx.json) ctx.io.stdout.write(toJson(entry) + \"\\n\");\n else ctx.io.stdout.write(`${verb} ${entry.id}${entry.slug ? ` ${entry.slug}` : \"\"} (${statusLabel(entry)})\\n`);\n}\n","import type { ListOptions, ReadOptions, Sort, Where } from \"@plenary/client\";\nimport { usageError } from \"../errors.js\";\nimport { readData } from \"../input.js\";\n\n/** The flags shared by every listing command. */\nexport interface ListFlags {\n where?: string[];\n filters?: string;\n sort?: string[];\n limit?: string;\n offset?: string;\n include?: string;\n exclude?: string;\n hydrate?: string[];\n count?: boolean;\n}\n\nconst OPERATORS = new Set([\"$eq\", \"$ne\", \"$lt\", \"$lte\", \"$gt\", \"$gte\", \"$in\", \"$nin\", \"$like\", \"$ilike\", \"$is_null\"]);\n\n/**\n * `field=value` is equality; `field=$op:value` is one of the Content API's\n * operators, with `$in`/`$nin` taking a comma list and `$is_null` a boolean.\n */\nexport function parseWhere(specs: string[]): Where {\n const where: Where = {};\n for (const spec of specs) {\n const eq = spec.indexOf(\"=\");\n if (eq <= 0) throw usageError(`invalid --where \"${spec}\": expected field=value or field=$op:value`);\n const field = spec.slice(0, eq).trim();\n const raw = spec.slice(eq + 1);\n if (!raw.startsWith(\"$\")) {\n where[field] = raw;\n continue;\n }\n const colon = raw.indexOf(\":\");\n const op = colon === -1 ? raw : raw.slice(0, colon);\n const value = colon === -1 ? \"\" : raw.slice(colon + 1);\n if (!OPERATORS.has(op)) throw usageError(`invalid --where \"${spec}\": unknown operator ${op}`);\n let typed: unknown = value;\n if (op === \"$in\" || op === \"$nin\") typed = value.split(\",\").map((s) => s.trim()).filter(Boolean);\n else if (op === \"$is_null\") typed = value === \"\" || value === \"true\";\n const existing = (where[field] ?? {}) as Record<string, unknown>;\n where[field] = { ...(typeof existing === \"object\" ? existing : {}), [op]: typed };\n }\n return where;\n}\n\n/** `field` or `field:desc`, in precedence order. */\nexport function parseSort(specs: string[]): Sort {\n const sort: Sort = {};\n for (const spec of specs) {\n const [field, dir = \"asc\"] = spec.split(\":\");\n if (!field || (dir !== \"asc\" && dir !== \"desc\")) {\n throw usageError(`invalid --sort \"${spec}\": expected field or field:asc|desc`);\n }\n sort[field] = dir;\n }\n return sort;\n}\n\nfunction parseHydrate(specs: string[]): ReadOptions[\"hydrate\"] {\n const out: Record<string, \"*\" | string[]> = {};\n for (const spec of specs) {\n const [field, list] = spec.split(\"=\");\n if (!field) throw usageError(`invalid --hydrate \"${spec}\"`);\n out[field] = list === undefined || list === \"*\" ? \"*\" : list.split(\",\");\n }\n return out;\n}\n\nfunction parseInt10(value: string | undefined, flag: string): number | undefined {\n if (value === undefined) return undefined;\n const n = Number(value);\n if (!Number.isInteger(n) || n < 0) throw usageError(`${flag} must be a non-negative integer`);\n return n;\n}\n\nexport async function toReadOptions(flags: ListFlags): Promise<ReadOptions> {\n const opts: ReadOptions = {};\n if (flags.include) opts.include = flags.include.split(\",\");\n if (flags.exclude) opts.exclude = flags.exclude.split(\",\");\n if (flags.hydrate?.length) opts.hydrate = parseHydrate(flags.hydrate);\n return opts;\n}\n\nexport async function toListOptions(flags: ListFlags, stdin: NodeJS.ReadableStream): Promise<ListOptions> {\n const opts: ListOptions = await toReadOptions(flags);\n if (flags.where?.length && flags.filters) throw usageError(\"--where and --filters are mutually exclusive\");\n if (flags.where?.length) opts.where = parseWhere(flags.where);\n if (flags.filters) opts.filters = (await readData(flags.filters, stdin, \"--filters\")) as ListOptions[\"filters\"];\n if (flags.sort?.length) opts.sort = parseSort(flags.sort);\n const limit = parseInt10(flags.limit, \"--limit\");\n const offset = parseInt10(flags.offset, \"--offset\");\n if (limit !== undefined) opts.limit = limit;\n if (offset !== undefined) opts.offset = offset;\n if (flags.count) opts.count = true;\n return opts;\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { confirm } from \"../input.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { requireSiteKey } from \"../entries/client.js\";\n\ninterface Folder {\n id: string;\n site_key: string;\n parent_id: string | null;\n name: string;\n slug: string;\n path: string;\n entry_count?: number;\n media_count?: number;\n}\n\n/**\n * Where a kind of folder lives: a model's content folders on one site, or the\n * media library's, which span every site the credential may read unless one\n * is configured.\n */\ninterface FolderScope {\n path: string;\n siteKey: string | undefined;\n}\n\nexport function contentFolders(ctx: Context, model: string): FolderScope {\n return { path: `content/${encodeURIComponent(model)}/folders`, siteKey: requireSiteKey(ctx) };\n}\n\nexport function mediaFolders(ctx: Context): FolderScope {\n return { path: \"media/folders\", siteKey: ctx.siteKey };\n}\n\n/** \"/company/team/\" → \"/company/team\"; \"\" and \"/\" → \"/\". */\nfunction normalizePath(p: string): string {\n const trimmed = p.trim().replace(/\\/+$/, \"\");\n return trimmed === \"\" ? \"/\" : trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n}\n\nasync function listFolders(ctx: Context, scope: FolderScope): Promise<Folder[]> {\n const res = await request<{ folders: Folder[] }>(ctx, \"GET\", scope.path, { query: { site_key: scope.siteKey } });\n return res.data.folders;\n}\n\n/** The folder an id or a /path names. */\nasync function findFolder(ctx: Context, scope: FolderScope, ref: string): Promise<Folder> {\n const folders = await listFolders(ctx, scope);\n const byPath = ref.startsWith(\"/\");\n const path = normalizePath(ref);\n const matches = folders.filter((f) => (byPath ? f.path === path : f.id === ref));\n if (matches.length === 0) throw usageError(`no folder ${ref}`);\n if (matches.length > 1) throw usageError(`${ref} is a folder on several sites; pass --site`);\n return matches[0]!;\n}\n\n/** The folder id at a path, or null for the root \"/\". */\nexport async function folderIdAt(ctx: Context, scope: FolderScope, path: string): Promise<string | null> {\n if (normalizePath(path) === \"/\") return null;\n return (await findFolder(ctx, scope, normalizePath(path))).id;\n}\n\nfunction registerFolderCommands(parent: Command, io: Io, kind: \"content\" | \"media\"): void {\n const scopeFor = (ctx: Context, model: string | undefined) =>\n kind === \"content\" ? contentFolders(ctx, model!) : mediaFolders(ctx);\n // Content folders belong to a model, so every content command takes one first.\n const withModel = (cmd: Command) => (kind === \"content\" ? cmd.argument(\"<model>\") : cmd);\n // Commander passes the positional arguments first, then the flags and the command.\n const split = (args: unknown[]) => {\n const cmd = args[args.length - 1] as Command;\n const flags = args[args.length - 2] as Record<string, unknown>;\n const positional = args.slice(0, -2) as string[];\n const model = kind === \"content\" ? positional.shift() : undefined;\n return { ctx: resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io), model, positional, flags };\n };\n const countHeader = kind === \"content\" ? \"ENTRIES\" : \"MEDIA\";\n\n withModel(parent.command(\"list\").description(\"List folders by path\")).action(async (...args: unknown[]) => {\n const { ctx, model } = split(args);\n const folders = await listFolders(ctx, scopeFor(ctx, model));\n if (ctx.json) {\n io.stdout.write(toJson(folders) + \"\\n\");\n return;\n }\n const rows = folders.map((f) => [f.id, f.path, f.name, String(f.entry_count ?? f.media_count ?? \"\")]);\n io.stdout.write(formatTable(rows, [\"ID\", \"PATH\", \"NAME\", countHeader]) + \"\\n\");\n });\n\n withModel(parent.command(\"get\").description(\"Print one folder as JSON\"))\n .argument(\"<id-or-path>\", \"a folder id, or its path such as /company/team\")\n .action(async (...args: unknown[]) => {\n const { ctx, model, positional } = split(args);\n io.stdout.write(toJson(await findFolder(ctx, scopeFor(ctx, model), positional[0]!)) + \"\\n\");\n });\n\n withModel(parent.command(\"create\").description(\"Create a folder; its parent must exist\"))\n .argument(\"<path>\", \"the new folder's path, such as /company/team; the last segment is its slug\")\n .option(\"--name <name>\", \"display name (default: the slug)\")\n .action(async (...args: unknown[]) => {\n const { ctx, model, positional, flags } = split(args);\n const scope = scopeFor(ctx, model);\n const path = normalizePath(positional[0]!);\n if (path === \"/\") throw usageError(\"the root folder always exists\");\n const slug = path.slice(path.lastIndexOf(\"/\") + 1);\n const parentId = await folderIdAt(ctx, scope, path.slice(0, path.lastIndexOf(\"/\")));\n const res = await request<Folder>(ctx, \"POST\", scope.path, {\n query: { site_key: scope.siteKey },\n body: { parent_id: parentId, name: (flags.name as string | undefined) ?? slug, slug },\n });\n if (ctx.json) io.stdout.write(toJson(res.data) + \"\\n\");\n else io.stdout.write(`created ${res.data.id} ${res.data.path}\\n`);\n });\n\n withModel(\n parent\n .command(\"delete\")\n .description(`Delete a folder; its sub-folders and ${kind === \"content\" ? \"entries\" : \"media\"} move up to its parent`),\n )\n .argument(\"<id-or-path>\")\n .option(\"-y, --yes\", \"do not ask\")\n .action(async (...args: unknown[]) => {\n const { ctx, model, positional, flags } = split(args);\n const scope = scopeFor(ctx, model);\n const folder = await findFolder(ctx, scope, positional[0]!);\n await confirm(io, `Delete folder ${folder.path}?`, Boolean(flags.yes));\n await request(ctx, \"DELETE\", `${scope.path}/${encodeURIComponent(folder.id)}`, {\n query: { site_key: kind === \"content\" ? scope.siteKey : undefined },\n });\n if (ctx.json) io.stdout.write(toJson({ id: folder.id, deleted: true }) + \"\\n\");\n else io.stdout.write(`deleted ${folder.id} ${folder.path}\\n`);\n });\n}\n\nexport function registerContentFolders(program: Command, io: Io): void {\n registerFolderCommands(program.command(\"folders\").description(\"A model's content folders\"), io, \"content\");\n}\n\nexport function registerMediaFolders(media: Command, io: Io): void {\n registerFolderCommands(media.command(\"folders\").description(\"Media library folders\"), io, \"media\");\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { toListOptions, type ListFlags } from \"../entries/query.js\";\nimport type { ListOptions } from \"@plenary/client\";\n\ninterface FormEntry {\n id: string;\n form_key: string;\n site_key: string;\n status: string;\n created_at: string;\n data: Record<string, unknown>;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/**\n * Form-entry lists take the Content API's query engine, but not through\n * @plenary/client (which is the public delivery surface), so the options are\n * compiled to a query string here with the same rules.\n */\nfunction toQuery(ctx: Context, opts: ListOptions): Record<string, string> {\n const q: Record<string, string> = {};\n if (ctx.siteKey) q.site_key = ctx.siteKey;\n for (const [field, value] of Object.entries(opts.where ?? {})) {\n if (typeof value === \"object\" && value !== null) {\n for (const [op, v] of Object.entries(value as Record<string, unknown>)) {\n q[`where:${field}.${op}`] = Array.isArray(v) ? v.join(\",\") : String(v);\n }\n } else {\n q[`where:${field}`] = String(value);\n }\n }\n if (opts.filters) q.filters = JSON.stringify(opts.filters);\n for (const [field, dir] of Object.entries(opts.sort ?? {})) q[`sort:${field}`] = dir;\n if (opts.limit !== undefined) q.limit = String(opts.limit);\n if (opts.offset !== undefined) q.offset = String(opts.offset);\n if (opts.count) q.count = \"true\";\n return q;\n}\n\nconst PAGE = 100;\n\nexport function registerFormEntries(forms: Command, io: Io): void {\n const entries = forms.command(\"entries\").description(\"Form entries (what visitors submitted)\");\n\n const listFlags = (cmd: Command) =>\n cmd\n .option(\"-w, --where <field=value>\", \"filter: field=value or field=$op:value (repeatable)\", collect, [])\n .option(\"--filters <json>\", \"a filter tree (inline JSON, @file, or -)\")\n .option(\"-s, --sort <field[:dir]>\", \"sort field, asc unless :desc (repeatable)\", collect, [])\n .option(\"--limit <n>\")\n .option(\"--offset <n>\")\n .option(\"--count\", \"ask for the total and show it\");\n\n listFlags(entries.command(\"list\").description(\"List a form's entries\").argument(\"<form>\")).action(\n async (form: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const opts = await toListOptions(flags, io.stdin);\n const res = await request<FormEntry[]>(ctx, \"GET\", `forms/${encodeURIComponent(form)}/entries`, {\n query: toQuery(ctx, opts),\n });\n const total = res.headers.get(\"X-Total-Count\");\n if (ctx.json) {\n io.stdout.write(toJson({ items: res.data, ...(total !== null ? { total: Number(total) } : {}) }) + \"\\n\");\n return;\n }\n const rows = res.data.map((e) => [e.id, e.status, e.site_key, e.created_at, summary(e.data)]);\n io.stdout.write(formatTable(rows, [\"ID\", \"STATUS\", \"SITE\", \"CREATED\", \"DATA\"]) + \"\\n\");\n if (total !== null) io.stdout.write(`${res.data.length} of ${total}\\n`);\n },\n );\n\n listFlags(entries.command(\"export\").description(\"Write every matching entry to stdout as NDJSON\").argument(\"<form>\")).action(\n async (form: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const opts = await toListOptions(flags, io.stdin);\n const limit = opts.limit ?? PAGE;\n let offset = opts.offset ?? 0;\n for (;;) {\n const res = await request<FormEntry[]>(ctx, \"GET\", `forms/${encodeURIComponent(form)}/entries`, {\n query: toQuery(ctx, { ...opts, limit, offset, count: false }),\n });\n for (const e of res.data) io.stdout.write(JSON.stringify(e) + \"\\n\");\n if (res.data.length < limit) return;\n offset += res.data.length;\n }\n },\n );\n}\n\n/** The first few values, for a glance at what was submitted. */\nfunction summary(data: Record<string, unknown>): string {\n return Object.entries(data)\n .slice(0, 3)\n .map(([k, v]) => `${k}=${typeof v === \"string\" ? v : JSON.stringify(v)}`)\n .join(\" \");\n}\n","import { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { CliError, usageError } from \"../errors.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { folderIdAt, mediaFolders, registerMediaFolders } from \"./folders.js\";\n\ninterface MediaItem {\n media_id: string;\n media_type: string;\n mime_type: string;\n file_name: string;\n file_size: number;\n folder_id: string | null;\n path: string;\n visibility: string;\n original_url: string;\n created_at: string;\n}\n\n// The server sniffs the bytes itself; the declared part type is a hint for it\n// and for anything in between, so a file goes out as what its extension says.\nconst MIME_BY_EXT: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".svg\": \"image/svg+xml\",\n \".tif\": \"image/tiff\",\n \".tiff\": \"image/tiff\",\n \".bmp\": \"image/bmp\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".ogv\": \"video/ogg\",\n \".mov\": \"video/quicktime\",\n \".mp3\": \"audio/mpeg\",\n \".ogg\": \"audio/ogg\",\n \".wav\": \"audio/wav\",\n \".flac\": \"audio/flac\",\n \".pdf\": \"application/pdf\",\n \".zip\": \"application/zip\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n};\n\nexport function mimeForFile(file: string): string {\n return MIME_BY_EXT[path.extname(file).toLowerCase()] ?? \"application/octet-stream\";\n}\n\nfunction size(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/** The asset already uploaded under this file name to this folder (the root without one), if any. */\nasync function findExisting(ctx: Context, name: string, folder: string | undefined): Promise<MediaItem | undefined> {\n // search is a case-insensitive regex over file name and caption, so it is\n // anchored and escaped here and the exact match picked out below.\n const pattern = `^${name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}$`;\n const res = await request<MediaItem[]>(ctx, \"GET\", \"media\", {\n query: { search: pattern, site_key: ctx.siteKey, limit: \"100\" },\n });\n return res.data.find((m) => m.file_name === name && (m.folder_id ?? undefined) === folder);\n}\n\ninterface UploadFlags {\n folder?: string;\n folderPath?: string;\n private?: boolean;\n skipExisting?: boolean;\n}\n\nexport function registerMedia(program: Command, io: Io): void {\n const media = program.command(\"media\").description(\"Media library\");\n\n media\n .command(\"upload\")\n .description(\"Upload one or more files\")\n .argument(\"<files...>\")\n .option(\"--folder <id>\", \"media folder id\")\n .option(\"--folder-path <path>\", \"media folder path, such as /brand/logos (instead of --folder)\")\n .option(\"--private\", \"store as a private asset\")\n .option(\"--skip-existing\", \"skip a file whose name is already in the folder\")\n .action(async (files: string[], flags: UploadFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n if (flags.folderPath !== undefined) {\n if (flags.folder !== undefined) throw usageError(\"pass --folder or --folder-path, not both\");\n flags.folder = (await folderIdAt(ctx, mediaFolders(ctx), flags.folderPath)) ?? undefined;\n }\n const uploaded: MediaItem[] = [];\n let failed = 0;\n for (const file of files) {\n let bytes: Buffer;\n try {\n bytes = readFileSync(file);\n } catch (err) {\n throw usageError(`cannot read ${file}: ${(err as Error).message}`);\n }\n if (flags.skipExisting) {\n const existing = await findExisting(ctx, path.basename(file), flags.folder);\n if (existing) {\n uploaded.push(existing);\n if (!ctx.json) io.stdout.write(`${existing.media_id} ${existing.file_name} (exists)\\n`);\n continue;\n }\n }\n const form = new FormData();\n form.append(\"upload_file\", new Blob([new Uint8Array(bytes)], { type: mimeForFile(file) }), path.basename(file));\n if (ctx.siteKey) form.append(\"site_key\", ctx.siteKey);\n if (flags.folder) form.append(\"folder_id\", flags.folder);\n if (flags.private) form.append(\"visibility\", \"private\");\n try {\n const res = await request<MediaItem>(ctx, \"POST\", \"media\", { form });\n uploaded.push(res.data);\n if (!ctx.json) io.stdout.write(`${res.data.media_id} ${res.data.file_name}\\n`);\n } catch (err) {\n if (files.length === 1) throw err;\n failed++;\n const code = (err as { code?: string }).code ?? (err as Error).message;\n io.stdout.write(`fail ${file}: ${code}\\n`);\n }\n }\n if (ctx.json) io.stdout.write(toJson(uploaded) + \"\\n\");\n if (failed) throw new CliError(\"\", 1);\n });\n\n media\n .command(\"list\")\n .description(\"List media\")\n .option(\"--search <text>\", \"match file names and captions\")\n .option(\"--path <prefix>\", \"only assets under this folder path\")\n .option(\"--limit <n>\")\n .option(\"--page <n>\")\n .action(async (flags: { search?: string; path?: string; limit?: string; page?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<MediaItem[]>(ctx, \"GET\", \"media\", {\n query: { search: flags.search, path_prefix: flags.path, limit: flags.limit, page: flags.page },\n });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((m) => [m.media_id, m.media_type, m.file_name, size(m.file_size), m.path, m.visibility]);\n io.stdout.write(formatTable(rows, [\"ID\", \"TYPE\", \"FILE\", \"SIZE\", \"PATH\", \"VISIBILITY\"]) + \"\\n\");\n });\n\n media\n .command(\"get\")\n .description(\"Print one media item as JSON\")\n .argument(\"<id>\")\n .action(async (id: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request(ctx, \"GET\", `media/${encodeURIComponent(id)}`);\n io.stdout.write(toJson(res.data) + \"\\n\");\n });\n\n registerMediaFolders(media, io);\n}\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { PlenaryError } from \"@plenary/client\";\nimport { request, type ApiResponse, type RequestOptions } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { confirm } from \"../input.js\";\nimport { toJson } from \"../output.js\";\nimport { filterKinds, parseKinds, readTree, writeTree, type Kind, type YamlFile } from \"../metadata/dir.js\";\nimport { formatPlan, type ImportResult } from \"../metadata/plan.js\";\n\ninterface DirOption {\n dir?: string;\n only?: string;\n verbose?: boolean;\n dryRun?: boolean;\n prune?: boolean;\n yes?: boolean;\n allSites?: boolean;\n}\n\n/**\n * The site whose tree the command moves: the configured one (--site,\n * PLENARY_SITE_KEY, plenary.json) unless --all-sites asks for the whole\n * instance. Roles belong to a site, so only a site's tree holds them.\n */\nfunction siteOf(ctx: Context, opts: DirOption): string | undefined {\n return opts.allSites ? undefined : ctx.siteKey;\n}\n\nfunction kindsOf(opts: DirOption, site?: string): Kind[] {\n let kinds: Kind[];\n try {\n kinds = parseKinds(opts.only);\n } catch (err) {\n throw usageError(`--only: ${(err as Error).message}`);\n }\n if (site) return kinds;\n if (opts.only && opts.only !== \"all\" && kinds.includes(\"roles\")) {\n throw usageError(\"roles belong to a site and are not part of the instance-wide tree; drop --all-sites\");\n }\n return kinds.filter((k) => k !== \"roles\");\n}\n\n/**\n * A server that predates per-site trees ignores site_key and answers for the\n * whole instance, so the echo is what says the answer is the site's alone.\n */\nfunction isSiteAnswer(data: { site_key?: string }, site: string | undefined): boolean {\n return !site || data.site_key === site;\n}\n\nconst UNSCOPED_SERVER = (site: string) =>\n `this server predates per-site metadata: it answered for every site, not just ${site}`;\n\n/** `--dir` is relative to the cwd; the configured directory to the config file. */\nfunction treeRoot(ctx: Context, opts: DirOption): string {\n return opts.dir ? path.resolve(ctx.io.cwd, opts.dir) : path.resolve(ctx.projectRoot, ctx.metadataDir);\n}\n\nfunction readTreeOrFail(root: string, kinds: Kind[]): YamlFile[] {\n const files = filterKinds(readTree(root), kinds);\n if (files.length === 0) throw usageError(`no YAML files under ${root}/{${kinds.join(\",\")}}`);\n return files;\n}\n\nconst OLDER_SERVER =\n \"this server predates the whole-tree metadata endpoints: it can sync models and forms only\";\n\n/**\n * The whole-tree route, falling back to the models-only one a server from\n * without them has, so an older instance keeps working for models and\n * forms. Roles, sites and --prune have nowhere to go there and are refused\n * with a message rather than a bare 404.\n */\nasync function metadataRequest<T>(\n ctx: Context,\n method: \"GET\" | \"POST\",\n opts: RequestOptions,\n needsWholeTree: boolean,\n): Promise<ApiResponse<T>> {\n const path = method === \"GET\" ? \"metadata\" : \"metadata/import\";\n try {\n return await request<T>(ctx, method, path, opts);\n } catch (err) {\n if (!(err instanceof PlenaryError) || err.status !== 404 || err.code !== \"http_404\") throw err;\n if (needsWholeTree) throw usageError(OLDER_SERVER);\n const fallback = method === \"GET\" ? \"metadata/models\" : \"metadata/models/import\";\n return request<T>(ctx, method, fallback, opts);\n }\n}\n\n/**\n * Both diff and push: the plan is always previewed first, and a push with\n * --prune is confirmed against that preview before anything is deleted.\n */\nasync function runImport(ctx: Context, root: string, opts: DirOption, apply: boolean): Promise<void> {\n const site = siteOf(ctx, opts);\n const kinds = kindsOf(opts, site);\n const files = readTreeOrFail(root, kinds);\n const prune = Boolean(opts.prune);\n const body = { files, apply: false, prune };\n const query = site ? { site_key: site } : undefined;\n const wholeTree = prune || files.some((f) => !/^(models|forms)\\//.test(f.path));\n let res = await metadataRequest<ImportResult>(ctx, \"POST\", { body, query }, wholeTree);\n // Pruning against a server that ignored the site would delete every other\n // site's models; refuse before anything is applied.\n if (!isSiteAnswer(res.data, site)) {\n if (prune) throw usageError(`${UNSCOPED_SERVER(site!)}; --prune would delete other sites' models (use --all-sites if that is meant)`);\n ctx.io.stderr.write(`warning: ${UNSCOPED_SERVER(site!)}\\n`);\n }\n const deletes = res.data.changes.filter((c) => c.action === \"delete\");\n\n if (apply) {\n if (deletes.length > 0) {\n if (!ctx.json) ctx.io.stdout.write(formatPlan(res.data, Boolean(opts.verbose)) + \"\\n\");\n await confirm(ctx.io, `Delete ${deletes.length} ${deletes.length === 1 ? \"entity\" : \"entities\"} from the instance?`, Boolean(opts.yes));\n }\n res = await metadataRequest<ImportResult>(ctx, \"POST\", { body: { ...body, apply: true }, query }, wholeTree);\n }\n if (ctx.json) ctx.io.stdout.write(toJson(res.data) + \"\\n\");\n else ctx.io.stdout.write(formatPlan(res.data, Boolean(opts.verbose)) + \"\\n\");\n}\n\nconst onlyOption = [\"--only <kinds>\", \"comma list of models, forms, roles, sites (default: all)\"] as const;\nconst allSitesOption = [\"--all-sites\", \"the whole instance, not just the configured site (no roles)\"] as const;\n\nexport function registerMetadata(program: Command, io: Io): void {\n const metadata = program\n .command(\"metadata\")\n .description(\"Keep a directory of model and form YAML in step with the instance\")\n .addHelpText(\n \"after\",\n `\nThe tree is models/, forms/, roles/ and sites/ under the metadata directory\n(\"metadataDir\" in plenary.json, default ./plenary), one <key>.yaml per\nentity. With a site configured (--site, PLENARY_SITE_KEY or \"siteKey\" in\nplenary.json) the tree is that site's alone: its models, forms, roles and\nsite file, and --prune deletes only within it. --all-sites moves the whole\ninstance, which holds no roles. Models and forms need an API key or a\nsession; roles need a super user session and sites a session that may update\nthem (plenary login). See docs/CLI.md.`,\n );\n\n metadata\n .command(\"pull\")\n .description(\"Write every model, form, role and site the credential may read into the directory\")\n .option(\"--dir <path>\", \"metadata directory (default: the configured one)\")\n .option(...onlyOption)\n .option(...allSitesOption)\n .action(async (opts: DirOption, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const root = treeRoot(ctx, opts);\n const site = siteOf(ctx, opts);\n const kinds = kindsOf(opts, site);\n const wholeTree = kinds.some((k) => k === \"roles\" || k === \"sites\") && Boolean(opts.only);\n const res = await metadataRequest<{ files: YamlFile[]; omitted?: string[]; site_key?: string }>(\n ctx,\n \"GET\",\n { query: { only: kinds.join(\",\"), ...(site ? { site_key: site } : {}) } },\n wholeTree,\n );\n // Writing every site's models into one site's repository is never what\n // a pull meant, and a later push --prune would then own them.\n if (!isSiteAnswer(res.data, site)) throw usageError(`${UNSCOPED_SERVER(site!)}; pull with --all-sites for the whole instance`);\n const result = writeTree(root, res.data.files, kinds);\n const omitted = res.data.omitted ?? [];\n if (ctx.json) {\n io.stdout.write(toJson({ dir: root, ...result, omitted }) + \"\\n\");\n return;\n }\n io.stdout.write(`wrote ${result.written.length} file${result.written.length === 1 ? \"\" : \"s\"} to ${root}\\n`);\n if (omitted.length) {\n io.stderr.write(`not included, the credential may not read them: ${omitted.join(\", \")}\\n`);\n }\n if (result.written.length === 0 && omitted.length === 0) {\n // The server answers a key that may read no models with an empty tree,\n // not a refusal, so say what the likely cause is.\n io.stderr.write(\"the server sent no models: the key may lack content:models:read (a public key never has it)\\n\");\n }\n if (result.stale.length) {\n io.stdout.write(`not on the server (left in place):\\n${result.stale.map((p) => ` ${p}`).join(\"\\n\")}\\n`);\n }\n });\n\n metadata\n .command(\"diff\")\n .description(\"Preview what push would change, without writing anything\")\n .option(\"--dir <path>\", \"metadata directory (default: the configured one)\")\n .option(...onlyOption)\n .option(...allSitesOption)\n .option(\"--prune\", \"include what push --prune would delete\")\n .option(\"--verbose\", \"list unchanged entities too\")\n .action(async (opts: DirOption, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await runImport(ctx, treeRoot(ctx, opts), opts, false);\n });\n\n metadata\n .command(\"push\")\n .description(\"Apply the directory to the instance (creates and updates; deletes only with --prune)\")\n .option(\"--dir <path>\", \"metadata directory (default: the configured one)\")\n .option(...onlyOption)\n .option(...allSitesOption)\n .option(\"--prune\", \"also delete entities absent from the directory, within the kinds (and site) it holds\")\n .option(\"-y, --yes\", \"do not ask before pruning\")\n .option(\"--dry-run\", \"same as diff\")\n .option(\"--verbose\", \"list unchanged entities too\")\n .addHelpText(\n \"after\",\n `\n--prune deletes only within the kinds present in the directory: a tree with\nno roles/ cannot delete a role. System-owned roles are never touched and are\nreported as skipped. The plan is shown and confirmed before anything is\ndeleted; -y skips the question, and a run with no terminal needs it.`,\n )\n .action(async (opts: DirOption, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await runImport(ctx, treeRoot(ctx, opts), opts, !opts.dryRun);\n });\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** One file of a metadata tree, `path` relative to the tree's root. */\nexport interface YamlFile {\n path: string;\n content: string;\n}\n\n/** The directories the server reads and writes. */\nexport const MANAGED_DIRS = [\"models\", \"forms\", \"roles\", \"sites\"] as const;\nexport type Kind = (typeof MANAGED_DIRS)[number];\n\n/** `--only models,roles` → the kinds it names; empty or \"all\" → every kind. */\nexport function parseKinds(spec: string | undefined): Kind[] {\n if (!spec || spec === \"all\") return [...MANAGED_DIRS];\n const out: Kind[] = [];\n for (const raw of spec.split(\",\")) {\n const k = raw.trim() as Kind;\n if (!MANAGED_DIRS.includes(k)) throw new Error(`unknown kind \"${k}\" (want ${MANAGED_DIRS.join(\", \")} or all)`);\n if (!out.includes(k)) out.push(k);\n }\n return out;\n}\n\n/** Only the files under the named kinds' directories. */\nexport function filterKinds(files: YamlFile[], kinds: Kind[]): YamlFile[] {\n return files.filter((f) => kinds.includes(f.path.split(\"/\")[0] as Kind));\n}\n\n/** Every `models/*.yaml` and `forms/*.yaml` directly under `root`, sorted by path. */\nexport function readTree(root: string): YamlFile[] {\n const out: YamlFile[] = [];\n for (const rel of managedFiles(root)) {\n out.push({ path: rel, content: readFileSync(path.join(root, rel), \"utf8\") });\n }\n return out;\n}\n\nexport interface WriteResult {\n written: string[];\n /** Managed files already on disk that the server did not send — reported, never deleted. */\n stale: string[];\n}\n\n/**\n * Writes the server's files into `root`, creating directories as needed.\n * Stale files are only looked for under `kinds`, since a pull of models\n * alone says nothing about the roles on disk.\n */\nexport function writeTree(root: string, files: YamlFile[], kinds: Kind[] = [...MANAGED_DIRS]): WriteResult {\n const before = new Set(managedFiles(root).filter((p) => kinds.includes(p.split(\"/\")[0] as Kind)));\n const written: string[] = [];\n for (const f of [...files].sort((a, b) => a.path.localeCompare(b.path))) {\n if (!isTreePath(f.path)) continue;\n const abs = path.join(root, f.path);\n mkdirSync(path.dirname(abs), { recursive: true });\n writeFileSync(abs, f.content);\n written.push(f.path);\n before.delete(f.path);\n }\n return { written, stale: [...before].sort() };\n}\n\n/** `models/x.yaml` or `forms/x.yaml`, directly under the root; nothing else. */\nexport function isTreePath(p: string): boolean {\n const parts = p.split(\"/\");\n return (\n parts.length === 2 &&\n (MANAGED_DIRS as readonly string[]).includes(parts[0] as string) &&\n (parts[1] as string).endsWith(\".yaml\")\n );\n}\n\nfunction managedFiles(root: string): string[] {\n const out: string[] = [];\n for (const dir of MANAGED_DIRS) {\n const abs = path.join(root, dir);\n if (!existsSync(abs)) continue;\n for (const name of readdirSync(abs).sort()) {\n if (name.endsWith(\".yaml\")) out.push(`${dir}/${name}`);\n }\n }\n return out.sort();\n}\n","/** One row of the server's import plan. */\nexport interface ImportChange {\n key: string;\n kind: string;\n action: \"create\" | \"update\" | \"noop\" | \"delete\" | \"skip\";\n detail?: {\n fields_added: string[];\n fields_removed: string[];\n fields_changed: string[];\n attributes_changed: boolean;\n transformers_changed: boolean;\n };\n}\n\nexport interface ImportResult {\n applied: boolean;\n changes: ImportChange[];\n /** The site the plan was made for; absent on a whole-instance import. */\n site_key?: string;\n}\n\n/**\n * The plan as lines: one per create/update (noops too with `verbose`), then a\n * summary. `applied` picks the tense of the summary.\n */\nexport function formatPlan(result: ImportResult, verbose = false): string {\n const lines: string[] = [];\n const n = { create: 0, update: 0, delete: 0, skip: 0, noop: 0 };\n // Deletes first: they are what a person scanning a --prune plan must see.\n const ordered = [...result.changes].sort((a, b) => Number(b.action === \"delete\") - Number(a.action === \"delete\"));\n for (const c of ordered) {\n n[c.action]++;\n if (c.action === \"noop\" && !verbose) continue;\n const label = c.action === \"noop\" ? \"unchanged\" : c.action === \"skip\" ? \"skipped\" : c.action;\n const note = c.action === \"skip\" ? \" (system-owned)\" : detail(c);\n lines.push(`${label.padEnd(9)} ${c.kind.padEnd(10)} ${c.key}${note}`);\n }\n const parts = [`${n.create} to create`, `${n.update} to update`];\n if (n.delete) parts.push(`${n.delete} to delete`);\n if (n.skip) parts.push(`${n.skip} skipped`);\n parts.push(`${n.noop} unchanged`);\n if (n.create + n.update + n.delete === 0) {\n lines.push(`No changes: ${n.noop} unchanged${n.skip ? `, ${n.skip} skipped` : \"\"}.`);\n } else {\n lines.push(`${result.applied ? \"Applied\" : \"Plan\"}: ${parts.join(\", \")}.`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction detail(c: ImportChange): string {\n const d = c.detail;\n if (!d) return \"\";\n const parts: string[] = [];\n if (d.fields_added.length) parts.push(`+${d.fields_added.join(\",\")}`);\n if (d.fields_changed.length) parts.push(`~${d.fields_changed.join(\",\")}`);\n if (d.fields_removed.length) parts.push(`-${d.fields_removed.join(\",\")}`);\n if (d.attributes_changed) parts.push(\"settings\");\n if (d.transformers_changed) parts.push(\"transformers\");\n return parts.length ? ` (${parts.join(\" \")})` : \"\";\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport type { Command } from \"commander\";\nimport {\n CONFIG_FILE,\n DEFAULT_METADATA_DIR,\n resolveContext,\n type GlobalOptions,\n type Io,\n type ProjectConfig,\n} from \"../config.js\";\nimport { usageError } from \"../errors.js\";\n\nexport function registerInit(program: Command, io: Io): void {\n program\n .command(\"init\")\n .description(`Write a ${CONFIG_FILE} for this project (never a credential)`)\n .option(\"--dir <path>\", \"metadata directory, relative to the config file\", DEFAULT_METADATA_DIR)\n .option(\"-f, --force\", `overwrite an existing ${CONFIG_FILE}`)\n .addHelpText(\n \"after\",\n `\nThe base URL, site and locale come from --base-url, --site and --locale (or\ntheir PLENARY_* variables); anything missing is prompted for on a terminal.`,\n )\n .action(async (opts: { dir: string; force?: boolean }, cmd: Command) => {\n const target = path.join(io.cwd, CONFIG_FILE);\n if (existsSync(target) && !opts.force) {\n throw usageError(`${target} already exists (pass --force to overwrite)`);\n }\n const globals = cmd.optsWithGlobals<GlobalOptions>();\n // Read what the environment already says, but not a parent's plenary.json:\n // init describes this directory, not one above it.\n const ctx = resolveContext({ ...globals, config: undefined }, { ...io, cwd: path.parse(io.cwd).root });\n\n const baseUrl = globals.baseUrl ?? ctx.baseUrl ?? (await ask(io, \"Base URL (https://cms.example.com)\"));\n if (!baseUrl) throw usageError(\"a base URL is required: pass --base-url or set PLENARY_BASE_URL\");\n const siteKey = globals.site ?? ctx.siteKey ?? (await ask(io, \"Site key\", \"default\"));\n const locale = globals.locale ?? ctx.locale ?? (await ask(io, \"Locale\", \"en-us\"));\n\n const config: ProjectConfig = { baseUrl: baseUrl.replace(/\\/+$/, \"\") };\n if (siteKey) config.siteKey = siteKey;\n if (locale) config.locale = locale;\n if (opts.dir !== DEFAULT_METADATA_DIR) config.metadataDir = opts.dir;\n\n writeFileSync(target, JSON.stringify(config, null, 2) + \"\\n\");\n io.stdout.write(`wrote ${target}\\n`);\n });\n}\n\n/** Prompts on a terminal; returns the default (or undefined) without one. */\nasync function ask(io: Io, label: string, fallback?: string): Promise<string | undefined> {\n if (!io.isTTY) return fallback;\n const rl = createInterface({ input: io.stdin, output: io.stderr });\n try {\n const answer = (await rl.question(fallback ? `${label} [${fallback}]: ` : `${label}: `)).trim();\n return answer === \"\" ? fallback : answer;\n } finally {\n rl.close();\n }\n}\n","import type { Command } from \"commander\";\nimport { describeUser } from \"./auth.js\";\nimport { PlenaryError } from \"@plenary/client\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { credentialHeaders, request } from \"../api/http.js\";\nimport { CliError } from \"../errors.js\";\nimport { toJson } from \"../output.js\";\n\ninterface Health {\n status: string;\n database: string;\n version: string;\n edition: string;\n license?: string;\n}\n\ninterface MeGrant {\n key: string;\n site_key?: string;\n content_model_id?: string;\n source: string;\n role_key?: string;\n}\n\ntype Me =\n | { principal: \"api_key\"; key_id: string; key_type: string; name: string; grants: MeGrant[]; site_key?: string }\n | { principal: \"user\"; user_id: string; is_super_user: boolean; grants: MeGrant[] };\n\nexport function registerStatus(program: Command, io: Io): void {\n program\n .command(\"status\")\n .description(\"Show the instance's health and which credential this run holds\")\n .action(async (_opts: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const health = await request<Health>(ctx, \"GET\", \"/api/v1/health\", { auth: \"none\", allowError: true });\n\n let me: Me | undefined;\n let credentialError: PlenaryError | undefined;\n // A server without API-key support on /auth/me answers /auth/me with 403 for a key it\n // accepted: the key authenticated, the server just cannot describe it.\n let undescribed = false;\n const headers = await credentialHeaders(ctx, \"optional\");\n if (Object.keys(headers).length > 0) {\n try {\n me = (await request<Me>(ctx, \"GET\", \"/api/v1/auth/me\", { auth: \"none\", headers })).data;\n } catch (err) {\n if (!(err instanceof PlenaryError)) throw err;\n if (err.status === 403) undescribed = true;\n else credentialError = err;\n }\n }\n\n const failed = !health.ok || credentialError !== undefined;\n if (ctx.json) {\n io.stdout.write(\n toJson({\n base_url: ctx.baseUrl,\n health: health.data,\n credential: me ?? null,\n credential_error: credentialError ? { status: credentialError.status, code: credentialError.code } : null,\n }) + \"\\n\",\n );\n if (failed) throw new CliError(\"\", 1);\n return;\n }\n\n const lines = [`Instance ${ctx.baseUrl}`];\n if (health.ok || (health.status === 503 && typeof health.data === \"object\")) {\n const h = health.data;\n lines.push(`Version ${h.version} (${h.edition})`);\n lines.push(`Status ${h.status}, database ${h.database}${h.license ? `, license ${h.license}` : \"\"}`);\n } else {\n lines.push(`Status unreachable (HTTP ${health.status})`);\n }\n if (me?.principal === \"api_key\") {\n lines.push(`Credential ${me.key_type} API key \"${me.name}\" (${me.grants.length} grant${me.grants.length === 1 ? \"\" : \"s\"}${\n me.site_key ? `, site ${me.site_key}` : \", instance-wide\"\n })`);\n } else if (me?.principal === \"user\") {\n lines.push(`Credential user session (stored login), ${describeUser(me)}`);\n } else if (credentialError) {\n lines.push(`Credential rejected: ${credentialError.code} (HTTP ${credentialError.status})`);\n } else if (undescribed) {\n lines.push(\"Credential API key accepted (this server predates API-key support on /auth/me and cannot describe the key)\");\n } else {\n lines.push(\"Credential none (set PLENARY_CLI_API_KEY, pass --api-key, or run `plenary login`)\");\n }\n if (ctx.configPath) lines.push(`Config ${ctx.configPath}`);\n io.stdout.write(lines.join(\"\\n\") + \"\\n\");\n // The report itself is the message; the exit code is the only extra signal.\n if (failed) throw new CliError(\"\", 1);\n });\n}\n","import { run } from \"./cli.js\";\n\nrun(process.argv.slice(2), {\n stdout: process.stdout,\n stderr: process.stderr,\n stdin: process.stdin,\n env: process.env,\n cwd: process.cwd(),\n fetch: globalThis.fetch,\n isTTY: Boolean(process.stdin.isTTY),\n}).then((code) => {\n process.exitCode = code;\n});\n"],"mappings":"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","names":["readFileSync","CommanderError","existsSync","readFileSync","path","path","existsSync","readFileSync","token","path","readFileSync","readFileSync","errorFromResponse","collect","path","path","collect","collect","PAGE","readFileSync","path","path","readFileSync","path","PlenaryError","existsSync","mkdirSync","readFileSync","writeFileSync","path","path","PlenaryError","existsSync","writeFileSync","path","createInterface","path","existsSync","writeFileSync","createInterface","PlenaryError","PlenaryError","readFileSync","CommanderError"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/output.ts","../src/errors.ts","../src/config.ts","../src/api/http.ts","../src/session.ts","../src/input.ts","../src/entries/client.ts","../src/commands/admin.ts","../src/commands/api.ts","../src/commands/auth.ts","../src/commands/catalog.ts","../src/commands/entries.ts","../src/entries/query.ts","../src/commands/folders.ts","../src/commands/formentries.ts","../src/commands/media.ts","../src/commands/metadata.ts","../src/metadata/dir.ts","../src/metadata/plan.ts","../src/commands/init.ts","../src/commands/status.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { Command, CommanderError } from \"commander\";\nimport type { Io } from \"./config.js\";\nimport { describeError, exitCodeFor } from \"./output.js\";\nimport { registerAdmin } from \"./commands/admin.js\";\nimport { registerApi } from \"./commands/api.js\";\nimport { registerAuth } from \"./commands/auth.js\";\nimport { registerCatalog } from \"./commands/catalog.js\";\nimport { registerEntries } from \"./commands/entries.js\";\nimport { registerContentFolders } from \"./commands/folders.js\";\nimport { registerFormEntries } from \"./commands/formentries.js\";\nimport { registerMedia } from \"./commands/media.js\";\nimport { registerMetadata } from \"./commands/metadata.js\";\nimport { registerInit } from \"./commands/init.js\";\nimport { registerStatus } from \"./commands/status.js\";\n\nfunction version(): string {\n try {\n const pkg = JSON.parse(readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\")) as { version: string };\n return pkg.version;\n } catch {\n return \"0.0.0\";\n }\n}\n\nexport function createProgram(io: Io): Command {\n const program = new Command(\"plenary\")\n .description(\"Command-line client for the Plenary API\")\n .version(version(), \"-v, --version\")\n .option(\"--base-url <url>\", \"instance URL (PLENARY_BASE_URL)\")\n .option(\"--api-key <key>\", \"API key (PLENARY_CLI_API_KEY)\")\n .option(\"--site <key>\", \"site key (PLENARY_SITE_KEY)\")\n .option(\"--locale <code>\", \"locale (PLENARY_LOCALE)\")\n .option(\"--config <path>\", \"plenary.json to use (default: nearest, searching upward)\")\n .option(\"--json\", \"print machine-readable JSON\")\n .option(\"--debug\", \"print requests and stack traces to stderr\")\n .showHelpAfterError(\"(run with --help for usage)\")\n .exitOverride()\n .configureOutput({\n writeOut: (s) => io.stdout.write(s),\n writeErr: (s) => io.stderr.write(s),\n });\n\n registerInit(program, io);\n registerAuth(program, io);\n registerStatus(program, io);\n registerMetadata(program, io);\n registerCatalog(program, io, \"models\");\n registerFormEntries(registerCatalog(program, io, \"forms\"), io);\n registerEntries(program, io);\n registerContentFolders(program, io);\n registerMedia(program, io);\n registerAdmin(program, io);\n registerApi(program, io);\n return program;\n}\n\n/** Runs one invocation and returns the exit code; never throws. */\nexport async function run(argv: string[], io: Io): Promise<number> {\n const program = createProgram(io);\n try {\n await program.parseAsync(argv, { from: \"user\" });\n return 0;\n } catch (err) {\n if (err instanceof CommanderError) {\n // Commander has already written help or its own message.\n return exitCodeFor(err);\n }\n const debug = Boolean(program.opts<{ debug?: boolean }>().debug);\n const message = describeError(err, debug);\n if (message !== \"plenary: \") io.stderr.write(message + \"\\n\");\n return exitCodeFor(err);\n }\n}\n","import { PlenaryError } from \"@plenary/client\";\nimport { CommanderError } from \"commander\";\nimport { CliError } from \"./errors.js\";\n\n/** Renders rows as aligned columns; the first row is the header when `header` is set. */\nexport function formatTable(rows: string[][], header?: string[]): string {\n const all = header ? [header, ...rows] : rows;\n if (all.length === 0) return \"\";\n const widths: number[] = [];\n for (const row of all) {\n row.forEach((cell, i) => {\n widths[i] = Math.max(widths[i] ?? 0, cell.length);\n });\n }\n return all\n .map((row) =>\n row\n .map((cell, i) => (i === row.length - 1 ? cell : cell.padEnd(widths[i] ?? 0)))\n .join(\" \")\n .trimEnd(),\n )\n .join(\"\\n\");\n}\n\nexport function toJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\n/** One line for stderr describing why a command failed. */\nexport function describeError(err: unknown, debug = false): string {\n if (err instanceof PlenaryError) {\n let line = `plenary: ${err.code} (HTTP ${err.status})`;\n if (err.vars && Object.keys(err.vars).length > 0) {\n line += \"\\n\" + Object.entries(err.vars).map(([k, v]) => ` ${k}: ${fmtVar(v)}`).join(\"\\n\");\n }\n return line;\n }\n if (err instanceof CliError) return `plenary: ${err.message}`;\n if (err instanceof Error) {\n const cause = err.cause instanceof Error ? `: ${err.cause.message}` : \"\";\n return debug && err.stack ? err.stack : `plenary: ${err.message}${cause}`;\n }\n return `plenary: ${String(err)}`;\n}\n\nexport function exitCodeFor(err: unknown): number {\n if (err instanceof CliError) return err.exitCode;\n if (err instanceof CommanderError) return err.exitCode === 0 ? 0 : 2;\n return 1;\n}\n\nfunction fmtVar(v: unknown): string {\n return typeof v === \"string\" ? v : JSON.stringify(v);\n}\n","/**\n * An error the CLI raised itself (as opposed to one the server returned).\n * exitCode 2 is a usage problem — a missing credential, a malformed flag —\n * and 1 is everything else.\n */\nexport class CliError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode = 1) {\n super(message);\n this.name = \"CliError\";\n this.exitCode = exitCode;\n }\n}\n\nexport function usageError(message: string): CliError {\n return new CliError(message, 2);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { usageError } from \"./errors.js\";\n\n/** The streams and environment a run reads and writes — injected so tests can capture them. */\nexport interface Io {\n stdout: NodeJS.WritableStream;\n stderr: NodeJS.WritableStream;\n stdin: NodeJS.ReadableStream;\n env: NodeJS.ProcessEnv;\n cwd: string;\n fetch: typeof globalThis.fetch;\n /** Whether stdin is a terminal: prompts are only ever issued when it is. */\n isTTY: boolean;\n}\n\n/** The global options every command accepts (declared on the root program). */\nexport interface GlobalOptions {\n baseUrl?: string;\n apiKey?: string;\n site?: string;\n locale?: string;\n config?: string;\n json?: boolean;\n debug?: boolean;\n}\n\n/** The shape of `plenary.json`. Never holds a credential. */\nexport interface ProjectConfig {\n baseUrl?: string;\n siteKey?: string;\n locale?: string;\n metadataDir?: string;\n}\n\n/** Everything a command needs, resolved once per invocation. */\nexport interface Context {\n io: Io;\n baseUrl?: string;\n apiKey?: string;\n siteKey?: string;\n locale?: string;\n metadataDir: string;\n /** The directory holding plenary.json, or the cwd when there is none. */\n projectRoot: string;\n configPath?: string;\n json: boolean;\n debug: boolean;\n /** The access token minted from a stored session, once this run has one. */\n sessionToken?: string;\n}\n\nexport const CONFIG_FILE = \"plenary.json\";\nexport const DEFAULT_METADATA_DIR = \"plenary\";\n\n/** Walks up from `from` and returns the first plenary.json found, if any. */\nexport function findConfigFile(from: string): string | undefined {\n let dir = path.resolve(from);\n for (;;) {\n const candidate = path.join(dir, CONFIG_FILE);\n if (existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n\nconst CONFIG_KEYS: ReadonlyArray<keyof ProjectConfig> = [\"baseUrl\", \"siteKey\", \"locale\", \"metadataDir\"];\n\nexport function readProjectConfig(file: string): ProjectConfig {\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(file, \"utf8\"));\n } catch (err) {\n throw usageError(`${file}: ${(err as Error).message}`);\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw usageError(`${file}: expected a JSON object`);\n }\n const out: ProjectConfig = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (!(CONFIG_KEYS as readonly string[]).includes(key)) {\n throw usageError(`${file}: unknown key \"${key}\"`);\n }\n if (typeof value !== \"string\") {\n throw usageError(`${file}: \"${key}\" must be a string`);\n }\n out[key as keyof ProjectConfig] = value;\n }\n return out;\n}\n\n/**\n * Reads the PLENARY_* lines of a .env file. Deliberately minimal — `KEY=value`,\n * optional surrounding quotes, `#` comments — because a project that needs\n * more has a real env loader already.\n */\nexport function readDotEnv(file: string): Record<string, string> {\n const out: Record<string, string> = {};\n let text: string;\n try {\n text = readFileSync(file, \"utf8\");\n } catch {\n return out;\n }\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (line === \"\" || line.startsWith(\"#\")) continue;\n const m = /^(?:export\\s+)?(PLENARY_[A-Z0-9_]+)=(.*)$/.exec(line);\n if (!m) continue;\n let value = (m[2] ?? \"\").trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[m[1] as string] = value;\n }\n return out;\n}\n\n/**\n * Resolves the run context. Precedence, highest first: flag, process\n * environment, `.env` beside plenary.json (or in the cwd), plenary.json,\n * default.\n */\nexport function resolveContext(opts: GlobalOptions, io: Io): Context {\n const configPath = opts.config ? path.resolve(io.cwd, opts.config) : findConfigFile(io.cwd);\n if (opts.config && !existsSync(configPath as string)) {\n throw usageError(`config file not found: ${configPath}`);\n }\n const file = configPath ? readProjectConfig(configPath) : {};\n const projectRoot = configPath ? path.dirname(configPath) : io.cwd;\n const env = { ...readDotEnv(path.join(projectRoot, \".env\")), ...pick(io.env) };\n\n const baseUrl = opts.baseUrl ?? env.PLENARY_BASE_URL ?? file.baseUrl;\n return {\n io,\n baseUrl: baseUrl ? baseUrl.replace(/\\/+$/, \"\") : undefined,\n apiKey: opts.apiKey ?? env.PLENARY_CLI_API_KEY,\n siteKey: opts.site ?? env.PLENARY_SITE_KEY ?? file.siteKey,\n locale: opts.locale ?? env.PLENARY_LOCALE ?? file.locale,\n metadataDir: env.PLENARY_METADATA_DIR ?? file.metadataDir ?? DEFAULT_METADATA_DIR,\n projectRoot,\n configPath,\n json: opts.json ?? false,\n debug: opts.debug ?? false,\n };\n}\n\n/** Only the PLENARY_* variables, and only those actually set. */\nfunction pick(env: NodeJS.ProcessEnv): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n if (k.startsWith(\"PLENARY_\") && v !== undefined && v !== \"\") out[k] = v;\n }\n return out;\n}\n\nexport function requireBaseUrl(ctx: Context): string {\n if (!ctx.baseUrl) {\n throw usageError(\n \"no base URL: pass --base-url, set PLENARY_BASE_URL, or run `plenary init`\",\n );\n }\n return ctx.baseUrl;\n}\n","import { errorFromResponse } from \"@plenary/client\";\nimport { requireBaseUrl, type Context } from \"../config.js\";\nimport { usageError } from \"../errors.js\";\nimport { sessionAccessToken } from \"../session.js\";\n\n/**\n * Which credential a request carries. A configured API key wins over a\n * stored session for content work, so a person's login never silently\n * becomes the actor of a deploy job that also has a key; a session is what\n * admin work needs, since a key can never hold admin:* capabilities.\n */\nexport type AuthMode = \"required\" | \"optional\" | \"none\" | \"session\";\n\nexport async function credentialHeaders(ctx: Context, mode: AuthMode): Promise<Record<string, string>> {\n if (mode === \"none\") return {};\n if (mode === \"session\") {\n const token = await sessionAccessToken(ctx);\n if (!token) throw usageError(\"this command needs a user session: run `plenary login`\");\n return { Authorization: `Bearer ${token}` };\n }\n if (ctx.apiKey) return { \"X-API-KEY\": ctx.apiKey };\n const token = await sessionAccessToken(ctx);\n if (token) return { Authorization: `Bearer ${token}` };\n if (mode === \"required\") {\n throw usageError(\"no credential: pass --api-key, set PLENARY_CLI_API_KEY, or run `plenary login`\");\n }\n return {};\n}\n\nexport interface RequestOptions {\n /** Query parameters; undefined values are dropped. */\n query?: Record<string, string | undefined>;\n /** A JSON body. */\n body?: unknown;\n /** A multipart body; wins over `body`. */\n form?: FormData;\n headers?: Record<string, string>;\n /**\n * \"required\" (default) refuses to run without a credential; \"optional\"\n * sends one when there is one; \"none\" never does (the health check);\n * \"session\" insists on a user login (admin routes).\n */\n auth?: AuthMode;\n /** Return a non-2xx response instead of throwing its PlenaryError. */\n allowError?: boolean;\n}\n\nexport interface ApiResponse<T = unknown> {\n status: number;\n ok: boolean;\n headers: Headers;\n /** The parsed JSON body, the text body for non-JSON responses, or null for 204. */\n data: T;\n}\n\n/** Turns `models` into `/api/v1/models`; a path that already starts with `/` is kept. */\nexport function apiPath(p: string): string {\n return p.startsWith(\"/\") ? p : `/api/v1/${p}`;\n}\n\nexport async function request<T = unknown>(\n ctx: Context,\n method: string,\n path: string,\n opts: RequestOptions = {},\n): Promise<ApiResponse<T>> {\n const base = requireBaseUrl(ctx);\n const headers: Record<string, string> = { ...opts.headers, ...(await credentialHeaders(ctx, opts.auth ?? \"required\")) };\n\n const url = new URL(base + apiPath(path));\n for (const [k, v] of Object.entries(opts.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, v);\n }\n\n let body: RequestInit[\"body\"];\n if (opts.form) {\n body = opts.form;\n } else if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(opts.body);\n }\n\n if (ctx.debug) ctx.io.stderr.write(`> ${method} ${url}\\n`);\n const response = await ctx.io.fetch(url, { method, headers, body });\n const data = await parseBody(response);\n if (ctx.debug) ctx.io.stderr.write(`< ${response.status}\\n`);\n\n if (!response.ok && !opts.allowError) {\n throw errorFromResponse(response.status, data);\n }\n return { status: response.status, ok: response.ok, headers: response.headers, data: data as T };\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n if (response.status === 204) return null;\n const text = await response.text();\n if (text === \"\") return null;\n const type = response.headers.get(\"content-type\") ?? \"\";\n if (type.includes(\"json\")) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return text;\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport type { Context, Io } from \"./config.js\";\nimport { usageError } from \"./errors.js\";\n\n/** What login stores: never an access token, only the refresh token that mints one. */\nexport interface StoredSession {\n refresh_token: string;\n identifier?: string;\n updated_at: string;\n}\n\ntype Store = Record<string, StoredSession>;\n\n/** `$XDG_CONFIG_HOME/plenary/credentials.json`, `~/.config` by default. */\nexport function credentialsPath(io: Io): string {\n const base = io.env.XDG_CONFIG_HOME || path.join(io.env.HOME || homedir(), \".config\");\n return path.join(base, \"plenary\", \"credentials.json\");\n}\n\nfunction readStore(io: Io): Store {\n const file = credentialsPath(io);\n if (!existsSync(file)) return {};\n try {\n const parsed = JSON.parse(readFileSync(file, \"utf8\")) as unknown;\n return typeof parsed === \"object\" && parsed !== null ? (parsed as Store) : {};\n } catch {\n return {};\n }\n}\n\nfunction writeStore(io: Io, store: Store): void {\n const file = credentialsPath(io);\n mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });\n // Written whole and renamed into place, so a crash mid-write never leaves\n // a half file where a refresh token used to be.\n const tmp = `${file}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(store, null, 2) + \"\\n\", { mode: 0o600 });\n chmodSync(tmp, 0o600);\n renameSync(tmp, file);\n}\n\nexport function loadSession(io: Io, baseUrl: string): StoredSession | undefined {\n return readStore(io)[baseUrl];\n}\n\nexport function saveSession(io: Io, baseUrl: string, session: Omit<StoredSession, \"updated_at\">): void {\n const store = readStore(io);\n store[baseUrl] = { ...session, updated_at: new Date().toISOString() };\n writeStore(io, store);\n}\n\nexport function clearSession(io: Io, baseUrl: string): boolean {\n const store = readStore(io);\n if (!(baseUrl in store)) return false;\n delete store[baseUrl];\n writeStore(io, store);\n return true;\n}\n\ninterface RefreshResponse {\n status: string;\n access_token: string;\n refresh_token: string;\n}\n\n/**\n * The access token for this run, minted from the stored refresh token. The\n * rotated refresh token is written back before the access token is used for\n * anything, because presenting the old one again would revoke the family.\n * Undefined when there is no session for this instance.\n */\nexport async function sessionAccessToken(ctx: Context): Promise<string | undefined> {\n if (ctx.sessionToken) return ctx.sessionToken;\n const baseUrl = ctx.baseUrl;\n if (!baseUrl) return undefined;\n const stored = loadSession(ctx.io, baseUrl);\n if (!stored) return undefined;\n\n const response = await ctx.io.fetch(`${baseUrl}/api/v1/auth/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: stored.refresh_token }),\n });\n const body = (await response.json().catch(() => null)) as RefreshResponse | { error?: { code?: string } } | null;\n if (!response.ok || !body || !(\"access_token\" in body)) {\n const code = (body as { error?: { code?: string } } | null)?.error?.code ?? `http_${response.status}`;\n if (response.status === 401) {\n clearSession(ctx.io, baseUrl);\n throw usageError(`session for ${baseUrl} is no longer valid (${code}): run \\`plenary login\\``);\n }\n throw usageError(`could not refresh the session for ${baseUrl} (${code})`);\n }\n saveSession(ctx.io, baseUrl, { refresh_token: body.refresh_token, identifier: stored.identifier });\n ctx.sessionToken = body.access_token;\n return body.access_token;\n}\n","import { readFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline/promises\";\nimport type { Io } from \"./config.js\";\nimport { usageError } from \"./errors.js\";\n\n/** `k=v` pairs → object; a repeated key keeps the last value. */\nexport function parsePairs(pairs: string[], sep: string, what: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const pair of pairs) {\n const i = pair.indexOf(sep);\n if (i <= 0) throw usageError(`invalid ${what} \"${pair}\": expected key${sep}value`);\n out[pair.slice(0, i).trim()] = pair.slice(i + 1).trim();\n }\n return out;\n}\n\n/** Inline text, `@file`, or `-` for stdin. */\nexport async function readText(data: string, stdin: NodeJS.ReadableStream): Promise<string> {\n if (data === \"-\") return readStream(stdin);\n if (data.startsWith(\"@\")) {\n try {\n return readFileSync(data.slice(1), \"utf8\");\n } catch (err) {\n throw usageError(`cannot read ${data.slice(1)}: ${(err as Error).message}`);\n }\n }\n return data;\n}\n\n/** Inline JSON, `@file`, or `-` for stdin; returns the parsed value. */\nexport async function readData(data: string, stdin: NodeJS.ReadableStream, flag = \"--data\"): Promise<unknown> {\n const text = await readText(data, stdin);\n try {\n return JSON.parse(text);\n } catch (err) {\n throw usageError(`${flag} is not valid JSON: ${(err as Error).message}`);\n }\n}\n\n/** Like readData, but insists on a JSON object. */\nexport async function readObject(\n data: string,\n stdin: NodeJS.ReadableStream,\n flag = \"--data\",\n): Promise<Record<string, unknown>> {\n const value = await readData(data, stdin, flag);\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw usageError(`${flag} must be a JSON object`);\n }\n return value as Record<string, unknown>;\n}\n\nexport async function readStream(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) chunks.push(Buffer.from(chunk as Buffer | string));\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\n/**\n * Asks before something destructive. `yes` (from -y) skips the question; a\n * run with no terminal and no -y is refused rather than silently answered.\n */\nexport async function confirm(io: Io, question: string, yes: boolean): Promise<void> {\n if (yes) return;\n if (!io.isTTY) throw usageError(`${question} — pass -y to confirm without a terminal`);\n const rl = createInterface({ input: io.stdin, output: io.stderr });\n try {\n const answer = (await rl.question(`${question} [y/N] `)).trim().toLowerCase();\n if (answer !== \"y\" && answer !== \"yes\") throw usageError(\"aborted\");\n } finally {\n rl.close();\n }\n}\n\n/** Prompts for one line on a terminal; without one, reads a line from stdin. */\nexport async function readLine(io: Io, prompt: string): Promise<string> {\n const rl = createInterface({ input: io.stdin, output: io.isTTY ? io.stderr : undefined, terminal: io.isTTY });\n try {\n if (!io.isTTY) {\n const it = rl[Symbol.asyncIterator]();\n const { value } = await it.next();\n return (value ?? \"\").trim();\n }\n return (await rl.question(prompt)).trim();\n } finally {\n rl.close();\n }\n}\n\n/**\n * Prompts for a secret without echoing it. On a terminal the input is put in\n * raw mode and read a key at a time; otherwise a line is read from stdin, so\n * a script can pipe a password in.\n */\nexport async function readSecret(io: Io, prompt: string): Promise<string> {\n const stdin = io.stdin as NodeJS.ReadableStream & { setRawMode?: (raw: boolean) => void };\n if (!io.isTTY || typeof stdin.setRawMode !== \"function\") return readLine(io, prompt);\n io.stderr.write(prompt);\n stdin.setRawMode(true);\n stdin.resume();\n try {\n return await new Promise<string>((resolve, reject) => {\n let value = \"\";\n const onData = (chunk: Buffer | string) => {\n for (const ch of String(chunk)) {\n const code = ch.charCodeAt(0);\n if (code === 3) {\n cleanup();\n reject(usageError(\"aborted\"));\n return;\n }\n if (code === 13 || code === 10) {\n cleanup();\n io.stderr.write(\"\\n\");\n resolve(value);\n return;\n }\n if (code === 127 || code === 8) value = value.slice(0, -1);\n else value += ch;\n }\n };\n const cleanup = () => {\n stdin.off(\"data\", onData);\n stdin.setRawMode?.(false);\n stdin.pause();\n };\n stdin.on(\"data\", onData);\n });\n } finally {\n stdin.setRawMode?.(false);\n }\n}\n","import { createClient, type PlenaryClient } from \"@plenary/client\";\nimport { requireBaseUrl, type Context } from \"../config.js\";\nimport { credentialHeaders, request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\n\ninterface Site {\n key: string;\n default_locale: string;\n}\n\nexport function requireSiteKey(ctx: Context): string {\n if (!ctx.siteKey) {\n throw usageError(\"no site key: pass --site, set PLENARY_SITE_KEY, or set siteKey in plenary.json\");\n }\n return ctx.siteKey;\n}\n\n/**\n * The locale every content read states. When none is configured it is the\n * site's default, which every authenticated principal may look up.\n */\nexport async function resolveLocale(ctx: Context, siteKey: string): Promise<string> {\n if (ctx.locale) return ctx.locale;\n const sites = await request<Site[]>(ctx, \"GET\", \"sites\");\n const site = sites.data.find((s) => s.key === siteKey);\n if (!site) throw usageError(`site \"${siteKey}\" not found on the instance`);\n return site.default_locale;\n}\n\n/**\n * A @plenary/client for this run: the content reads go through it. The\n * client only knows how to send an API key, so with a session instead the\n * fetch it is given swaps the key header for the bearer token.\n */\nexport async function contentClient(ctx: Context): Promise<PlenaryClient> {\n const siteKey = requireSiteKey(ctx);\n const baseUrl = requireBaseUrl(ctx);\n const auth = await credentialHeaders(ctx, \"required\");\n const apiKey = auth[\"X-API-KEY\"] ?? \"\";\n const fetch: typeof globalThis.fetch = apiKey\n ? ctx.io.fetch\n : (input, init = {}) => {\n const headers = new Headers(init.headers);\n headers.delete(\"X-API-KEY\");\n for (const [k, v] of Object.entries(auth)) headers.set(k, v);\n return ctx.io.fetch(input, { ...init, headers });\n };\n return createClient({ baseUrl, siteKey, apiKey, locale: await resolveLocale(ctx, siteKey), fetch });\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { confirm } from \"../input.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { requireSiteKey } from \"../entries/client.js\";\n\ninterface Site {\n key: string;\n name: string;\n is_active: boolean;\n default_locale: string;\n locales: string[];\n timezone: string;\n}\n\ninterface RoleItem {\n site_key: string;\n key: string;\n name: string;\n description: string | null;\n is_system: boolean;\n grant_count: number;\n assigned_user_count: number;\n}\n\ninterface Grant {\n key: string;\n site_key?: string;\n content_model_key?: string;\n}\n\ninterface Role extends Omit<RoleItem, \"grant_count\" | \"assigned_user_count\"> {\n grants: Grant[];\n}\n\ninterface ApiKeyItem {\n id: string;\n name: string;\n key_type: string;\n is_active: boolean;\n last_used_at: string | null;\n expires_at: string | null;\n revoked_at: string | null;\n}\n\ninterface ApiKeyCreated extends ApiKeyItem {\n key: string;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/** `content:entries:read`, optionally `,site=<key>` and `,model=<key>`. */\nexport function parseGrant(spec: string): Grant {\n const [key, ...filters] = spec.split(\",\").map((s) => s.trim());\n if (!key) throw usageError(`invalid --grant \"${spec}\"`);\n const grant: Grant = { key };\n for (const f of filters) {\n const [name, value] = f.split(\"=\");\n if (name === \"site\" && value) grant.site_key = value;\n else if (name === \"model\" && value) grant.content_model_key = value;\n else throw usageError(`invalid --grant \"${spec}\": expected key[,site=<key>][,model=<key>]`);\n }\n return grant;\n}\n\nexport function registerAdmin(program: Command, io: Io): void {\n program\n .command(\"sites\")\n .description(\"Sites\")\n .command(\"list\")\n .description(\"List sites\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<Site[]>(ctx, \"GET\", \"sites\");\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((s) => [\n s.key,\n s.name,\n s.default_locale,\n s.locales.join(\",\"),\n s.timezone,\n s.is_active ? \"\" : \"inactive\",\n ]);\n io.stdout.write(formatTable(rows, [\"KEY\", \"NAME\", \"DEFAULT\", \"LOCALES\", \"TIMEZONE\", \"\"]) + \"\\n\");\n });\n\n // A role belongs to a site, so both commands take the configured one\n // (--site, PLENARY_SITE_KEY or siteKey in plenary.json).\n const roles = program.command(\"roles\").description(\"The configured site's roles (needs a super user session)\");\n roles\n .command(\"list\")\n .description(\"List the site's roles\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const site = requireSiteKey(ctx);\n const res = await request<RoleItem[]>(ctx, \"GET\", `sites/${encodeURIComponent(site)}/roles`, { auth: \"session\" });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((r) => [\n r.key,\n r.name,\n String(r.grant_count),\n String(r.assigned_user_count),\n r.is_system ? \"system\" : \"\",\n ]);\n io.stdout.write(formatTable(rows, [\"KEY\", \"NAME\", \"GRANTS\", \"USERS\", \"\"]) + \"\\n\");\n });\n roles\n .command(\"get\")\n .description(\"Show one of the site's roles and its grants\")\n .argument(\"<key>\")\n .action(async (key: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const site = requireSiteKey(ctx);\n const res = await request<Role>(ctx, \"GET\", `sites/${encodeURIComponent(site)}/roles/${encodeURIComponent(key)}`, {\n auth: \"session\",\n });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const r = res.data;\n const head = [\n [\"Site\", r.site_key],\n [\"Key\", r.key],\n [\"Name\", r.name],\n [\"System\", r.is_system ? \"yes\" : \"no\"],\n ];\n if (r.description) head.push([\"Description\", r.description]);\n const grants = r.grants.map((g) => [g.key, g.site_key ?? \"\", g.content_model_key ?? \"\"]);\n io.stdout.write(formatTable(head) + \"\\n\\n\" + formatTable(grants, [\"GRANT\", \"SITE\", \"MODEL\"]) + \"\\n\");\n });\n\n const keys = program.command(\"api-keys\").description(\"API keys (needs a user session)\");\n keys\n .command(\"list\")\n .description(\"List API keys\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<ApiKeyItem[]>(ctx, \"GET\", \"api-keys\", { auth: \"session\" });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((k) => [\n k.id,\n k.name,\n k.key_type,\n k.revoked_at ? \"revoked\" : k.is_active ? \"active\" : \"inactive\",\n k.last_used_at ?? \"never\",\n k.expires_at ?? \"\",\n ]);\n io.stdout.write(formatTable(rows, [\"ID\", \"NAME\", \"TYPE\", \"STATE\", \"LAST USED\", \"EXPIRES\"]) + \"\\n\");\n });\n keys\n .command(\"get\")\n .description(\"Show one API key (never its secret)\")\n .argument(\"<id>\")\n .action(async (id: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request(ctx, \"GET\", `api-keys/${encodeURIComponent(id)}`, { auth: \"session\" });\n io.stdout.write(toJson(res.data) + \"\\n\");\n });\n keys\n .command(\"create\")\n // --site is the global option: a subcommand option of the same name never\n // receives a value, because the program-level one consumes it first.\n .description(\n \"Create an API key; the secret is printed once, alone on stdout. --site names the site the key belongs to: \" +\n \"a public key reads it (default: the configured site), a private key's grants are held to it\",\n )\n .requiredOption(\"-n, --name <name>\")\n .option(\"-t, --type <private|public>\", \"key type\", \"private\")\n .option(\"--description <text>\")\n .option(\"-g, --grant <spec>\", \"private keys: key[,site=<key>][,model=<model key>] (repeatable)\", collect, [])\n .option(\"--expires <iso>\", \"expiry timestamp\")\n .option(\"--origin <origin>\", \"an allowed browser origin (repeatable)\", collect, [])\n .option(\"--rate-limit <n>\", \"requests per minute, 0 = unlimited\", \"0\")\n .option(\"--include-drafts\", \"public keys: read drafts too\")\n .action(\n async (\n flags: {\n name: string;\n type: string;\n description?: string;\n grant: string[];\n expires?: string;\n origin: string[];\n rateLimit: string;\n includeDrafts?: boolean;\n },\n cmd: Command,\n ) => {\n const globals = cmd.optsWithGlobals<GlobalOptions>();\n const ctx = resolveContext(globals, io);\n if (flags.type !== \"private\" && flags.type !== \"public\") throw usageError(\"--type must be private or public\");\n // Only an explicit --site binds a private key; a public key can't exist\n // without a site, so it falls back to the configured one.\n const site = globals.site ?? (flags.type === \"public\" ? ctx.siteKey : undefined);\n const body = {\n name: flags.name,\n description: flags.description ?? null,\n key_type: flags.type,\n is_active: true,\n expires_at: flags.expires ?? null,\n grants: flags.grant.map(parseGrant),\n ...(site ? { site_key: site } : {}),\n allowed_origins: flags.origin,\n rate_limit_per_minute: Number(flags.rateLimit),\n include_drafts: Boolean(flags.includeDrafts),\n };\n const res = await request<ApiKeyCreated>(ctx, \"POST\", \"api-keys\", { auth: \"session\", body });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n io.stderr.write(\n `created ${flags.type} key \"${flags.name}\" (${res.data.id}); the secret follows and is not shown again\\n`,\n );\n io.stdout.write(res.data.key + \"\\n\");\n },\n );\n keys\n .command(\"delete\")\n .description(\"Delete an API key\")\n .argument(\"<id>\")\n .option(\"-y, --yes\", \"do not ask\")\n .action(async (id: string, flags: { yes?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await confirm(io, `Delete API key ${id}?`, Boolean(flags.yes));\n await request(ctx, \"DELETE\", `api-keys/${encodeURIComponent(id)}`, { auth: \"session\" });\n io.stdout.write(`deleted ${id}\\n`);\n });\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { CliError, usageError } from \"../errors.js\";\nimport { parsePairs, readData } from \"../input.js\";\nimport { describeError, toJson } from \"../output.js\";\nimport { errorFromResponse } from \"@plenary/client\";\n\nconst METHODS = new Set([\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"HEAD\"]);\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nexport function registerApi(program: Command, io: Io): void {\n program\n .command(\"api\")\n .description(\"Call any API endpoint and print the response body\")\n .argument(\"<method>\", \"GET, POST, PUT, PATCH, DELETE, or HEAD\")\n .argument(\"<path>\", \"a path such as models or /api/v1/models\")\n .option(\"-d, --data <json>\", \"request body: inline JSON, @file, or - for stdin\")\n .option(\"-q, --query <key=value>\", \"query parameter (repeatable)\", collect, [])\n .option(\"-H, --header <key:value>\", \"request header (repeatable)\", collect, [])\n .option(\"-i, --include\", \"print the status line and response headers to stderr\")\n .addHelpText(\n \"after\",\n `\nExamples:\n plenary api GET models\n plenary api GET content/post -q site_key=main -q limit=5\n plenary api POST content/post -q site_key=main -d '{\"fields\":{\"title\":\"Hello\"}}'\n plenary api PUT models/<uuid> -d @model.json`,\n )\n .action(\n async (\n methodArg: string,\n path: string,\n opts: { data?: string; query: string[]; header: string[]; include?: boolean },\n cmd: Command,\n ) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const method = methodArg.toUpperCase();\n if (!METHODS.has(method)) throw usageError(`unsupported method \"${methodArg}\"`);\n\n const body = opts.data !== undefined ? await readData(opts.data, io.stdin) : undefined;\n const res = await request(ctx, method, path, {\n query: parsePairs(opts.query, \"=\", \"query parameter\"),\n headers: parsePairs(opts.header, \":\", \"header\"),\n body,\n auth: \"optional\",\n allowError: true,\n });\n\n if (opts.include) {\n io.stderr.write(`HTTP ${res.status}\\n`);\n res.headers.forEach((v: string, k: string) => io.stderr.write(`${k}: ${v}\\n`));\n io.stderr.write(\"\\n\");\n }\n if (res.data !== null) {\n io.stdout.write((typeof res.data === \"string\" ? res.data : toJson(res.data)) + \"\\n\");\n }\n if (!res.ok) {\n io.stderr.write(describeError(errorFromResponse(res.status, res.data)) + \"\\n\");\n throw new CliError(\"\", 1);\n }\n },\n );\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, requireBaseUrl, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { credentialHeaders, request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { readLine, readSecret } from \"../input.js\";\nimport { toJson } from \"../output.js\";\nimport { clearSession, credentialsPath, loadSession, saveSession } from \"../session.js\";\n\ntype LoginResponse =\n | { status: \"success\"; access_token: string; refresh_token: string }\n | { status: \"otp_sent\" | \"otp_required\"; challenge_id: string; otp_methods: Record<string, string> };\n\ninterface Tokens {\n access_token: string;\n refresh_token: string;\n}\n\ninterface MeUser {\n principal: \"user\";\n is_super_user: boolean;\n grants: { site_key?: string; role_key?: string }[];\n}\n\n/** \"super user\", or the site roles a session's grants come from. */\nexport function describeUser(me: MeUser): string {\n if (me.is_super_user) return \"super user\";\n const roles = new Set<string>();\n for (const g of me.grants) if (g.role_key && g.site_key) roles.add(`${g.role_key} on ${g.site_key}`);\n return roles.size ? [...roles].join(\", \") : \"no site roles\";\n}\n\n/** The password, then OTP, then tokens conversation, prompting only where needed. */\nasync function login(ctx: Context, identifier: string, password: string, otpMethod?: string): Promise<Tokens> {\n const io = ctx.io;\n const first = await request<LoginResponse>(ctx, \"POST\", \"auth/login\", {\n auth: \"none\",\n body: { identifier, password },\n });\n const res = first.data;\n if (res.status === \"success\") return res;\n\n const challengeId = res.challenge_id;\n const methods = Object.keys(res.otp_methods);\n if (res.status === \"otp_required\") {\n let method = otpMethod ?? (methods.length === 1 ? methods[0] : undefined);\n if (!method) {\n if (!io.isTTY) throw usageError(`2FA needs a delivery method: pass --otp-method ${methods.join(\"|\")}`);\n const shown = methods.map((m) => `${m} (${res.otp_methods[m]})`).join(\", \");\n method = await readLine(io, `Send the code by ${shown}? [${methods[0]}] `);\n if (method === \"\") method = methods[0];\n }\n if (!methods.includes(method as string)) throw usageError(`--otp-method must be one of ${methods.join(\", \")}`);\n await request(ctx, \"POST\", \"auth/login/otp/send\", {\n auth: \"none\",\n body: { challenge_id: challengeId, otp_method: method },\n });\n io.stderr.write(`code sent by ${method}\\n`);\n } else {\n io.stderr.write(`code sent to ${Object.values(res.otp_methods).join(\", \")}\\n`);\n }\n\n if (!io.isTTY) throw usageError(\"2FA needs a terminal to enter the code\");\n const code = await readLine(io, \"Code: \");\n const verified = await request<Tokens & { status: string }>(ctx, \"POST\", \"auth/login/otp/verify\", {\n auth: \"none\",\n body: { challenge_id: challengeId, otp_code: code },\n });\n return verified.data;\n}\n\nexport function registerAuth(program: Command, io: Io): void {\n program\n .command(\"login\")\n .description(\"Sign in as a user and keep the session for admin commands\")\n .option(\"-u, --identifier <email-or-username>\", \"or PLENARY_USERNAME\")\n .option(\"--otp-method <email|sms>\", \"how to receive a 2FA code when more than one way is offered\")\n .addHelpText(\n \"after\",\n `\nThe password is prompted for (never a flag); PLENARY_PASSWORD supplies it\nwithout a terminal. Only the refresh token is stored, in\n$XDG_CONFIG_HOME/plenary/credentials.json, keyed by instance.`,\n )\n .action(async (flags: { identifier?: string; otpMethod?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const baseUrl = requireBaseUrl(ctx);\n let identifier = flags.identifier ?? io.env.PLENARY_USERNAME;\n if (!identifier) {\n if (!io.isTTY) throw usageError(\"no identifier: pass --identifier or set PLENARY_USERNAME\");\n identifier = await readLine(io, \"Email or username: \");\n }\n let password = io.env.PLENARY_PASSWORD;\n if (!password) {\n if (!io.isTTY) throw usageError(\"no password: set PLENARY_PASSWORD or run on a terminal\");\n password = await readSecret(io, \"Password: \");\n }\n const tokens = await login(ctx, identifier, password, flags.otpMethod);\n saveSession(io, baseUrl, { refresh_token: tokens.refresh_token, identifier });\n ctx.sessionToken = tokens.access_token;\n\n const me = await request<MeUser>(ctx, \"GET\", \"auth/me\", { auth: \"session\" });\n if (ctx.json) {\n io.stdout.write(\n toJson({ base_url: baseUrl, identifier, is_super_user: me.data.is_super_user, credentials: credentialsPath(io) }) + \"\\n\",\n );\n return;\n }\n io.stdout.write(`logged in to ${baseUrl} as ${identifier} (${describeUser(me.data)})\\n`);\n });\n\n program\n .command(\"logout\")\n .description(\"Revoke the stored session for this instance\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const baseUrl = requireBaseUrl(ctx);\n const stored = loadSession(io, baseUrl);\n if (!stored) {\n io.stdout.write(`no session for ${baseUrl}\\n`);\n return;\n }\n // Logout is idempotent server-side; a failure there must not keep a\n // token on disk the person asked to be rid of.\n try {\n await request(ctx, \"POST\", \"auth/logout\", { auth: \"none\", body: { refresh_token: stored.refresh_token } });\n } finally {\n clearSession(io, baseUrl);\n }\n io.stdout.write(`logged out of ${baseUrl}\\n`);\n });\n\n program\n .command(\"whoami\")\n .description(\"Show the credentials this run would use\")\n .action(async (_flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const baseUrl = requireBaseUrl(ctx);\n const stored = loadSession(io, baseUrl);\n const out: Record<string, unknown> = { base_url: baseUrl, api_key: null, session: null };\n const lines: string[] = [];\n if (ctx.apiKey) {\n const me = await request<{ key_type?: string; name?: string; grants?: unknown[] }>(ctx, \"GET\", \"auth/me\", {\n auth: \"none\",\n headers: { \"X-API-KEY\": ctx.apiKey },\n allowError: true,\n });\n out.api_key = me.ok ? me.data : { error: (me.data as { error?: unknown } | null)?.error ?? me.status };\n if (me.ok && me.data.key_type) {\n lines.push(\n `API key ${me.data.key_type} \"${me.data.name}\" (${me.data.grants?.length ?? 0} grants), used for content commands`,\n );\n } else if (me.status === 403) {\n lines.push(\"API key accepted (this server cannot describe keys), used for content commands\");\n } else {\n lines.push(`API key rejected (HTTP ${me.status})`);\n }\n }\n if (stored) {\n const headers = await credentialHeaders(ctx, \"session\");\n const me = await request<MeUser>(ctx, \"GET\", \"auth/me\", { auth: \"none\", headers });\n out.session = { identifier: stored.identifier ?? null, is_super_user: me.data.is_super_user };\n lines.push(\n `Session ${stored.identifier ?? \"user\"} (${describeUser(me.data)}), used for admin commands${\n ctx.apiKey ? \"\" : \" and content\"\n }`,\n );\n }\n if (lines.length === 0) lines.push(\"no credentials: set PLENARY_CLI_API_KEY or run `plenary login`\");\n io.stdout.write((ctx.json ? toJson(out) : lines.join(\"\\n\")) + \"\\n\");\n });\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { formatTable, toJson } from \"../output.js\";\n\ninterface CatalogItem {\n id: string;\n key: string;\n kind: string;\n name_singular: string;\n active: boolean;\n fields_count: number;\n site_key?: string;\n}\n\ninterface CatalogField {\n key: string;\n name: string;\n type: string;\n required: boolean;\n localized: boolean;\n}\n\ninterface CatalogDetail extends CatalogItem {\n name_plural: string;\n description?: string;\n private: boolean;\n fields: CatalogField[];\n transformers?: unknown[];\n entry_count?: number;\n}\n\n/**\n * A model key is unique within its site only, so the configured site, when\n * there is one, narrows a list and says which model a key names.\n */\nfunction siteQuery(siteKey: string | undefined) {\n return siteKey ? { query: { site_key: siteKey } } : undefined;\n}\n\n/** `models` and `forms` are the same surface at two paths. */\nexport function registerCatalog(program: Command, io: Io, name: \"models\" | \"forms\"): Command {\n const group = program.command(name).description(name === \"models\" ? \"Content models and objects\" : \"Forms\");\n\n group\n .command(\"list\")\n .description(`List ${name}`)\n .action(async (_opts: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<CatalogItem[]>(ctx, \"GET\", name, siteQuery(ctx.siteKey));\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((m) => [\n m.key,\n m.kind,\n m.name_singular,\n String(m.fields_count),\n m.active ? \"\" : \"inactive\",\n ]);\n io.stdout.write(formatTable(rows, [\"KEY\", \"KIND\", \"NAME\", \"FIELDS\", \"\"]) + \"\\n\");\n });\n\n group\n .command(\"get\")\n .description(`Show one of the ${name} by key or id`)\n .argument(\"<key>\")\n .option(\"--yaml\", \"print the YAML file the metadata commands use\")\n .action(async (key: string, opts: { yaml?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<CatalogDetail>(ctx, \"GET\", `${name}/${encodeURIComponent(key)}`, siteQuery(ctx.siteKey));\n const m = res.data;\n if (opts.yaml) {\n const yaml = await request<string>(ctx, \"GET\", `${name}/${m.id}/yaml`);\n io.stdout.write(yaml.data.endsWith(\"\\n\") ? yaml.data : yaml.data + \"\\n\");\n return;\n }\n if (ctx.json) {\n io.stdout.write(toJson(m) + \"\\n\");\n return;\n }\n const head = [\n [\"Key\", m.key],\n [\"Kind\", m.kind],\n [\"Name\", `${m.name_singular} / ${m.name_plural}`],\n [\"Id\", m.id],\n [\"Site\", m.site_key || \"-\"],\n [\"Active\", m.active ? \"yes\" : \"no\"],\n ];\n if (m.description) head.push([\"Description\", m.description]);\n if (m.entry_count !== undefined) head.push([\"Entries\", String(m.entry_count)]);\n const fields = m.fields.map((f) => [\n f.key,\n f.type,\n f.name,\n [f.required ? \"required\" : \"\", f.localized ? \"localized\" : \"\"].filter(Boolean).join(\", \"),\n ]);\n io.stdout.write(\n formatTable(head) + \"\\n\\n\" + formatTable(fields, [\"FIELD\", \"TYPE\", \"NAME\", \"\"]) + \"\\n\",\n );\n });\n\n return group;\n}\n","import type { Command } from \"commander\";\nimport { PlenaryNotFoundError, type Entry, type ListOptions, type PlenaryClient } from \"@plenary/client\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { CliError, usageError } from \"../errors.js\";\nimport { confirm, readObject, readText } from \"../input.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { contentClient, requireSiteKey } from \"../entries/client.js\";\nimport { toListOptions, toReadOptions, type ListFlags } from \"../entries/query.js\";\nimport { contentFolders, folderIdAt } from \"./folders.js\";\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/** The flags every listing command shares, declared once. */\nfunction withListFlags(cmd: Command): Command {\n return cmd\n .option(\"-w, --where <field=value>\", \"filter: field=value or field=$op:value (repeatable)\", collect, [])\n .option(\"--filters <json>\", \"a filter tree (inline JSON, @file, or -); excludes --where\")\n .option(\"-s, --sort <field[:dir]>\", \"sort field, asc unless :desc (repeatable, in precedence order)\", collect, [])\n .option(\"--limit <n>\", \"page size\")\n .option(\"--offset <n>\", \"rows to skip\")\n .option(\"--include <fields>\", \"comma-separated data fields to return\")\n .option(\"--exclude <fields>\", \"comma-separated data fields to omit\")\n .option(\"--hydrate <field[=subfields]>\", \"hydrate a reference field (repeatable)\", collect, [])\n .option(\"--count\", \"ask for the total and show it\");\n}\n\n/** The intrinsic flags a create or update accepts beside --data. */\ninterface WriteFlags {\n data?: string;\n slug?: string;\n folder?: string;\n folderPath?: string;\n note?: string;\n publishAt?: string;\n unpublishAt?: string;\n}\n\nfunction withWriteFlags(cmd: Command): Command {\n return cmd\n .option(\"-d, --data <json>\", \"the field values as a JSON object (inline, @file, or -)\")\n .option(\"--slug <slug>\")\n .option(\"--folder <id>\", \"content folder id\")\n .option(\"--folder-path <path>\", \"content folder path, such as /company (instead of --folder; / is the root)\")\n .option(\"--note <text>\", \"revision note (required by models with Require Change Notes)\")\n .option(\"--publish-at <iso>\", \"schedule a publish\")\n .option(\"--unpublish-at <iso>\", \"schedule an unpublish\");\n}\n\n/** The write body the Content API takes. */\ninterface EntryBody {\n fields: Record<string, unknown>;\n slug?: string;\n locale?: string;\n folder_id?: string | null;\n publish_at?: string | null;\n unpublish_at?: string | null;\n note?: string;\n}\n\n// --include narrows the response to the fields it names, so any column may be\n// missing from a row and prints blank.\nfunction entryRow(e: Partial<Entry>): string[] {\n return [e.id ?? \"\", statusLabel(e), e.slug ?? \"\", e.title ?? \"\", e.updated_at ?? \"\"];\n}\n\n/** The status column: a published entry with changes pending is `published*`. */\nfunction statusLabel(e: Partial<Entry>): string {\n return `${e.status ?? \"\"}${e.draft ? \"*\" : \"\"}`;\n}\n\nconst ENTRY_HEADER = [\"ID\", \"STATUS\", \"SLUG\", \"TITLE\", \"UPDATED\"];\n\n/** One row of GET content/{model}/entries/archived: read off the entry's delete revision. */\ninterface ArchivedEntry {\n id: string;\n revision_id: string;\n title: string | null;\n slug: string | null;\n archived_at: string;\n actor: { label: string };\n}\n\nconst PAGE = 100;\n\n/** Every entry matching the options, one page at a time. */\nasync function* pageAll(client: PlenaryClient, model: string, opts: ListOptions): AsyncGenerator<Entry> {\n const limit = opts.limit ?? PAGE;\n let offset = opts.offset ?? 0;\n for (;;) {\n const { items } = await client.listEntries(model, { ...opts, limit, offset, count: false });\n for (const e of items) yield e;\n if (items.length < limit) return;\n offset += items.length;\n }\n}\n\nasync function publish(ctx: Context, id: string, action: \"publish\" | \"unpublish\"): Promise<Entry> {\n return (await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(id)}/${action}`)).data;\n}\n\nexport function registerEntries(program: Command, io: Io): void {\n const entries = program.command(\"entries\").description(\"Content entries\");\n\n withListFlags(entries.command(\"list\").description(\"List a model's entries\").argument(\"<model>\")).action(\n async (model: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n const result = await client.listEntries(model, await toListOptions(flags, io.stdin));\n // A singleton model's collection route answers with its one entry, not a list.\n if (!Array.isArray(result.items)) {\n throw usageError(`${model} is a singleton; use 'plenary entries get ${model}'`);\n }\n if (ctx.json) {\n io.stdout.write(toJson(result) + \"\\n\");\n return;\n }\n io.stdout.write(formatTable(result.items.map(entryRow), ENTRY_HEADER) + \"\\n\");\n if (result.total !== undefined) io.stdout.write(`${result.items.length} of ${result.total}\\n`);\n },\n );\n\n entries\n .command(\"get\")\n .description(\"Print one entry as JSON; omit the slug for a singleton\")\n .argument(\"<model>\")\n .argument(\"[slug-or-id]\")\n .option(\"--include <fields>\")\n .option(\"--exclude <fields>\")\n .option(\"--hydrate <field[=subfields]>\", \"hydrate a reference field (repeatable)\", collect, [])\n .action(async (model: string, slug: string | undefined, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n const opts = await toReadOptions(flags);\n const entry = slug === undefined ? await client.getSingleton(model, opts) : await client.getEntry(model, slug, opts);\n io.stdout.write(toJson(entry) + \"\\n\");\n });\n\n withWriteFlags(entries.command(\"create\").description(\"Create a draft entry\").argument(\"<model>\"))\n .option(\"--publish\", \"publish it right after creating\")\n .action(async (model: string, flags: WriteFlags & { publish?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const siteKey = requireSiteKey(ctx);\n if (flags.data === undefined) throw usageError(\"--data is required\");\n const body: EntryBody = { fields: await readObject(flags.data, io.stdin) };\n if (ctx.locale) body.locale = ctx.locale;\n applyWriteFlags(body, flags);\n await applyFolderPath(ctx, model, body, flags);\n let entry = (\n await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(model)}`, { query: { site_key: siteKey }, body })\n ).data;\n if (flags.publish) entry = await publish(ctx, entry.id, \"publish\");\n report(ctx, entry, \"created\");\n });\n\n withWriteFlags(\n entries\n .command(\"update\")\n .description(\"Update an entry: --data is merged into its fields (a null removes one)\")\n .argument(\"<model>\")\n .argument(\"<slug-or-id>\"),\n )\n .option(\"--publish\", \"publish it right after updating (on a published entry, publish the pending changes)\")\n .addHelpText(\n \"after\",\n `\nOn a published entry the update is saved as pending changes and the live\ncopy stays as it was until the entry is published again; --data is then\nmerged into the pending copy. --publish makes the change live in a second\ncall.`,\n )\n .action(async (model: string, slug: string, flags: WriteFlags & { publish?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n const current = await client.getEntry(model, slug);\n // Pending changes are what the editor last saved, so they are what --data\n // merges into; carrying the live copy forward would silently drop them.\n const working = current.draft ?? current;\n const fields: Record<string, unknown> = { ...working.data };\n if (flags.data !== undefined) {\n for (const [k, v] of Object.entries(await readObject(flags.data, io.stdin))) {\n if (v === null) delete fields[k];\n else fields[k] = v;\n }\n }\n // PUT replaces the whole entry, so everything not being changed is carried.\n const body: EntryBody = {\n fields,\n slug: working.slug ?? undefined,\n locale: current.locale ?? undefined,\n folder_id: current.folder_id,\n publish_at: current.publish_at,\n unpublish_at: current.unpublish_at,\n };\n applyWriteFlags(body, flags);\n await applyFolderPath(ctx, model, body, flags);\n let entry = (await request<Entry>(ctx, \"PUT\", `content/${encodeURIComponent(current.id)}`, { body })).data;\n if (flags.publish) entry = await publish(ctx, entry.id, \"publish\");\n report(ctx, entry, \"updated\");\n });\n\n entries\n .command(\"archive\")\n .description(\"Archive an entry (restorable from the console's Archived view while the model tracks revisions)\")\n .argument(\"<id>\")\n .option(\"--note <text>\", \"revision note\")\n .option(\"-y, --yes\", \"do not ask\")\n .action(async (id: string, flags: { note?: string; yes?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await confirm(io, `Archive entry ${id}?`, Boolean(flags.yes));\n await request(ctx, \"DELETE\", `content/${encodeURIComponent(id)}`, { query: { note: flags.note } });\n if (ctx.json) io.stdout.write(toJson({ id, archived: true }) + \"\\n\");\n else io.stdout.write(`archived ${id}\\n`);\n });\n\n // `delete` archived until 1.2; it now purges, so for this release it insists on\n // --permanent rather than silently turning an old script's archive into a purge.\n entries\n .command(\"delete\")\n .description(\"Permanently delete an entry and its revision history (a live or an archived one); cannot be undone\")\n .argument(\"<id>\")\n .option(\"--permanent\", \"required this release: delete used to archive, which is now 'entries archive'\")\n .option(\"-y, --yes\", \"do not ask\")\n .action(async (id: string, flags: { permanent?: boolean; yes?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n if (!flags.permanent) {\n throw usageError(\n \"entries delete now deletes permanently: pass --permanent, or use 'plenary entries archive' for what delete did before\",\n );\n }\n await confirm(io, `Permanently delete entry ${id} and its history? This cannot be undone.`, Boolean(flags.yes));\n await request(ctx, \"DELETE\", `content/${encodeURIComponent(id)}`, { query: { permanent: \"true\" } });\n if (ctx.json) io.stdout.write(toJson({ id, deleted: true }) + \"\\n\");\n else io.stdout.write(`deleted ${id}\\n`);\n });\n\n entries\n .command(\"archived\")\n .description(\"List a model's archived entries, newest first\")\n .argument(\"<model>\")\n .option(\"--limit <n>\", \"page size (max 200)\")\n .option(\"--offset <n>\", \"rows to skip\")\n .action(async (model: string, flags: { limit?: string; offset?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const siteKey = requireSiteKey(ctx);\n const res = await request<ArchivedEntry[]>(ctx, \"GET\", `content/${encodeURIComponent(model)}/entries/archived`, {\n query: { site_key: siteKey, limit: flags.limit, offset: flags.offset },\n });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((r) => [r.id, r.slug ?? \"\", r.title ?? \"\", r.archived_at, r.actor.label]);\n io.stdout.write(formatTable(rows, [\"ID\", \"SLUG\", \"TITLE\", \"ARCHIVED\", \"BY\"]) + \"\\n\");\n const total = res.headers.get(\"X-Total-Count\");\n if (total !== null) io.stdout.write(`${res.data.length} of ${total}\\n`);\n });\n\n entries\n .command(\"restore\")\n .description(\"Restore an archived entry; it comes back as a draft under its original id\")\n .argument(\"<id>\")\n .option(\"--note <text>\", \"revision note\")\n .action(async (id: string, flags: { note?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n // An archived entry is one whose newest revision is its delete; the\n // restore route takes that revision, not the entry.\n const [newest] = (\n await request<{ id: string; action: string }[]>(ctx, \"GET\", `content/${encodeURIComponent(id)}/revisions`, {\n query: { limit: \"1\" },\n })\n ).data;\n if (!newest) throw usageError(`entry ${id} has no history to restore from`);\n if (newest.action !== \"delete\") {\n throw usageError(`entry ${id} is not archived: its newest revision is a ${newest.action}`);\n }\n const entry = (\n await request<Entry>(ctx, \"POST\", `revisions/${encodeURIComponent(newest.id)}/restore`, {\n body: flags.note === undefined ? {} : { note: flags.note },\n })\n ).data;\n report(ctx, entry, \"restored\");\n });\n\n entries\n .command(\"publish\")\n .description(\"Publish an entry now; on a published entry, make its pending changes live\")\n .argument(\"<id>\")\n .action(async (id: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n report(ctx, await publish(ctx, id, \"publish\"), \"published\");\n });\n\n entries\n .command(\"unpublish\")\n .description(\"Unpublish an entry now\")\n .argument(\"<id>\")\n .option(\"--draft <merge|discard>\", \"with changes pending: keep them as the draft's content (merge) or drop them (discard)\")\n .action(async (id: string, flags: { draft?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const entry = (\n await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(id)}/unpublish`, { query: { draft: flags.draft } })\n ).data;\n report(ctx, entry, \"unpublished\");\n });\n\n entries\n .command(\"discard\")\n .description(\"Drop the pending changes on a published entry, leaving the live copy as it is\")\n .argument(\"<id>\")\n .option(\"--note <text>\", \"revision note\")\n .action(async (id: string, flags: { note?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const entry = (\n await request<Entry>(ctx, \"DELETE\", `content/${encodeURIComponent(id)}/draft`, { query: { note: flags.note } })\n ).data;\n report(ctx, entry, \"discarded\");\n });\n\n withListFlags(\n entries.command(\"export\").description(\"Write every matching entry to stdout as NDJSON\").argument(\"<model>\"),\n ).action(async (model: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const client = await contentClient(ctx);\n for await (const e of pageAll(client, model, await toListOptions(flags, io.stdin))) {\n io.stdout.write(JSON.stringify(e) + \"\\n\");\n }\n });\n\n entries\n .command(\"import\")\n .description(\"Create one entry per NDJSON line (exported entries or {fields, slug, …} bodies)\")\n .argument(\"<model>\")\n .argument(\"<file>\", \"a file, or - for stdin\")\n .option(\"--publish\", \"publish each entry after writing it\")\n .option(\"--upsert\", \"update the entry with the line's slug when it exists, instead of failing\")\n .addHelpText(\n \"after\",\n `\nEvery line is tried; a line that fails is reported with its number and the\nrun continues, exiting 1 at the end if any failed.\n\nWith --upsert a line is matched by its slug (unique per site, model and\nlocale), so a seed file can be imported again. A match has its fields\nreplaced by the line's; the slug, folder and schedule it doesn't state are\nkept. A line without a slug fails.`,\n )\n .action(async (model: string, file: string, flags: { publish?: boolean; upsert?: boolean }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const siteKey = requireSiteKey(ctx);\n const client = flags.upsert ? await contentClient(ctx) : undefined;\n const text = await readText(file === \"-\" ? \"-\" : `@${file}`, io.stdin);\n let failed = 0;\n let updated = 0;\n let n = 0;\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (line === \"\") continue;\n n++;\n try {\n const body = importBody(JSON.parse(line) as Record<string, unknown>, ctx);\n const current = client && (await findBySlug(client, model, body));\n let entry = current\n ? (\n await request<Entry>(ctx, \"PUT\", `content/${encodeURIComponent(current.id)}`, {\n body: {\n slug: current.slug ?? undefined,\n locale: current.locale ?? undefined,\n folder_id: current.folder_id,\n publish_at: current.publish_at,\n unpublish_at: current.unpublish_at,\n ...body,\n },\n })\n ).data\n : (\n await request<Entry>(ctx, \"POST\", `content/${encodeURIComponent(model)}`, {\n query: { site_key: siteKey },\n body,\n })\n ).data;\n if (current) updated++;\n if (flags.publish) entry = await publish(ctx, entry.id, \"publish\");\n io.stdout.write(`ok ${entry.id}${entry.slug ? ` ${entry.slug}` : \"\"}${current ? \" (updated)\" : \"\"}\\n`);\n } catch (err) {\n failed++;\n const why = err instanceof Error ? (err as { code?: string }).code ?? err.message : String(err);\n io.stdout.write(`fail line ${n}: ${why}\\n`);\n }\n }\n io.stderr.write(`${n - failed - updated} created, ${updated ? `${updated} updated, ` : \"\"}${failed} failed\\n`);\n if (failed) throw new CliError(\"\", 1);\n });\n}\n\nfunction applyWriteFlags(body: EntryBody, flags: WriteFlags): void {\n if (flags.slug !== undefined) body.slug = flags.slug;\n if (flags.folder !== undefined) body.folder_id = flags.folder;\n if (flags.publishAt !== undefined) body.publish_at = flags.publishAt;\n if (flags.unpublishAt !== undefined) body.unpublish_at = flags.unpublishAt;\n if (flags.note !== undefined) body.note = flags.note;\n}\n\n/** --folder-path resolved against the model's folders; \"/\" moves the entry to the root. */\nasync function applyFolderPath(ctx: Context, model: string, body: EntryBody, flags: WriteFlags): Promise<void> {\n if (flags.folderPath === undefined) return;\n if (flags.folder !== undefined) throw usageError(\"pass --folder or --folder-path, not both\");\n body.folder_id = await folderIdAt(ctx, contentFolders(ctx, model), flags.folderPath);\n}\n\n/** An exported entry (`data`) or a bare write body (`fields`) → the write body. */\nfunction importBody(line: Record<string, unknown>, ctx: Context): EntryBody {\n if (\"fields\" in line) return line as unknown as EntryBody;\n if (!(\"data\" in line)) throw usageError(\"expected an object with fields or data\");\n const e = line as Partial<Entry>;\n const body: EntryBody = { fields: (e.data ?? {}) as Record<string, unknown> };\n if (e.slug) body.slug = e.slug;\n if (e.locale ?? ctx.locale) body.locale = e.locale ?? ctx.locale;\n if (e.folder_id) body.folder_id = e.folder_id;\n if (e.publish_at) body.publish_at = e.publish_at;\n if (e.unpublish_at) body.unpublish_at = e.unpublish_at;\n return body;\n}\n\n/** The entry an upserted line names by slug, or undefined when there is none yet. */\nasync function findBySlug(client: PlenaryClient, model: string, body: EntryBody): Promise<Entry | undefined> {\n if (!body.slug) throw usageError(\"--upsert needs a slug on every line\");\n try {\n return await client.getEntry(model, body.slug, body.locale ? { locale: body.locale } : {});\n } catch (err) {\n if (err instanceof PlenaryNotFoundError) return undefined;\n throw err;\n }\n}\n\nfunction report(ctx: Context, entry: Entry, verb: string): void {\n if (ctx.json) ctx.io.stdout.write(toJson(entry) + \"\\n\");\n else ctx.io.stdout.write(`${verb} ${entry.id}${entry.slug ? ` ${entry.slug}` : \"\"} (${statusLabel(entry)})\\n`);\n}\n","import type { ListOptions, ReadOptions, Sort, Where } from \"@plenary/client\";\nimport { usageError } from \"../errors.js\";\nimport { readData } from \"../input.js\";\n\n/** The flags shared by every listing command. */\nexport interface ListFlags {\n where?: string[];\n filters?: string;\n sort?: string[];\n limit?: string;\n offset?: string;\n include?: string;\n exclude?: string;\n hydrate?: string[];\n count?: boolean;\n}\n\nconst OPERATORS = new Set([\"$eq\", \"$ne\", \"$lt\", \"$lte\", \"$gt\", \"$gte\", \"$in\", \"$nin\", \"$like\", \"$ilike\", \"$is_null\"]);\n\n/**\n * `field=value` is equality; `field=$op:value` is one of the Content API's\n * operators, with `$in`/`$nin` taking a comma list and `$is_null` a boolean.\n */\nexport function parseWhere(specs: string[]): Where {\n const where: Where = {};\n for (const spec of specs) {\n const eq = spec.indexOf(\"=\");\n if (eq <= 0) throw usageError(`invalid --where \"${spec}\": expected field=value or field=$op:value`);\n const field = spec.slice(0, eq).trim();\n const raw = spec.slice(eq + 1);\n if (!raw.startsWith(\"$\")) {\n where[field] = raw;\n continue;\n }\n const colon = raw.indexOf(\":\");\n const op = colon === -1 ? raw : raw.slice(0, colon);\n const value = colon === -1 ? \"\" : raw.slice(colon + 1);\n if (!OPERATORS.has(op)) throw usageError(`invalid --where \"${spec}\": unknown operator ${op}`);\n let typed: unknown = value;\n if (op === \"$in\" || op === \"$nin\") typed = value.split(\",\").map((s) => s.trim()).filter(Boolean);\n else if (op === \"$is_null\") typed = value === \"\" || value === \"true\";\n const existing = (where[field] ?? {}) as Record<string, unknown>;\n where[field] = { ...(typeof existing === \"object\" ? existing : {}), [op]: typed };\n }\n return where;\n}\n\n/** `field` or `field:desc`, in precedence order. */\nexport function parseSort(specs: string[]): Sort {\n const sort: Sort = {};\n for (const spec of specs) {\n const [field, dir = \"asc\"] = spec.split(\":\");\n if (!field || (dir !== \"asc\" && dir !== \"desc\")) {\n throw usageError(`invalid --sort \"${spec}\": expected field or field:asc|desc`);\n }\n sort[field] = dir;\n }\n return sort;\n}\n\nfunction parseHydrate(specs: string[]): ReadOptions[\"hydrate\"] {\n const out: Record<string, \"*\" | string[]> = {};\n for (const spec of specs) {\n const [field, list] = spec.split(\"=\");\n if (!field) throw usageError(`invalid --hydrate \"${spec}\"`);\n out[field] = list === undefined || list === \"*\" ? \"*\" : list.split(\",\");\n }\n return out;\n}\n\nfunction parseInt10(value: string | undefined, flag: string): number | undefined {\n if (value === undefined) return undefined;\n const n = Number(value);\n if (!Number.isInteger(n) || n < 0) throw usageError(`${flag} must be a non-negative integer`);\n return n;\n}\n\nexport async function toReadOptions(flags: ListFlags): Promise<ReadOptions> {\n const opts: ReadOptions = {};\n if (flags.include) opts.include = flags.include.split(\",\");\n if (flags.exclude) opts.exclude = flags.exclude.split(\",\");\n if (flags.hydrate?.length) opts.hydrate = parseHydrate(flags.hydrate);\n return opts;\n}\n\nexport async function toListOptions(flags: ListFlags, stdin: NodeJS.ReadableStream): Promise<ListOptions> {\n const opts: ListOptions = await toReadOptions(flags);\n if (flags.where?.length && flags.filters) throw usageError(\"--where and --filters are mutually exclusive\");\n if (flags.where?.length) opts.where = parseWhere(flags.where);\n if (flags.filters) opts.filters = (await readData(flags.filters, stdin, \"--filters\")) as ListOptions[\"filters\"];\n if (flags.sort?.length) opts.sort = parseSort(flags.sort);\n const limit = parseInt10(flags.limit, \"--limit\");\n const offset = parseInt10(flags.offset, \"--offset\");\n if (limit !== undefined) opts.limit = limit;\n if (offset !== undefined) opts.offset = offset;\n if (flags.count) opts.count = true;\n return opts;\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { confirm } from \"../input.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { requireSiteKey } from \"../entries/client.js\";\n\ninterface Folder {\n id: string;\n site_key: string;\n parent_id: string | null;\n name: string;\n slug: string;\n path: string;\n entry_count?: number;\n media_count?: number;\n}\n\n/**\n * Where a kind of folder lives: a model's content folders on one site, or the\n * media library's, which span every site the credential may read unless one\n * is configured.\n */\ninterface FolderScope {\n path: string;\n siteKey: string | undefined;\n}\n\nexport function contentFolders(ctx: Context, model: string): FolderScope {\n return { path: `content/${encodeURIComponent(model)}/folders`, siteKey: requireSiteKey(ctx) };\n}\n\nexport function mediaFolders(ctx: Context): FolderScope {\n return { path: \"media/folders\", siteKey: ctx.siteKey };\n}\n\n/** \"/company/team/\" → \"/company/team\"; \"\" and \"/\" → \"/\". */\nfunction normalizePath(p: string): string {\n const trimmed = p.trim().replace(/\\/+$/, \"\");\n return trimmed === \"\" ? \"/\" : trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n}\n\nasync function listFolders(ctx: Context, scope: FolderScope): Promise<Folder[]> {\n const res = await request<{ folders: Folder[] }>(ctx, \"GET\", scope.path, { query: { site_key: scope.siteKey } });\n return res.data.folders;\n}\n\n/** The folder an id or a /path names. */\nasync function findFolder(ctx: Context, scope: FolderScope, ref: string): Promise<Folder> {\n const folders = await listFolders(ctx, scope);\n const byPath = ref.startsWith(\"/\");\n const path = normalizePath(ref);\n const matches = folders.filter((f) => (byPath ? f.path === path : f.id === ref));\n if (matches.length === 0) throw usageError(`no folder ${ref}`);\n if (matches.length > 1) throw usageError(`${ref} is a folder on several sites; pass --site`);\n return matches[0]!;\n}\n\n/** The folder id at a path, or null for the root \"/\". */\nexport async function folderIdAt(ctx: Context, scope: FolderScope, path: string): Promise<string | null> {\n if (normalizePath(path) === \"/\") return null;\n return (await findFolder(ctx, scope, normalizePath(path))).id;\n}\n\nfunction registerFolderCommands(parent: Command, io: Io, kind: \"content\" | \"media\"): void {\n const scopeFor = (ctx: Context, model: string | undefined) =>\n kind === \"content\" ? contentFolders(ctx, model!) : mediaFolders(ctx);\n // Content folders belong to a model, so every content command takes one first.\n const withModel = (cmd: Command) => (kind === \"content\" ? cmd.argument(\"<model>\") : cmd);\n // Commander passes the positional arguments first, then the flags and the command.\n const split = (args: unknown[]) => {\n const cmd = args[args.length - 1] as Command;\n const flags = args[args.length - 2] as Record<string, unknown>;\n const positional = args.slice(0, -2) as string[];\n const model = kind === \"content\" ? positional.shift() : undefined;\n return { ctx: resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io), model, positional, flags };\n };\n const countHeader = kind === \"content\" ? \"ENTRIES\" : \"MEDIA\";\n\n withModel(parent.command(\"list\").description(\"List folders by path\")).action(async (...args: unknown[]) => {\n const { ctx, model } = split(args);\n const folders = await listFolders(ctx, scopeFor(ctx, model));\n if (ctx.json) {\n io.stdout.write(toJson(folders) + \"\\n\");\n return;\n }\n const rows = folders.map((f) => [f.id, f.path, f.name, String(f.entry_count ?? f.media_count ?? \"\")]);\n io.stdout.write(formatTable(rows, [\"ID\", \"PATH\", \"NAME\", countHeader]) + \"\\n\");\n });\n\n withModel(parent.command(\"get\").description(\"Print one folder as JSON\"))\n .argument(\"<id-or-path>\", \"a folder id, or its path such as /company/team\")\n .action(async (...args: unknown[]) => {\n const { ctx, model, positional } = split(args);\n io.stdout.write(toJson(await findFolder(ctx, scopeFor(ctx, model), positional[0]!)) + \"\\n\");\n });\n\n withModel(parent.command(\"create\").description(\"Create a folder; its parent must exist\"))\n .argument(\"<path>\", \"the new folder's path, such as /company/team; the last segment is its slug\")\n .option(\"--name <name>\", \"display name (default: the slug)\")\n .action(async (...args: unknown[]) => {\n const { ctx, model, positional, flags } = split(args);\n const scope = scopeFor(ctx, model);\n const path = normalizePath(positional[0]!);\n if (path === \"/\") throw usageError(\"the root folder always exists\");\n const slug = path.slice(path.lastIndexOf(\"/\") + 1);\n const parentId = await folderIdAt(ctx, scope, path.slice(0, path.lastIndexOf(\"/\")));\n const res = await request<Folder>(ctx, \"POST\", scope.path, {\n query: { site_key: scope.siteKey },\n body: { parent_id: parentId, name: (flags.name as string | undefined) ?? slug, slug },\n });\n if (ctx.json) io.stdout.write(toJson(res.data) + \"\\n\");\n else io.stdout.write(`created ${res.data.id} ${res.data.path}\\n`);\n });\n\n withModel(\n parent\n .command(\"delete\")\n .description(`Delete a folder; its sub-folders and ${kind === \"content\" ? \"entries\" : \"media\"} move up to its parent`),\n )\n .argument(\"<id-or-path>\")\n .option(\"-y, --yes\", \"do not ask\")\n .action(async (...args: unknown[]) => {\n const { ctx, model, positional, flags } = split(args);\n const scope = scopeFor(ctx, model);\n const folder = await findFolder(ctx, scope, positional[0]!);\n await confirm(io, `Delete folder ${folder.path}?`, Boolean(flags.yes));\n await request(ctx, \"DELETE\", `${scope.path}/${encodeURIComponent(folder.id)}`, {\n query: { site_key: kind === \"content\" ? scope.siteKey : undefined },\n });\n if (ctx.json) io.stdout.write(toJson({ id: folder.id, deleted: true }) + \"\\n\");\n else io.stdout.write(`deleted ${folder.id} ${folder.path}\\n`);\n });\n}\n\nexport function registerContentFolders(program: Command, io: Io): void {\n registerFolderCommands(program.command(\"folders\").description(\"A model's content folders\"), io, \"content\");\n}\n\nexport function registerMediaFolders(media: Command, io: Io): void {\n registerFolderCommands(media.command(\"folders\").description(\"Media library folders\"), io, \"media\");\n}\n","import type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { toListOptions, type ListFlags } from \"../entries/query.js\";\nimport type { ListOptions } from \"@plenary/client\";\n\ninterface FormEntry {\n id: string;\n form_key: string;\n site_key: string;\n status: string;\n created_at: string;\n data: Record<string, unknown>;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/**\n * Form-entry lists take the Content API's query engine, but not through\n * @plenary/client (which is the public delivery surface), so the options are\n * compiled to a query string here with the same rules.\n */\nfunction toQuery(ctx: Context, opts: ListOptions): Record<string, string> {\n const q: Record<string, string> = {};\n if (ctx.siteKey) q.site_key = ctx.siteKey;\n for (const [field, value] of Object.entries(opts.where ?? {})) {\n if (typeof value === \"object\" && value !== null) {\n for (const [op, v] of Object.entries(value as Record<string, unknown>)) {\n q[`where:${field}.${op}`] = Array.isArray(v) ? v.join(\",\") : String(v);\n }\n } else {\n q[`where:${field}`] = String(value);\n }\n }\n if (opts.filters) q.filters = JSON.stringify(opts.filters);\n for (const [field, dir] of Object.entries(opts.sort ?? {})) q[`sort:${field}`] = dir;\n if (opts.limit !== undefined) q.limit = String(opts.limit);\n if (opts.offset !== undefined) q.offset = String(opts.offset);\n if (opts.count) q.count = \"true\";\n return q;\n}\n\nconst PAGE = 100;\n\nexport function registerFormEntries(forms: Command, io: Io): void {\n const entries = forms.command(\"entries\").description(\"Form entries (what visitors submitted)\");\n\n const listFlags = (cmd: Command) =>\n cmd\n .option(\"-w, --where <field=value>\", \"filter: field=value or field=$op:value (repeatable)\", collect, [])\n .option(\"--filters <json>\", \"a filter tree (inline JSON, @file, or -)\")\n .option(\"-s, --sort <field[:dir]>\", \"sort field, asc unless :desc (repeatable)\", collect, [])\n .option(\"--limit <n>\")\n .option(\"--offset <n>\")\n .option(\"--count\", \"ask for the total and show it\");\n\n listFlags(entries.command(\"list\").description(\"List a form's entries\").argument(\"<form>\")).action(\n async (form: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const opts = await toListOptions(flags, io.stdin);\n const res = await request<FormEntry[]>(ctx, \"GET\", `forms/${encodeURIComponent(form)}/entries`, {\n query: toQuery(ctx, opts),\n });\n const total = res.headers.get(\"X-Total-Count\");\n if (ctx.json) {\n io.stdout.write(toJson({ items: res.data, ...(total !== null ? { total: Number(total) } : {}) }) + \"\\n\");\n return;\n }\n const rows = res.data.map((e) => [e.id, e.status, e.site_key, e.created_at, summary(e.data)]);\n io.stdout.write(formatTable(rows, [\"ID\", \"STATUS\", \"SITE\", \"CREATED\", \"DATA\"]) + \"\\n\");\n if (total !== null) io.stdout.write(`${res.data.length} of ${total}\\n`);\n },\n );\n\n listFlags(entries.command(\"export\").description(\"Write every matching entry to stdout as NDJSON\").argument(\"<form>\")).action(\n async (form: string, flags: ListFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const opts = await toListOptions(flags, io.stdin);\n const limit = opts.limit ?? PAGE;\n let offset = opts.offset ?? 0;\n for (;;) {\n const res = await request<FormEntry[]>(ctx, \"GET\", `forms/${encodeURIComponent(form)}/entries`, {\n query: toQuery(ctx, { ...opts, limit, offset, count: false }),\n });\n for (const e of res.data) io.stdout.write(JSON.stringify(e) + \"\\n\");\n if (res.data.length < limit) return;\n offset += res.data.length;\n }\n },\n );\n}\n\n/** The first few values, for a glance at what was submitted. */\nfunction summary(data: Record<string, unknown>): string {\n return Object.entries(data)\n .slice(0, 3)\n .map(([k, v]) => `${k}=${typeof v === \"string\" ? v : JSON.stringify(v)}`)\n .join(\" \");\n}\n","import { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { request } from \"../api/http.js\";\nimport { CliError, usageError } from \"../errors.js\";\nimport { formatTable, toJson } from \"../output.js\";\nimport { folderIdAt, mediaFolders, registerMediaFolders } from \"./folders.js\";\n\ninterface MediaItem {\n media_id: string;\n media_type: string;\n mime_type: string;\n file_name: string;\n file_size: number;\n folder_id: string | null;\n path: string;\n visibility: string;\n original_url: string;\n created_at: string;\n}\n\n// The server sniffs the bytes itself; the declared part type is a hint for it\n// and for anything in between, so a file goes out as what its extension says.\nconst MIME_BY_EXT: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".svg\": \"image/svg+xml\",\n \".tif\": \"image/tiff\",\n \".tiff\": \"image/tiff\",\n \".bmp\": \"image/bmp\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".ogv\": \"video/ogg\",\n \".mov\": \"video/quicktime\",\n \".mp3\": \"audio/mpeg\",\n \".ogg\": \"audio/ogg\",\n \".wav\": \"audio/wav\",\n \".flac\": \"audio/flac\",\n \".pdf\": \"application/pdf\",\n \".zip\": \"application/zip\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n};\n\nexport function mimeForFile(file: string): string {\n return MIME_BY_EXT[path.extname(file).toLowerCase()] ?? \"application/octet-stream\";\n}\n\nfunction size(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/** The asset already uploaded under this file name to this folder (the root without one), if any. */\nasync function findExisting(ctx: Context, name: string, folder: string | undefined): Promise<MediaItem | undefined> {\n // search is a case-insensitive regex over file name and caption, so it is\n // anchored and escaped here and the exact match picked out below.\n const pattern = `^${name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}$`;\n const res = await request<MediaItem[]>(ctx, \"GET\", \"media\", {\n query: { search: pattern, site_key: ctx.siteKey, limit: \"100\" },\n });\n return res.data.find((m) => m.file_name === name && (m.folder_id ?? undefined) === folder);\n}\n\ninterface UploadFlags {\n folder?: string;\n folderPath?: string;\n private?: boolean;\n skipExisting?: boolean;\n}\n\nexport function registerMedia(program: Command, io: Io): void {\n const media = program.command(\"media\").description(\"Media library\");\n\n media\n .command(\"upload\")\n .description(\"Upload one or more files\")\n .argument(\"<files...>\")\n .option(\"--folder <id>\", \"media folder id\")\n .option(\"--folder-path <path>\", \"media folder path, such as /brand/logos (instead of --folder)\")\n .option(\"--private\", \"store as a private asset\")\n .option(\"--skip-existing\", \"skip a file whose name is already in the folder\")\n .action(async (files: string[], flags: UploadFlags, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n if (flags.folderPath !== undefined) {\n if (flags.folder !== undefined) throw usageError(\"pass --folder or --folder-path, not both\");\n flags.folder = (await folderIdAt(ctx, mediaFolders(ctx), flags.folderPath)) ?? undefined;\n }\n const uploaded: MediaItem[] = [];\n let failed = 0;\n for (const file of files) {\n let bytes: Buffer;\n try {\n bytes = readFileSync(file);\n } catch (err) {\n throw usageError(`cannot read ${file}: ${(err as Error).message}`);\n }\n if (flags.skipExisting) {\n const existing = await findExisting(ctx, path.basename(file), flags.folder);\n if (existing) {\n uploaded.push(existing);\n if (!ctx.json) io.stdout.write(`${existing.media_id} ${existing.file_name} (exists)\\n`);\n continue;\n }\n }\n const form = new FormData();\n form.append(\"upload_file\", new Blob([new Uint8Array(bytes)], { type: mimeForFile(file) }), path.basename(file));\n if (ctx.siteKey) form.append(\"site_key\", ctx.siteKey);\n if (flags.folder) form.append(\"folder_id\", flags.folder);\n if (flags.private) form.append(\"visibility\", \"private\");\n try {\n const res = await request<MediaItem>(ctx, \"POST\", \"media\", { form });\n uploaded.push(res.data);\n if (!ctx.json) io.stdout.write(`${res.data.media_id} ${res.data.file_name}\\n`);\n } catch (err) {\n if (files.length === 1) throw err;\n failed++;\n const code = (err as { code?: string }).code ?? (err as Error).message;\n io.stdout.write(`fail ${file}: ${code}\\n`);\n }\n }\n if (ctx.json) io.stdout.write(toJson(uploaded) + \"\\n\");\n if (failed) throw new CliError(\"\", 1);\n });\n\n media\n .command(\"list\")\n .description(\"List media\")\n .option(\"--search <text>\", \"match file names and captions\")\n .option(\"--path <prefix>\", \"only assets under this folder path\")\n .option(\"--limit <n>\")\n .option(\"--page <n>\")\n .action(async (flags: { search?: string; path?: string; limit?: string; page?: string }, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request<MediaItem[]>(ctx, \"GET\", \"media\", {\n query: { search: flags.search, path_prefix: flags.path, limit: flags.limit, page: flags.page },\n });\n if (ctx.json) {\n io.stdout.write(toJson(res.data) + \"\\n\");\n return;\n }\n const rows = res.data.map((m) => [m.media_id, m.media_type, m.file_name, size(m.file_size), m.path, m.visibility]);\n io.stdout.write(formatTable(rows, [\"ID\", \"TYPE\", \"FILE\", \"SIZE\", \"PATH\", \"VISIBILITY\"]) + \"\\n\");\n });\n\n media\n .command(\"get\")\n .description(\"Print one media item as JSON\")\n .argument(\"<id>\")\n .action(async (id: string, _flags: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const res = await request(ctx, \"GET\", `media/${encodeURIComponent(id)}`);\n io.stdout.write(toJson(res.data) + \"\\n\");\n });\n\n registerMediaFolders(media, io);\n}\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport { resolveContext, type Context, type GlobalOptions, type Io } from \"../config.js\";\nimport { PlenaryError } from \"@plenary/client\";\nimport { request, type ApiResponse, type RequestOptions } from \"../api/http.js\";\nimport { usageError } from \"../errors.js\";\nimport { confirm } from \"../input.js\";\nimport { toJson } from \"../output.js\";\nimport { filterKinds, parseKinds, readTree, writeTree, type Kind, type YamlFile } from \"../metadata/dir.js\";\nimport { formatPlan, type ImportResult } from \"../metadata/plan.js\";\n\ninterface DirOption {\n dir?: string;\n only?: string;\n verbose?: boolean;\n dryRun?: boolean;\n prune?: boolean;\n yes?: boolean;\n allSites?: boolean;\n}\n\n/**\n * The site whose tree the command moves: the configured one (--site,\n * PLENARY_SITE_KEY, plenary.json) unless --all-sites asks for the whole\n * instance. Roles belong to a site, so only a site's tree holds them.\n */\nfunction siteOf(ctx: Context, opts: DirOption): string | undefined {\n return opts.allSites ? undefined : ctx.siteKey;\n}\n\nfunction kindsOf(opts: DirOption, site?: string): Kind[] {\n let kinds: Kind[];\n try {\n kinds = parseKinds(opts.only);\n } catch (err) {\n throw usageError(`--only: ${(err as Error).message}`);\n }\n if (site) return kinds;\n if (opts.only && opts.only !== \"all\" && kinds.includes(\"roles\")) {\n throw usageError(\"roles belong to a site and are not part of the instance-wide tree; drop --all-sites\");\n }\n return kinds.filter((k) => k !== \"roles\");\n}\n\n/**\n * A server that predates per-site trees ignores site_key and answers for the\n * whole instance, so the echo is what says the answer is the site's alone.\n */\nfunction isSiteAnswer(data: { site_key?: string }, site: string | undefined): boolean {\n return !site || data.site_key === site;\n}\n\nconst UNSCOPED_SERVER = (site: string) =>\n `this server predates per-site metadata: it answered for every site, not just ${site}`;\n\n/** `--dir` is relative to the cwd; the configured directory to the config file. */\nfunction treeRoot(ctx: Context, opts: DirOption): string {\n return opts.dir ? path.resolve(ctx.io.cwd, opts.dir) : path.resolve(ctx.projectRoot, ctx.metadataDir);\n}\n\nfunction readTreeOrFail(root: string, kinds: Kind[]): YamlFile[] {\n const files = filterKinds(readTree(root), kinds);\n if (files.length === 0) throw usageError(`no YAML files under ${root}/{${kinds.join(\",\")}}`);\n return files;\n}\n\nconst OLDER_SERVER =\n \"this server predates the whole-tree metadata endpoints: it can sync models and forms only\";\n\n/**\n * The whole-tree route, falling back to the models-only one a server from\n * without them has, so an older instance keeps working for models and\n * forms. Roles, sites and --prune have nowhere to go there and are refused\n * with a message rather than a bare 404.\n */\nasync function metadataRequest<T>(\n ctx: Context,\n method: \"GET\" | \"POST\",\n opts: RequestOptions,\n needsWholeTree: boolean,\n): Promise<ApiResponse<T>> {\n const path = method === \"GET\" ? \"metadata\" : \"metadata/import\";\n try {\n return await request<T>(ctx, method, path, opts);\n } catch (err) {\n if (!(err instanceof PlenaryError) || err.status !== 404 || err.code !== \"http_404\") throw err;\n if (needsWholeTree) throw usageError(OLDER_SERVER);\n const fallback = method === \"GET\" ? \"metadata/models\" : \"metadata/models/import\";\n return request<T>(ctx, method, fallback, opts);\n }\n}\n\n/**\n * Both diff and push: the plan is always previewed first, and a push with\n * --prune is confirmed against that preview before anything is deleted.\n */\nasync function runImport(ctx: Context, root: string, opts: DirOption, apply: boolean): Promise<void> {\n const site = siteOf(ctx, opts);\n const kinds = kindsOf(opts, site);\n const files = readTreeOrFail(root, kinds);\n const prune = Boolean(opts.prune);\n const body = { files, apply: false, prune };\n const query = site ? { site_key: site } : undefined;\n const wholeTree = prune || files.some((f) => !/^(models|forms)\\//.test(f.path));\n let res = await metadataRequest<ImportResult>(ctx, \"POST\", { body, query }, wholeTree);\n // Pruning against a server that ignored the site would delete every other\n // site's models; refuse before anything is applied.\n if (!isSiteAnswer(res.data, site)) {\n if (prune) throw usageError(`${UNSCOPED_SERVER(site!)}; --prune would delete other sites' models (use --all-sites if that is meant)`);\n ctx.io.stderr.write(`warning: ${UNSCOPED_SERVER(site!)}\\n`);\n }\n const deletes = res.data.changes.filter((c) => c.action === \"delete\");\n\n if (apply) {\n if (deletes.length > 0) {\n if (!ctx.json) ctx.io.stdout.write(formatPlan(res.data, Boolean(opts.verbose)) + \"\\n\");\n await confirm(ctx.io, `Delete ${deletes.length} ${deletes.length === 1 ? \"entity\" : \"entities\"} from the instance?`, Boolean(opts.yes));\n }\n res = await metadataRequest<ImportResult>(ctx, \"POST\", { body: { ...body, apply: true }, query }, wholeTree);\n }\n if (ctx.json) ctx.io.stdout.write(toJson(res.data) + \"\\n\");\n else ctx.io.stdout.write(formatPlan(res.data, Boolean(opts.verbose)) + \"\\n\");\n}\n\nconst onlyOption = [\"--only <kinds>\", \"comma list of models, forms, roles, sites (default: all)\"] as const;\nconst allSitesOption = [\"--all-sites\", \"the whole instance, not just the configured site (no roles)\"] as const;\n\nexport function registerMetadata(program: Command, io: Io): void {\n const metadata = program\n .command(\"metadata\")\n .description(\"Keep a directory of model and form YAML in step with the instance\")\n .addHelpText(\n \"after\",\n `\nThe tree is models/, forms/, roles/ and sites/ under the metadata directory\n(\"metadataDir\" in plenary.json, default ./plenary), one <key>.yaml per\nentity. With a site configured (--site, PLENARY_SITE_KEY or \"siteKey\" in\nplenary.json) the tree is that site's alone: its models, forms, roles and\nsite file, and --prune deletes only within it. --all-sites moves the whole\ninstance, which holds no roles. Models and forms need an API key or a\nsession; roles need a super user session and sites a session that may update\nthem (plenary login). See docs/CLI.md.`,\n );\n\n metadata\n .command(\"pull\")\n .description(\"Write every model, form, role and site the credential may read into the directory\")\n .option(\"--dir <path>\", \"metadata directory (default: the configured one)\")\n .option(...onlyOption)\n .option(...allSitesOption)\n .action(async (opts: DirOption, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const root = treeRoot(ctx, opts);\n const site = siteOf(ctx, opts);\n const kinds = kindsOf(opts, site);\n const wholeTree = kinds.some((k) => k === \"roles\" || k === \"sites\") && Boolean(opts.only);\n const res = await metadataRequest<{ files: YamlFile[]; omitted?: string[]; site_key?: string }>(\n ctx,\n \"GET\",\n { query: { only: kinds.join(\",\"), ...(site ? { site_key: site } : {}) } },\n wholeTree,\n );\n // Writing every site's models into one site's repository is never what\n // a pull meant, and a later push --prune would then own them.\n if (!isSiteAnswer(res.data, site)) throw usageError(`${UNSCOPED_SERVER(site!)}; pull with --all-sites for the whole instance`);\n const result = writeTree(root, res.data.files, kinds);\n const omitted = res.data.omitted ?? [];\n if (ctx.json) {\n io.stdout.write(toJson({ dir: root, ...result, omitted }) + \"\\n\");\n return;\n }\n io.stdout.write(`wrote ${result.written.length} file${result.written.length === 1 ? \"\" : \"s\"} to ${root}\\n`);\n if (omitted.length) {\n io.stderr.write(`not included, the credential may not read them: ${omitted.join(\", \")}\\n`);\n }\n if (result.written.length === 0 && omitted.length === 0) {\n // The server answers a key that may read no models with an empty tree,\n // not a refusal, so say what the likely cause is.\n io.stderr.write(\"the server sent no models: the key may lack content:models:read (a public key never has it)\\n\");\n }\n if (result.stale.length) {\n io.stdout.write(`not on the server (left in place):\\n${result.stale.map((p) => ` ${p}`).join(\"\\n\")}\\n`);\n }\n });\n\n metadata\n .command(\"diff\")\n .description(\"Preview what push would change, without writing anything\")\n .option(\"--dir <path>\", \"metadata directory (default: the configured one)\")\n .option(...onlyOption)\n .option(...allSitesOption)\n .option(\"--prune\", \"include what push --prune would delete\")\n .option(\"--verbose\", \"list unchanged entities too\")\n .action(async (opts: DirOption, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await runImport(ctx, treeRoot(ctx, opts), opts, false);\n });\n\n metadata\n .command(\"push\")\n .description(\"Apply the directory to the instance (creates and updates; deletes only with --prune)\")\n .option(\"--dir <path>\", \"metadata directory (default: the configured one)\")\n .option(...onlyOption)\n .option(...allSitesOption)\n .option(\"--prune\", \"also delete entities absent from the directory, within the kinds (and site) it holds\")\n .option(\"-y, --yes\", \"do not ask before pruning\")\n .option(\"--dry-run\", \"same as diff\")\n .option(\"--verbose\", \"list unchanged entities too\")\n .addHelpText(\n \"after\",\n `\n--prune deletes only within the kinds present in the directory: a tree with\nno roles/ cannot delete a role. System-owned roles are never touched and are\nreported as skipped. The plan is shown and confirmed before anything is\ndeleted; -y skips the question, and a run with no terminal needs it.`,\n )\n .action(async (opts: DirOption, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n await runImport(ctx, treeRoot(ctx, opts), opts, !opts.dryRun);\n });\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/** One file of a metadata tree, `path` relative to the tree's root. */\nexport interface YamlFile {\n path: string;\n content: string;\n}\n\n/** The directories the server reads and writes. */\nexport const MANAGED_DIRS = [\"models\", \"forms\", \"roles\", \"sites\"] as const;\nexport type Kind = (typeof MANAGED_DIRS)[number];\n\n/** `--only models,roles` → the kinds it names; empty or \"all\" → every kind. */\nexport function parseKinds(spec: string | undefined): Kind[] {\n if (!spec || spec === \"all\") return [...MANAGED_DIRS];\n const out: Kind[] = [];\n for (const raw of spec.split(\",\")) {\n const k = raw.trim() as Kind;\n if (!MANAGED_DIRS.includes(k)) throw new Error(`unknown kind \"${k}\" (want ${MANAGED_DIRS.join(\", \")} or all)`);\n if (!out.includes(k)) out.push(k);\n }\n return out;\n}\n\n/** Only the files under the named kinds' directories. */\nexport function filterKinds(files: YamlFile[], kinds: Kind[]): YamlFile[] {\n return files.filter((f) => kinds.includes(f.path.split(\"/\")[0] as Kind));\n}\n\n/** Every `models/*.yaml` and `forms/*.yaml` directly under `root`, sorted by path. */\nexport function readTree(root: string): YamlFile[] {\n const out: YamlFile[] = [];\n for (const rel of managedFiles(root)) {\n out.push({ path: rel, content: readFileSync(path.join(root, rel), \"utf8\") });\n }\n return out;\n}\n\nexport interface WriteResult {\n written: string[];\n /** Managed files already on disk that the server did not send — reported, never deleted. */\n stale: string[];\n}\n\n/**\n * Writes the server's files into `root`, creating directories as needed.\n * Stale files are only looked for under `kinds`, since a pull of models\n * alone says nothing about the roles on disk.\n */\nexport function writeTree(root: string, files: YamlFile[], kinds: Kind[] = [...MANAGED_DIRS]): WriteResult {\n const before = new Set(managedFiles(root).filter((p) => kinds.includes(p.split(\"/\")[0] as Kind)));\n const written: string[] = [];\n for (const f of [...files].sort((a, b) => a.path.localeCompare(b.path))) {\n if (!isTreePath(f.path)) continue;\n const abs = path.join(root, f.path);\n mkdirSync(path.dirname(abs), { recursive: true });\n writeFileSync(abs, f.content);\n written.push(f.path);\n before.delete(f.path);\n }\n return { written, stale: [...before].sort() };\n}\n\n/** `models/x.yaml` or `forms/x.yaml`, directly under the root; nothing else. */\nexport function isTreePath(p: string): boolean {\n const parts = p.split(\"/\");\n return (\n parts.length === 2 &&\n (MANAGED_DIRS as readonly string[]).includes(parts[0] as string) &&\n (parts[1] as string).endsWith(\".yaml\")\n );\n}\n\nfunction managedFiles(root: string): string[] {\n const out: string[] = [];\n for (const dir of MANAGED_DIRS) {\n const abs = path.join(root, dir);\n if (!existsSync(abs)) continue;\n for (const name of readdirSync(abs).sort()) {\n if (name.endsWith(\".yaml\")) out.push(`${dir}/${name}`);\n }\n }\n return out.sort();\n}\n","/** One row of the server's import plan. */\nexport interface ImportChange {\n key: string;\n kind: string;\n action: \"create\" | \"update\" | \"noop\" | \"delete\" | \"skip\";\n detail?: {\n fields_added: string[];\n fields_removed: string[];\n fields_changed: string[];\n attributes_changed: boolean;\n transformers_changed: boolean;\n };\n}\n\nexport interface ImportResult {\n applied: boolean;\n changes: ImportChange[];\n /** The site the plan was made for; absent on a whole-instance import. */\n site_key?: string;\n}\n\n/**\n * The plan as lines: one per create/update (noops too with `verbose`), then a\n * summary. `applied` picks the tense of the summary.\n */\nexport function formatPlan(result: ImportResult, verbose = false): string {\n const lines: string[] = [];\n const n = { create: 0, update: 0, delete: 0, skip: 0, noop: 0 };\n // Deletes first: they are what a person scanning a --prune plan must see.\n const ordered = [...result.changes].sort((a, b) => Number(b.action === \"delete\") - Number(a.action === \"delete\"));\n for (const c of ordered) {\n n[c.action]++;\n if (c.action === \"noop\" && !verbose) continue;\n const label = c.action === \"noop\" ? \"unchanged\" : c.action === \"skip\" ? \"skipped\" : c.action;\n const note = c.action === \"skip\" ? \" (system-owned)\" : detail(c);\n lines.push(`${label.padEnd(9)} ${c.kind.padEnd(10)} ${c.key}${note}`);\n }\n const parts = [`${n.create} to create`, `${n.update} to update`];\n if (n.delete) parts.push(`${n.delete} to delete`);\n if (n.skip) parts.push(`${n.skip} skipped`);\n parts.push(`${n.noop} unchanged`);\n if (n.create + n.update + n.delete === 0) {\n lines.push(`No changes: ${n.noop} unchanged${n.skip ? `, ${n.skip} skipped` : \"\"}.`);\n } else {\n lines.push(`${result.applied ? \"Applied\" : \"Plan\"}: ${parts.join(\", \")}.`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction detail(c: ImportChange): string {\n const d = c.detail;\n if (!d) return \"\";\n const parts: string[] = [];\n if (d.fields_added.length) parts.push(`+${d.fields_added.join(\",\")}`);\n if (d.fields_changed.length) parts.push(`~${d.fields_changed.join(\",\")}`);\n if (d.fields_removed.length) parts.push(`-${d.fields_removed.join(\",\")}`);\n if (d.attributes_changed) parts.push(\"settings\");\n if (d.transformers_changed) parts.push(\"transformers\");\n return parts.length ? ` (${parts.join(\" \")})` : \"\";\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport type { Command } from \"commander\";\nimport {\n CONFIG_FILE,\n DEFAULT_METADATA_DIR,\n resolveContext,\n type GlobalOptions,\n type Io,\n type ProjectConfig,\n} from \"../config.js\";\nimport { usageError } from \"../errors.js\";\n\nexport function registerInit(program: Command, io: Io): void {\n program\n .command(\"init\")\n .description(`Write a ${CONFIG_FILE} for this project (never a credential)`)\n .option(\"--dir <path>\", \"metadata directory, relative to the config file\", DEFAULT_METADATA_DIR)\n .option(\"-f, --force\", `overwrite an existing ${CONFIG_FILE}`)\n .addHelpText(\n \"after\",\n `\nThe base URL, site and locale come from --base-url, --site and --locale (or\ntheir PLENARY_* variables); anything missing is prompted for on a terminal.`,\n )\n .action(async (opts: { dir: string; force?: boolean }, cmd: Command) => {\n const target = path.join(io.cwd, CONFIG_FILE);\n if (existsSync(target) && !opts.force) {\n throw usageError(`${target} already exists (pass --force to overwrite)`);\n }\n const globals = cmd.optsWithGlobals<GlobalOptions>();\n // Read what the environment already says, but not a parent's plenary.json:\n // init describes this directory, not one above it.\n const ctx = resolveContext({ ...globals, config: undefined }, { ...io, cwd: path.parse(io.cwd).root });\n\n const baseUrl = globals.baseUrl ?? ctx.baseUrl ?? (await ask(io, \"Base URL (https://cms.example.com)\"));\n if (!baseUrl) throw usageError(\"a base URL is required: pass --base-url or set PLENARY_BASE_URL\");\n const siteKey = globals.site ?? ctx.siteKey ?? (await ask(io, \"Site key\", \"default\"));\n const locale = globals.locale ?? ctx.locale ?? (await ask(io, \"Locale\", \"en-us\"));\n\n const config: ProjectConfig = { baseUrl: baseUrl.replace(/\\/+$/, \"\") };\n if (siteKey) config.siteKey = siteKey;\n if (locale) config.locale = locale;\n if (opts.dir !== DEFAULT_METADATA_DIR) config.metadataDir = opts.dir;\n\n writeFileSync(target, JSON.stringify(config, null, 2) + \"\\n\");\n io.stdout.write(`wrote ${target}\\n`);\n });\n}\n\n/** Prompts on a terminal; returns the default (or undefined) without one. */\nasync function ask(io: Io, label: string, fallback?: string): Promise<string | undefined> {\n if (!io.isTTY) return fallback;\n const rl = createInterface({ input: io.stdin, output: io.stderr });\n try {\n const answer = (await rl.question(fallback ? `${label} [${fallback}]: ` : `${label}: `)).trim();\n return answer === \"\" ? fallback : answer;\n } finally {\n rl.close();\n }\n}\n","import type { Command } from \"commander\";\nimport { describeUser } from \"./auth.js\";\nimport { PlenaryError } from \"@plenary/client\";\nimport { resolveContext, type GlobalOptions, type Io } from \"../config.js\";\nimport { credentialHeaders, request } from \"../api/http.js\";\nimport { CliError } from \"../errors.js\";\nimport { toJson } from \"../output.js\";\n\ninterface Health {\n status: string;\n database: string;\n version: string;\n edition: string;\n license?: string;\n}\n\ninterface MeGrant {\n key: string;\n site_key?: string;\n content_model_id?: string;\n source: string;\n role_key?: string;\n}\n\ntype Me =\n | { principal: \"api_key\"; key_id: string; key_type: string; name: string; grants: MeGrant[]; site_key?: string }\n | { principal: \"user\"; user_id: string; is_super_user: boolean; grants: MeGrant[] };\n\nexport function registerStatus(program: Command, io: Io): void {\n program\n .command(\"status\")\n .description(\"Show the instance's health and which credential this run holds\")\n .action(async (_opts: unknown, cmd: Command) => {\n const ctx = resolveContext(cmd.optsWithGlobals<GlobalOptions>(), io);\n const health = await request<Health>(ctx, \"GET\", \"/api/v1/health\", { auth: \"none\", allowError: true });\n\n let me: Me | undefined;\n let credentialError: PlenaryError | undefined;\n // A server without API-key support on /auth/me answers /auth/me with 403 for a key it\n // accepted: the key authenticated, the server just cannot describe it.\n let undescribed = false;\n const headers = await credentialHeaders(ctx, \"optional\");\n if (Object.keys(headers).length > 0) {\n try {\n me = (await request<Me>(ctx, \"GET\", \"/api/v1/auth/me\", { auth: \"none\", headers })).data;\n } catch (err) {\n if (!(err instanceof PlenaryError)) throw err;\n if (err.status === 403) undescribed = true;\n else credentialError = err;\n }\n }\n\n const failed = !health.ok || credentialError !== undefined;\n if (ctx.json) {\n io.stdout.write(\n toJson({\n base_url: ctx.baseUrl,\n health: health.data,\n credential: me ?? null,\n credential_error: credentialError ? { status: credentialError.status, code: credentialError.code } : null,\n }) + \"\\n\",\n );\n if (failed) throw new CliError(\"\", 1);\n return;\n }\n\n const lines = [`Instance ${ctx.baseUrl}`];\n if (health.ok || (health.status === 503 && typeof health.data === \"object\")) {\n const h = health.data;\n lines.push(`Version ${h.version} (${h.edition})`);\n lines.push(`Status ${h.status}, database ${h.database}${h.license ? `, license ${h.license}` : \"\"}`);\n } else {\n lines.push(`Status unreachable (HTTP ${health.status})`);\n }\n if (me?.principal === \"api_key\") {\n lines.push(`Credential ${me.key_type} API key \"${me.name}\" (${me.grants.length} grant${me.grants.length === 1 ? \"\" : \"s\"}${\n me.site_key ? `, site ${me.site_key}` : \", instance-wide\"\n })`);\n } else if (me?.principal === \"user\") {\n lines.push(`Credential user session (stored login), ${describeUser(me)}`);\n } else if (credentialError) {\n lines.push(`Credential rejected: ${credentialError.code} (HTTP ${credentialError.status})`);\n } else if (undescribed) {\n lines.push(\"Credential API key accepted (this server predates API-key support on /auth/me and cannot describe the key)\");\n } else {\n lines.push(\"Credential none (set PLENARY_CLI_API_KEY, pass --api-key, or run `plenary login`)\");\n }\n if (ctx.configPath) lines.push(`Config ${ctx.configPath}`);\n io.stdout.write(lines.join(\"\\n\") + \"\\n\");\n // The report itself is the message; the exit code is the only extra signal.\n if (failed) throw new CliError(\"\", 1);\n });\n}\n","import { run } from \"./cli.js\";\n\nrun(process.argv.slice(2), {\n stdout: process.stdout,\n stderr: process.stderr,\n stdin: process.stdin,\n env: process.env,\n cwd: process.cwd(),\n fetch: globalThis.fetch,\n isTTY: Boolean(process.stdin.isTTY),\n}).then((code) => {\n process.exitCode = code;\n});\n"],"mappings":"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","names":["readFileSync","CommanderError","existsSync","readFileSync","path","path","existsSync","readFileSync","token","path","readFileSync","readFileSync","errorFromResponse","collect","path","path","collect","collect","PAGE","readFileSync","path","path","readFileSync","path","PlenaryError","existsSync","mkdirSync","readFileSync","writeFileSync","path","path","PlenaryError","existsSync","writeFileSync","path","createInterface","path","existsSync","writeFileSync","createInterface","PlenaryError","PlenaryError","readFileSync","CommanderError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plenary/cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Plenary command-line client: metadata sync, content automation, and a raw API escape hatch.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,7 +15,7 @@
15
15
  "dependencies": {
16
16
  "commander": "^15.0.0",
17
17
  "yaml": "^2.9.1",
18
- "@plenary/client": "1.1.0"
18
+ "@plenary/client": "1.2.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^26.1.2"