@letterapp/cli 0.3.2 → 0.3.3
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 +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -669,7 +669,7 @@ function printAgentHandoff(sdkNote, envFile, verifyCmd) {
|
|
|
669
669
|
log();
|
|
670
670
|
log(c.bold("Next: finish setup with your coding agent"));
|
|
671
671
|
log();
|
|
672
|
-
log(c.dim(" Paste this to your agent (Cursor, Claude Code, Codex, \u2026):"));
|
|
672
|
+
log(c.dim(" Paste this to your agent (Cursor, Claude Code, Codex, OpenClaw, Hermes, \u2026):"));
|
|
673
673
|
log(c.dim(rule));
|
|
674
674
|
log(" Integrate Letter (product email automation) into this app. The CLI");
|
|
675
675
|
log(` already did setup: LETTER_API_KEY is in ${envFile} and ${sdkNote}.`);
|
|
@@ -1385,7 +1385,7 @@ function registerResourceCommands(program2) {
|
|
|
1385
1385
|
|
|
1386
1386
|
// src/index.ts
|
|
1387
1387
|
var program = new Command();
|
|
1388
|
-
program.name("letter").description("Connect your app to Letter, then manage it from the command line").version("0.3.
|
|
1388
|
+
program.name("letter").description("Connect your app to Letter, then manage it from the command line").version("0.3.3").option("--json", "Output raw JSON (for scripting / agents)").hook("preAction", (thisCommand) => {
|
|
1389
1389
|
if (thisCommand.opts().json) setJsonMode(true);
|
|
1390
1390
|
});
|
|
1391
1391
|
registerLoginCommand(program);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/output.ts","../src/config.ts","../src/client.ts","../src/browser.ts","../src/env-file.ts","../src/pm.ts","../src/commands/login.ts","../src/commands/auth.ts","../src/commands/status.ts","../src/commands/config.ts","../src/commands/resources.ts"],"sourcesContent":["declare const PKG_VERSION: string;\nimport { Command } from \"commander\";\nimport { setJsonMode } from \"./output.js\";\nimport { registerLoginCommand } from \"./commands/login.js\";\nimport { registerAuthCommands } from \"./commands/auth.js\";\nimport { registerStatusCommand } from \"./commands/status.js\";\nimport { registerConfigCommands } from \"./commands/config.js\";\nimport { registerResourceCommands } from \"./commands/resources.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"letter\")\n .description(\"Connect your app to Letter, then manage it from the command line\")\n .version(PKG_VERSION)\n .option(\"--json\", \"Output raw JSON (for scripting / agents)\")\n .hook(\"preAction\", (thisCommand) => {\n if (thisCommand.opts().json) setJsonMode(true);\n });\n\n// Two layers, one login:\n// - login/auth/status/config wire up the project and its ingestion key\n// (lt_live_*, written to the project env as LETTER_API_KEY).\n// - the resource groups drive the Management API with the workspace PAT\n// (lt_pat_*, stored in ~/.letter/credentials.json). Both credentials are\n// minted by `letter login`; each command picks the right one on its own.\nregisterLoginCommand(program); // default command (`letter` == `letter login`)\nregisterAuthCommands(program);\nregisterStatusCommand(program);\nregisterConfigCommands(program);\nregisterResourceCommands(program); // control-plane resource groups (PAT-backed)\n\nprogram.parseAsync();\n","import chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\nimport { createInterface } from \"node:readline\";\n\nlet jsonMode = false;\n\nexport function setJsonMode(enabled: boolean) {\n jsonMode = enabled;\n}\nexport function isJsonMode() {\n return jsonMode;\n}\n\nexport function printJson(data: unknown) {\n console.log(JSON.stringify(data, null, 2));\n}\n\n/**\n * The command users should repeat to run us again, so printed hints are\n * copy-pasteable. When launched through `npx`, Node runs us from the npx cache\n * (`…/_npx/<hash>/…`) and there's no `letter` on PATH, so suggest the npx form;\n * a global install resolves the bare `letter` binary.\n */\nexport function cliCommand(): string {\n return (process.argv[1] ?? \"\").includes(\"_npx\") ? \"npx @letterapp/cli\" : \"letter\";\n}\n\nexport function log(msg = \"\") {\n if (jsonMode) return;\n console.log(msg);\n}\n\nexport function printSuccess(msg: string) {\n if (jsonMode) return;\n console.log(chalk.green(\"✓\") + \" \" + msg);\n}\n\nexport function printInfo(msg: string) {\n if (jsonMode) return;\n console.log(chalk.cyan(\"›\") + \" \" + msg);\n}\n\nexport function printWarning(msg: string) {\n if (jsonMode) return;\n console.log(chalk.yellow(\"!\") + \" \" + msg);\n}\n\nexport function printError(err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n if (jsonMode) {\n printJson({ error: msg });\n return;\n }\n console.error(chalk.red(\"✗\") + \" \" + msg);\n}\n\n/** The Letter wordmark banner. Suppressed in JSON mode. */\nexport function banner() {\n if (jsonMode) return;\n console.log(\"\");\n console.log(\" \" + chalk.bold(\"Letter\") + chalk.red(\".\") + \" \" + chalk.dim(\"CLI\"));\n console.log(\"\");\n}\n\nexport function spinner(text: string): Ora {\n return ora({ text, color: \"cyan\", isEnabled: !jsonMode });\n}\n\n/**\n * Prompts the user and resolves with their input. Returns \"\" immediately on a\n * non-interactive stdin so automated/agent runs don't hang.\n */\nexport function prompt(question: string): Promise<string> {\n if (!process.stdin.isTTY) return Promise.resolve(\"\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\n/**\n * Print a management API result. In `--json` mode, emits the raw payload so\n * agents/scripts can parse it. In human mode, renders list envelopes as a\n * compact `id label` table and single resources as pretty JSON.\n */\nexport function emit(data: unknown) {\n if (jsonMode) {\n printJson(data);\n return;\n }\n if (data && typeof data === \"object\" && Array.isArray((data as { data?: unknown }).data)) {\n const env = data as { data: Record<string, unknown>[]; next_cursor?: string | null };\n if (env.data.length === 0) {\n console.log(chalk.dim(\"(none)\"));\n } else {\n for (const row of env.data) {\n const id = String(row.id ?? row.slug ?? row.external_id ?? \"\");\n const label =\n (row.name as string) ??\n (row.email as string) ??\n (row.domain as string) ??\n (row.subject as string) ??\n \"\";\n console.log(`${chalk.bold(id)}${label ? \" \" + label : \"\"}`);\n }\n }\n if (env.next_cursor) {\n console.log(chalk.dim(`\\n› more: --cursor ${env.next_cursor}`));\n }\n return;\n }\n printJson(data);\n}\n\nexport const c = chalk;\n","import Conf from \"conf\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { mkdir, readFile, writeFile, rm } from \"node:fs/promises\";\nimport { cliCommand } from \"./output.js\";\n\n/** The SDK / API default. When the resolved base equals this we don't bother\n * writing LETTER_BASE_URL into the project env. */\nexport const DEFAULT_BASE_URL = \"https://api.letter.app\";\n\n/* -------------------------------------------------------------------------- */\n/* Non-secret CLI preferences (base URL). */\n/* Stored with `conf`, mirroring how the SDK/MCP resolve their endpoint. */\n/* -------------------------------------------------------------------------- */\n\nconst config = new Conf({\n projectName: \"letterapp-cli\",\n schema: {\n baseUrl: { type: \"string\", default: DEFAULT_BASE_URL },\n },\n});\n\n/** Resolve the API base: explicit flag > env > stored config > prod default. */\nexport function getBaseUrl(flag?: string): string {\n const raw =\n flag ||\n process.env.LETTER_BASE_URL ||\n (config.get(\"baseUrl\") as string) ||\n DEFAULT_BASE_URL;\n return raw.replace(/\\/$/, \"\");\n}\n\nexport function setBaseUrl(url: string): void {\n config.set(\"baseUrl\", url.replace(/\\/$/, \"\"));\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n\nexport function resetConfig(): void {\n config.clear();\n}\n\n/* -------------------------------------------------------------------------- */\n/* Secret credential store (~/.letter/credentials.json). */\n/* Written here, read by @letterapp/mcp so the secret never lands in an MCP */\n/* config. Kept separate from `conf` and locked to owner-only permissions. */\n/* -------------------------------------------------------------------------- */\n\nexport type StoredCredential = {\n apiKey: string;\n /** Workspace Personal Access Token (lt_pat_*) for the management API/CLI. */\n pat?: string;\n baseUrl: string;\n project: { slug: string; name: string };\n workspace?: { id: string; name: string };\n savedAt: string;\n};\n\n/**\n * Resolve the project slug a management command should target: explicit\n * `--project` flag > `LETTER_PROJECT` env (for scripts/CI) > the connected\n * project from `letter login`. Throws a clear error when none is available so\n * scripts fail loudly.\n */\nexport async function resolveProjectSlug(flag?: string): Promise<string> {\n if (flag) return flag;\n if (process.env.LETTER_PROJECT) return process.env.LETTER_PROJECT;\n const cred = await readCredential();\n if (cred?.project?.slug) return cred.project.slug;\n throw new Error(\n `No project. Pass --project <slug>, set LETTER_PROJECT, or run \\`${cliCommand()} login\\`.`,\n );\n}\n\nexport function credentialsPath(): string {\n return path.join(homedir(), \".letter\", \"credentials.json\");\n}\n\nexport async function saveCredential(cred: StoredCredential): Promise<string> {\n const file = credentialsPath();\n await mkdir(path.dirname(file), { recursive: true, mode: 0o700 });\n await writeFile(file, `${JSON.stringify(cred, null, 2)}\\n`, { mode: 0o600 });\n return file;\n}\n\nexport async function readCredential(): Promise<StoredCredential | null> {\n try {\n const raw = await readFile(credentialsPath(), \"utf8\");\n return JSON.parse(raw) as StoredCredential;\n } catch {\n return null;\n }\n}\n\nexport async function clearCredential(): Promise<void> {\n await rm(credentialsPath(), { force: true });\n}\n","import { getBaseUrl, readCredential } from \"./config.js\";\nimport { cliCommand } from \"./output.js\";\n\nconst USER_AGENT = \"@letterapp/cli\";\n\n/* -------------------------------------------------------------------------- */\n/* Device authorization (RFC 8628 style). No secret ever passes through argv. */\n/* -------------------------------------------------------------------------- */\n\nexport type StartResponse = {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n interval: number;\n expires_in: number;\n};\n\nexport type PollResponse =\n | { status: \"authorization_pending\" }\n | { status: \"slow_down\"; retryAfter?: number }\n | { status: \"access_denied\" }\n | { status: \"expired_token\" }\n | {\n status: \"approved\";\n api_key: string;\n /** Workspace PAT for the management API (lt_pat_*). */\n pat: string;\n base_url: string;\n project: { slug: string; name: string };\n workspace?: { id: string; name: string };\n };\n\n/** Starts a device-authorization flow against the given API base. */\nexport async function startDeviceAuth(base: string): Promise<StartResponse> {\n const res = await fetch(`${base}/v1/cli/auth/start`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: \"{}\",\n });\n if (!res.ok) {\n throw new Error(\n `Could not start login (HTTP ${res.status}). Is ${base} reachable?`,\n );\n }\n return (await res.json()) as StartResponse;\n}\n\n/** Polls once for approval. */\nexport async function pollDeviceAuth(\n base: string,\n deviceCode: string,\n): Promise<PollResponse> {\n const res = await fetch(`${base}/v1/cli/auth/poll`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: JSON.stringify({ device_code: deviceCode }),\n });\n\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get(\"retry-after\") ?? \"5\");\n return { status: \"slow_down\", retryAfter };\n }\n if (!res.ok) {\n throw new Error(`Login poll failed (HTTP ${res.status}).`);\n }\n return (await res.json()) as PollResponse;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Authenticated client. Resolves the key from the stored credential (written */\n/* by `letter login`) or LETTER_API_KEY. Used by data commands like `status`. */\n/* -------------------------------------------------------------------------- */\n\nexport interface ApiResponse<T = unknown> {\n status: number;\n data: T;\n}\n\nclass LetterClient {\n private maxRetries = 3;\n\n private async resolveAuth(): Promise<{ base: string; token: string }> {\n const cred = await readCredential();\n const token = process.env.LETTER_API_KEY || cred?.apiKey || \"\";\n if (!token) {\n throw new Error(\n `Not connected. Run \\`${cliCommand()} login\\` (or set LETTER_API_KEY) first.`,\n );\n }\n const base = getBaseUrl(process.env.LETTER_API_KEY ? undefined : cred?.baseUrl);\n return { base, token };\n }\n\n private async request<T = unknown>(\n method: string,\n path: string,\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n const { base, token } = await this.resolveAuth();\n const res = await fetch(`${base}${path}`, {\n method,\n headers: {\n authorization: `Bearer ${token}`,\n accept: \"application/json\",\n \"user-agent\": USER_AGENT,\n },\n });\n\n if (res.status === 429 && attempt <= this.maxRetries) {\n const retryAfter = Number(res.headers.get(\"retry-after\") || 2);\n await new Promise((r) => setTimeout(r, retryAfter * 1000 * attempt));\n return this.request<T>(method, path, attempt + 1);\n }\n\n const data = (res.status === 204 ? {} : await res.json()) as T;\n if (!res.ok) {\n const msg =\n (data as { error?: { message?: string } })?.error?.message ||\n `HTTP ${res.status}`;\n const err = new Error(msg) as Error & { status: number };\n err.status = res.status;\n throw err;\n }\n return { status: res.status, data };\n }\n\n get<T = unknown>(path: string) {\n return this.request<T>(\"GET\", path);\n }\n}\n\nexport const client = new LetterClient();\n\n/* -------------------------------------------------------------------------- */\n/* Management client. Authenticates with the workspace PAT (lt_pat_*) and */\n/* drives the control-plane (/v1/projects, sequences, broadcasts, ...). Used by */\n/* the resource command groups. */\n/* -------------------------------------------------------------------------- */\n\nexport type RequestInitLite = {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n form?: FormData;\n};\n\nclass ManagementClient {\n private maxRetries = 3;\n\n private async resolveAuth(): Promise<{ base: string; token: string }> {\n const cred = await readCredential();\n const token = process.env.LETTER_PAT || cred?.pat || \"\";\n if (!token) {\n throw new Error(\n `Not connected for management. Run \\`${cliCommand()} login\\` (or set LETTER_PAT) first.`,\n );\n }\n const base = getBaseUrl(process.env.LETTER_PAT ? undefined : cred?.baseUrl);\n return { base, token };\n }\n\n async request<T = unknown>(\n method: string,\n path: string,\n init: RequestInitLite = {},\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n const { base, token } = await this.resolveAuth();\n\n let url = `${base}${path}`;\n if (init.query) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(init.query)) {\n if (v !== undefined && v !== \"\") qs.set(k, String(v));\n }\n const s = qs.toString();\n if (s) url += `?${s}`;\n }\n\n const headers: Record<string, string> = {\n authorization: `Bearer ${token}`,\n accept: \"application/json\",\n \"user-agent\": USER_AGENT,\n };\n let body: BodyInit | undefined;\n if (init.form) {\n body = init.form;\n } else if (init.body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n body = JSON.stringify(init.body);\n }\n\n const res = await fetch(url, { method, headers, body });\n\n if (res.status === 429 && attempt <= this.maxRetries) {\n const retryAfter = Number(res.headers.get(\"retry-after\") || 2);\n await new Promise((r) => setTimeout(r, retryAfter * 1000 * attempt));\n return this.request<T>(method, path, init, attempt + 1);\n }\n\n const text = await res.text();\n const data = (text ? JSON.parse(text) : {}) as T;\n if (!res.ok) {\n const msg =\n (data as { error?: { message?: string } })?.error?.message ||\n `HTTP ${res.status}`;\n const err = new Error(msg) as Error & { status: number };\n err.status = res.status;\n throw err;\n }\n return { status: res.status, data };\n }\n\n get<T = unknown>(path: string, query?: RequestInitLite[\"query\"]) {\n return this.request<T>(\"GET\", path, { query });\n }\n post<T = unknown>(path: string, body?: unknown) {\n return this.request<T>(\"POST\", path, { body });\n }\n postForm<T = unknown>(path: string, form: FormData) {\n return this.request<T>(\"POST\", path, { form });\n }\n patch<T = unknown>(path: string, body?: unknown) {\n return this.request<T>(\"PATCH\", path, { body });\n }\n put<T = unknown>(path: string, body?: unknown) {\n return this.request<T>(\"PUT\", path, { body });\n }\n delete<T = unknown>(path: string) {\n return this.request<T>(\"DELETE\", path);\n }\n}\n\nexport const mgmt = new ManagementClient();\n","import { spawn } from \"node:child_process\";\n\n/**\n * Opens `url` in the default browser. Best-effort and non-blocking: if it fails\n * (headless box, no DISPLAY) the caller has already printed the URL so the user\n * can open it manually. Returns true if a launcher was spawned.\n */\nexport function openUrl(url: string): boolean {\n const platform = process.platform;\n let command: string;\n let args: string[];\n\n if (platform === \"darwin\") {\n command = \"open\";\n args = [url];\n } else if (platform === \"win32\") {\n command = \"cmd\";\n // `start` needs an empty title arg; the comma-free form avoids quoting woes.\n args = [\"/c\", \"start\", \"\", url];\n } else {\n command = \"xdg-open\";\n args = [url];\n }\n\n try {\n const child = spawn(command, args, { stdio: \"ignore\", detached: true });\n child.on(\"error\", () => {});\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n","import path from \"node:path\";\nimport { readFile, writeFile, stat } from \"node:fs/promises\";\n\n/**\n * Upserts `key=value` in an env file, creating it if needed. Existing keys are\n * replaced in place; new keys are appended. Returns the file path. The value is\n * never logged by this module - callers print only the key name.\n */\nexport async function upsertEnv(\n cwd: string,\n file: string,\n entries: Record<string, string>,\n): Promise<string> {\n const filePath = path.join(cwd, file);\n let contents = \"\";\n try {\n contents = await readFile(filePath, \"utf8\");\n } catch {\n contents = \"\";\n }\n\n let next = contents;\n for (const [key, value] of Object.entries(entries)) {\n const line = `${key}=${value}`;\n const re = new RegExp(`^${escapeRegExp(key)}=.*$`, \"m\");\n if (re.test(next)) {\n next = next.replace(re, line);\n } else {\n if (next.length && !next.endsWith(\"\\n\")) next += \"\\n\";\n next += `${line}\\n`;\n }\n }\n\n await writeFile(filePath, next, \"utf8\");\n return filePath;\n}\n\n/** True if a file exists at `cwd/name`. */\nexport async function fileExists(cwd: string, name: string): Promise<boolean> {\n try {\n await stat(path.join(cwd, name));\n return true;\n } catch {\n return false;\n }\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport { fileExists } from \"./env-file.js\";\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\n/**\n * Detects the package manager from lockfiles (then the `npm_config_user_agent`\n * of the running process), defaulting to npm.\n */\nexport async function detectPackageManager(\n cwd: string,\n): Promise<PackageManager> {\n if (await fileExists(cwd, \"pnpm-lock.yaml\")) return \"pnpm\";\n if (await fileExists(cwd, \"yarn.lock\")) return \"yarn\";\n if (await fileExists(cwd, \"bun.lockb\")) return \"bun\";\n if (await fileExists(cwd, \"package-lock.json\")) return \"npm\";\n\n const ua = process.env.npm_config_user_agent ?? \"\";\n if (ua.startsWith(\"pnpm\")) return \"pnpm\";\n if (ua.startsWith(\"yarn\")) return \"yarn\";\n if (ua.startsWith(\"bun\")) return \"bun\";\n return \"npm\";\n}\n\n/** Detects a likely Node web framework for friendlier guidance. */\nexport async function detectFramework(cwd: string): Promise<string | null> {\n try {\n const pkg = JSON.parse(await readFile(`${cwd}/package.json`, \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.next) return \"Next.js\";\n if (deps.nuxt) return \"Nuxt\";\n if (deps[\"@remix-run/node\"] || deps[\"@remix-run/react\"]) return \"Remix\";\n if (deps.express) return \"Express\";\n if (deps.fastify) return \"Fastify\";\n if (deps.hono) return \"Hono\";\n if (deps[\"@sveltejs/kit\"]) return \"SvelteKit\";\n return null;\n } catch {\n return null;\n }\n}\n\nexport type Runtime = \"node\" | \"python\" | \"ruby\" | \"go\" | \"php\" | \"other\";\nexport type Stack = { runtime: Runtime; framework: string | null };\n\n/**\n * Detects the project's language/runtime so the CLI installs the right thing\n * (only Node has an SDK today) and prints instructions in the right language.\n * Node is checked first since it's this CLI's primary audience.\n */\nexport async function detectStack(cwd: string): Promise<Stack> {\n if (await fileExists(cwd, \"package.json\")) {\n return { runtime: \"node\", framework: await detectFramework(cwd) };\n }\n if (\n (await fileExists(cwd, \"pyproject.toml\")) ||\n (await fileExists(cwd, \"requirements.txt\")) ||\n (await fileExists(cwd, \"Pipfile\")) ||\n (await fileExists(cwd, \"setup.py\"))\n ) {\n return { runtime: \"python\", framework: await detectPythonFramework(cwd) };\n }\n if ((await fileExists(cwd, \"Gemfile\")) || (await hasGemspec(cwd))) {\n return { runtime: \"ruby\", framework: await detectRubyFramework(cwd) };\n }\n if (await fileExists(cwd, \"go.mod\")) return { runtime: \"go\", framework: null };\n if (await fileExists(cwd, \"composer.json\")) {\n return { runtime: \"php\", framework: await detectPhpFramework(cwd) };\n }\n return { runtime: \"other\", framework: null };\n}\n\n/** Human-friendly label for the detected stack (framework if known). */\nexport function stackLabel(stack: Stack): string {\n if (stack.framework) return stack.framework;\n switch (stack.runtime) {\n case \"node\":\n return \"a Node.js project\";\n case \"python\":\n return \"a Python project\";\n case \"ruby\":\n return \"a Ruby project\";\n case \"go\":\n return \"a Go project\";\n case \"php\":\n return \"a PHP project\";\n default:\n return \"your project\";\n }\n}\n\n/** The language name to tell the agent to write in. */\nexport function languageName(stack: Stack): string {\n switch (stack.runtime) {\n case \"node\":\n return \"TypeScript\";\n case \"python\":\n return \"Python\";\n case \"ruby\":\n return \"Ruby\";\n case \"go\":\n return \"Go\";\n case \"php\":\n return \"PHP\";\n default:\n return \"your language\";\n }\n}\n\nasync function readIf(cwd: string, name: string): Promise<string> {\n try {\n return await readFile(`${cwd}/${name}`, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\nasync function hasGemspec(cwd: string): Promise<boolean> {\n try {\n return (await readdir(cwd)).some((f) => f.endsWith(\".gemspec\"));\n } catch {\n return false;\n }\n}\n\nasync function detectPythonFramework(cwd: string): Promise<string | null> {\n const txt = (\n (await readIf(cwd, \"requirements.txt\")) +\n (await readIf(cwd, \"pyproject.toml\")) +\n (await readIf(cwd, \"Pipfile\"))\n ).toLowerCase();\n if (txt.includes(\"django\")) return \"Django\";\n if (txt.includes(\"fastapi\")) return \"FastAPI\";\n if (txt.includes(\"flask\")) return \"Flask\";\n return null;\n}\n\nasync function detectRubyFramework(cwd: string): Promise<string | null> {\n const txt = (await readIf(cwd, \"Gemfile\")).toLowerCase();\n if (txt.includes(\"rails\")) return \"Rails\";\n if (txt.includes(\"sinatra\")) return \"Sinatra\";\n return null;\n}\n\nasync function detectPhpFramework(cwd: string): Promise<string | null> {\n const txt = (await readIf(cwd, \"composer.json\")).toLowerCase();\n if (txt.includes(\"laravel\")) return \"Laravel\";\n if (txt.includes(\"symfony\")) return \"Symfony\";\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Non-Node SDK installs (letterapp on PyPI / RubyGems) */\n/* -------------------------------------------------------------------------- */\n\nconst SDK_PYPI = \"letterapp\";\nconst SDK_GEM = \"letterapp\";\n\nexport type SdkInstall = { cmd: string; args: string[]; display: string };\n\nfunction sdkInstall(cmd: string, args: string[]): SdkInstall {\n return { cmd, args, display: `${cmd} ${args.join(\" \")}` };\n}\n\n/**\n * Picks the right Python installer for the project: uv > poetry > pipenv > pip.\n * Returns the command we'd run to add `letterapp`.\n */\nexport async function pythonSdkInstall(cwd: string): Promise<SdkInstall> {\n if (await fileExists(cwd, \"uv.lock\")) return sdkInstall(\"uv\", [\"add\", SDK_PYPI]);\n const pyproject = (await readIf(cwd, \"pyproject.toml\")).toLowerCase();\n if (\n (await fileExists(cwd, \"poetry.lock\")) ||\n pyproject.includes(\"[tool.poetry]\")\n ) {\n return sdkInstall(\"poetry\", [\"add\", SDK_PYPI]);\n }\n if (await fileExists(cwd, \"Pipfile\")) {\n return sdkInstall(\"pipenv\", [\"install\", SDK_PYPI]);\n }\n return sdkInstall(\"pip\", [\"install\", SDK_PYPI]);\n}\n\n/** Bundler when there's a Gemfile, otherwise a plain `gem install`. */\nexport async function rubySdkInstall(cwd: string): Promise<SdkInstall> {\n if (await fileExists(cwd, \"Gemfile\")) {\n return sdkInstall(\"bundle\", [\"add\", SDK_GEM]);\n }\n return sdkInstall(\"gem\", [\"install\", SDK_GEM]);\n}\n\n/** Runs an SdkInstall command, streaming output. Resolves to the exit code. */\nexport function runSdkInstall(\n install: SdkInstall,\n cwd: string,\n): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(install.cmd, install.args, {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", () => resolve(1));\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n}\n\nexport function installCommand(pm: PackageManager, pkg: string): string {\n switch (pm) {\n case \"pnpm\":\n return `pnpm add ${pkg}`;\n case \"yarn\":\n return `yarn add ${pkg}`;\n case \"bun\":\n return `bun add ${pkg}`;\n default:\n return `npm install ${pkg}`;\n }\n}\n\n/** Runs the install command, streaming output. Resolves to the exit code. */\nexport function runInstall(\n pm: PackageManager,\n pkg: string,\n cwd: string,\n): Promise<number> {\n const args = pm === \"npm\" ? [\"install\", pkg] : [\"add\", pkg];\n return new Promise((resolve) => {\n const child = spawn(pm, args, {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", () => resolve(1));\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n}\n","import { Command } from \"commander\";\nimport {\n getBaseUrl,\n DEFAULT_BASE_URL,\n saveCredential,\n} from \"../config.js\";\nimport { startDeviceAuth, pollDeviceAuth } from \"../client.js\";\nimport { openUrl } from \"../browser.js\";\nimport { upsertEnv } from \"../env-file.js\";\nimport {\n detectPackageManager,\n detectStack,\n installCommand,\n languageName,\n pythonSdkInstall,\n rubySdkInstall,\n runInstall,\n runSdkInstall,\n stackLabel,\n type SdkInstall,\n type Stack,\n} from \"../pm.js\";\nimport {\n banner,\n c,\n cliCommand,\n log,\n printError,\n printInfo,\n printSuccess,\n printWarning,\n prompt,\n} from \"../output.js\";\n\nconst SDK_PACKAGE = \"@letterapp/node\";\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\n// Node projects use .env.local (Next.js convention, gitignored by default);\n// everything else uses the more universal .env.\nfunction envFileFor(stack: Stack): string {\n return stack.runtime === \"node\" ? \".env.local\" : \".env\";\n}\n\ninterface LoginOptions {\n open: boolean;\n install: boolean;\n yes?: boolean;\n baseUrl?: string;\n apiKey?: string;\n}\n\nexport function registerLoginCommand(program: Command) {\n program\n .command(\"login\", { isDefault: true })\n .alias(\"init\")\n .description(\"Connect this project to Letter (interactive device login)\")\n .option(\"--no-open\", \"Don't open the browser; print the URL to open manually\")\n .option(\"-y, --yes\", \"Non-interactive: don't wait for Enter (agents/CI)\")\n .option(\"--no-install\", \"Skip installing the SDK\")\n .option(\"--base-url <url>\", \"Target a self-hosted or local Letter instance\")\n .option(\n \"--api-key <key>\",\n \"CI only: write a key without the device flow (never use in chat)\",\n )\n .action(async (opts: LoginOptions) => {\n const code = await runLogin(opts);\n if (code !== 0) process.exitCode = code;\n });\n}\n\nasync function runLogin(opts: LoginOptions): Promise<number> {\n const base = getBaseUrl(opts.baseUrl);\n const cwd = process.cwd();\n const interactive = process.stdin.isTTY && !opts.yes;\n\n banner();\n\n // CI escape hatch: write the provided key non-interactively. Documented as\n // automation-only; interactive/agent use should rely on the device flow so\n // no secret passes through the command line or chat.\n if (opts.apiKey) {\n const envFile = envFileFor(await detectStack(cwd));\n const entries: Record<string, string> = { LETTER_API_KEY: opts.apiKey };\n if (base !== DEFAULT_BASE_URL) entries.LETTER_BASE_URL = base;\n const file = await upsertEnv(cwd, envFile, entries);\n printSuccess(`Saved LETTER_API_KEY to ${rel(cwd, file)} (--api-key).`);\n printWarning(\n `--api-key is for CI. For interactive setup, run \\`${cliCommand()} login\\`.`,\n );\n return 0;\n }\n\n // 1. Begin the flow.\n let flow;\n try {\n flow = await startDeviceAuth(base);\n } catch (err) {\n printError(err);\n return 1;\n }\n\n log(c.bold(\"Confirm this code in your browser:\"));\n log();\n log(\" \" + c.cyan(c.bold(flow.user_code)));\n log();\n\n // 2. Open the browser (interactive: wait for Enter; otherwise auto/print).\n if (interactive && opts.open) {\n await prompt(c.dim(\"Press Enter to open your browser… \"));\n }\n if (opts.open) openUrl(flow.verification_uri_complete);\n printInfo(\"If your browser didn't open, visit:\");\n log(\" \" + c.blue(flow.verification_uri_complete));\n log();\n printInfo(\"Waiting for you to approve… (Ctrl+C to cancel)\");\n\n // 3. Poll until the user approves/denies or the code expires.\n const deadline = Date.now() + flow.expires_in * 1000;\n let intervalMs = Math.max(1, flow.interval) * 1000;\n\n while (Date.now() < deadline) {\n await sleep(intervalMs);\n let res;\n try {\n res = await pollDeviceAuth(base, flow.device_code);\n } catch (err) {\n printError(err);\n return 1;\n }\n\n if (res.status === \"authorization_pending\") continue;\n if (res.status === \"slow_down\") {\n intervalMs += 1000;\n continue;\n }\n if (res.status === \"access_denied\") {\n printError(new Error(\"Request denied in the browser. Nothing was changed.\"));\n return 1;\n }\n if (res.status === \"expired_token\") {\n printError(new Error(\"This login expired. Run the command again to retry.\"));\n return 1;\n }\n\n return finish(res, cwd, opts.install);\n }\n\n printError(new Error(\"Timed out waiting for approval. Run the command again.\"));\n return 1;\n}\n\nasync function finish(\n approved: {\n api_key: string;\n pat: string;\n base_url: string;\n project: { slug: string; name: string };\n workspace?: { id: string; name: string };\n },\n cwd: string,\n doInstall: boolean,\n): Promise<number> {\n const { api_key: apiKey, pat, base_url: baseUrl, project, workspace } = approved;\n log();\n printSuccess(`Approved for project ${c.bold(project.name)}.`);\n\n const stack = await detectStack(cwd);\n const isNode = stack.runtime === \"node\";\n const envFile = envFileFor(stack);\n\n // Write the key to the project env (value never printed) + shared store.\n const entries: Record<string, string> = { LETTER_API_KEY: apiKey };\n if (baseUrl && baseUrl !== DEFAULT_BASE_URL) entries.LETTER_BASE_URL = baseUrl;\n const written = await upsertEnv(cwd, envFile, entries);\n printSuccess(`Saved LETTER_API_KEY to ${rel(cwd, written)}.`);\n\n try {\n const credFile = await saveCredential({\n apiKey,\n pat,\n baseUrl: baseUrl || DEFAULT_BASE_URL,\n project,\n workspace,\n savedAt: new Date().toISOString(),\n });\n printSuccess(`Stored credentials in ${tildify(credFile)} for tooling (MCP + CLI).`);\n } catch {\n printWarning(\"Could not write ~/.letter/credentials.json (continuing).\");\n }\n\n // Install the SDK for the detected language. Node, Python, and Ruby have\n // official SDKs; everything else integrates over the HTTP API. We capture a\n // one-line `sdkNote` per path and hand the agent a single, language-agnostic\n // prompt - the agent knows the repo and writes idiomatic calls itself.\n let sdkNote: string;\n if (isNode) {\n const pm = await detectPackageManager(cwd);\n if (doInstall) {\n printInfo(`Installing ${SDK_PACKAGE} with ${pm}…`);\n const code = await runInstall(pm, SDK_PACKAGE, cwd);\n if (code === 0) printSuccess(`Installed ${SDK_PACKAGE}.`);\n else printWarning(`Install failed. Run: ${installCommand(pm, SDK_PACKAGE)}`);\n } else {\n printInfo(`Skipped install. Run: ${installCommand(pm, SDK_PACKAGE)}`);\n }\n sdkNote = `the ${SDK_PACKAGE} SDK is installed`;\n } else if (stack.runtime === \"python\" || stack.runtime === \"ruby\") {\n const install =\n stack.runtime === \"python\"\n ? await pythonSdkInstall(cwd)\n : await rubySdkInstall(cwd);\n await installSdk(install, doInstall);\n sdkNote =\n stack.runtime === \"python\"\n ? \"the letterapp Python SDK is installed\"\n : \"the letterapp Ruby gem is installed\";\n } else {\n printInfo(\n `Detected ${stackLabel(stack)}. No ${languageName(stack)} SDK yet, so the agent should use the HTTP API.`,\n );\n sdkNote =\n `there's no official ${languageName(stack)} SDK, so call the HTTP ingestion ` +\n \"API directly (POST /v1/identify and /v1/track with \" +\n \"Authorization: Bearer LETTER_API_KEY and Content-Type: application/json)\";\n }\n\n printAgentHandoff(sdkNote, envFile, cliCommand());\n return 0;\n}\n\n/** Shared install-or-print step for the non-Node SDKs (letterapp). */\nasync function installSdk(install: SdkInstall, doInstall: boolean): Promise<void> {\n if (doInstall) {\n printInfo(`Installing letterapp (${install.display})…`);\n const code = await runSdkInstall(install, process.cwd());\n if (code === 0) printSuccess(\"Installed letterapp.\");\n else printWarning(`Install failed. Run: ${install.display}`);\n } else {\n printInfo(`Skipped install. Run: ${install.display}`);\n }\n}\n\nconst AGENT_DOCS = \"https://letter.app/docs/agent-setup\";\n\n/**\n * Language-agnostic handoff for the last mile. The CLI does the mechanical setup\n * (key in the env, SDK installed where one exists) but deliberately does NOT\n * edit source - the coding agent has the repo context to write idiomatic calls.\n * So we print one ready-to-paste prompt that works for any stack plus a link to\n * the full guide, instead of language-specific snippets.\n */\nfunction printAgentHandoff(\n sdkNote: string,\n envFile: string,\n verifyCmd: string,\n): void {\n const rule = \" \" + \"─\".repeat(68);\n log();\n log(c.bold(\"Next: finish setup with your coding agent\"));\n log();\n log(c.dim(\" Paste this to your agent (Cursor, Claude Code, Codex, …):\"));\n log(c.dim(rule));\n // Plain (uncolored) so it copies cleanly into an agent prompt.\n log(\" Integrate Letter (product email automation) into this app. The CLI\");\n log(` already did setup: LETTER_API_KEY is in ${envFile} and ${sdkNote}.`);\n log(\" Using the right idioms for this codebase:\");\n log(\" - create a shared, server-side Letter client that reads\");\n log(\" LETTER_API_KEY from the environment (only set baseUrl/base_url\");\n log(\" when LETTER_BASE_URL is present),\");\n log(\" - call identify({ userId, email }) where users sign up or log in,\");\n log(\" - call track({ userId, event }) on the 2-3 most important actions,\");\n log(\" - flush before serverless handlers or scripts exit.\");\n log(\" Never print or commit the key. Then verify with the command below.\");\n log(` Full guide: ${AGENT_DOCS}`);\n log(c.dim(rule));\n log();\n log(c.dim(` Prefer to wire it up yourself? Same guide: ${AGENT_DOCS}`));\n log();\n log(c.dim(\"Verify it landed: \") + c.bold(`${verifyCmd} status`));\n log(\n c.dim(\n `Your API key is in ${envFile} - keep it out of source control, and don't echo its value.`,\n ),\n );\n log();\n}\n\nfunction rel(cwd: string, file: string): string {\n return file.startsWith(cwd) ? file.slice(cwd.length + 1) || file : file;\n}\n\nfunction tildify(file: string): string {\n const home = process.env.HOME || process.env.USERPROFILE;\n return home && file.startsWith(home) ? `~${file.slice(home.length)}` : file;\n}\n","import { Command } from \"commander\";\nimport { readCredential, clearCredential } from \"../config.js\";\nimport { c, cliCommand, isJsonMode, printJson, printInfo, printSuccess } from \"../output.js\";\n\nfunction mask(key: string): string {\n return key.length > 12 ? key.slice(0, 8) + \"…\" + key.slice(-4) : \"set\";\n}\n\nexport function registerAuthCommands(program: Command) {\n const auth = program.command(\"auth\").description(\"Manage the stored Letter connection\");\n\n auth\n .command(\"status\")\n .description(\"Show whether this machine is connected to Letter\")\n .action(async () => {\n const cred = await readCredential();\n const envKey = process.env.LETTER_API_KEY;\n\n if (!cred && !envKey) {\n if (isJsonMode()) printJson({ connected: false });\n else printInfo(\"Not connected. Run \" + c.bold(`${cliCommand()} login`) + \" to set up.\");\n return;\n }\n\n if (isJsonMode()) {\n printJson({\n connected: true,\n source: envKey ? \"env\" : \"credentials\",\n project: cred?.project ?? null,\n base_url: cred?.baseUrl ?? null,\n key: envKey ? \"env\" : cred ? mask(cred.apiKey) : null,\n });\n return;\n }\n\n printSuccess(\"Connected\" + (cred ? ` to ${c.bold(cred.project.name)}` : \"\"));\n if (cred) {\n console.log(c.dim(\" Project: \") + cred.project.slug);\n console.log(c.dim(\" Key: \") + mask(cred.apiKey));\n console.log(c.dim(\" API: \") + cred.baseUrl);\n }\n if (envKey) console.log(c.dim(\" LETTER_API_KEY is set in the environment.\"));\n });\n\n auth\n .command(\"logout\")\n .description(\"Remove the stored credential (~/.letter/credentials.json)\")\n .action(async () => {\n await clearCredential();\n printSuccess(\"Removed stored credential.\");\n });\n}\n","import { Command } from \"commander\";\nimport { client } from \"../client.js\";\nimport { readCredential } from \"../config.js\";\nimport { c, isJsonMode, printError, printInfo, printJson, printSuccess, spinner } from \"../output.js\";\n\ntype StatusResponse = {\n contacts?: number;\n events?: number;\n [k: string]: unknown;\n};\n\nexport function registerStatusCommand(program: Command) {\n program\n .command(\"status\")\n .description(\"Check whether your project has received any contacts or events\")\n .action(async () => {\n const spin = spinner(\"Checking your Letter project…\").start();\n try {\n const { data } = await client.get<StatusResponse>(\"/v1/status\");\n spin.stop();\n\n if (isJsonMode()) {\n printJson(data);\n return;\n }\n\n const cred = await readCredential();\n const contacts = data.contacts ?? 0;\n const events = data.events ?? 0;\n\n if (cred) printInfo(`Project ${c.bold(cred.project.name)}`);\n if (contacts > 0 || events > 0) {\n printSuccess(`Connected. ${contacts} contact(s), ${events} event(s) received.`);\n } else {\n printInfo(\"Connected, but no data yet. Fire your first identify/track call.\");\n }\n } catch (err) {\n spin.stop();\n printError(err);\n process.exitCode = 1;\n }\n });\n}\n","import { Command } from \"commander\";\nimport {\n getBaseUrl,\n setBaseUrl,\n getConfigPath,\n resetConfig,\n} from \"../config.js\";\nimport { c, isJsonMode, printError, printJson, printSuccess } from \"../output.js\";\n\nexport function registerConfigCommands(program: Command) {\n const cfg = program.command(\"config\").description(\"Manage CLI configuration\");\n\n cfg\n .command(\"set\")\n .description(\"Set a config value\")\n .argument(\"<key>\", \"Config key: base-url\")\n .argument(\"<value>\", \"Value to set\")\n .action((key: string, value: string) => {\n switch (key) {\n case \"base-url\":\n setBaseUrl(value);\n printSuccess(`Base URL set to ${getBaseUrl()}`);\n break;\n default:\n printError(new Error(`Unknown config key: ${key}. Valid keys: base-url`));\n process.exitCode = 1;\n }\n });\n\n cfg\n .command(\"get\")\n .description(\"Show CLI configuration\")\n .argument(\"[key]\", \"Config key (omit to show all)\")\n .action((key?: string) => {\n const all = { base_url: getBaseUrl(), config_path: getConfigPath() };\n if (key && key !== \"base-url\" && key !== \"path\") {\n printError(new Error(`Unknown config key: ${key}`));\n process.exitCode = 1;\n return;\n }\n if (isJsonMode()) {\n printJson(key === \"base-url\" ? { base_url: all.base_url } : key === \"path\" ? { config_path: all.config_path } : all);\n return;\n }\n if (key === \"base-url\") console.log(all.base_url);\n else if (key === \"path\") console.log(all.config_path);\n else for (const [k, v] of Object.entries(all)) console.log(c.bold(k + \":\") + \" \" + v);\n });\n\n cfg\n .command(\"reset\")\n .description(\"Reset CLI configuration to defaults\")\n .action(() => {\n resetConfig();\n printSuccess(\"Configuration reset.\");\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport { Command } from \"commander\";\nimport { mgmt } from \"../client.js\";\nimport { resolveProjectSlug } from \"../config.js\";\nimport { emit, printError, printSuccess } from \"../output.js\";\n\n/**\n * Resource command groups for the management API. Each group wraps the same\n * REST endpoints the dashboard uses (`/v1/...`), so the whole app is operable\n * from the terminal. Everything honors the global `--json` flag (see\n * `output.emit`) and project-scoped groups take `--project <slug>` (defaulting\n * to the project connected by `letter login`).\n *\n * The shape is data-driven: one `ResourceSpec` per resource, expanded into\n * `list/get/create/update/delete` + custom verb subcommands by `register()`.\n * Keeping it declarative means a new endpoint is a few lines, not a new file.\n */\n\ntype Field = {\n /** commander option flag, e.g. \"--name <name>\". */\n flag: string;\n /** request-body key, e.g. \"name\". */\n key: string;\n /** parse the value as JSON (supports `@file.json` to read from disk). */\n json?: boolean;\n /** coerce to a number. */\n number?: boolean;\n /** coerce to a boolean. */\n boolean?: boolean;\n /** (multipart only) read the value as a file path and upload its bytes. */\n file?: boolean;\n description?: string;\n};\n\ntype Action = {\n name: string;\n describe: string;\n method: \"get\" | \"post\" | \"put\" | \"patch\" | \"delete\";\n /** Path suffix appended after the resource (and id, if `needsId`). */\n suffix: string;\n /** Whether the verb operates on a single item (default true). */\n needsId?: boolean;\n fields?: Field[];\n /** Query params for GET verbs. */\n query?: Field[];\n /** Send fields as multipart/form-data (for file uploads). */\n multipart?: boolean;\n};\n\ntype ResourceSpec = {\n /** Command group name (also the default path segment). */\n name: string;\n describe: string;\n /** Nested under /v1/projects/{slug} when true. */\n scoped: boolean;\n /** Path segment if different from `name`. */\n segment?: string;\n /** Hidden back-compat alias for the group name. */\n alias?: string;\n /** Positional id arg name (e.g. \"externalId\", \"email\"). Default \"id\". */\n idName?: string;\n list?: { paginated?: boolean; query?: Field[] };\n get?: boolean;\n create?: Field[];\n update?: Field[];\n remove?: boolean;\n actions?: Action[];\n};\n\nasync function readValue(raw: string): Promise<string> {\n if (raw.startsWith(\"@\")) return (await readFile(raw.slice(1), \"utf8\")).trim();\n return raw;\n}\n\nasync function buildBody(\n fields: Field[],\n opts: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const body: Record<string, unknown> = {};\n for (const f of fields) {\n const v = opts[camel(f.key)];\n if (v === undefined) continue;\n if (f.json) {\n body[f.key] = JSON.parse(await readValue(String(v)));\n } else if (f.number) {\n body[f.key] = Number(v);\n } else if (f.boolean) {\n body[f.key] = v === true || v === \"true\";\n } else {\n body[f.key] = await readValue(String(v));\n }\n }\n return body;\n}\n\nasync function buildForm(\n fields: Field[],\n opts: Record<string, unknown>,\n): Promise<FormData> {\n const form = new FormData();\n for (const f of fields) {\n const v = opts[camel(f.key)];\n if (v === undefined) continue;\n if (f.file) {\n const path = String(v);\n const bytes = await readFile(path);\n const name = path.split(\"/\").pop() || f.key;\n form.append(f.key, new Blob([new Uint8Array(bytes)]), name);\n } else if (f.json) {\n // The server parses these fields with JSON.parse; keep them as strings.\n form.append(f.key, await readValue(String(v)));\n } else {\n form.append(f.key, String(v));\n }\n }\n return form;\n}\n\nfunction buildQuery(\n fields: Field[],\n opts: Record<string, unknown>,\n): Record<string, string | number | undefined> {\n const q: Record<string, string | number | undefined> = {};\n for (const f of fields) {\n const v = opts[camel(f.key)];\n if (v === undefined) continue;\n q[f.key] = f.number ? Number(v) : String(v);\n }\n return q;\n}\n\n/** \"external-id\" / \"external_id\" → \"externalId\" (commander camelCases flags). */\nfunction camel(key: string): string {\n return key.replace(/[-_]([a-z])/g, (_, ch: string) => ch.toUpperCase());\n}\n\nfunction applyFields(cmd: Command, fields: Field[]) {\n for (const f of fields) {\n cmd.option(f.flag, f.description ?? f.key);\n }\n}\n\nasync function basePath(spec: ResourceSpec, project?: string): Promise<string> {\n const seg = spec.segment ?? spec.name;\n if (!spec.scoped) return `/v1/${seg}`;\n const slug = await resolveProjectSlug(project);\n return `/v1/projects/${slug}/${seg}`;\n}\n\nfunction withProject(cmd: Command, scoped: boolean): Command {\n if (scoped) {\n cmd.option(\"-p, --project <slug>\", \"Project slug (default: connected project)\");\n }\n return cmd;\n}\n\nfunction fail(err: unknown) {\n printError(err);\n process.exitCode = 1;\n}\n\nfunction register(program: Command, spec: ResourceSpec) {\n const group = program.command(spec.name).description(spec.describe);\n if (spec.alias) group.alias(spec.alias);\n const idName = spec.idName ?? \"id\";\n\n if (spec.list) {\n const cmd = withProject(\n group.command(\"list\").description(`List ${spec.name}`),\n spec.scoped,\n );\n if (spec.list.paginated) {\n cmd.option(\"--limit <n>\", \"Max items (1-100)\");\n cmd.option(\"--cursor <cursor>\", \"Pagination cursor\");\n }\n if (spec.list.query) applyFields(cmd, spec.list.query);\n cmd.action(async (opts) => {\n try {\n const query: Record<string, string | number | undefined> = {};\n if (spec.list?.paginated) {\n if (opts.limit) query.limit = Number(opts.limit);\n if (opts.cursor) query.cursor = opts.cursor;\n }\n if (spec.list?.query) Object.assign(query, buildQuery(spec.list.query, opts));\n const { data } = await mgmt.get(await basePath(spec, opts.project), query);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.get) {\n const cmd = withProject(\n group\n .command(\"get\")\n .description(`Get a ${spec.name} by ${idName}`)\n .argument(`<${idName}>`, idName),\n spec.scoped,\n );\n cmd.action(async (idValue: string, opts) => {\n try {\n const path = `${await basePath(spec, opts.project)}/${encodeURIComponent(idValue)}`;\n const { data } = await mgmt.get(path);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.create) {\n const cmd = withProject(\n group.command(\"create\").description(`Create a ${spec.name}`),\n spec.scoped,\n );\n applyFields(cmd, spec.create);\n cmd.action(async (opts) => {\n try {\n const body = await buildBody(spec.create!, opts);\n const { data } = await mgmt.post(await basePath(spec, opts.project), body);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.update) {\n const cmd = withProject(\n group\n .command(\"update\")\n .description(`Update a ${spec.name}`)\n .argument(`<${idName}>`, idName),\n spec.scoped,\n );\n applyFields(cmd, spec.update);\n cmd.action(async (idValue: string, opts) => {\n try {\n const body = await buildBody(spec.update!, opts);\n const path = `${await basePath(spec, opts.project)}/${encodeURIComponent(idValue)}`;\n const { data } = await mgmt.patch(path, body);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.remove) {\n const cmd = withProject(\n group\n .command(\"delete\")\n .description(`Delete a ${spec.name}`)\n .argument(`<${idName}>`, idName),\n spec.scoped,\n );\n cmd.action(async (idValue: string, opts) => {\n try {\n const path = `${await basePath(spec, opts.project)}/${encodeURIComponent(idValue)}`;\n await mgmt.delete(path);\n printSuccess(`Deleted ${spec.name.replace(/s$/, \"\")} ${idValue}.`);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n for (const action of spec.actions ?? []) {\n const needsId = action.needsId ?? true;\n const cmd = withProject(\n needsId\n ? group\n .command(action.name)\n .description(action.describe)\n .argument(`<${idName}>`, idName)\n : group.command(action.name).description(action.describe),\n spec.scoped,\n );\n if (action.fields) applyFields(cmd, action.fields);\n if (action.query) applyFields(cmd, action.query);\n\n const handler = async (...args: unknown[]) => {\n // commander passes (idValue?, opts, command). Last arg is the Command.\n const opts = args[args.length - 2] as Record<string, unknown>;\n const idValue = needsId ? (args[0] as string) : undefined;\n try {\n let path = await basePath(spec, opts.project as string | undefined);\n if (needsId) path += `/${encodeURIComponent(idValue!)}`;\n path += action.suffix;\n\n if (action.method === \"get\") {\n const query = action.query ? buildQuery(action.query, opts) : undefined;\n const { data } = await mgmt.get(path, query);\n emit(data);\n return;\n }\n if (action.multipart && action.fields) {\n const form = await buildForm(action.fields, opts);\n const { data, status } = await mgmt.request(\n action.method.toUpperCase(),\n path,\n { form },\n );\n if (status === 204) printSuccess(`${action.name} ok.`);\n else emit(data);\n return;\n }\n const body = action.fields ? await buildBody(action.fields, opts) : undefined;\n const { data, status } = await mgmt.request(\n action.method.toUpperCase(),\n path,\n { body },\n );\n if (status === 204) printSuccess(`${action.name} ok.`);\n else emit(data);\n } catch (err) {\n fail(err);\n }\n };\n cmd.action(handler);\n }\n}\n\nconst cursor = { paginated: true } as const;\n\nconst SPECS: ResourceSpec[] = [\n // -- Workspace ------------------------------------------------------------\n {\n name: \"projects\",\n describe: \"Manage projects\",\n scoped: false,\n idName: \"slug\",\n list: {},\n get: true,\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--timezone <tz>\", key: \"timezone\" },\n ],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--timezone <tz>\", key: \"timezone\" },\n ],\n remove: true,\n },\n {\n name: \"members\",\n describe: \"Manage workspace members\",\n scoped: false,\n idName: \"userId\",\n list: {},\n create: [\n { flag: \"--email <email>\", key: \"email\" },\n { flag: \"--role <role>\", key: \"role\", description: \"member | admin\" },\n ],\n remove: true,\n },\n {\n name: \"invitations\",\n describe: \"Manage workspace invitations\",\n scoped: false,\n list: {},\n create: [\n { flag: \"--email <email>\", key: \"email\" },\n { flag: \"--role <role>\", key: \"role\", description: \"member | admin\" },\n ],\n remove: true,\n },\n {\n // Personal access tokens (lt_pat_*) authenticate the CLI / Management API.\n // The dashboard calls these \"API keys\"; `tokens` stays as a hidden alias.\n name: \"api-keys\",\n alias: \"tokens\",\n segment: \"tokens\",\n describe: \"Manage your personal access tokens (lt_pat_*, the CLI/API credential)\",\n scoped: false,\n list: {},\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n {\n flag: \"--expires-at <iso>\",\n key: \"expires_at\",\n description: \"Expiry as an ISO 8601 datetime (default: never)\",\n },\n ],\n remove: true,\n },\n // -- Contacts & data ------------------------------------------------------\n {\n name: \"contacts\",\n describe: \"Manage contacts\",\n scoped: true,\n idName: \"externalId\",\n list: { ...cursor },\n get: true,\n actions: [\n {\n name: \"suppress\",\n describe: \"Suppress a contact\",\n method: \"post\",\n suffix: \"/suppress\",\n },\n {\n name: \"resubscribe\",\n describe: \"Resubscribe a contact\",\n method: \"post\",\n suffix: \"/resubscribe\",\n },\n {\n name: \"import\",\n describe: \"Upload a CSV import (--file <path> --mapping <json|@file>)\",\n method: \"post\",\n needsId: false,\n suffix: \"/imports\",\n multipart: true,\n fields: [\n { flag: \"--file <path>\", key: \"file\", file: true },\n { flag: \"--mapping <json>\", key: \"mapping\", json: true },\n { flag: \"--dedupe <strategy>\", key: \"dedupe\", description: \"update | skip\" },\n { flag: \"--row-count <n>\", key: \"rowCount\" },\n ],\n },\n ],\n },\n {\n name: \"accounts\",\n describe: \"Inspect accounts\",\n scoped: true,\n idName: \"externalId\",\n list: { ...cursor },\n get: true,\n },\n {\n name: \"events\",\n describe: \"List events\",\n scoped: true,\n list: { ...cursor, query: [{ flag: \"--name <name>\", key: \"name\" }] },\n },\n {\n name: \"suppressions\",\n describe: \"Manage the suppression list\",\n scoped: true,\n idName: \"email\",\n list: { ...cursor },\n create: [{ flag: \"--email <email>\", key: \"email\" }],\n remove: true,\n },\n {\n name: \"segments\",\n describe: \"Manage segments\",\n scoped: true,\n list: {},\n get: true,\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--filter <json>\", key: \"filter\", json: true },\n ],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--filter <json>\", key: \"filter\", json: true },\n ],\n remove: true,\n actions: [\n {\n name: \"preview\",\n describe: \"Count contacts matching a filter (--filter <json|@file>)\",\n method: \"post\",\n needsId: false,\n suffix: \"/preview\",\n fields: [{ flag: \"--filter <json>\", key: \"filter\", json: true }],\n },\n ],\n },\n // -- Sequences ------------------------------------------------------------\n {\n name: \"sequences\",\n describe: \"Manage drip sequences\",\n scoped: true,\n list: {},\n get: true,\n create: [{ flag: \"--name <name>\", key: \"name\" }],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--status <status>\", key: \"status\", description: \"active | archived\" },\n ],\n remove: true,\n actions: [\n {\n name: \"draft\",\n describe: \"Save the draft graph + trigger\",\n method: \"put\",\n suffix: \"/draft\",\n fields: [\n { flag: \"--graph <json>\", key: \"graph\", json: true },\n { flag: \"--trigger <json>\", key: \"trigger\", json: true },\n { flag: \"--expected-revision <n>\", key: \"expected_revision\", number: true },\n ],\n },\n {\n name: \"publish\",\n describe: \"Publish the current draft\",\n method: \"post\",\n suffix: \"/publish\",\n },\n {\n name: \"preview\",\n describe: \"Render an email node (--node-id <id>)\",\n method: \"post\",\n suffix: \"/preview\",\n fields: [{ flag: \"--node-id <id>\", key: \"nodeId\" }],\n },\n {\n name: \"test-email\",\n describe: \"Send a test email (--node-id <id> --to <email>)\",\n method: \"post\",\n suffix: \"/test-email\",\n fields: [\n { flag: \"--node-id <id>\", key: \"nodeId\" },\n { flag: \"--to <email>\", key: \"to\" },\n ],\n },\n {\n name: \"activity\",\n describe: \"Show enrollment activity\",\n method: \"get\",\n suffix: \"/activity\",\n },\n {\n name: \"versions\",\n describe: \"List published versions\",\n method: \"get\",\n suffix: \"/versions\",\n },\n ],\n },\n // -- Broadcasts -----------------------------------------------------------\n {\n name: \"broadcasts\",\n describe: \"Manage broadcasts\",\n scoped: true,\n list: {},\n get: true,\n create: [{ flag: \"--name <name>\", key: \"name\" }],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--subject <subject>\", key: \"subject\" },\n { flag: \"--preview <preview>\", key: \"preview\" },\n { flag: \"--audience <json>\", key: \"audience\", json: true },\n { flag: \"--template-id <id>\", key: \"template_id\" },\n { flag: \"--body-doc <json>\", key: \"body_doc\", json: true },\n ],\n remove: true,\n actions: [\n {\n name: \"preflight\",\n describe: \"Validate before sending\",\n method: \"post\",\n suffix: \"/preflight\",\n },\n {\n name: \"schedule\",\n describe: \"Schedule (--scheduled-at <iso>) or send now (omit)\",\n method: \"post\",\n suffix: \"/schedule\",\n fields: [{ flag: \"--scheduled-at <iso>\", key: \"scheduled_at\" }],\n },\n {\n name: \"cancel\",\n describe: \"Cancel a scheduled or sending broadcast\",\n method: \"post\",\n suffix: \"/cancel\",\n },\n {\n name: \"live\",\n describe: \"Live status, stats, and recent activity\",\n method: \"get\",\n suffix: \"/live\",\n },\n ],\n },\n // -- Templates ------------------------------------------------------------\n {\n name: \"templates\",\n describe: \"Manage email templates\",\n scoped: true,\n list: {},\n get: true,\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--design <json>\", key: \"design\", json: true },\n ],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--design <json>\", key: \"design\", json: true },\n ],\n remove: true,\n actions: [\n {\n name: \"default\",\n describe: \"Set as the project default\",\n method: \"post\",\n suffix: \"/default\",\n },\n {\n name: \"reset\",\n describe: \"Reset design to a preset (--preset plain|branded)\",\n method: \"post\",\n suffix: \"/reset\",\n fields: [{ flag: \"--preset <preset>\", key: \"preset\" }],\n },\n {\n name: \"logo\",\n describe: \"Upload a logo (--file <path>)\",\n method: \"post\",\n suffix: \"/logo\",\n multipart: true,\n fields: [{ flag: \"--file <path>\", key: \"file\", file: true }],\n },\n {\n name: \"remove-logo\",\n describe: \"Remove the template logo\",\n method: \"delete\",\n suffix: \"/logo\",\n },\n ],\n },\n // -- Settings -------------------------------------------------------------\n {\n name: \"domains\",\n describe: \"Manage sending domains\",\n scoped: true,\n list: {},\n create: [{ flag: \"--domain <domain>\", key: \"domain\" }],\n remove: true,\n actions: [\n {\n name: \"verify\",\n describe: \"Re-check DKIM verification\",\n method: \"post\",\n suffix: \"/verify\",\n },\n ],\n },\n {\n // Project ingestion keys (lt_live_*) authenticate the SDKs / ingestion API.\n // The dashboard calls these \"Project tokens\"; `keys` stays as a hidden alias.\n name: \"project-tokens\",\n alias: \"keys\",\n segment: \"keys\",\n describe: \"Manage project ingestion keys (lt_live_*, the SDK/ingestion credential)\",\n scoped: true,\n list: {},\n create: [{ flag: \"--name <name>\", key: \"name\" }],\n remove: true,\n },\n];\n\nexport function registerResourceCommands(program: Command) {\n for (const spec of SPECS) register(program, spec);\n\n // `letter me` — the token's identity (handy sanity check).\n program\n .command(\"me\")\n .description(\"Show the token's user, workspace, and role\")\n .action(async () => {\n try {\n const { data } = await mgmt.get(\"/v1/me\");\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n\n // Sender identity + sending mode don't fit the CRUD mold: register directly.\n program\n .command(\"sender-identity\")\n .description(\"Set From / From-name / Reply-To (--from-email, --from-name, --reply-to-email)\")\n .option(\"-p, --project <slug>\", \"Project slug (default: connected project)\")\n .option(\"--from-email <email>\", \"From address\")\n .option(\"--from-name <name>\", \"From display name\")\n .option(\"--reply-to-email <email>\", \"Reply-To address\")\n .action(async (opts) => {\n try {\n const slug = await resolveProjectSlug(opts.project);\n const body: Record<string, unknown> = {};\n if (opts.fromEmail !== undefined) body.from_email = opts.fromEmail;\n if (opts.fromName !== undefined) body.from_name = opts.fromName;\n if (opts.replyToEmail !== undefined) body.reply_to_email = opts.replyToEmail;\n const { data } = await mgmt.put(`/v1/projects/${slug}/sender-identity`, body);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"sending-mode\")\n .description(\"Set the sending mode (letter_subdomain | byo_domain)\")\n .argument(\"<mode>\", \"letter_subdomain | byo_domain\")\n .option(\"-p, --project <slug>\", \"Project slug (default: connected project)\")\n .action(async (mode: string, opts) => {\n try {\n const slug = await resolveProjectSlug(opts.project);\n const { data } = await mgmt.put(`/v1/projects/${slug}/sending-mode`, {\n sending_mode: mode,\n });\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n}\n"],"mappings":";;;AACA,SAAS,eAAe;;;ACDxB,OAAO,WAAW;AAClB,OAAO,SAAuB;AAC9B,SAAS,uBAAuB;AAEhC,IAAI,WAAW;AAER,SAAS,YAAY,SAAkB;AAC5C,aAAW;AACb;AACO,SAAS,aAAa;AAC3B,SAAO;AACT;AAEO,SAAS,UAAU,MAAe;AACvC,UAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAC3C;AAQO,SAAS,aAAqB;AACnC,UAAQ,QAAQ,KAAK,CAAC,KAAK,IAAI,SAAS,MAAM,IAAI,uBAAuB;AAC3E;AAEO,SAAS,IAAI,MAAM,IAAI;AAC5B,MAAI,SAAU;AACd,UAAQ,IAAI,GAAG;AACjB;AAEO,SAAS,aAAa,KAAa;AACxC,MAAI,SAAU;AACd,UAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,MAAM,GAAG;AAC1C;AAEO,SAAS,UAAU,KAAa;AACrC,MAAI,SAAU;AACd,UAAQ,IAAI,MAAM,KAAK,QAAG,IAAI,MAAM,GAAG;AACzC;AAEO,SAAS,aAAa,KAAa;AACxC,MAAI,SAAU;AACd,UAAQ,IAAI,MAAM,OAAO,GAAG,IAAI,MAAM,GAAG;AAC3C;AAEO,SAAS,WAAW,KAAc;AACvC,QAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,MAAI,UAAU;AACZ,cAAU,EAAE,OAAO,IAAI,CAAC;AACxB;AAAA,EACF;AACA,UAAQ,MAAM,MAAM,IAAI,QAAG,IAAI,MAAM,GAAG;AAC1C;AAGO,SAAS,SAAS;AACvB,MAAI,SAAU;AACd,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,MAAM,IAAI,KAAK,CAAC;AACjF,UAAQ,IAAI,EAAE;AAChB;AAEO,SAAS,QAAQ,MAAmB;AACzC,SAAO,IAAI,EAAE,MAAM,OAAO,QAAQ,WAAW,CAAC,SAAS,CAAC;AAC1D;AAMO,SAAS,OAAO,UAAmC;AACxD,MAAI,CAAC,QAAQ,MAAM,MAAO,QAAO,QAAQ,QAAQ,EAAE;AACnD,QAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,OAAG,SAAS,UAAU,CAAC,WAAW;AAChC,SAAG,MAAM;AACT,cAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AACH;AAOO,SAAS,KAAK,MAAe;AAClC,MAAI,UAAU;AACZ,cAAU,IAAI;AACd;AAAA,EACF;AACA,MAAI,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAS,KAA4B,IAAI,GAAG;AACxF,UAAM,MAAM;AACZ,QAAI,IAAI,KAAK,WAAW,GAAG;AACzB,cAAQ,IAAI,MAAM,IAAI,QAAQ,CAAC;AAAA,IACjC,OAAO;AACL,iBAAW,OAAO,IAAI,MAAM;AAC1B,cAAM,KAAK,OAAO,IAAI,MAAM,IAAI,QAAQ,IAAI,eAAe,EAAE;AAC7D,cAAM,QACH,IAAI,QACJ,IAAI,SACJ,IAAI,UACJ,IAAI,WACL;AACF,gBAAQ,IAAI,GAAG,MAAM,KAAK,EAAE,CAAC,GAAG,QAAQ,OAAO,QAAQ,EAAE,EAAE;AAAA,MAC7D;AAAA,IACF;AACA,QAAI,IAAI,aAAa;AACnB,cAAQ,IAAI,MAAM,IAAI;AAAA,wBAAsB,IAAI,WAAW,EAAE,CAAC;AAAA,IAChE;AACA;AAAA,EACF;AACA,YAAU,IAAI;AAChB;AAEO,IAAM,IAAI;;;ACrHjB,OAAO,UAAU;AACjB,SAAS,eAAe;AACxB,OAAO,UAAU;AACjB,SAAS,OAAO,UAAU,WAAW,UAAU;AAKxC,IAAM,mBAAmB;AAOhC,IAAM,SAAS,IAAI,KAAK;AAAA,EACtB,aAAa;AAAA,EACb,QAAQ;AAAA,IACN,SAAS,EAAE,MAAM,UAAU,SAAS,iBAAiB;AAAA,EACvD;AACF,CAAC;AAGM,SAAS,WAAW,MAAuB;AAChD,QAAM,MACJ,QACA,QAAQ,IAAI,mBACX,OAAO,IAAI,SAAS,KACrB;AACF,SAAO,IAAI,QAAQ,OAAO,EAAE;AAC9B;AAEO,SAAS,WAAW,KAAmB;AAC5C,SAAO,IAAI,WAAW,IAAI,QAAQ,OAAO,EAAE,CAAC;AAC9C;AAEO,SAAS,gBAAwB;AACtC,SAAO,OAAO;AAChB;AAEO,SAAS,cAAoB;AAClC,SAAO,MAAM;AACf;AAwBA,eAAsB,mBAAmB,MAAgC;AACvE,MAAI,KAAM,QAAO;AACjB,MAAI,QAAQ,IAAI,eAAgB,QAAO,QAAQ,IAAI;AACnD,QAAM,OAAO,MAAM,eAAe;AAClC,MAAI,MAAM,SAAS,KAAM,QAAO,KAAK,QAAQ;AAC7C,QAAM,IAAI;AAAA,IACR,mEAAmE,WAAW,CAAC;AAAA,EACjF;AACF;AAEO,SAAS,kBAA0B;AACxC,SAAO,KAAK,KAAK,QAAQ,GAAG,WAAW,kBAAkB;AAC3D;AAEA,eAAsB,eAAe,MAAyC;AAC5E,QAAM,OAAO,gBAAgB;AAC7B,QAAM,MAAM,KAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAChE,QAAM,UAAU,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AAC3E,SAAO;AACT;AAEA,eAAsB,iBAAmD;AACvE,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,gBAAgB,GAAG,MAAM;AACpD,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,kBAAiC;AACrD,QAAM,GAAG,gBAAgB,GAAG,EAAE,OAAO,KAAK,CAAC;AAC7C;;;AC/FA,IAAM,aAAa;AA+BnB,eAAsB,gBAAgB,MAAsC;AAC1E,QAAM,MAAM,MAAM,MAAM,GAAG,IAAI,sBAAsB;AAAA,IACnD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,cAAc,WAAW;AAAA,IACxE,MAAM;AAAA,EACR,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI;AAAA,MACR,+BAA+B,IAAI,MAAM,SAAS,IAAI;AAAA,IACxD;AAAA,EACF;AACA,SAAQ,MAAM,IAAI,KAAK;AACzB;AAGA,eAAsB,eACpB,MACA,YACuB;AACvB,QAAM,MAAM,MAAM,MAAM,GAAG,IAAI,qBAAqB;AAAA,IAClD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oBAAoB,cAAc,WAAW;AAAA,IACxE,MAAM,KAAK,UAAU,EAAE,aAAa,WAAW,CAAC;AAAA,EAClD,CAAC;AAED,MAAI,IAAI,WAAW,KAAK;AACtB,UAAM,aAAa,OAAO,IAAI,QAAQ,IAAI,aAAa,KAAK,GAAG;AAC/D,WAAO,EAAE,QAAQ,aAAa,WAAW;AAAA,EAC3C;AACA,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,2BAA2B,IAAI,MAAM,IAAI;AAAA,EAC3D;AACA,SAAQ,MAAM,IAAI,KAAK;AACzB;AAYA,IAAM,eAAN,MAAmB;AAAA,EACT,aAAa;AAAA,EAErB,MAAc,cAAwD;AACpE,UAAM,OAAO,MAAM,eAAe;AAClC,UAAM,QAAQ,QAAQ,IAAI,kBAAkB,MAAM,UAAU;AAC5D,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,wBAAwB,WAAW,CAAC;AAAA,MACtC;AAAA,IACF;AACA,UAAM,OAAO,WAAW,QAAQ,IAAI,iBAAiB,SAAY,MAAM,OAAO;AAC9E,WAAO,EAAE,MAAM,MAAM;AAAA,EACvB;AAAA,EAEA,MAAc,QACZ,QACAA,OACA,UAAU,GACe;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,YAAY;AAC/C,UAAM,MAAM,MAAM,MAAM,GAAG,IAAI,GAAGA,KAAI,IAAI;AAAA,MACxC;AAAA,MACA,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,QAC9B,QAAQ;AAAA,QACR,cAAc;AAAA,MAChB;AAAA,IACF,CAAC;AAED,QAAI,IAAI,WAAW,OAAO,WAAW,KAAK,YAAY;AACpD,YAAM,aAAa,OAAO,IAAI,QAAQ,IAAI,aAAa,KAAK,CAAC;AAC7D,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,aAAa,MAAO,OAAO,CAAC;AACnE,aAAO,KAAK,QAAW,QAAQA,OAAM,UAAU,CAAC;AAAA,IAClD;AAEA,UAAM,OAAQ,IAAI,WAAW,MAAM,CAAC,IAAI,MAAM,IAAI,KAAK;AACvD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,MACH,MAA2C,OAAO,WACnD,QAAQ,IAAI,MAAM;AACpB,YAAM,MAAM,IAAI,MAAM,GAAG;AACzB,UAAI,SAAS,IAAI;AACjB,YAAM;AAAA,IACR;AACA,WAAO,EAAE,QAAQ,IAAI,QAAQ,KAAK;AAAA,EACpC;AAAA,EAEA,IAAiBA,OAAc;AAC7B,WAAO,KAAK,QAAW,OAAOA,KAAI;AAAA,EACpC;AACF;AAEO,IAAM,SAAS,IAAI,aAAa;AAcvC,IAAM,mBAAN,MAAuB;AAAA,EACb,aAAa;AAAA,EAErB,MAAc,cAAwD;AACpE,UAAM,OAAO,MAAM,eAAe;AAClC,UAAM,QAAQ,QAAQ,IAAI,cAAc,MAAM,OAAO;AACrD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,uCAAuC,WAAW,CAAC;AAAA,MACrD;AAAA,IACF;AACA,UAAM,OAAO,WAAW,QAAQ,IAAI,aAAa,SAAY,MAAM,OAAO;AAC1E,WAAO,EAAE,MAAM,MAAM;AAAA,EACvB;AAAA,EAEA,MAAM,QACJ,QACAA,OACA,OAAwB,CAAC,GACzB,UAAU,GACe;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,YAAY;AAE/C,QAAI,MAAM,GAAG,IAAI,GAAGA,KAAI;AACxB,QAAI,KAAK,OAAO;AACd,YAAM,KAAK,IAAI,gBAAgB;AAC/B,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,KAAK,GAAG;AAC/C,YAAI,MAAM,UAAa,MAAM,GAAI,IAAG,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,MACtD;AACA,YAAM,IAAI,GAAG,SAAS;AACtB,UAAI,EAAG,QAAO,IAAI,CAAC;AAAA,IACrB;AAEA,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,KAAK;AAAA,MAC9B,QAAQ;AAAA,MACR,cAAc;AAAA,IAChB;AACA,QAAI;AACJ,QAAI,KAAK,MAAM;AACb,aAAO,KAAK;AAAA,IACd,WAAW,KAAK,SAAS,QAAW;AAClC,cAAQ,cAAc,IAAI;AAC1B,aAAO,KAAK,UAAU,KAAK,IAAI;AAAA,IACjC;AAEA,UAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,SAAS,KAAK,CAAC;AAEtD,QAAI,IAAI,WAAW,OAAO,WAAW,KAAK,YAAY;AACpD,YAAM,aAAa,OAAO,IAAI,QAAQ,IAAI,aAAa,KAAK,CAAC;AAC7D,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,aAAa,MAAO,OAAO,CAAC;AACnE,aAAO,KAAK,QAAW,QAAQA,OAAM,MAAM,UAAU,CAAC;AAAA,IACxD;AAEA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAM,OAAQ,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC;AACzC,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,MACH,MAA2C,OAAO,WACnD,QAAQ,IAAI,MAAM;AACpB,YAAM,MAAM,IAAI,MAAM,GAAG;AACzB,UAAI,SAAS,IAAI;AACjB,YAAM;AAAA,IACR;AACA,WAAO,EAAE,QAAQ,IAAI,QAAQ,KAAK;AAAA,EACpC;AAAA,EAEA,IAAiBA,OAAc,OAAkC;AAC/D,WAAO,KAAK,QAAW,OAAOA,OAAM,EAAE,MAAM,CAAC;AAAA,EAC/C;AAAA,EACA,KAAkBA,OAAc,MAAgB;AAC9C,WAAO,KAAK,QAAW,QAAQA,OAAM,EAAE,KAAK,CAAC;AAAA,EAC/C;AAAA,EACA,SAAsBA,OAAc,MAAgB;AAClD,WAAO,KAAK,QAAW,QAAQA,OAAM,EAAE,KAAK,CAAC;AAAA,EAC/C;AAAA,EACA,MAAmBA,OAAc,MAAgB;AAC/C,WAAO,KAAK,QAAW,SAASA,OAAM,EAAE,KAAK,CAAC;AAAA,EAChD;AAAA,EACA,IAAiBA,OAAc,MAAgB;AAC7C,WAAO,KAAK,QAAW,OAAOA,OAAM,EAAE,KAAK,CAAC;AAAA,EAC9C;AAAA,EACA,OAAoBA,OAAc;AAChC,WAAO,KAAK,QAAW,UAAUA,KAAI;AAAA,EACvC;AACF;AAEO,IAAM,OAAO,IAAI,iBAAiB;;;ACzOzC,SAAS,aAAa;AAOf,SAAS,QAAQ,KAAsB;AAC5C,QAAM,WAAW,QAAQ;AACzB,MAAI;AACJ,MAAI;AAEJ,MAAI,aAAa,UAAU;AACzB,cAAU;AACV,WAAO,CAAC,GAAG;AAAA,EACb,WAAW,aAAa,SAAS;AAC/B,cAAU;AAEV,WAAO,CAAC,MAAM,SAAS,IAAI,GAAG;AAAA,EAChC,OAAO;AACL,cAAU;AACV,WAAO,CAAC,GAAG;AAAA,EACb;AAEA,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,MAAM,EAAE,OAAO,UAAU,UAAU,KAAK,CAAC;AACtE,UAAM,GAAG,SAAS,MAAM;AAAA,IAAC,CAAC;AAC1B,UAAM,MAAM;AACZ,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AChCA,OAAOC,WAAU;AACjB,SAAS,YAAAC,WAAU,aAAAC,YAAW,YAAY;AAO1C,eAAsB,UACpB,KACA,MACA,SACiB;AACjB,QAAM,WAAWF,MAAK,KAAK,KAAK,IAAI;AACpC,MAAI,WAAW;AACf,MAAI;AACF,eAAW,MAAMC,UAAS,UAAU,MAAM;AAAA,EAC5C,QAAQ;AACN,eAAW;AAAA,EACb;AAEA,MAAI,OAAO;AACX,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAM,OAAO,GAAG,GAAG,IAAI,KAAK;AAC5B,UAAM,KAAK,IAAI,OAAO,IAAI,aAAa,GAAG,CAAC,QAAQ,GAAG;AACtD,QAAI,GAAG,KAAK,IAAI,GAAG;AACjB,aAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,IAC9B,OAAO;AACL,UAAI,KAAK,UAAU,CAAC,KAAK,SAAS,IAAI,EAAG,SAAQ;AACjD,cAAQ,GAAG,IAAI;AAAA;AAAA,IACjB;AAAA,EACF;AAEA,QAAMC,WAAU,UAAU,MAAM,MAAM;AACtC,SAAO;AACT;AAGA,eAAsB,WAAW,KAAa,MAAgC;AAC5E,MAAI;AACF,UAAM,KAAKF,MAAK,KAAK,KAAK,IAAI,CAAC;AAC/B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,GAAmB;AACvC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;;;ACjDA,SAAS,SAAAG,cAAa;AACtB,SAAS,YAAAC,WAAU,eAAe;AASlC,eAAsB,qBACpB,KACyB;AACzB,MAAI,MAAM,WAAW,KAAK,gBAAgB,EAAG,QAAO;AACpD,MAAI,MAAM,WAAW,KAAK,WAAW,EAAG,QAAO;AAC/C,MAAI,MAAM,WAAW,KAAK,WAAW,EAAG,QAAO;AAC/C,MAAI,MAAM,WAAW,KAAK,mBAAmB,EAAG,QAAO;AAEvD,QAAM,KAAK,QAAQ,IAAI,yBAAyB;AAChD,MAAI,GAAG,WAAW,MAAM,EAAG,QAAO;AAClC,MAAI,GAAG,WAAW,MAAM,EAAG,QAAO;AAClC,MAAI,GAAG,WAAW,KAAK,EAAG,QAAO;AACjC,SAAO;AACT;AAGA,eAAsB,gBAAgB,KAAqC;AACzE,MAAI;AACF,UAAM,MAAM,KAAK,MAAM,MAAMC,UAAS,GAAG,GAAG,iBAAiB,MAAM,CAAC;AAIpE,UAAM,OAAO,EAAE,GAAG,IAAI,cAAc,GAAG,IAAI,gBAAgB;AAC3D,QAAI,KAAK,KAAM,QAAO;AACtB,QAAI,KAAK,KAAM,QAAO;AACtB,QAAI,KAAK,iBAAiB,KAAK,KAAK,kBAAkB,EAAG,QAAO;AAChE,QAAI,KAAK,QAAS,QAAO;AACzB,QAAI,KAAK,QAAS,QAAO;AACzB,QAAI,KAAK,KAAM,QAAO;AACtB,QAAI,KAAK,eAAe,EAAG,QAAO;AAClC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUA,eAAsB,YAAY,KAA6B;AAC7D,MAAI,MAAM,WAAW,KAAK,cAAc,GAAG;AACzC,WAAO,EAAE,SAAS,QAAQ,WAAW,MAAM,gBAAgB,GAAG,EAAE;AAAA,EAClE;AACA,MACG,MAAM,WAAW,KAAK,gBAAgB,KACtC,MAAM,WAAW,KAAK,kBAAkB,KACxC,MAAM,WAAW,KAAK,SAAS,KAC/B,MAAM,WAAW,KAAK,UAAU,GACjC;AACA,WAAO,EAAE,SAAS,UAAU,WAAW,MAAM,sBAAsB,GAAG,EAAE;AAAA,EAC1E;AACA,MAAK,MAAM,WAAW,KAAK,SAAS,KAAO,MAAM,WAAW,GAAG,GAAI;AACjE,WAAO,EAAE,SAAS,QAAQ,WAAW,MAAM,oBAAoB,GAAG,EAAE;AAAA,EACtE;AACA,MAAI,MAAM,WAAW,KAAK,QAAQ,EAAG,QAAO,EAAE,SAAS,MAAM,WAAW,KAAK;AAC7E,MAAI,MAAM,WAAW,KAAK,eAAe,GAAG;AAC1C,WAAO,EAAE,SAAS,OAAO,WAAW,MAAM,mBAAmB,GAAG,EAAE;AAAA,EACpE;AACA,SAAO,EAAE,SAAS,SAAS,WAAW,KAAK;AAC7C;AAGO,SAAS,WAAW,OAAsB;AAC/C,MAAI,MAAM,UAAW,QAAO,MAAM;AAClC,UAAQ,MAAM,SAAS;AAAA,IACrB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAGO,SAAS,aAAa,OAAsB;AACjD,UAAQ,MAAM,SAAS;AAAA,IACrB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,eAAe,OAAO,KAAa,MAA+B;AAChE,MAAI;AACF,WAAO,MAAMA,UAAS,GAAG,GAAG,IAAI,IAAI,IAAI,MAAM;AAAA,EAChD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,WAAW,KAA+B;AACvD,MAAI;AACF,YAAQ,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,CAAC;AAAA,EAChE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,sBAAsB,KAAqC;AACxE,QAAM,OACH,MAAM,OAAO,KAAK,kBAAkB,IACpC,MAAM,OAAO,KAAK,gBAAgB,IAClC,MAAM,OAAO,KAAK,SAAS,GAC5B,YAAY;AACd,MAAI,IAAI,SAAS,QAAQ,EAAG,QAAO;AACnC,MAAI,IAAI,SAAS,SAAS,EAAG,QAAO;AACpC,MAAI,IAAI,SAAS,OAAO,EAAG,QAAO;AAClC,SAAO;AACT;AAEA,eAAe,oBAAoB,KAAqC;AACtE,QAAM,OAAO,MAAM,OAAO,KAAK,SAAS,GAAG,YAAY;AACvD,MAAI,IAAI,SAAS,OAAO,EAAG,QAAO;AAClC,MAAI,IAAI,SAAS,SAAS,EAAG,QAAO;AACpC,SAAO;AACT;AAEA,eAAe,mBAAmB,KAAqC;AACrE,QAAM,OAAO,MAAM,OAAO,KAAK,eAAe,GAAG,YAAY;AAC7D,MAAI,IAAI,SAAS,SAAS,EAAG,QAAO;AACpC,MAAI,IAAI,SAAS,SAAS,EAAG,QAAO;AACpC,SAAO;AACT;AAMA,IAAM,WAAW;AACjB,IAAM,UAAU;AAIhB,SAAS,WAAW,KAAa,MAA4B;AAC3D,SAAO,EAAE,KAAK,MAAM,SAAS,GAAG,GAAG,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG;AAC1D;AAMA,eAAsB,iBAAiB,KAAkC;AACvE,MAAI,MAAM,WAAW,KAAK,SAAS,EAAG,QAAO,WAAW,MAAM,CAAC,OAAO,QAAQ,CAAC;AAC/E,QAAM,aAAa,MAAM,OAAO,KAAK,gBAAgB,GAAG,YAAY;AACpE,MACG,MAAM,WAAW,KAAK,aAAa,KACpC,UAAU,SAAS,eAAe,GAClC;AACA,WAAO,WAAW,UAAU,CAAC,OAAO,QAAQ,CAAC;AAAA,EAC/C;AACA,MAAI,MAAM,WAAW,KAAK,SAAS,GAAG;AACpC,WAAO,WAAW,UAAU,CAAC,WAAW,QAAQ,CAAC;AAAA,EACnD;AACA,SAAO,WAAW,OAAO,CAAC,WAAW,QAAQ,CAAC;AAChD;AAGA,eAAsB,eAAe,KAAkC;AACrE,MAAI,MAAM,WAAW,KAAK,SAAS,GAAG;AACpC,WAAO,WAAW,UAAU,CAAC,OAAO,OAAO,CAAC;AAAA,EAC9C;AACA,SAAO,WAAW,OAAO,CAAC,WAAW,OAAO,CAAC;AAC/C;AAGO,SAAS,cACd,SACA,KACiB;AACjB,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQC,OAAM,QAAQ,KAAK,QAAQ,MAAM;AAAA,MAC7C;AAAA,MACA,OAAO;AAAA,MACP,OAAO,QAAQ,aAAa;AAAA,IAC9B,CAAC;AACD,UAAM,GAAG,SAAS,MAAM,QAAQ,CAAC,CAAC;AAClC,UAAM,GAAG,SAAS,CAAC,SAAS,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAChD,CAAC;AACH;AAEO,SAAS,eAAe,IAAoB,KAAqB;AACtE,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,aAAO,YAAY,GAAG;AAAA,IACxB,KAAK;AACH,aAAO,YAAY,GAAG;AAAA,IACxB,KAAK;AACH,aAAO,WAAW,GAAG;AAAA,IACvB;AACE,aAAO,eAAe,GAAG;AAAA,EAC7B;AACF;AAGO,SAAS,WACd,IACA,KACA,KACiB;AACjB,QAAM,OAAO,OAAO,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,GAAG;AAC1D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQA,OAAM,IAAI,MAAM;AAAA,MAC5B;AAAA,MACA,OAAO;AAAA,MACP,OAAO,QAAQ,aAAa;AAAA,IAC9B,CAAC;AACD,UAAM,GAAG,SAAS,MAAM,QAAQ,CAAC,CAAC;AAClC,UAAM,GAAG,SAAS,CAAC,SAAS,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAChD,CAAC;AACH;;;AC9MA,IAAM,cAAc;AACpB,IAAM,QAAQ,CAAC,OAAe,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAIlE,SAAS,WAAW,OAAsB;AACxC,SAAO,MAAM,YAAY,SAAS,eAAe;AACnD;AAUO,SAAS,qBAAqBC,UAAkB;AACrD,EAAAA,SACG,QAAQ,SAAS,EAAE,WAAW,KAAK,CAAC,EACpC,MAAM,MAAM,EACZ,YAAY,2DAA2D,EACvE,OAAO,aAAa,wDAAwD,EAC5E,OAAO,aAAa,mDAAmD,EACvE,OAAO,gBAAgB,yBAAyB,EAChD,OAAO,oBAAoB,+CAA+C,EAC1E;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,OAAO,SAAuB;AACpC,UAAM,OAAO,MAAM,SAAS,IAAI;AAChC,QAAI,SAAS,EAAG,SAAQ,WAAW;AAAA,EACrC,CAAC;AACL;AAEA,eAAe,SAAS,MAAqC;AAC3D,QAAM,OAAO,WAAW,KAAK,OAAO;AACpC,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,cAAc,QAAQ,MAAM,SAAS,CAAC,KAAK;AAEjD,SAAO;AAKP,MAAI,KAAK,QAAQ;AACf,UAAM,UAAU,WAAW,MAAM,YAAY,GAAG,CAAC;AACjD,UAAM,UAAkC,EAAE,gBAAgB,KAAK,OAAO;AACtE,QAAI,SAAS,iBAAkB,SAAQ,kBAAkB;AACzD,UAAM,OAAO,MAAM,UAAU,KAAK,SAAS,OAAO;AAClD,iBAAa,2BAA2B,IAAI,KAAK,IAAI,CAAC,eAAe;AACrE;AAAA,MACE,qDAAqD,WAAW,CAAC;AAAA,IACnE;AACA,WAAO;AAAA,EACT;AAGA,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,gBAAgB,IAAI;AAAA,EACnC,SAAS,KAAK;AACZ,eAAW,GAAG;AACd,WAAO;AAAA,EACT;AAEA,MAAI,EAAE,KAAK,oCAAoC,CAAC;AAChD,MAAI;AACJ,MAAI,SAAS,EAAE,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC;AAC3C,MAAI;AAGJ,MAAI,eAAe,KAAK,MAAM;AAC5B,UAAM,OAAO,EAAE,IAAI,yCAAoC,CAAC;AAAA,EAC1D;AACA,MAAI,KAAK,KAAM,SAAQ,KAAK,yBAAyB;AACrD,YAAU,qCAAqC;AAC/C,MAAI,SAAS,EAAE,KAAK,KAAK,yBAAyB,CAAC;AACnD,MAAI;AACJ,YAAU,qDAAgD;AAG1D,QAAM,WAAW,KAAK,IAAI,IAAI,KAAK,aAAa;AAChD,MAAI,aAAa,KAAK,IAAI,GAAG,KAAK,QAAQ,IAAI;AAE9C,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,MAAM,UAAU;AACtB,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,eAAe,MAAM,KAAK,WAAW;AAAA,IACnD,SAAS,KAAK;AACZ,iBAAW,GAAG;AACd,aAAO;AAAA,IACT;AAEA,QAAI,IAAI,WAAW,wBAAyB;AAC5C,QAAI,IAAI,WAAW,aAAa;AAC9B,oBAAc;AACd;AAAA,IACF;AACA,QAAI,IAAI,WAAW,iBAAiB;AAClC,iBAAW,IAAI,MAAM,qDAAqD,CAAC;AAC3E,aAAO;AAAA,IACT;AACA,QAAI,IAAI,WAAW,iBAAiB;AAClC,iBAAW,IAAI,MAAM,qDAAqD,CAAC;AAC3E,aAAO;AAAA,IACT;AAEA,WAAO,OAAO,KAAK,KAAK,KAAK,OAAO;AAAA,EACtC;AAEA,aAAW,IAAI,MAAM,wDAAwD,CAAC;AAC9E,SAAO;AACT;AAEA,eAAe,OACb,UAOA,KACA,WACiB;AACjB,QAAM,EAAE,SAAS,QAAQ,KAAK,UAAU,SAAS,SAAS,UAAU,IAAI;AACxE,MAAI;AACJ,eAAa,wBAAwB,EAAE,KAAK,QAAQ,IAAI,CAAC,GAAG;AAE5D,QAAM,QAAQ,MAAM,YAAY,GAAG;AACnC,QAAM,SAAS,MAAM,YAAY;AACjC,QAAM,UAAU,WAAW,KAAK;AAGhC,QAAM,UAAkC,EAAE,gBAAgB,OAAO;AACjE,MAAI,WAAW,YAAY,iBAAkB,SAAQ,kBAAkB;AACvE,QAAM,UAAU,MAAM,UAAU,KAAK,SAAS,OAAO;AACrD,eAAa,2BAA2B,IAAI,KAAK,OAAO,CAAC,GAAG;AAE5D,MAAI;AACF,UAAM,WAAW,MAAM,eAAe;AAAA,MACpC;AAAA,MACA;AAAA,MACA,SAAS,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,MACA,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,CAAC;AACD,iBAAa,yBAAyB,QAAQ,QAAQ,CAAC,2BAA2B;AAAA,EACpF,QAAQ;AACN,iBAAa,0DAA0D;AAAA,EACzE;AAMA,MAAI;AACJ,MAAI,QAAQ;AACV,UAAM,KAAK,MAAM,qBAAqB,GAAG;AACzC,QAAI,WAAW;AACb,gBAAU,cAAc,WAAW,SAAS,EAAE,QAAG;AACjD,YAAM,OAAO,MAAM,WAAW,IAAI,aAAa,GAAG;AAClD,UAAI,SAAS,EAAG,cAAa,aAAa,WAAW,GAAG;AAAA,UACnD,cAAa,wBAAwB,eAAe,IAAI,WAAW,CAAC,EAAE;AAAA,IAC7E,OAAO;AACL,gBAAU,yBAAyB,eAAe,IAAI,WAAW,CAAC,EAAE;AAAA,IACtE;AACA,cAAU,OAAO,WAAW;AAAA,EAC9B,WAAW,MAAM,YAAY,YAAY,MAAM,YAAY,QAAQ;AACjE,UAAM,UACJ,MAAM,YAAY,WACd,MAAM,iBAAiB,GAAG,IAC1B,MAAM,eAAe,GAAG;AAC9B,UAAM,WAAW,SAAS,SAAS;AACnC,cACE,MAAM,YAAY,WACd,0CACA;AAAA,EACR,OAAO;AACL;AAAA,MACE,YAAY,WAAW,KAAK,CAAC,QAAQ,aAAa,KAAK,CAAC;AAAA,IAC1D;AACA,cACE,uBAAuB,aAAa,KAAK,CAAC;AAAA,EAG9C;AAEA,oBAAkB,SAAS,SAAS,WAAW,CAAC;AAChD,SAAO;AACT;AAGA,eAAe,WAAW,SAAqB,WAAmC;AAChF,MAAI,WAAW;AACb,cAAU,yBAAyB,QAAQ,OAAO,SAAI;AACtD,UAAM,OAAO,MAAM,cAAc,SAAS,QAAQ,IAAI,CAAC;AACvD,QAAI,SAAS,EAAG,cAAa,sBAAsB;AAAA,QAC9C,cAAa,wBAAwB,QAAQ,OAAO,EAAE;AAAA,EAC7D,OAAO;AACL,cAAU,yBAAyB,QAAQ,OAAO,EAAE;AAAA,EACtD;AACF;AAEA,IAAM,aAAa;AASnB,SAAS,kBACP,SACA,SACA,WACM;AACN,QAAM,OAAO,OAAO,SAAI,OAAO,EAAE;AACjC,MAAI;AACJ,MAAI,EAAE,KAAK,2CAA2C,CAAC;AACvD,MAAI;AACJ,MAAI,EAAE,IAAI,kEAA6D,CAAC;AACxE,MAAI,EAAE,IAAI,IAAI,CAAC;AAEf,MAAI,sEAAsE;AAC1E,MAAI,6CAA6C,OAAO,QAAQ,OAAO,GAAG;AAC1E,MAAI,6CAA6C;AACjD,MAAI,6DAA6D;AACjE,MAAI,sEAAsE;AAC1E,MAAI,yCAAyC;AAC7C,MAAI,uEAAuE;AAC3E,MAAI,wEAAwE;AAC5E,MAAI,yDAAyD;AAC7D,MAAI,sEAAsE;AAC1E,MAAI,iBAAiB,UAAU,EAAE;AACjC,MAAI,EAAE,IAAI,IAAI,CAAC;AACf,MAAI;AACJ,MAAI,EAAE,IAAI,gDAAgD,UAAU,EAAE,CAAC;AACvE,MAAI;AACJ,MAAI,EAAE,IAAI,oBAAoB,IAAI,EAAE,KAAK,GAAG,SAAS,SAAS,CAAC;AAC/D;AAAA,IACE,EAAE;AAAA,MACA,sBAAsB,OAAO;AAAA,IAC/B;AAAA,EACF;AACA,MAAI;AACN;AAEA,SAAS,IAAI,KAAa,MAAsB;AAC9C,SAAO,KAAK,WAAW,GAAG,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,KAAK,OAAO;AACrE;AAEA,SAAS,QAAQ,MAAsB;AACrC,QAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI;AAC7C,SAAO,QAAQ,KAAK,WAAW,IAAI,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,CAAC,KAAK;AACzE;;;AClSA,SAAS,KAAK,KAAqB;AACjC,SAAO,IAAI,SAAS,KAAK,IAAI,MAAM,GAAG,CAAC,IAAI,WAAM,IAAI,MAAM,EAAE,IAAI;AACnE;AAEO,SAAS,qBAAqBC,UAAkB;AACrD,QAAM,OAAOA,SAAQ,QAAQ,MAAM,EAAE,YAAY,qCAAqC;AAEtF,OACG,QAAQ,QAAQ,EAChB,YAAY,kDAAkD,EAC9D,OAAO,YAAY;AAClB,UAAM,OAAO,MAAM,eAAe;AAClC,UAAM,SAAS,QAAQ,IAAI;AAE3B,QAAI,CAAC,QAAQ,CAAC,QAAQ;AACpB,UAAI,WAAW,EAAG,WAAU,EAAE,WAAW,MAAM,CAAC;AAAA,UAC3C,WAAU,wBAAwB,EAAE,KAAK,GAAG,WAAW,CAAC,QAAQ,IAAI,aAAa;AACtF;AAAA,IACF;AAEA,QAAI,WAAW,GAAG;AAChB,gBAAU;AAAA,QACR,WAAW;AAAA,QACX,QAAQ,SAAS,QAAQ;AAAA,QACzB,SAAS,MAAM,WAAW;AAAA,QAC1B,UAAU,MAAM,WAAW;AAAA,QAC3B,KAAK,SAAS,QAAQ,OAAO,KAAK,KAAK,MAAM,IAAI;AAAA,MACnD,CAAC;AACD;AAAA,IACF;AAEA,iBAAa,eAAe,OAAO,OAAO,EAAE,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,GAAG;AAC3E,QAAI,MAAM;AACR,cAAQ,IAAI,EAAE,IAAI,aAAa,IAAI,KAAK,QAAQ,IAAI;AACpD,cAAQ,IAAI,EAAE,IAAI,aAAa,IAAI,KAAK,KAAK,MAAM,CAAC;AACpD,cAAQ,IAAI,EAAE,IAAI,aAAa,IAAI,KAAK,OAAO;AAAA,IACjD;AACA,QAAI,OAAQ,SAAQ,IAAI,EAAE,IAAI,6CAA6C,CAAC;AAAA,EAC9E,CAAC;AAEH,OACG,QAAQ,QAAQ,EAChB,YAAY,2DAA2D,EACvE,OAAO,YAAY;AAClB,UAAM,gBAAgB;AACtB,iBAAa,4BAA4B;AAAA,EAC3C,CAAC;AACL;;;ACxCO,SAAS,sBAAsBC,UAAkB;AACtD,EAAAA,SACG,QAAQ,QAAQ,EAChB,YAAY,gEAAgE,EAC5E,OAAO,YAAY;AAClB,UAAM,OAAO,QAAQ,oCAA+B,EAAE,MAAM;AAC5D,QAAI;AACF,YAAM,EAAE,KAAK,IAAI,MAAM,OAAO,IAAoB,YAAY;AAC9D,WAAK,KAAK;AAEV,UAAI,WAAW,GAAG;AAChB,kBAAU,IAAI;AACd;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,eAAe;AAClC,YAAM,WAAW,KAAK,YAAY;AAClC,YAAM,SAAS,KAAK,UAAU;AAE9B,UAAI,KAAM,WAAU,WAAW,EAAE,KAAK,KAAK,QAAQ,IAAI,CAAC,EAAE;AAC1D,UAAI,WAAW,KAAK,SAAS,GAAG;AAC9B,qBAAa,cAAc,QAAQ,gBAAgB,MAAM,qBAAqB;AAAA,MAChF,OAAO;AACL,kBAAU,kEAAkE;AAAA,MAC9E;AAAA,IACF,SAAS,KAAK;AACZ,WAAK,KAAK;AACV,iBAAW,GAAG;AACd,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF,CAAC;AACL;;;ACjCO,SAAS,uBAAuBC,UAAkB;AACvD,QAAM,MAAMA,SAAQ,QAAQ,QAAQ,EAAE,YAAY,0BAA0B;AAE5E,MACG,QAAQ,KAAK,EACb,YAAY,oBAAoB,EAChC,SAAS,SAAS,sBAAsB,EACxC,SAAS,WAAW,cAAc,EAClC,OAAO,CAAC,KAAa,UAAkB;AACtC,YAAQ,KAAK;AAAA,MACX,KAAK;AACH,mBAAW,KAAK;AAChB,qBAAa,mBAAmB,WAAW,CAAC,EAAE;AAC9C;AAAA,MACF;AACE,mBAAW,IAAI,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AACxE,gBAAQ,WAAW;AAAA,IACvB;AAAA,EACF,CAAC;AAEH,MACG,QAAQ,KAAK,EACb,YAAY,wBAAwB,EACpC,SAAS,SAAS,+BAA+B,EACjD,OAAO,CAAC,QAAiB;AACxB,UAAM,MAAM,EAAE,UAAU,WAAW,GAAG,aAAa,cAAc,EAAE;AACnE,QAAI,OAAO,QAAQ,cAAc,QAAQ,QAAQ;AAC/C,iBAAW,IAAI,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAClD,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,QAAI,WAAW,GAAG;AAChB,gBAAU,QAAQ,aAAa,EAAE,UAAU,IAAI,SAAS,IAAI,QAAQ,SAAS,EAAE,aAAa,IAAI,YAAY,IAAI,GAAG;AACnH;AAAA,IACF;AACA,QAAI,QAAQ,WAAY,SAAQ,IAAI,IAAI,QAAQ;AAAA,aACvC,QAAQ,OAAQ,SAAQ,IAAI,IAAI,WAAW;AAAA,QAC/C,YAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,EAAG,SAAQ,IAAI,EAAE,KAAK,IAAI,GAAG,IAAI,MAAM,CAAC;AAAA,EACtF,CAAC;AAEH,MACG,QAAQ,OAAO,EACf,YAAY,qCAAqC,EACjD,OAAO,MAAM;AACZ,gBAAY;AACZ,iBAAa,sBAAsB;AAAA,EACrC,CAAC;AACL;;;ACxDA,SAAS,YAAAC,iBAAgB;AAqEzB,eAAe,UAAU,KAA8B;AACrD,MAAI,IAAI,WAAW,GAAG,EAAG,SAAQ,MAAMC,UAAS,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK;AAC5E,SAAO;AACT;AAEA,eAAe,UACb,QACA,MACkC;AAClC,QAAM,OAAgC,CAAC;AACvC,aAAW,KAAK,QAAQ;AACtB,UAAM,IAAI,KAAK,MAAM,EAAE,GAAG,CAAC;AAC3B,QAAI,MAAM,OAAW;AACrB,QAAI,EAAE,MAAM;AACV,WAAK,EAAE,GAAG,IAAI,KAAK,MAAM,MAAM,UAAU,OAAO,CAAC,CAAC,CAAC;AAAA,IACrD,WAAW,EAAE,QAAQ;AACnB,WAAK,EAAE,GAAG,IAAI,OAAO,CAAC;AAAA,IACxB,WAAW,EAAE,SAAS;AACpB,WAAK,EAAE,GAAG,IAAI,MAAM,QAAQ,MAAM;AAAA,IACpC,OAAO;AACL,WAAK,EAAE,GAAG,IAAI,MAAM,UAAU,OAAO,CAAC,CAAC;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,UACb,QACA,MACmB;AACnB,QAAM,OAAO,IAAI,SAAS;AAC1B,aAAW,KAAK,QAAQ;AACtB,UAAM,IAAI,KAAK,MAAM,EAAE,GAAG,CAAC;AAC3B,QAAI,MAAM,OAAW;AACrB,QAAI,EAAE,MAAM;AACV,YAAMC,QAAO,OAAO,CAAC;AACrB,YAAM,QAAQ,MAAMD,UAASC,KAAI;AACjC,YAAM,OAAOA,MAAK,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE;AACxC,WAAK,OAAO,EAAE,KAAK,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,CAAC,GAAG,IAAI;AAAA,IAC5D,WAAW,EAAE,MAAM;AAEjB,WAAK,OAAO,EAAE,KAAK,MAAM,UAAU,OAAO,CAAC,CAAC,CAAC;AAAA,IAC/C,OAAO;AACL,WAAK,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC;AAAA,IAC9B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WACP,QACA,MAC6C;AAC7C,QAAM,IAAiD,CAAC;AACxD,aAAW,KAAK,QAAQ;AACtB,UAAM,IAAI,KAAK,MAAM,EAAE,GAAG,CAAC;AAC3B,QAAI,MAAM,OAAW;AACrB,MAAE,EAAE,GAAG,IAAI,EAAE,SAAS,OAAO,CAAC,IAAI,OAAO,CAAC;AAAA,EAC5C;AACA,SAAO;AACT;AAGA,SAAS,MAAM,KAAqB;AAClC,SAAO,IAAI,QAAQ,gBAAgB,CAAC,GAAG,OAAe,GAAG,YAAY,CAAC;AACxE;AAEA,SAAS,YAAY,KAAc,QAAiB;AAClD,aAAW,KAAK,QAAQ;AACtB,QAAI,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG;AAAA,EAC3C;AACF;AAEA,eAAe,SAAS,MAAoB,SAAmC;AAC7E,QAAM,MAAM,KAAK,WAAW,KAAK;AACjC,MAAI,CAAC,KAAK,OAAQ,QAAO,OAAO,GAAG;AACnC,QAAM,OAAO,MAAM,mBAAmB,OAAO;AAC7C,SAAO,gBAAgB,IAAI,IAAI,GAAG;AACpC;AAEA,SAAS,YAAY,KAAc,QAA0B;AAC3D,MAAI,QAAQ;AACV,QAAI,OAAO,wBAAwB,2CAA2C;AAAA,EAChF;AACA,SAAO;AACT;AAEA,SAAS,KAAK,KAAc;AAC1B,aAAW,GAAG;AACd,UAAQ,WAAW;AACrB;AAEA,SAAS,SAASC,UAAkB,MAAoB;AACtD,QAAM,QAAQA,SAAQ,QAAQ,KAAK,IAAI,EAAE,YAAY,KAAK,QAAQ;AAClE,MAAI,KAAK,MAAO,OAAM,MAAM,KAAK,KAAK;AACtC,QAAM,SAAS,KAAK,UAAU;AAE9B,MAAI,KAAK,MAAM;AACb,UAAM,MAAM;AAAA,MACV,MAAM,QAAQ,MAAM,EAAE,YAAY,QAAQ,KAAK,IAAI,EAAE;AAAA,MACrD,KAAK;AAAA,IACP;AACA,QAAI,KAAK,KAAK,WAAW;AACvB,UAAI,OAAO,eAAe,mBAAmB;AAC7C,UAAI,OAAO,qBAAqB,mBAAmB;AAAA,IACrD;AACA,QAAI,KAAK,KAAK,MAAO,aAAY,KAAK,KAAK,KAAK,KAAK;AACrD,QAAI,OAAO,OAAO,SAAS;AACzB,UAAI;AACF,cAAM,QAAqD,CAAC;AAC5D,YAAI,KAAK,MAAM,WAAW;AACxB,cAAI,KAAK,MAAO,OAAM,QAAQ,OAAO,KAAK,KAAK;AAC/C,cAAI,KAAK,OAAQ,OAAM,SAAS,KAAK;AAAA,QACvC;AACA,YAAI,KAAK,MAAM,MAAO,QAAO,OAAO,OAAO,WAAW,KAAK,KAAK,OAAO,IAAI,CAAC;AAC5E,cAAM,EAAE,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,SAAS,MAAM,KAAK,OAAO,GAAG,KAAK;AACzE,aAAK,IAAI;AAAA,MACX,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,KAAK;AACZ,UAAM,MAAM;AAAA,MACV,MACG,QAAQ,KAAK,EACb,YAAY,SAAS,KAAK,IAAI,OAAO,MAAM,EAAE,EAC7C,SAAS,IAAI,MAAM,KAAK,MAAM;AAAA,MACjC,KAAK;AAAA,IACP;AACA,QAAI,OAAO,OAAO,SAAiB,SAAS;AAC1C,UAAI;AACF,cAAMD,QAAO,GAAG,MAAM,SAAS,MAAM,KAAK,OAAO,CAAC,IAAI,mBAAmB,OAAO,CAAC;AACjF,cAAM,EAAE,KAAK,IAAI,MAAM,KAAK,IAAIA,KAAI;AACpC,aAAK,IAAI;AAAA,MACX,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,QAAQ;AACf,UAAM,MAAM;AAAA,MACV,MAAM,QAAQ,QAAQ,EAAE,YAAY,YAAY,KAAK,IAAI,EAAE;AAAA,MAC3D,KAAK;AAAA,IACP;AACA,gBAAY,KAAK,KAAK,MAAM;AAC5B,QAAI,OAAO,OAAO,SAAS;AACzB,UAAI;AACF,cAAM,OAAO,MAAM,UAAU,KAAK,QAAS,IAAI;AAC/C,cAAM,EAAE,KAAK,IAAI,MAAM,KAAK,KAAK,MAAM,SAAS,MAAM,KAAK,OAAO,GAAG,IAAI;AACzE,aAAK,IAAI;AAAA,MACX,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,QAAQ;AACf,UAAM,MAAM;AAAA,MACV,MACG,QAAQ,QAAQ,EAChB,YAAY,YAAY,KAAK,IAAI,EAAE,EACnC,SAAS,IAAI,MAAM,KAAK,MAAM;AAAA,MACjC,KAAK;AAAA,IACP;AACA,gBAAY,KAAK,KAAK,MAAM;AAC5B,QAAI,OAAO,OAAO,SAAiB,SAAS;AAC1C,UAAI;AACF,cAAM,OAAO,MAAM,UAAU,KAAK,QAAS,IAAI;AAC/C,cAAMA,QAAO,GAAG,MAAM,SAAS,MAAM,KAAK,OAAO,CAAC,IAAI,mBAAmB,OAAO,CAAC;AACjF,cAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAMA,OAAM,IAAI;AAC5C,aAAK,IAAI;AAAA,MACX,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,QAAQ;AACf,UAAM,MAAM;AAAA,MACV,MACG,QAAQ,QAAQ,EAChB,YAAY,YAAY,KAAK,IAAI,EAAE,EACnC,SAAS,IAAI,MAAM,KAAK,MAAM;AAAA,MACjC,KAAK;AAAA,IACP;AACA,QAAI,OAAO,OAAO,SAAiB,SAAS;AAC1C,UAAI;AACF,cAAMA,QAAO,GAAG,MAAM,SAAS,MAAM,KAAK,OAAO,CAAC,IAAI,mBAAmB,OAAO,CAAC;AACjF,cAAM,KAAK,OAAOA,KAAI;AACtB,qBAAa,WAAW,KAAK,KAAK,QAAQ,MAAM,EAAE,CAAC,IAAI,OAAO,GAAG;AAAA,MACnE,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAEA,aAAW,UAAU,KAAK,WAAW,CAAC,GAAG;AACvC,UAAM,UAAU,OAAO,WAAW;AAClC,UAAM,MAAM;AAAA,MACV,UACI,MACG,QAAQ,OAAO,IAAI,EACnB,YAAY,OAAO,QAAQ,EAC3B,SAAS,IAAI,MAAM,KAAK,MAAM,IACjC,MAAM,QAAQ,OAAO,IAAI,EAAE,YAAY,OAAO,QAAQ;AAAA,MAC1D,KAAK;AAAA,IACP;AACA,QAAI,OAAO,OAAQ,aAAY,KAAK,OAAO,MAAM;AACjD,QAAI,OAAO,MAAO,aAAY,KAAK,OAAO,KAAK;AAE/C,UAAM,UAAU,UAAU,SAAoB;AAE5C,YAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,YAAM,UAAU,UAAW,KAAK,CAAC,IAAe;AAChD,UAAI;AACF,YAAIA,QAAO,MAAM,SAAS,MAAM,KAAK,OAA6B;AAClE,YAAI,QAAS,CAAAA,SAAQ,IAAI,mBAAmB,OAAQ,CAAC;AACrD,QAAAA,SAAQ,OAAO;AAEf,YAAI,OAAO,WAAW,OAAO;AAC3B,gBAAM,QAAQ,OAAO,QAAQ,WAAW,OAAO,OAAO,IAAI,IAAI;AAC9D,gBAAM,EAAE,MAAAE,MAAK,IAAI,MAAM,KAAK,IAAIF,OAAM,KAAK;AAC3C,eAAKE,KAAI;AACT;AAAA,QACF;AACA,YAAI,OAAO,aAAa,OAAO,QAAQ;AACrC,gBAAM,OAAO,MAAM,UAAU,OAAO,QAAQ,IAAI;AAChD,gBAAM,EAAE,MAAAA,OAAM,QAAAC,QAAO,IAAI,MAAM,KAAK;AAAA,YAClC,OAAO,OAAO,YAAY;AAAA,YAC1BH;AAAA,YACA,EAAE,KAAK;AAAA,UACT;AACA,cAAIG,YAAW,IAAK,cAAa,GAAG,OAAO,IAAI,MAAM;AAAA,cAChD,MAAKD,KAAI;AACd;AAAA,QACF;AACA,cAAM,OAAO,OAAO,SAAS,MAAM,UAAU,OAAO,QAAQ,IAAI,IAAI;AACpE,cAAM,EAAE,MAAM,OAAO,IAAI,MAAM,KAAK;AAAA,UAClC,OAAO,OAAO,YAAY;AAAA,UAC1BF;AAAA,UACA,EAAE,KAAK;AAAA,QACT;AACA,YAAI,WAAW,IAAK,cAAa,GAAG,OAAO,IAAI,MAAM;AAAA,YAChD,MAAK,IAAI;AAAA,MAChB,SAAS,KAAK;AACZ,aAAK,GAAG;AAAA,MACV;AAAA,IACF;AACA,QAAI,OAAO,OAAO;AAAA,EACpB;AACF;AAEA,IAAM,SAAS,EAAE,WAAW,KAAK;AAEjC,IAAM,QAAwB;AAAA;AAAA,EAE5B;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,mBAAmB,KAAK,WAAW;AAAA,IAC7C;AAAA,IACA,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,mBAAmB,KAAK,WAAW;AAAA,IAC7C;AAAA,IACA,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,QAAQ;AAAA,MACN,EAAE,MAAM,mBAAmB,KAAK,QAAQ;AAAA,MACxC,EAAE,MAAM,iBAAiB,KAAK,QAAQ,aAAa,iBAAiB;AAAA,IACtE;AAAA,IACA,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,QAAQ;AAAA,MACN,EAAE,MAAM,mBAAmB,KAAK,QAAQ;AAAA,MACxC,EAAE,MAAM,iBAAiB,KAAK,QAAQ,aAAa,iBAAiB;AAAA,IACtE;AAAA,IACA,QAAQ;AAAA,EACV;AAAA,EACA;AAAA;AAAA;AAAA,IAGE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,EACV;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM,EAAE,GAAG,OAAO;AAAA,IAClB,KAAK;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,QAAQ;AAAA,UACN,EAAE,MAAM,iBAAiB,KAAK,QAAQ,MAAM,KAAK;AAAA,UACjD,EAAE,MAAM,oBAAoB,KAAK,WAAW,MAAM,KAAK;AAAA,UACvD,EAAE,MAAM,uBAAuB,KAAK,UAAU,aAAa,gBAAgB;AAAA,UAC3E,EAAE,MAAM,mBAAmB,KAAK,WAAW;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM,EAAE,GAAG,OAAO;AAAA,IAClB,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,EAAE,GAAG,QAAQ,OAAO,CAAC,EAAE,MAAM,iBAAiB,KAAK,OAAO,CAAC,EAAE;AAAA,EACrE;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM,EAAE,GAAG,OAAO;AAAA,IAClB,QAAQ,CAAC,EAAE,MAAM,mBAAmB,KAAK,QAAQ,CAAC;AAAA,IAClD,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,mBAAmB,KAAK,UAAU,MAAM,KAAK;AAAA,IACvD;AAAA,IACA,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,mBAAmB,KAAK,UAAU,MAAM,KAAK;AAAA,IACvD;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,EAAE,MAAM,mBAAmB,KAAK,UAAU,MAAM,KAAK,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,KAAK;AAAA,IACL,QAAQ,CAAC,EAAE,MAAM,iBAAiB,KAAK,OAAO,CAAC;AAAA,IAC/C,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,qBAAqB,KAAK,UAAU,aAAa,oBAAoB;AAAA,IAC/E;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,UACN,EAAE,MAAM,kBAAkB,KAAK,SAAS,MAAM,KAAK;AAAA,UACnD,EAAE,MAAM,oBAAoB,KAAK,WAAW,MAAM,KAAK;AAAA,UACvD,EAAE,MAAM,2BAA2B,KAAK,qBAAqB,QAAQ,KAAK;AAAA,QAC5E;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,CAAC,EAAE,MAAM,kBAAkB,KAAK,SAAS,CAAC;AAAA,MACpD;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,UACN,EAAE,MAAM,kBAAkB,KAAK,SAAS;AAAA,UACxC,EAAE,MAAM,gBAAgB,KAAK,KAAK;AAAA,QACpC;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,KAAK;AAAA,IACL,QAAQ,CAAC,EAAE,MAAM,iBAAiB,KAAK,OAAO,CAAC;AAAA,IAC/C,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,uBAAuB,KAAK,UAAU;AAAA,MAC9C,EAAE,MAAM,uBAAuB,KAAK,UAAU;AAAA,MAC9C,EAAE,MAAM,qBAAqB,KAAK,YAAY,MAAM,KAAK;AAAA,MACzD,EAAE,MAAM,sBAAsB,KAAK,cAAc;AAAA,MACjD,EAAE,MAAM,qBAAqB,KAAK,YAAY,MAAM,KAAK;AAAA,IAC3D;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,CAAC,EAAE,MAAM,wBAAwB,KAAK,eAAe,CAAC;AAAA,MAChE;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,mBAAmB,KAAK,UAAU,MAAM,KAAK;AAAA,IACvD;AAAA,IACA,QAAQ;AAAA,MACN,EAAE,MAAM,iBAAiB,KAAK,OAAO;AAAA,MACrC,EAAE,MAAM,mBAAmB,KAAK,UAAU,MAAM,KAAK;AAAA,IACvD;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,CAAC,EAAE,MAAM,qBAAqB,KAAK,SAAS,CAAC;AAAA,MACvD;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,QAAQ,CAAC,EAAE,MAAM,iBAAiB,KAAK,QAAQ,MAAM,KAAK,CAAC;AAAA,MAC7D;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,QAAQ,CAAC,EAAE,MAAM,qBAAqB,KAAK,SAAS,CAAC;AAAA,IACrD,QAAQ;AAAA,IACR,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA;AAAA;AAAA,IAGE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,CAAC;AAAA,IACP,QAAQ,CAAC,EAAE,MAAM,iBAAiB,KAAK,OAAO,CAAC;AAAA,IAC/C,QAAQ;AAAA,EACV;AACF;AAEO,SAAS,yBAAyBC,UAAkB;AACzD,aAAW,QAAQ,MAAO,UAASA,UAAS,IAAI;AAGhD,EAAAA,SACG,QAAQ,IAAI,EACZ,YAAY,4CAA4C,EACxD,OAAO,YAAY;AAClB,QAAI;AACF,YAAM,EAAE,KAAK,IAAI,MAAM,KAAK,IAAI,QAAQ;AACxC,WAAK,IAAI;AAAA,IACX,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAGH,EAAAA,SACG,QAAQ,iBAAiB,EACzB,YAAY,+EAA+E,EAC3F,OAAO,wBAAwB,2CAA2C,EAC1E,OAAO,wBAAwB,cAAc,EAC7C,OAAO,sBAAsB,mBAAmB,EAChD,OAAO,4BAA4B,kBAAkB,EACrD,OAAO,OAAO,SAAS;AACtB,QAAI;AACF,YAAM,OAAO,MAAM,mBAAmB,KAAK,OAAO;AAClD,YAAM,OAAgC,CAAC;AACvC,UAAI,KAAK,cAAc,OAAW,MAAK,aAAa,KAAK;AACzD,UAAI,KAAK,aAAa,OAAW,MAAK,YAAY,KAAK;AACvD,UAAI,KAAK,iBAAiB,OAAW,MAAK,iBAAiB,KAAK;AAChE,YAAM,EAAE,KAAK,IAAI,MAAM,KAAK,IAAI,gBAAgB,IAAI,oBAAoB,IAAI;AAC5E,WAAK,IAAI;AAAA,IACX,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AAEH,EAAAA,SACG,QAAQ,cAAc,EACtB,YAAY,sDAAsD,EAClE,SAAS,UAAU,+BAA+B,EAClD,OAAO,wBAAwB,2CAA2C,EAC1E,OAAO,OAAO,MAAc,SAAS;AACpC,QAAI;AACF,YAAM,OAAO,MAAM,mBAAmB,KAAK,OAAO;AAClD,YAAM,EAAE,KAAK,IAAI,MAAM,KAAK,IAAI,gBAAgB,IAAI,iBAAiB;AAAA,QACnE,cAAc;AAAA,MAChB,CAAC;AACD,WAAK,IAAI;AAAA,IACX,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF,CAAC;AACL;;;AX9rBA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,QAAQ,EACb,YAAY,kEAAkE,EAC9E,QAAQ,OAAW,EACnB,OAAO,UAAU,0CAA0C,EAC3D,KAAK,aAAa,CAAC,gBAAgB;AAClC,MAAI,YAAY,KAAK,EAAE,KAAM,aAAY,IAAI;AAC/C,CAAC;AAQH,qBAAqB,OAAO;AAC5B,qBAAqB,OAAO;AAC5B,sBAAsB,OAAO;AAC7B,uBAAuB,OAAO;AAC9B,yBAAyB,OAAO;AAEhC,QAAQ,WAAW;","names":["path","path","readFile","writeFile","spawn","readFile","readFile","spawn","program","program","program","program","readFile","readFile","path","program","data","status"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/output.ts","../src/config.ts","../src/client.ts","../src/browser.ts","../src/env-file.ts","../src/pm.ts","../src/commands/login.ts","../src/commands/auth.ts","../src/commands/status.ts","../src/commands/config.ts","../src/commands/resources.ts"],"sourcesContent":["declare const PKG_VERSION: string;\nimport { Command } from \"commander\";\nimport { setJsonMode } from \"./output.js\";\nimport { registerLoginCommand } from \"./commands/login.js\";\nimport { registerAuthCommands } from \"./commands/auth.js\";\nimport { registerStatusCommand } from \"./commands/status.js\";\nimport { registerConfigCommands } from \"./commands/config.js\";\nimport { registerResourceCommands } from \"./commands/resources.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"letter\")\n .description(\"Connect your app to Letter, then manage it from the command line\")\n .version(PKG_VERSION)\n .option(\"--json\", \"Output raw JSON (for scripting / agents)\")\n .hook(\"preAction\", (thisCommand) => {\n if (thisCommand.opts().json) setJsonMode(true);\n });\n\n// Two layers, one login:\n// - login/auth/status/config wire up the project and its ingestion key\n// (lt_live_*, written to the project env as LETTER_API_KEY).\n// - the resource groups drive the Management API with the workspace PAT\n// (lt_pat_*, stored in ~/.letter/credentials.json). Both credentials are\n// minted by `letter login`; each command picks the right one on its own.\nregisterLoginCommand(program); // default command (`letter` == `letter login`)\nregisterAuthCommands(program);\nregisterStatusCommand(program);\nregisterConfigCommands(program);\nregisterResourceCommands(program); // control-plane resource groups (PAT-backed)\n\nprogram.parseAsync();\n","import chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\nimport { createInterface } from \"node:readline\";\n\nlet jsonMode = false;\n\nexport function setJsonMode(enabled: boolean) {\n jsonMode = enabled;\n}\nexport function isJsonMode() {\n return jsonMode;\n}\n\nexport function printJson(data: unknown) {\n console.log(JSON.stringify(data, null, 2));\n}\n\n/**\n * The command users should repeat to run us again, so printed hints are\n * copy-pasteable. When launched through `npx`, Node runs us from the npx cache\n * (`…/_npx/<hash>/…`) and there's no `letter` on PATH, so suggest the npx form;\n * a global install resolves the bare `letter` binary.\n */\nexport function cliCommand(): string {\n return (process.argv[1] ?? \"\").includes(\"_npx\") ? \"npx @letterapp/cli\" : \"letter\";\n}\n\nexport function log(msg = \"\") {\n if (jsonMode) return;\n console.log(msg);\n}\n\nexport function printSuccess(msg: string) {\n if (jsonMode) return;\n console.log(chalk.green(\"✓\") + \" \" + msg);\n}\n\nexport function printInfo(msg: string) {\n if (jsonMode) return;\n console.log(chalk.cyan(\"›\") + \" \" + msg);\n}\n\nexport function printWarning(msg: string) {\n if (jsonMode) return;\n console.log(chalk.yellow(\"!\") + \" \" + msg);\n}\n\nexport function printError(err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n if (jsonMode) {\n printJson({ error: msg });\n return;\n }\n console.error(chalk.red(\"✗\") + \" \" + msg);\n}\n\n/** The Letter wordmark banner. Suppressed in JSON mode. */\nexport function banner() {\n if (jsonMode) return;\n console.log(\"\");\n console.log(\" \" + chalk.bold(\"Letter\") + chalk.red(\".\") + \" \" + chalk.dim(\"CLI\"));\n console.log(\"\");\n}\n\nexport function spinner(text: string): Ora {\n return ora({ text, color: \"cyan\", isEnabled: !jsonMode });\n}\n\n/**\n * Prompts the user and resolves with their input. Returns \"\" immediately on a\n * non-interactive stdin so automated/agent runs don't hang.\n */\nexport function prompt(question: string): Promise<string> {\n if (!process.stdin.isTTY) return Promise.resolve(\"\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\n/**\n * Print a management API result. In `--json` mode, emits the raw payload so\n * agents/scripts can parse it. In human mode, renders list envelopes as a\n * compact `id label` table and single resources as pretty JSON.\n */\nexport function emit(data: unknown) {\n if (jsonMode) {\n printJson(data);\n return;\n }\n if (data && typeof data === \"object\" && Array.isArray((data as { data?: unknown }).data)) {\n const env = data as { data: Record<string, unknown>[]; next_cursor?: string | null };\n if (env.data.length === 0) {\n console.log(chalk.dim(\"(none)\"));\n } else {\n for (const row of env.data) {\n const id = String(row.id ?? row.slug ?? row.external_id ?? \"\");\n const label =\n (row.name as string) ??\n (row.email as string) ??\n (row.domain as string) ??\n (row.subject as string) ??\n \"\";\n console.log(`${chalk.bold(id)}${label ? \" \" + label : \"\"}`);\n }\n }\n if (env.next_cursor) {\n console.log(chalk.dim(`\\n› more: --cursor ${env.next_cursor}`));\n }\n return;\n }\n printJson(data);\n}\n\nexport const c = chalk;\n","import Conf from \"conf\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { mkdir, readFile, writeFile, rm } from \"node:fs/promises\";\nimport { cliCommand } from \"./output.js\";\n\n/** The SDK / API default. When the resolved base equals this we don't bother\n * writing LETTER_BASE_URL into the project env. */\nexport const DEFAULT_BASE_URL = \"https://api.letter.app\";\n\n/* -------------------------------------------------------------------------- */\n/* Non-secret CLI preferences (base URL). */\n/* Stored with `conf`, mirroring how the SDK/MCP resolve their endpoint. */\n/* -------------------------------------------------------------------------- */\n\nconst config = new Conf({\n projectName: \"letterapp-cli\",\n schema: {\n baseUrl: { type: \"string\", default: DEFAULT_BASE_URL },\n },\n});\n\n/** Resolve the API base: explicit flag > env > stored config > prod default. */\nexport function getBaseUrl(flag?: string): string {\n const raw =\n flag ||\n process.env.LETTER_BASE_URL ||\n (config.get(\"baseUrl\") as string) ||\n DEFAULT_BASE_URL;\n return raw.replace(/\\/$/, \"\");\n}\n\nexport function setBaseUrl(url: string): void {\n config.set(\"baseUrl\", url.replace(/\\/$/, \"\"));\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n\nexport function resetConfig(): void {\n config.clear();\n}\n\n/* -------------------------------------------------------------------------- */\n/* Secret credential store (~/.letter/credentials.json). */\n/* Written here, read by @letterapp/mcp so the secret never lands in an MCP */\n/* config. Kept separate from `conf` and locked to owner-only permissions. */\n/* -------------------------------------------------------------------------- */\n\nexport type StoredCredential = {\n apiKey: string;\n /** Workspace Personal Access Token (lt_pat_*) for the management API/CLI. */\n pat?: string;\n baseUrl: string;\n project: { slug: string; name: string };\n workspace?: { id: string; name: string };\n savedAt: string;\n};\n\n/**\n * Resolve the project slug a management command should target: explicit\n * `--project` flag > `LETTER_PROJECT` env (for scripts/CI) > the connected\n * project from `letter login`. Throws a clear error when none is available so\n * scripts fail loudly.\n */\nexport async function resolveProjectSlug(flag?: string): Promise<string> {\n if (flag) return flag;\n if (process.env.LETTER_PROJECT) return process.env.LETTER_PROJECT;\n const cred = await readCredential();\n if (cred?.project?.slug) return cred.project.slug;\n throw new Error(\n `No project. Pass --project <slug>, set LETTER_PROJECT, or run \\`${cliCommand()} login\\`.`,\n );\n}\n\nexport function credentialsPath(): string {\n return path.join(homedir(), \".letter\", \"credentials.json\");\n}\n\nexport async function saveCredential(cred: StoredCredential): Promise<string> {\n const file = credentialsPath();\n await mkdir(path.dirname(file), { recursive: true, mode: 0o700 });\n await writeFile(file, `${JSON.stringify(cred, null, 2)}\\n`, { mode: 0o600 });\n return file;\n}\n\nexport async function readCredential(): Promise<StoredCredential | null> {\n try {\n const raw = await readFile(credentialsPath(), \"utf8\");\n return JSON.parse(raw) as StoredCredential;\n } catch {\n return null;\n }\n}\n\nexport async function clearCredential(): Promise<void> {\n await rm(credentialsPath(), { force: true });\n}\n","import { getBaseUrl, readCredential } from \"./config.js\";\nimport { cliCommand } from \"./output.js\";\n\nconst USER_AGENT = \"@letterapp/cli\";\n\n/* -------------------------------------------------------------------------- */\n/* Device authorization (RFC 8628 style). No secret ever passes through argv. */\n/* -------------------------------------------------------------------------- */\n\nexport type StartResponse = {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n interval: number;\n expires_in: number;\n};\n\nexport type PollResponse =\n | { status: \"authorization_pending\" }\n | { status: \"slow_down\"; retryAfter?: number }\n | { status: \"access_denied\" }\n | { status: \"expired_token\" }\n | {\n status: \"approved\";\n api_key: string;\n /** Workspace PAT for the management API (lt_pat_*). */\n pat: string;\n base_url: string;\n project: { slug: string; name: string };\n workspace?: { id: string; name: string };\n };\n\n/** Starts a device-authorization flow against the given API base. */\nexport async function startDeviceAuth(base: string): Promise<StartResponse> {\n const res = await fetch(`${base}/v1/cli/auth/start`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: \"{}\",\n });\n if (!res.ok) {\n throw new Error(\n `Could not start login (HTTP ${res.status}). Is ${base} reachable?`,\n );\n }\n return (await res.json()) as StartResponse;\n}\n\n/** Polls once for approval. */\nexport async function pollDeviceAuth(\n base: string,\n deviceCode: string,\n): Promise<PollResponse> {\n const res = await fetch(`${base}/v1/cli/auth/poll`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: JSON.stringify({ device_code: deviceCode }),\n });\n\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get(\"retry-after\") ?? \"5\");\n return { status: \"slow_down\", retryAfter };\n }\n if (!res.ok) {\n throw new Error(`Login poll failed (HTTP ${res.status}).`);\n }\n return (await res.json()) as PollResponse;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Authenticated client. Resolves the key from the stored credential (written */\n/* by `letter login`) or LETTER_API_KEY. Used by data commands like `status`. */\n/* -------------------------------------------------------------------------- */\n\nexport interface ApiResponse<T = unknown> {\n status: number;\n data: T;\n}\n\nclass LetterClient {\n private maxRetries = 3;\n\n private async resolveAuth(): Promise<{ base: string; token: string }> {\n const cred = await readCredential();\n const token = process.env.LETTER_API_KEY || cred?.apiKey || \"\";\n if (!token) {\n throw new Error(\n `Not connected. Run \\`${cliCommand()} login\\` (or set LETTER_API_KEY) first.`,\n );\n }\n const base = getBaseUrl(process.env.LETTER_API_KEY ? undefined : cred?.baseUrl);\n return { base, token };\n }\n\n private async request<T = unknown>(\n method: string,\n path: string,\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n const { base, token } = await this.resolveAuth();\n const res = await fetch(`${base}${path}`, {\n method,\n headers: {\n authorization: `Bearer ${token}`,\n accept: \"application/json\",\n \"user-agent\": USER_AGENT,\n },\n });\n\n if (res.status === 429 && attempt <= this.maxRetries) {\n const retryAfter = Number(res.headers.get(\"retry-after\") || 2);\n await new Promise((r) => setTimeout(r, retryAfter * 1000 * attempt));\n return this.request<T>(method, path, attempt + 1);\n }\n\n const data = (res.status === 204 ? {} : await res.json()) as T;\n if (!res.ok) {\n const msg =\n (data as { error?: { message?: string } })?.error?.message ||\n `HTTP ${res.status}`;\n const err = new Error(msg) as Error & { status: number };\n err.status = res.status;\n throw err;\n }\n return { status: res.status, data };\n }\n\n get<T = unknown>(path: string) {\n return this.request<T>(\"GET\", path);\n }\n}\n\nexport const client = new LetterClient();\n\n/* -------------------------------------------------------------------------- */\n/* Management client. Authenticates with the workspace PAT (lt_pat_*) and */\n/* drives the control-plane (/v1/projects, sequences, broadcasts, ...). Used by */\n/* the resource command groups. */\n/* -------------------------------------------------------------------------- */\n\nexport type RequestInitLite = {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n form?: FormData;\n};\n\nclass ManagementClient {\n private maxRetries = 3;\n\n private async resolveAuth(): Promise<{ base: string; token: string }> {\n const cred = await readCredential();\n const token = process.env.LETTER_PAT || cred?.pat || \"\";\n if (!token) {\n throw new Error(\n `Not connected for management. Run \\`${cliCommand()} login\\` (or set LETTER_PAT) first.`,\n );\n }\n const base = getBaseUrl(process.env.LETTER_PAT ? undefined : cred?.baseUrl);\n return { base, token };\n }\n\n async request<T = unknown>(\n method: string,\n path: string,\n init: RequestInitLite = {},\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n const { base, token } = await this.resolveAuth();\n\n let url = `${base}${path}`;\n if (init.query) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(init.query)) {\n if (v !== undefined && v !== \"\") qs.set(k, String(v));\n }\n const s = qs.toString();\n if (s) url += `?${s}`;\n }\n\n const headers: Record<string, string> = {\n authorization: `Bearer ${token}`,\n accept: \"application/json\",\n \"user-agent\": USER_AGENT,\n };\n let body: BodyInit | undefined;\n if (init.form) {\n body = init.form;\n } else if (init.body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n body = JSON.stringify(init.body);\n }\n\n const res = await fetch(url, { method, headers, body });\n\n if (res.status === 429 && attempt <= this.maxRetries) {\n const retryAfter = Number(res.headers.get(\"retry-after\") || 2);\n await new Promise((r) => setTimeout(r, retryAfter * 1000 * attempt));\n return this.request<T>(method, path, init, attempt + 1);\n }\n\n const text = await res.text();\n const data = (text ? JSON.parse(text) : {}) as T;\n if (!res.ok) {\n const msg =\n (data as { error?: { message?: string } })?.error?.message ||\n `HTTP ${res.status}`;\n const err = new Error(msg) as Error & { status: number };\n err.status = res.status;\n throw err;\n }\n return { status: res.status, data };\n }\n\n get<T = unknown>(path: string, query?: RequestInitLite[\"query\"]) {\n return this.request<T>(\"GET\", path, { query });\n }\n post<T = unknown>(path: string, body?: unknown) {\n return this.request<T>(\"POST\", path, { body });\n }\n postForm<T = unknown>(path: string, form: FormData) {\n return this.request<T>(\"POST\", path, { form });\n }\n patch<T = unknown>(path: string, body?: unknown) {\n return this.request<T>(\"PATCH\", path, { body });\n }\n put<T = unknown>(path: string, body?: unknown) {\n return this.request<T>(\"PUT\", path, { body });\n }\n delete<T = unknown>(path: string) {\n return this.request<T>(\"DELETE\", path);\n }\n}\n\nexport const mgmt = new ManagementClient();\n","import { spawn } from \"node:child_process\";\n\n/**\n * Opens `url` in the default browser. Best-effort and non-blocking: if it fails\n * (headless box, no DISPLAY) the caller has already printed the URL so the user\n * can open it manually. Returns true if a launcher was spawned.\n */\nexport function openUrl(url: string): boolean {\n const platform = process.platform;\n let command: string;\n let args: string[];\n\n if (platform === \"darwin\") {\n command = \"open\";\n args = [url];\n } else if (platform === \"win32\") {\n command = \"cmd\";\n // `start` needs an empty title arg; the comma-free form avoids quoting woes.\n args = [\"/c\", \"start\", \"\", url];\n } else {\n command = \"xdg-open\";\n args = [url];\n }\n\n try {\n const child = spawn(command, args, { stdio: \"ignore\", detached: true });\n child.on(\"error\", () => {});\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n","import path from \"node:path\";\nimport { readFile, writeFile, stat } from \"node:fs/promises\";\n\n/**\n * Upserts `key=value` in an env file, creating it if needed. Existing keys are\n * replaced in place; new keys are appended. Returns the file path. The value is\n * never logged by this module - callers print only the key name.\n */\nexport async function upsertEnv(\n cwd: string,\n file: string,\n entries: Record<string, string>,\n): Promise<string> {\n const filePath = path.join(cwd, file);\n let contents = \"\";\n try {\n contents = await readFile(filePath, \"utf8\");\n } catch {\n contents = \"\";\n }\n\n let next = contents;\n for (const [key, value] of Object.entries(entries)) {\n const line = `${key}=${value}`;\n const re = new RegExp(`^${escapeRegExp(key)}=.*$`, \"m\");\n if (re.test(next)) {\n next = next.replace(re, line);\n } else {\n if (next.length && !next.endsWith(\"\\n\")) next += \"\\n\";\n next += `${line}\\n`;\n }\n }\n\n await writeFile(filePath, next, \"utf8\");\n return filePath;\n}\n\n/** True if a file exists at `cwd/name`. */\nexport async function fileExists(cwd: string, name: string): Promise<boolean> {\n try {\n await stat(path.join(cwd, name));\n return true;\n } catch {\n return false;\n }\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport { fileExists } from \"./env-file.js\";\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\n/**\n * Detects the package manager from lockfiles (then the `npm_config_user_agent`\n * of the running process), defaulting to npm.\n */\nexport async function detectPackageManager(\n cwd: string,\n): Promise<PackageManager> {\n if (await fileExists(cwd, \"pnpm-lock.yaml\")) return \"pnpm\";\n if (await fileExists(cwd, \"yarn.lock\")) return \"yarn\";\n if (await fileExists(cwd, \"bun.lockb\")) return \"bun\";\n if (await fileExists(cwd, \"package-lock.json\")) return \"npm\";\n\n const ua = process.env.npm_config_user_agent ?? \"\";\n if (ua.startsWith(\"pnpm\")) return \"pnpm\";\n if (ua.startsWith(\"yarn\")) return \"yarn\";\n if (ua.startsWith(\"bun\")) return \"bun\";\n return \"npm\";\n}\n\n/** Detects a likely Node web framework for friendlier guidance. */\nexport async function detectFramework(cwd: string): Promise<string | null> {\n try {\n const pkg = JSON.parse(await readFile(`${cwd}/package.json`, \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.next) return \"Next.js\";\n if (deps.nuxt) return \"Nuxt\";\n if (deps[\"@remix-run/node\"] || deps[\"@remix-run/react\"]) return \"Remix\";\n if (deps.express) return \"Express\";\n if (deps.fastify) return \"Fastify\";\n if (deps.hono) return \"Hono\";\n if (deps[\"@sveltejs/kit\"]) return \"SvelteKit\";\n return null;\n } catch {\n return null;\n }\n}\n\nexport type Runtime = \"node\" | \"python\" | \"ruby\" | \"go\" | \"php\" | \"other\";\nexport type Stack = { runtime: Runtime; framework: string | null };\n\n/**\n * Detects the project's language/runtime so the CLI installs the right thing\n * (only Node has an SDK today) and prints instructions in the right language.\n * Node is checked first since it's this CLI's primary audience.\n */\nexport async function detectStack(cwd: string): Promise<Stack> {\n if (await fileExists(cwd, \"package.json\")) {\n return { runtime: \"node\", framework: await detectFramework(cwd) };\n }\n if (\n (await fileExists(cwd, \"pyproject.toml\")) ||\n (await fileExists(cwd, \"requirements.txt\")) ||\n (await fileExists(cwd, \"Pipfile\")) ||\n (await fileExists(cwd, \"setup.py\"))\n ) {\n return { runtime: \"python\", framework: await detectPythonFramework(cwd) };\n }\n if ((await fileExists(cwd, \"Gemfile\")) || (await hasGemspec(cwd))) {\n return { runtime: \"ruby\", framework: await detectRubyFramework(cwd) };\n }\n if (await fileExists(cwd, \"go.mod\")) return { runtime: \"go\", framework: null };\n if (await fileExists(cwd, \"composer.json\")) {\n return { runtime: \"php\", framework: await detectPhpFramework(cwd) };\n }\n return { runtime: \"other\", framework: null };\n}\n\n/** Human-friendly label for the detected stack (framework if known). */\nexport function stackLabel(stack: Stack): string {\n if (stack.framework) return stack.framework;\n switch (stack.runtime) {\n case \"node\":\n return \"a Node.js project\";\n case \"python\":\n return \"a Python project\";\n case \"ruby\":\n return \"a Ruby project\";\n case \"go\":\n return \"a Go project\";\n case \"php\":\n return \"a PHP project\";\n default:\n return \"your project\";\n }\n}\n\n/** The language name to tell the agent to write in. */\nexport function languageName(stack: Stack): string {\n switch (stack.runtime) {\n case \"node\":\n return \"TypeScript\";\n case \"python\":\n return \"Python\";\n case \"ruby\":\n return \"Ruby\";\n case \"go\":\n return \"Go\";\n case \"php\":\n return \"PHP\";\n default:\n return \"your language\";\n }\n}\n\nasync function readIf(cwd: string, name: string): Promise<string> {\n try {\n return await readFile(`${cwd}/${name}`, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\nasync function hasGemspec(cwd: string): Promise<boolean> {\n try {\n return (await readdir(cwd)).some((f) => f.endsWith(\".gemspec\"));\n } catch {\n return false;\n }\n}\n\nasync function detectPythonFramework(cwd: string): Promise<string | null> {\n const txt = (\n (await readIf(cwd, \"requirements.txt\")) +\n (await readIf(cwd, \"pyproject.toml\")) +\n (await readIf(cwd, \"Pipfile\"))\n ).toLowerCase();\n if (txt.includes(\"django\")) return \"Django\";\n if (txt.includes(\"fastapi\")) return \"FastAPI\";\n if (txt.includes(\"flask\")) return \"Flask\";\n return null;\n}\n\nasync function detectRubyFramework(cwd: string): Promise<string | null> {\n const txt = (await readIf(cwd, \"Gemfile\")).toLowerCase();\n if (txt.includes(\"rails\")) return \"Rails\";\n if (txt.includes(\"sinatra\")) return \"Sinatra\";\n return null;\n}\n\nasync function detectPhpFramework(cwd: string): Promise<string | null> {\n const txt = (await readIf(cwd, \"composer.json\")).toLowerCase();\n if (txt.includes(\"laravel\")) return \"Laravel\";\n if (txt.includes(\"symfony\")) return \"Symfony\";\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Non-Node SDK installs (letterapp on PyPI / RubyGems) */\n/* -------------------------------------------------------------------------- */\n\nconst SDK_PYPI = \"letterapp\";\nconst SDK_GEM = \"letterapp\";\n\nexport type SdkInstall = { cmd: string; args: string[]; display: string };\n\nfunction sdkInstall(cmd: string, args: string[]): SdkInstall {\n return { cmd, args, display: `${cmd} ${args.join(\" \")}` };\n}\n\n/**\n * Picks the right Python installer for the project: uv > poetry > pipenv > pip.\n * Returns the command we'd run to add `letterapp`.\n */\nexport async function pythonSdkInstall(cwd: string): Promise<SdkInstall> {\n if (await fileExists(cwd, \"uv.lock\")) return sdkInstall(\"uv\", [\"add\", SDK_PYPI]);\n const pyproject = (await readIf(cwd, \"pyproject.toml\")).toLowerCase();\n if (\n (await fileExists(cwd, \"poetry.lock\")) ||\n pyproject.includes(\"[tool.poetry]\")\n ) {\n return sdkInstall(\"poetry\", [\"add\", SDK_PYPI]);\n }\n if (await fileExists(cwd, \"Pipfile\")) {\n return sdkInstall(\"pipenv\", [\"install\", SDK_PYPI]);\n }\n return sdkInstall(\"pip\", [\"install\", SDK_PYPI]);\n}\n\n/** Bundler when there's a Gemfile, otherwise a plain `gem install`. */\nexport async function rubySdkInstall(cwd: string): Promise<SdkInstall> {\n if (await fileExists(cwd, \"Gemfile\")) {\n return sdkInstall(\"bundle\", [\"add\", SDK_GEM]);\n }\n return sdkInstall(\"gem\", [\"install\", SDK_GEM]);\n}\n\n/** Runs an SdkInstall command, streaming output. Resolves to the exit code. */\nexport function runSdkInstall(\n install: SdkInstall,\n cwd: string,\n): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(install.cmd, install.args, {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", () => resolve(1));\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n}\n\nexport function installCommand(pm: PackageManager, pkg: string): string {\n switch (pm) {\n case \"pnpm\":\n return `pnpm add ${pkg}`;\n case \"yarn\":\n return `yarn add ${pkg}`;\n case \"bun\":\n return `bun add ${pkg}`;\n default:\n return `npm install ${pkg}`;\n }\n}\n\n/** Runs the install command, streaming output. Resolves to the exit code. */\nexport function runInstall(\n pm: PackageManager,\n pkg: string,\n cwd: string,\n): Promise<number> {\n const args = pm === \"npm\" ? [\"install\", pkg] : [\"add\", pkg];\n return new Promise((resolve) => {\n const child = spawn(pm, args, {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", () => resolve(1));\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n}\n","import { Command } from \"commander\";\nimport {\n getBaseUrl,\n DEFAULT_BASE_URL,\n saveCredential,\n} from \"../config.js\";\nimport { startDeviceAuth, pollDeviceAuth } from \"../client.js\";\nimport { openUrl } from \"../browser.js\";\nimport { upsertEnv } from \"../env-file.js\";\nimport {\n detectPackageManager,\n detectStack,\n installCommand,\n languageName,\n pythonSdkInstall,\n rubySdkInstall,\n runInstall,\n runSdkInstall,\n stackLabel,\n type SdkInstall,\n type Stack,\n} from \"../pm.js\";\nimport {\n banner,\n c,\n cliCommand,\n log,\n printError,\n printInfo,\n printSuccess,\n printWarning,\n prompt,\n} from \"../output.js\";\n\nconst SDK_PACKAGE = \"@letterapp/node\";\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\n// Node projects use .env.local (Next.js convention, gitignored by default);\n// everything else uses the more universal .env.\nfunction envFileFor(stack: Stack): string {\n return stack.runtime === \"node\" ? \".env.local\" : \".env\";\n}\n\ninterface LoginOptions {\n open: boolean;\n install: boolean;\n yes?: boolean;\n baseUrl?: string;\n apiKey?: string;\n}\n\nexport function registerLoginCommand(program: Command) {\n program\n .command(\"login\", { isDefault: true })\n .alias(\"init\")\n .description(\"Connect this project to Letter (interactive device login)\")\n .option(\"--no-open\", \"Don't open the browser; print the URL to open manually\")\n .option(\"-y, --yes\", \"Non-interactive: don't wait for Enter (agents/CI)\")\n .option(\"--no-install\", \"Skip installing the SDK\")\n .option(\"--base-url <url>\", \"Target a self-hosted or local Letter instance\")\n .option(\n \"--api-key <key>\",\n \"CI only: write a key without the device flow (never use in chat)\",\n )\n .action(async (opts: LoginOptions) => {\n const code = await runLogin(opts);\n if (code !== 0) process.exitCode = code;\n });\n}\n\nasync function runLogin(opts: LoginOptions): Promise<number> {\n const base = getBaseUrl(opts.baseUrl);\n const cwd = process.cwd();\n const interactive = process.stdin.isTTY && !opts.yes;\n\n banner();\n\n // CI escape hatch: write the provided key non-interactively. Documented as\n // automation-only; interactive/agent use should rely on the device flow so\n // no secret passes through the command line or chat.\n if (opts.apiKey) {\n const envFile = envFileFor(await detectStack(cwd));\n const entries: Record<string, string> = { LETTER_API_KEY: opts.apiKey };\n if (base !== DEFAULT_BASE_URL) entries.LETTER_BASE_URL = base;\n const file = await upsertEnv(cwd, envFile, entries);\n printSuccess(`Saved LETTER_API_KEY to ${rel(cwd, file)} (--api-key).`);\n printWarning(\n `--api-key is for CI. For interactive setup, run \\`${cliCommand()} login\\`.`,\n );\n return 0;\n }\n\n // 1. Begin the flow.\n let flow;\n try {\n flow = await startDeviceAuth(base);\n } catch (err) {\n printError(err);\n return 1;\n }\n\n log(c.bold(\"Confirm this code in your browser:\"));\n log();\n log(\" \" + c.cyan(c.bold(flow.user_code)));\n log();\n\n // 2. Open the browser (interactive: wait for Enter; otherwise auto/print).\n if (interactive && opts.open) {\n await prompt(c.dim(\"Press Enter to open your browser… \"));\n }\n if (opts.open) openUrl(flow.verification_uri_complete);\n printInfo(\"If your browser didn't open, visit:\");\n log(\" \" + c.blue(flow.verification_uri_complete));\n log();\n printInfo(\"Waiting for you to approve… (Ctrl+C to cancel)\");\n\n // 3. Poll until the user approves/denies or the code expires.\n const deadline = Date.now() + flow.expires_in * 1000;\n let intervalMs = Math.max(1, flow.interval) * 1000;\n\n while (Date.now() < deadline) {\n await sleep(intervalMs);\n let res;\n try {\n res = await pollDeviceAuth(base, flow.device_code);\n } catch (err) {\n printError(err);\n return 1;\n }\n\n if (res.status === \"authorization_pending\") continue;\n if (res.status === \"slow_down\") {\n intervalMs += 1000;\n continue;\n }\n if (res.status === \"access_denied\") {\n printError(new Error(\"Request denied in the browser. Nothing was changed.\"));\n return 1;\n }\n if (res.status === \"expired_token\") {\n printError(new Error(\"This login expired. Run the command again to retry.\"));\n return 1;\n }\n\n return finish(res, cwd, opts.install);\n }\n\n printError(new Error(\"Timed out waiting for approval. Run the command again.\"));\n return 1;\n}\n\nasync function finish(\n approved: {\n api_key: string;\n pat: string;\n base_url: string;\n project: { slug: string; name: string };\n workspace?: { id: string; name: string };\n },\n cwd: string,\n doInstall: boolean,\n): Promise<number> {\n const { api_key: apiKey, pat, base_url: baseUrl, project, workspace } = approved;\n log();\n printSuccess(`Approved for project ${c.bold(project.name)}.`);\n\n const stack = await detectStack(cwd);\n const isNode = stack.runtime === \"node\";\n const envFile = envFileFor(stack);\n\n // Write the key to the project env (value never printed) + shared store.\n const entries: Record<string, string> = { LETTER_API_KEY: apiKey };\n if (baseUrl && baseUrl !== DEFAULT_BASE_URL) entries.LETTER_BASE_URL = baseUrl;\n const written = await upsertEnv(cwd, envFile, entries);\n printSuccess(`Saved LETTER_API_KEY to ${rel(cwd, written)}.`);\n\n try {\n const credFile = await saveCredential({\n apiKey,\n pat,\n baseUrl: baseUrl || DEFAULT_BASE_URL,\n project,\n workspace,\n savedAt: new Date().toISOString(),\n });\n printSuccess(`Stored credentials in ${tildify(credFile)} for tooling (MCP + CLI).`);\n } catch {\n printWarning(\"Could not write ~/.letter/credentials.json (continuing).\");\n }\n\n // Install the SDK for the detected language. Node, Python, and Ruby have\n // official SDKs; everything else integrates over the HTTP API. We capture a\n // one-line `sdkNote` per path and hand the agent a single, language-agnostic\n // prompt - the agent knows the repo and writes idiomatic calls itself.\n let sdkNote: string;\n if (isNode) {\n const pm = await detectPackageManager(cwd);\n if (doInstall) {\n printInfo(`Installing ${SDK_PACKAGE} with ${pm}…`);\n const code = await runInstall(pm, SDK_PACKAGE, cwd);\n if (code === 0) printSuccess(`Installed ${SDK_PACKAGE}.`);\n else printWarning(`Install failed. Run: ${installCommand(pm, SDK_PACKAGE)}`);\n } else {\n printInfo(`Skipped install. Run: ${installCommand(pm, SDK_PACKAGE)}`);\n }\n sdkNote = `the ${SDK_PACKAGE} SDK is installed`;\n } else if (stack.runtime === \"python\" || stack.runtime === \"ruby\") {\n const install =\n stack.runtime === \"python\"\n ? await pythonSdkInstall(cwd)\n : await rubySdkInstall(cwd);\n await installSdk(install, doInstall);\n sdkNote =\n stack.runtime === \"python\"\n ? \"the letterapp Python SDK is installed\"\n : \"the letterapp Ruby gem is installed\";\n } else {\n printInfo(\n `Detected ${stackLabel(stack)}. No ${languageName(stack)} SDK yet, so the agent should use the HTTP API.`,\n );\n sdkNote =\n `there's no official ${languageName(stack)} SDK, so call the HTTP ingestion ` +\n \"API directly (POST /v1/identify and /v1/track with \" +\n \"Authorization: Bearer LETTER_API_KEY and Content-Type: application/json)\";\n }\n\n printAgentHandoff(sdkNote, envFile, cliCommand());\n return 0;\n}\n\n/** Shared install-or-print step for the non-Node SDKs (letterapp). */\nasync function installSdk(install: SdkInstall, doInstall: boolean): Promise<void> {\n if (doInstall) {\n printInfo(`Installing letterapp (${install.display})…`);\n const code = await runSdkInstall(install, process.cwd());\n if (code === 0) printSuccess(\"Installed letterapp.\");\n else printWarning(`Install failed. Run: ${install.display}`);\n } else {\n printInfo(`Skipped install. Run: ${install.display}`);\n }\n}\n\nconst AGENT_DOCS = \"https://letter.app/docs/agent-setup\";\n\n/**\n * Language-agnostic handoff for the last mile. The CLI does the mechanical setup\n * (key in the env, SDK installed where one exists) but deliberately does NOT\n * edit source - the coding agent has the repo context to write idiomatic calls.\n * So we print one ready-to-paste prompt that works for any stack plus a link to\n * the full guide, instead of language-specific snippets.\n */\nfunction printAgentHandoff(\n sdkNote: string,\n envFile: string,\n verifyCmd: string,\n): void {\n const rule = \" \" + \"─\".repeat(68);\n log();\n log(c.bold(\"Next: finish setup with your coding agent\"));\n log();\n log(c.dim(\" Paste this to your agent (Cursor, Claude Code, Codex, OpenClaw, Hermes, …):\"));\n log(c.dim(rule));\n // Plain (uncolored) so it copies cleanly into an agent prompt.\n log(\" Integrate Letter (product email automation) into this app. The CLI\");\n log(` already did setup: LETTER_API_KEY is in ${envFile} and ${sdkNote}.`);\n log(\" Using the right idioms for this codebase:\");\n log(\" - create a shared, server-side Letter client that reads\");\n log(\" LETTER_API_KEY from the environment (only set baseUrl/base_url\");\n log(\" when LETTER_BASE_URL is present),\");\n log(\" - call identify({ userId, email }) where users sign up or log in,\");\n log(\" - call track({ userId, event }) on the 2-3 most important actions,\");\n log(\" - flush before serverless handlers or scripts exit.\");\n log(\" Never print or commit the key. Then verify with the command below.\");\n log(` Full guide: ${AGENT_DOCS}`);\n log(c.dim(rule));\n log();\n log(c.dim(` Prefer to wire it up yourself? Same guide: ${AGENT_DOCS}`));\n log();\n log(c.dim(\"Verify it landed: \") + c.bold(`${verifyCmd} status`));\n log(\n c.dim(\n `Your API key is in ${envFile} - keep it out of source control, and don't echo its value.`,\n ),\n );\n log();\n}\n\nfunction rel(cwd: string, file: string): string {\n return file.startsWith(cwd) ? file.slice(cwd.length + 1) || file : file;\n}\n\nfunction tildify(file: string): string {\n const home = process.env.HOME || process.env.USERPROFILE;\n return home && file.startsWith(home) ? `~${file.slice(home.length)}` : file;\n}\n","import { Command } from \"commander\";\nimport { readCredential, clearCredential } from \"../config.js\";\nimport { c, cliCommand, isJsonMode, printJson, printInfo, printSuccess } from \"../output.js\";\n\nfunction mask(key: string): string {\n return key.length > 12 ? key.slice(0, 8) + \"…\" + key.slice(-4) : \"set\";\n}\n\nexport function registerAuthCommands(program: Command) {\n const auth = program.command(\"auth\").description(\"Manage the stored Letter connection\");\n\n auth\n .command(\"status\")\n .description(\"Show whether this machine is connected to Letter\")\n .action(async () => {\n const cred = await readCredential();\n const envKey = process.env.LETTER_API_KEY;\n\n if (!cred && !envKey) {\n if (isJsonMode()) printJson({ connected: false });\n else printInfo(\"Not connected. Run \" + c.bold(`${cliCommand()} login`) + \" to set up.\");\n return;\n }\n\n if (isJsonMode()) {\n printJson({\n connected: true,\n source: envKey ? \"env\" : \"credentials\",\n project: cred?.project ?? null,\n base_url: cred?.baseUrl ?? null,\n key: envKey ? \"env\" : cred ? mask(cred.apiKey) : null,\n });\n return;\n }\n\n printSuccess(\"Connected\" + (cred ? ` to ${c.bold(cred.project.name)}` : \"\"));\n if (cred) {\n console.log(c.dim(\" Project: \") + cred.project.slug);\n console.log(c.dim(\" Key: \") + mask(cred.apiKey));\n console.log(c.dim(\" API: \") + cred.baseUrl);\n }\n if (envKey) console.log(c.dim(\" LETTER_API_KEY is set in the environment.\"));\n });\n\n auth\n .command(\"logout\")\n .description(\"Remove the stored credential (~/.letter/credentials.json)\")\n .action(async () => {\n await clearCredential();\n printSuccess(\"Removed stored credential.\");\n });\n}\n","import { Command } from \"commander\";\nimport { client } from \"../client.js\";\nimport { readCredential } from \"../config.js\";\nimport { c, isJsonMode, printError, printInfo, printJson, printSuccess, spinner } from \"../output.js\";\n\ntype StatusResponse = {\n contacts?: number;\n events?: number;\n [k: string]: unknown;\n};\n\nexport function registerStatusCommand(program: Command) {\n program\n .command(\"status\")\n .description(\"Check whether your project has received any contacts or events\")\n .action(async () => {\n const spin = spinner(\"Checking your Letter project…\").start();\n try {\n const { data } = await client.get<StatusResponse>(\"/v1/status\");\n spin.stop();\n\n if (isJsonMode()) {\n printJson(data);\n return;\n }\n\n const cred = await readCredential();\n const contacts = data.contacts ?? 0;\n const events = data.events ?? 0;\n\n if (cred) printInfo(`Project ${c.bold(cred.project.name)}`);\n if (contacts > 0 || events > 0) {\n printSuccess(`Connected. ${contacts} contact(s), ${events} event(s) received.`);\n } else {\n printInfo(\"Connected, but no data yet. Fire your first identify/track call.\");\n }\n } catch (err) {\n spin.stop();\n printError(err);\n process.exitCode = 1;\n }\n });\n}\n","import { Command } from \"commander\";\nimport {\n getBaseUrl,\n setBaseUrl,\n getConfigPath,\n resetConfig,\n} from \"../config.js\";\nimport { c, isJsonMode, printError, printJson, printSuccess } from \"../output.js\";\n\nexport function registerConfigCommands(program: Command) {\n const cfg = program.command(\"config\").description(\"Manage CLI configuration\");\n\n cfg\n .command(\"set\")\n .description(\"Set a config value\")\n .argument(\"<key>\", \"Config key: base-url\")\n .argument(\"<value>\", \"Value to set\")\n .action((key: string, value: string) => {\n switch (key) {\n case \"base-url\":\n setBaseUrl(value);\n printSuccess(`Base URL set to ${getBaseUrl()}`);\n break;\n default:\n printError(new Error(`Unknown config key: ${key}. Valid keys: base-url`));\n process.exitCode = 1;\n }\n });\n\n cfg\n .command(\"get\")\n .description(\"Show CLI configuration\")\n .argument(\"[key]\", \"Config key (omit to show all)\")\n .action((key?: string) => {\n const all = { base_url: getBaseUrl(), config_path: getConfigPath() };\n if (key && key !== \"base-url\" && key !== \"path\") {\n printError(new Error(`Unknown config key: ${key}`));\n process.exitCode = 1;\n return;\n }\n if (isJsonMode()) {\n printJson(key === \"base-url\" ? { base_url: all.base_url } : key === \"path\" ? { config_path: all.config_path } : all);\n return;\n }\n if (key === \"base-url\") console.log(all.base_url);\n else if (key === \"path\") console.log(all.config_path);\n else for (const [k, v] of Object.entries(all)) console.log(c.bold(k + \":\") + \" \" + v);\n });\n\n cfg\n .command(\"reset\")\n .description(\"Reset CLI configuration to defaults\")\n .action(() => {\n resetConfig();\n printSuccess(\"Configuration reset.\");\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport { Command } from \"commander\";\nimport { mgmt } from \"../client.js\";\nimport { resolveProjectSlug } from \"../config.js\";\nimport { emit, printError, printSuccess } from \"../output.js\";\n\n/**\n * Resource command groups for the management API. Each group wraps the same\n * REST endpoints the dashboard uses (`/v1/...`), so the whole app is operable\n * from the terminal. Everything honors the global `--json` flag (see\n * `output.emit`) and project-scoped groups take `--project <slug>` (defaulting\n * to the project connected by `letter login`).\n *\n * The shape is data-driven: one `ResourceSpec` per resource, expanded into\n * `list/get/create/update/delete` + custom verb subcommands by `register()`.\n * Keeping it declarative means a new endpoint is a few lines, not a new file.\n */\n\ntype Field = {\n /** commander option flag, e.g. \"--name <name>\". */\n flag: string;\n /** request-body key, e.g. \"name\". */\n key: string;\n /** parse the value as JSON (supports `@file.json` to read from disk). */\n json?: boolean;\n /** coerce to a number. */\n number?: boolean;\n /** coerce to a boolean. */\n boolean?: boolean;\n /** (multipart only) read the value as a file path and upload its bytes. */\n file?: boolean;\n description?: string;\n};\n\ntype Action = {\n name: string;\n describe: string;\n method: \"get\" | \"post\" | \"put\" | \"patch\" | \"delete\";\n /** Path suffix appended after the resource (and id, if `needsId`). */\n suffix: string;\n /** Whether the verb operates on a single item (default true). */\n needsId?: boolean;\n fields?: Field[];\n /** Query params for GET verbs. */\n query?: Field[];\n /** Send fields as multipart/form-data (for file uploads). */\n multipart?: boolean;\n};\n\ntype ResourceSpec = {\n /** Command group name (also the default path segment). */\n name: string;\n describe: string;\n /** Nested under /v1/projects/{slug} when true. */\n scoped: boolean;\n /** Path segment if different from `name`. */\n segment?: string;\n /** Hidden back-compat alias for the group name. */\n alias?: string;\n /** Positional id arg name (e.g. \"externalId\", \"email\"). Default \"id\". */\n idName?: string;\n list?: { paginated?: boolean; query?: Field[] };\n get?: boolean;\n create?: Field[];\n update?: Field[];\n remove?: boolean;\n actions?: Action[];\n};\n\nasync function readValue(raw: string): Promise<string> {\n if (raw.startsWith(\"@\")) return (await readFile(raw.slice(1), \"utf8\")).trim();\n return raw;\n}\n\nasync function buildBody(\n fields: Field[],\n opts: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const body: Record<string, unknown> = {};\n for (const f of fields) {\n const v = opts[camel(f.key)];\n if (v === undefined) continue;\n if (f.json) {\n body[f.key] = JSON.parse(await readValue(String(v)));\n } else if (f.number) {\n body[f.key] = Number(v);\n } else if (f.boolean) {\n body[f.key] = v === true || v === \"true\";\n } else {\n body[f.key] = await readValue(String(v));\n }\n }\n return body;\n}\n\nasync function buildForm(\n fields: Field[],\n opts: Record<string, unknown>,\n): Promise<FormData> {\n const form = new FormData();\n for (const f of fields) {\n const v = opts[camel(f.key)];\n if (v === undefined) continue;\n if (f.file) {\n const path = String(v);\n const bytes = await readFile(path);\n const name = path.split(\"/\").pop() || f.key;\n form.append(f.key, new Blob([new Uint8Array(bytes)]), name);\n } else if (f.json) {\n // The server parses these fields with JSON.parse; keep them as strings.\n form.append(f.key, await readValue(String(v)));\n } else {\n form.append(f.key, String(v));\n }\n }\n return form;\n}\n\nfunction buildQuery(\n fields: Field[],\n opts: Record<string, unknown>,\n): Record<string, string | number | undefined> {\n const q: Record<string, string | number | undefined> = {};\n for (const f of fields) {\n const v = opts[camel(f.key)];\n if (v === undefined) continue;\n q[f.key] = f.number ? Number(v) : String(v);\n }\n return q;\n}\n\n/** \"external-id\" / \"external_id\" → \"externalId\" (commander camelCases flags). */\nfunction camel(key: string): string {\n return key.replace(/[-_]([a-z])/g, (_, ch: string) => ch.toUpperCase());\n}\n\nfunction applyFields(cmd: Command, fields: Field[]) {\n for (const f of fields) {\n cmd.option(f.flag, f.description ?? f.key);\n }\n}\n\nasync function basePath(spec: ResourceSpec, project?: string): Promise<string> {\n const seg = spec.segment ?? spec.name;\n if (!spec.scoped) return `/v1/${seg}`;\n const slug = await resolveProjectSlug(project);\n return `/v1/projects/${slug}/${seg}`;\n}\n\nfunction withProject(cmd: Command, scoped: boolean): Command {\n if (scoped) {\n cmd.option(\"-p, --project <slug>\", \"Project slug (default: connected project)\");\n }\n return cmd;\n}\n\nfunction fail(err: unknown) {\n printError(err);\n process.exitCode = 1;\n}\n\nfunction register(program: Command, spec: ResourceSpec) {\n const group = program.command(spec.name).description(spec.describe);\n if (spec.alias) group.alias(spec.alias);\n const idName = spec.idName ?? \"id\";\n\n if (spec.list) {\n const cmd = withProject(\n group.command(\"list\").description(`List ${spec.name}`),\n spec.scoped,\n );\n if (spec.list.paginated) {\n cmd.option(\"--limit <n>\", \"Max items (1-100)\");\n cmd.option(\"--cursor <cursor>\", \"Pagination cursor\");\n }\n if (spec.list.query) applyFields(cmd, spec.list.query);\n cmd.action(async (opts) => {\n try {\n const query: Record<string, string | number | undefined> = {};\n if (spec.list?.paginated) {\n if (opts.limit) query.limit = Number(opts.limit);\n if (opts.cursor) query.cursor = opts.cursor;\n }\n if (spec.list?.query) Object.assign(query, buildQuery(spec.list.query, opts));\n const { data } = await mgmt.get(await basePath(spec, opts.project), query);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.get) {\n const cmd = withProject(\n group\n .command(\"get\")\n .description(`Get a ${spec.name} by ${idName}`)\n .argument(`<${idName}>`, idName),\n spec.scoped,\n );\n cmd.action(async (idValue: string, opts) => {\n try {\n const path = `${await basePath(spec, opts.project)}/${encodeURIComponent(idValue)}`;\n const { data } = await mgmt.get(path);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.create) {\n const cmd = withProject(\n group.command(\"create\").description(`Create a ${spec.name}`),\n spec.scoped,\n );\n applyFields(cmd, spec.create);\n cmd.action(async (opts) => {\n try {\n const body = await buildBody(spec.create!, opts);\n const { data } = await mgmt.post(await basePath(spec, opts.project), body);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.update) {\n const cmd = withProject(\n group\n .command(\"update\")\n .description(`Update a ${spec.name}`)\n .argument(`<${idName}>`, idName),\n spec.scoped,\n );\n applyFields(cmd, spec.update);\n cmd.action(async (idValue: string, opts) => {\n try {\n const body = await buildBody(spec.update!, opts);\n const path = `${await basePath(spec, opts.project)}/${encodeURIComponent(idValue)}`;\n const { data } = await mgmt.patch(path, body);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n if (spec.remove) {\n const cmd = withProject(\n group\n .command(\"delete\")\n .description(`Delete a ${spec.name}`)\n .argument(`<${idName}>`, idName),\n spec.scoped,\n );\n cmd.action(async (idValue: string, opts) => {\n try {\n const path = `${await basePath(spec, opts.project)}/${encodeURIComponent(idValue)}`;\n await mgmt.delete(path);\n printSuccess(`Deleted ${spec.name.replace(/s$/, \"\")} ${idValue}.`);\n } catch (err) {\n fail(err);\n }\n });\n }\n\n for (const action of spec.actions ?? []) {\n const needsId = action.needsId ?? true;\n const cmd = withProject(\n needsId\n ? group\n .command(action.name)\n .description(action.describe)\n .argument(`<${idName}>`, idName)\n : group.command(action.name).description(action.describe),\n spec.scoped,\n );\n if (action.fields) applyFields(cmd, action.fields);\n if (action.query) applyFields(cmd, action.query);\n\n const handler = async (...args: unknown[]) => {\n // commander passes (idValue?, opts, command). Last arg is the Command.\n const opts = args[args.length - 2] as Record<string, unknown>;\n const idValue = needsId ? (args[0] as string) : undefined;\n try {\n let path = await basePath(spec, opts.project as string | undefined);\n if (needsId) path += `/${encodeURIComponent(idValue!)}`;\n path += action.suffix;\n\n if (action.method === \"get\") {\n const query = action.query ? buildQuery(action.query, opts) : undefined;\n const { data } = await mgmt.get(path, query);\n emit(data);\n return;\n }\n if (action.multipart && action.fields) {\n const form = await buildForm(action.fields, opts);\n const { data, status } = await mgmt.request(\n action.method.toUpperCase(),\n path,\n { form },\n );\n if (status === 204) printSuccess(`${action.name} ok.`);\n else emit(data);\n return;\n }\n const body = action.fields ? await buildBody(action.fields, opts) : undefined;\n const { data, status } = await mgmt.request(\n action.method.toUpperCase(),\n path,\n { body },\n );\n if (status === 204) printSuccess(`${action.name} ok.`);\n else emit(data);\n } catch (err) {\n fail(err);\n }\n };\n cmd.action(handler);\n }\n}\n\nconst cursor = { paginated: true } as const;\n\nconst SPECS: ResourceSpec[] = [\n // -- Workspace ------------------------------------------------------------\n {\n name: \"projects\",\n describe: \"Manage projects\",\n scoped: false,\n idName: \"slug\",\n list: {},\n get: true,\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--timezone <tz>\", key: \"timezone\" },\n ],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--timezone <tz>\", key: \"timezone\" },\n ],\n remove: true,\n },\n {\n name: \"members\",\n describe: \"Manage workspace members\",\n scoped: false,\n idName: \"userId\",\n list: {},\n create: [\n { flag: \"--email <email>\", key: \"email\" },\n { flag: \"--role <role>\", key: \"role\", description: \"member | admin\" },\n ],\n remove: true,\n },\n {\n name: \"invitations\",\n describe: \"Manage workspace invitations\",\n scoped: false,\n list: {},\n create: [\n { flag: \"--email <email>\", key: \"email\" },\n { flag: \"--role <role>\", key: \"role\", description: \"member | admin\" },\n ],\n remove: true,\n },\n {\n // Personal access tokens (lt_pat_*) authenticate the CLI / Management API.\n // The dashboard calls these \"API keys\"; `tokens` stays as a hidden alias.\n name: \"api-keys\",\n alias: \"tokens\",\n segment: \"tokens\",\n describe: \"Manage your personal access tokens (lt_pat_*, the CLI/API credential)\",\n scoped: false,\n list: {},\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n {\n flag: \"--expires-at <iso>\",\n key: \"expires_at\",\n description: \"Expiry as an ISO 8601 datetime (default: never)\",\n },\n ],\n remove: true,\n },\n // -- Contacts & data ------------------------------------------------------\n {\n name: \"contacts\",\n describe: \"Manage contacts\",\n scoped: true,\n idName: \"externalId\",\n list: { ...cursor },\n get: true,\n actions: [\n {\n name: \"suppress\",\n describe: \"Suppress a contact\",\n method: \"post\",\n suffix: \"/suppress\",\n },\n {\n name: \"resubscribe\",\n describe: \"Resubscribe a contact\",\n method: \"post\",\n suffix: \"/resubscribe\",\n },\n {\n name: \"import\",\n describe: \"Upload a CSV import (--file <path> --mapping <json|@file>)\",\n method: \"post\",\n needsId: false,\n suffix: \"/imports\",\n multipart: true,\n fields: [\n { flag: \"--file <path>\", key: \"file\", file: true },\n { flag: \"--mapping <json>\", key: \"mapping\", json: true },\n { flag: \"--dedupe <strategy>\", key: \"dedupe\", description: \"update | skip\" },\n { flag: \"--row-count <n>\", key: \"rowCount\" },\n ],\n },\n ],\n },\n {\n name: \"accounts\",\n describe: \"Inspect accounts\",\n scoped: true,\n idName: \"externalId\",\n list: { ...cursor },\n get: true,\n },\n {\n name: \"events\",\n describe: \"List events\",\n scoped: true,\n list: { ...cursor, query: [{ flag: \"--name <name>\", key: \"name\" }] },\n },\n {\n name: \"suppressions\",\n describe: \"Manage the suppression list\",\n scoped: true,\n idName: \"email\",\n list: { ...cursor },\n create: [{ flag: \"--email <email>\", key: \"email\" }],\n remove: true,\n },\n {\n name: \"segments\",\n describe: \"Manage segments\",\n scoped: true,\n list: {},\n get: true,\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--filter <json>\", key: \"filter\", json: true },\n ],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--filter <json>\", key: \"filter\", json: true },\n ],\n remove: true,\n actions: [\n {\n name: \"preview\",\n describe: \"Count contacts matching a filter (--filter <json|@file>)\",\n method: \"post\",\n needsId: false,\n suffix: \"/preview\",\n fields: [{ flag: \"--filter <json>\", key: \"filter\", json: true }],\n },\n ],\n },\n // -- Sequences ------------------------------------------------------------\n {\n name: \"sequences\",\n describe: \"Manage drip sequences\",\n scoped: true,\n list: {},\n get: true,\n create: [{ flag: \"--name <name>\", key: \"name\" }],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--status <status>\", key: \"status\", description: \"active | archived\" },\n ],\n remove: true,\n actions: [\n {\n name: \"draft\",\n describe: \"Save the draft graph + trigger\",\n method: \"put\",\n suffix: \"/draft\",\n fields: [\n { flag: \"--graph <json>\", key: \"graph\", json: true },\n { flag: \"--trigger <json>\", key: \"trigger\", json: true },\n { flag: \"--expected-revision <n>\", key: \"expected_revision\", number: true },\n ],\n },\n {\n name: \"publish\",\n describe: \"Publish the current draft\",\n method: \"post\",\n suffix: \"/publish\",\n },\n {\n name: \"preview\",\n describe: \"Render an email node (--node-id <id>)\",\n method: \"post\",\n suffix: \"/preview\",\n fields: [{ flag: \"--node-id <id>\", key: \"nodeId\" }],\n },\n {\n name: \"test-email\",\n describe: \"Send a test email (--node-id <id> --to <email>)\",\n method: \"post\",\n suffix: \"/test-email\",\n fields: [\n { flag: \"--node-id <id>\", key: \"nodeId\" },\n { flag: \"--to <email>\", key: \"to\" },\n ],\n },\n {\n name: \"activity\",\n describe: \"Show enrollment activity\",\n method: \"get\",\n suffix: \"/activity\",\n },\n {\n name: \"versions\",\n describe: \"List published versions\",\n method: \"get\",\n suffix: \"/versions\",\n },\n ],\n },\n // -- Broadcasts -----------------------------------------------------------\n {\n name: \"broadcasts\",\n describe: \"Manage broadcasts\",\n scoped: true,\n list: {},\n get: true,\n create: [{ flag: \"--name <name>\", key: \"name\" }],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--subject <subject>\", key: \"subject\" },\n { flag: \"--preview <preview>\", key: \"preview\" },\n { flag: \"--audience <json>\", key: \"audience\", json: true },\n { flag: \"--template-id <id>\", key: \"template_id\" },\n { flag: \"--body-doc <json>\", key: \"body_doc\", json: true },\n ],\n remove: true,\n actions: [\n {\n name: \"preflight\",\n describe: \"Validate before sending\",\n method: \"post\",\n suffix: \"/preflight\",\n },\n {\n name: \"schedule\",\n describe: \"Schedule (--scheduled-at <iso>) or send now (omit)\",\n method: \"post\",\n suffix: \"/schedule\",\n fields: [{ flag: \"--scheduled-at <iso>\", key: \"scheduled_at\" }],\n },\n {\n name: \"cancel\",\n describe: \"Cancel a scheduled or sending broadcast\",\n method: \"post\",\n suffix: \"/cancel\",\n },\n {\n name: \"live\",\n describe: \"Live status, stats, and recent activity\",\n method: \"get\",\n suffix: \"/live\",\n },\n ],\n },\n // -- Templates ------------------------------------------------------------\n {\n name: \"templates\",\n describe: \"Manage email templates\",\n scoped: true,\n list: {},\n get: true,\n create: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--design <json>\", key: \"design\", json: true },\n ],\n update: [\n { flag: \"--name <name>\", key: \"name\" },\n { flag: \"--design <json>\", key: \"design\", json: true },\n ],\n remove: true,\n actions: [\n {\n name: \"default\",\n describe: \"Set as the project default\",\n method: \"post\",\n suffix: \"/default\",\n },\n {\n name: \"reset\",\n describe: \"Reset design to a preset (--preset plain|branded)\",\n method: \"post\",\n suffix: \"/reset\",\n fields: [{ flag: \"--preset <preset>\", key: \"preset\" }],\n },\n {\n name: \"logo\",\n describe: \"Upload a logo (--file <path>)\",\n method: \"post\",\n suffix: \"/logo\",\n multipart: true,\n fields: [{ flag: \"--file <path>\", key: \"file\", file: true }],\n },\n {\n name: \"remove-logo\",\n describe: \"Remove the template logo\",\n method: \"delete\",\n suffix: \"/logo\",\n },\n ],\n },\n // -- Settings -------------------------------------------------------------\n {\n name: \"domains\",\n describe: \"Manage sending domains\",\n scoped: true,\n list: {},\n create: [{ flag: \"--domain <domain>\", key: \"domain\" }],\n remove: true,\n actions: [\n {\n name: \"verify\",\n describe: \"Re-check DKIM verification\",\n method: \"post\",\n suffix: \"/verify\",\n },\n ],\n },\n {\n // Project ingestion keys (lt_live_*) authenticate the SDKs / ingestion API.\n // The dashboard calls these \"Project tokens\"; `keys` stays as a hidden alias.\n name: \"project-tokens\",\n alias: \"keys\",\n segment: \"keys\",\n describe: \"Manage project ingestion keys (lt_live_*, the SDK/ingestion credential)\",\n scoped: true,\n list: {},\n create: [{ flag: \"--name <name>\", key: \"name\" }],\n remove: true,\n },\n];\n\nexport function registerResourceCommands(program: Command) {\n for (const spec of SPECS) register(program, spec);\n\n // `letter me` — the token's identity (handy sanity check).\n program\n .command(\"me\")\n .description(\"Show the token's user, workspace, and role\")\n .action(async () => {\n try {\n const { data } = await mgmt.get(\"/v1/me\");\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n\n // Sender identity + sending mode don't fit the CRUD mold: register directly.\n program\n .command(\"sender-identity\")\n .description(\"Set From / From-name / Reply-To (--from-email, --from-name, --reply-to-email)\")\n .option(\"-p, --project <slug>\", \"Project slug (default: connected project)\")\n .option(\"--from-email <email>\", \"From address\")\n .option(\"--from-name <name>\", \"From display name\")\n .option(\"--reply-to-email <email>\", \"Reply-To address\")\n .action(async (opts) => {\n try {\n const slug = await resolveProjectSlug(opts.project);\n const body: Record<string, unknown> = {};\n if (opts.fromEmail !== undefined) body.from_email = opts.fromEmail;\n if (opts.fromName !== undefined) body.from_name = opts.fromName;\n if (opts.replyToEmail !== undefined) body.reply_to_email = opts.replyToEmail;\n const { data } = await mgmt.put(`/v1/projects/${slug}/sender-identity`, body);\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"sending-mode\")\n .description(\"Set the sending mode (letter_subdomain | byo_domain)\")\n .argument(\"<mode>\", \"letter_subdomain | byo_domain\")\n .option(\"-p, --project <slug>\", \"Project slug (default: connected project)\")\n .action(async (mode: string, opts) => {\n try {\n const slug = await resolveProjectSlug(opts.project);\n const { data } = await mgmt.put(`/v1/projects/${slug}/sending-mode`, {\n sending_mode: mode,\n });\n emit(data);\n } catch (err) {\n fail(err);\n }\n });\n}\n"],"mappings":"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","names":["path","path","readFile","writeFile","spawn","readFile","readFile","spawn","program","program","program","program","readFile","readFile","path","program","data","status"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@letterapp/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Letter CLI - connect your app to Letter in one command. Interactive, secure device login: no API key ever touches your shell or chat.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://letter.app",
|