@animaapp/cli 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/auth/store.ts","../src/api/errors.ts","../src/auth/token.ts","../src/api/client.ts","../src/output/formatter.ts","../src/output/progress.ts","../src/output/pretty.ts","../src/utils/figma.ts","../src/commands/publish.ts","../src/api/mcp-client.ts","../src/commands/codegen.ts","../src/utils/files.ts","../src/commands/download.ts","../src/utils/download.ts","../src/commands/auth.ts","../src/auth/oauth.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createCommand } from \"./commands/create.js\";\nimport { publishCommand } from \"./commands/publish.js\";\nimport { codegenCommand } from \"./commands/codegen.js\";\nimport { downloadCommand } from \"./commands/download.js\";\nimport { authCommand } from \"./commands/auth.js\";\nimport { CliError } from \"./api/errors.js\";\n\nconst program = new Command()\n .name(\"anima\")\n .description(\n `Anima CLI - Generate production-ready apps from prompts, URLs, or Figma designs.\n\nAUTHENTICATION:\n Set ANIMA_API_TOKEN env var or run: npx @animaapp/cli auth --token <token>\n Get key: https://dev.animaapp.com > Settings > API Keys\n\nTIMING (important for AI agents):\n create → 3-7 minutes (SSE streaming, set timeout to 600000ms)\n publish → 1-3 minutes\n codegen → 2-5 minutes\n download → seconds\n The --timeout default is 600000ms (10 min). Do NOT reduce it.\n\nCOMMANDS:\n create Create app from prompt, URL, or Figma design\n publish Deploy playground to live URL or npm package\n codegen Convert Figma design to code files (no playground)\n download Download project from an Anima playground\n auth Manage authentication (token stored in ~/.config/anima/)\n\nEXAMPLES:\n npx @animaapp/cli auth --token <your-token>\n npx @animaapp/cli create -t p2c -p \"SaaS dashboard with sidebar and analytics\"\n npx @animaapp/cli create -t l2c -u https://stripe.com\n npx @animaapp/cli create -t f2c --file-key abc --nodes 42:15\n npx @animaapp/cli publish abc123xyz\n npx @animaapp/cli codegen --file-key abc --nodes 42:15 -o ./components\n npx @animaapp/cli download https://dev.animaapp.com/chat/abc123xyz\n\nOUTPUT: JSON to stdout when piped (for AI tools), pretty text in terminals.\n Progress is streamed to stderr via --verbose when in JSON mode.`\n )\n .version(\"0.1.0\", \"-v, --version\");\n\nprogram.addCommand(createCommand);\nprogram.addCommand(publishCommand);\nprogram.addCommand(codegenCommand);\nprogram.addCommand(downloadCommand);\nprogram.addCommand(authCommand);\n\nprogram.parseAsync(process.argv).catch((err) => {\n if (err instanceof CliError) {\n if (process.stdout.isTTY) {\n console.error(err.message);\n } else {\n process.stdout.write(\n JSON.stringify({\n success: false,\n error: { code: err.code, message: err.message },\n }) + \"\\n\"\n );\n }\n process.exit(err.exitCode);\n }\n\n console.error(err);\n process.exit(1);\n});\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { streamGeneration, buildHeaders } from \"../api/client.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { printSessionResult } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { validationError, CliError } from \"../api/errors.js\";\nimport type { CreateType, Conventions } from \"../api/types.js\";\n\nconst DEFAULT_API_URL = \"https://public-api.animaapp.com\";\nconst PLAYGROUND_BASE = \"https://dev.animaapp.com/chat\";\n\nexport const createCommand = new Command(\"create\")\n .description(\"Create app from prompt, URL, or Figma design (3-7 min)\")\n .requiredOption(\"-t, --type <type>\", \"Generation type: p2c, l2c, or f2c\")\n .option(\"-p, --prompt <prompt>\", \"Text prompt (p2c)\")\n .option(\"-u, --url <url>\", \"Website URL (l2c)\")\n .option(\"--file-key <key>\", \"Figma file key or URL (f2c)\")\n .option(\"--nodes <nodes>\", \"Figma node IDs, comma-separated (f2c)\")\n .option(\"--figma-token <token>\", \"Figma personal access token (f2c)\")\n .option(\"--framework <fw>\", \"react | html\", \"react\")\n .option(\"--styling <style>\", \"tailwind | css | plain_css | css_modules | inline_styles\", \"tailwind\")\n .option(\"--language <lang>\", \"typescript | javascript\")\n .option(\"--ui-library <lib>\", \"mui | antd | shadcn | clean_react\")\n .option(\"--guidelines <text>\", \"Additional constraints (p2c only)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const type = opts.type as CreateType;\n validateCreateOptions(type, opts);\n\n const auth = resolveAuth();\n const headers = buildHeaders(auth.token, auth.teamId);\n const { endpoint, body } = buildCreateRequest(type, opts, auth.figmaToken);\n\n progress.start(`Creating ${type.toUpperCase()} playground...`);\n\n const result = await streamGeneration(\n `${opts.apiUrl}${endpoint}`,\n body,\n headers,\n {\n onQueueing: () => progress.update(\"Queued, waiting...\"),\n onStart: (sid) => progress.update(`Started (${sid.slice(0, 8)}...)...`),\n onProgress: (msgs) => {\n const running = msgs.find((m) => m.status === \"running\");\n if (running) progress.update(running.title);\n },\n onGeneratingCode: (pct) => progress.update(`Generating code (${pct}%)...`),\n onCompleted: () => progress.update(\"Finalizing...\"),\n },\n parseInt(opts.timeout, 10)\n );\n\n const playgroundUrl = `${PLAYGROUND_BASE}/${result.sessionId}`;\n\n progress.succeed(\"Playground created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({\n sessionId: result.sessionId,\n playgroundUrl,\n tokenUsage: result.tokenUsage,\n });\n } else {\n outputResult(mode, {\n success: true,\n sessionId: result.sessionId,\n playgroundUrl,\n tokenUsage: result.tokenUsage,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\nfunction validateCreateOptions(type: CreateType, opts: Record<string, string>): void {\n if (![\"p2c\", \"l2c\", \"f2c\"].includes(type)) {\n throw validationError(`Invalid type \"${type}\". Must be p2c, l2c, or f2c.`);\n }\n\n if (type === \"p2c\" && !opts.prompt) {\n throw validationError(\"--prompt is required for p2c type\");\n }\n\n if (type === \"l2c\" && !opts.url) {\n throw validationError(\"--url is required for l2c type\");\n }\n\n if (type === \"f2c\" && !opts.fileKey) {\n throw validationError(\"--file-key is required for f2c type\");\n }\n}\n\nfunction buildCreateRequest(\n type: CreateType,\n opts: Record<string, string>,\n storedFigmaToken?: string\n): { endpoint: string; body: Record<string, unknown> } {\n // Default language to typescript when framework is react\n const language = opts.language ?? (opts.framework === \"react\" ? \"typescript\" : undefined);\n\n const conventions: Conventions = {\n framework: opts.framework as Conventions[\"framework\"],\n language: language as Conventions[\"language\"],\n styling: opts.styling as Conventions[\"styling\"],\n uiLibrary: opts.uiLibrary as Conventions[\"uiLibrary\"],\n };\n\n // Remove undefined values\n Object.keys(conventions).forEach((key) => {\n if (conventions[key as keyof Conventions] === undefined) {\n delete conventions[key as keyof Conventions];\n }\n });\n\n switch (type) {\n case \"p2c\":\n return {\n endpoint: \"/v1/p2c\",\n body: {\n params: {\n prompt: opts.prompt,\n conventions,\n ...(opts.guidelines ? { guidelines: opts.guidelines } : {}),\n },\n },\n };\n\n case \"l2c\":\n return {\n endpoint: \"/v1/l2c\",\n body: {\n params: {\n input: { type: \"url\", url: opts.url },\n conventions,\n assetsStorage: { type: \"bundled\" },\n },\n },\n };\n\n case \"f2c\": {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n: string) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n\n // Resolve Figma token: flag > env var > stored credentials > error\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || storedFigmaToken;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required for f2c. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n\n return {\n endpoint: \"/v1/codegen\",\n body: {\n fileKey,\n nodesId,\n figmaToken,\n framework: conventions.framework,\n language: conventions.language,\n styling: conventions.styling,\n uiLibrary: conventions.uiLibrary,\n },\n };\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".config\", \"anima\");\nconst CREDENTIALS_FILE = path.join(CONFIG_DIR, \"credentials.json\");\n\ntype Credentials = {\n token: string;\n teamId?: string;\n figmaToken?: string;\n};\n\nexport function readCredentials(): Credentials | null {\n try {\n if (!fs.existsSync(CREDENTIALS_FILE)) return null;\n const content = fs.readFileSync(CREDENTIALS_FILE, \"utf-8\");\n const parsed = JSON.parse(content);\n if (!parsed.token) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nexport function writeCredentials(credentials: Partial<Credentials>): void {\n // Merge with existing credentials so we can update fields independently\n const existing = readCredentials() ?? {};\n const merged = { ...existing, ...credentials };\n\n // Remove undefined values\n for (const key of Object.keys(merged) as (keyof Credentials)[]) {\n if (merged[key] === undefined) delete merged[key];\n }\n\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(\n CREDENTIALS_FILE,\n JSON.stringify(merged, null, 2) + \"\\n\",\n { mode: 0o600 }\n );\n}\n\nexport function deleteCredentials(): boolean {\n try {\n if (fs.existsSync(CREDENTIALS_FILE)) {\n fs.unlinkSync(CREDENTIALS_FILE);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\nexport function getCredentialsPath(): string {\n return CREDENTIALS_FILE;\n}\n\n/**\n * Extract the defaultTeamId from a JWT token payload (base64-decoded, no verification).\n * Returns undefined if extraction fails.\n */\nexport function extractTeamIdFromJWT(token: string): string | undefined {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf-8\")\n );\n return payload.defaultTeamId ?? undefined;\n } catch {\n return undefined;\n }\n}\n","export const EXIT_CODES = {\n SUCCESS: 0,\n API_ERROR: 1,\n AUTH_ERROR: 2,\n VALIDATION_ERROR: 3,\n TIMEOUT: 4,\n} as const;\n\nexport type ErrorCode =\n | \"AUTH_REQUIRED\"\n | \"AUTH_INVALID\"\n | \"VALIDATION_ERROR\"\n | \"API_ERROR\"\n | \"STREAM_ERROR\"\n | \"TIMEOUT\"\n | \"CONNECTION_ERROR\";\n\nexport class CliError extends Error {\n code: ErrorCode;\n exitCode: number;\n detail?: unknown;\n\n constructor(\n code: ErrorCode,\n message: string,\n exitCode: number,\n detail?: unknown\n ) {\n super(message);\n this.name = \"CliError\";\n this.code = code;\n this.exitCode = exitCode;\n this.detail = detail;\n }\n}\n\nexport function authError(message: string): CliError {\n return new CliError(\"AUTH_REQUIRED\", message, EXIT_CODES.AUTH_ERROR);\n}\n\nexport function validationError(message: string, detail?: unknown): CliError {\n return new CliError(\n \"VALIDATION_ERROR\",\n message,\n EXIT_CODES.VALIDATION_ERROR,\n detail\n );\n}\n\nexport function apiError(message: string, detail?: unknown): CliError {\n return new CliError(\"API_ERROR\", message, EXIT_CODES.API_ERROR, detail);\n}\n\nexport function streamError(message: string): CliError {\n return new CliError(\"STREAM_ERROR\", message, EXIT_CODES.API_ERROR);\n}\n\nexport function timeoutError(): CliError {\n return new CliError(\n \"TIMEOUT\",\n \"Request timed out. Generation can take 3-7 minutes. Try increasing --timeout.\",\n EXIT_CODES.TIMEOUT\n );\n}\n","import { readCredentials } from \"./store.js\";\nimport { authError } from \"../api/errors.js\";\n\nexport type ResolvedAuth = {\n token: string;\n teamId?: string;\n figmaToken?: string;\n source: \"env\" | \"file\";\n};\n\nexport function resolveAuth(): ResolvedAuth {\n const creds = readCredentials();\n\n // 1. Environment variable (primary — what AI tools use)\n const envToken = process.env.ANIMA_API_TOKEN;\n if (envToken) {\n return {\n token: envToken,\n teamId: process.env.ANIMA_TEAM_ID,\n figmaToken: process.env.FIGMA_TOKEN || creds?.figmaToken,\n source: \"env\",\n };\n }\n\n // 2. Stored credentials file\n if (creds) {\n return {\n token: creds.token,\n teamId: creds.teamId,\n figmaToken: process.env.FIGMA_TOKEN || creds.figmaToken,\n source: \"file\",\n };\n }\n\n // 3. No token found\n throw authError(\n \"No API token found. Set ANIMA_API_TOKEN env var or run: anima auth --token <token>\\n\" +\n \"Get your token at: https://dev.animaapp.com > Settings > API Keys\"\n );\n}\n","import type {\n SSEMessage,\n SSEDeployMessage,\n GenerationResult,\n DeployResult,\n ProgressMessage,\n} from \"./types.js\";\nimport { apiError, streamError, timeoutError } from \"./errors.js\";\n\nexport type SSECallbacks = {\n onQueueing?: (sessionId: string) => void;\n onStart?: (sessionId: string) => void;\n onProgress?: (messages: ProgressMessage[]) => void;\n onGeneratingCode?: (progress: number) => void;\n onCompleted?: () => void;\n};\n\nexport async function streamGeneration(\n url: string,\n body: Record<string, unknown>,\n headers: Record<string, string>,\n callbacks: SSECallbacks = {},\n timeoutMs: number = 600_000,\n signal?: AbortSignal\n): Promise<GenerationResult> {\n const controller = new AbortController();\n const combinedSignal = signal ?? controller.signal;\n\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n ...headers,\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify(body),\n signal: combinedSignal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let detail: unknown;\n try {\n detail = JSON.parse(errorText);\n } catch {\n detail = errorText;\n }\n throw apiError(\n `API returned ${response.status}: ${response.statusText}`,\n detail\n );\n }\n\n if (!response.body) {\n throw streamError(\"Response body is null\");\n }\n\n return await parseSSEStream<SSEMessage, GenerationResult>(\n response.body,\n (data, result) => {\n switch (data.type) {\n case \"queueing\":\n callbacks.onQueueing?.(data.payload.sessionId);\n break;\n case \"start\":\n result.sessionId = data.sessionId;\n callbacks.onStart?.(data.sessionId);\n break;\n case \"progress_messages_updated\":\n callbacks.onProgress?.(data.payload.progressMessages);\n break;\n case \"generating_code\":\n if (data.payload.status === \"success\") {\n result.files = data.payload.files;\n }\n callbacks.onGeneratingCode?.(data.payload.progress);\n break;\n case \"assets_list\":\n result.assets = data.payload.assets;\n break;\n case \"codegen_completed\":\n case \"generation_completed\":\n callbacks.onCompleted?.();\n break;\n case \"error\":\n throw apiError(\n `${data.payload.errorName}: ${data.payload.reason}`,\n data.payload\n );\n case \"done\":\n result.tokenUsage = data.payload.tokenUsage;\n result.sessionId = data.payload.sessionId;\n return true; // signal completion\n }\n return false;\n },\n { sessionId: \"\", files: {}, tokenUsage: 0 }\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw timeoutError();\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function streamDeploy(\n url: string,\n body: Record<string, unknown>,\n headers: Record<string, string>,\n callbacks: SSECallbacks = {},\n timeoutMs: number = 600_000\n): Promise<DeployResult> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n ...headers,\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let detail: unknown;\n try {\n detail = JSON.parse(errorText);\n } catch {\n detail = errorText;\n }\n throw apiError(\n `API returned ${response.status}: ${response.statusText}`,\n detail\n );\n }\n\n if (!response.body) {\n throw streamError(\"Response body is null\");\n }\n\n return await parseSSEStream<SSEDeployMessage, DeployResult>(\n response.body,\n (data, result) => {\n switch (data.type) {\n case \"queueing\":\n callbacks.onQueueing?.(data.payload.sessionId);\n break;\n case \"start\":\n result.sessionId = data.sessionId;\n callbacks.onStart?.(data.sessionId);\n break;\n case \"progress_messages_updated\":\n callbacks.onProgress?.(data.payload.progressMessages);\n break;\n case \"error\":\n throw apiError(\n `${data.payload.errorName}: ${data.payload.reason}`,\n data.payload\n );\n case \"done\":\n result.sessionId = data.payload.sessionId;\n result.url = data.payload.url;\n result.packageUrl = data.payload.packageUrl;\n result.packageName = data.payload.packageName;\n result.packageVersion = data.payload.packageVersion;\n return true;\n }\n return false;\n },\n { sessionId: \"\" }\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw timeoutError();\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function parseSSEStream<TMessage extends { type: string }, TResult>(\n body: ReadableStream<Uint8Array>,\n handler: (data: TMessage, result: TResult) => boolean,\n initial: TResult\n): Promise<TResult> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n const result = { ...initial };\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.trim() || line.startsWith(\":\")) continue;\n\n if (line.startsWith(\"data: \")) {\n let data: TMessage;\n try {\n data = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n const isDone = handler(data, result);\n if (isDone) return result;\n }\n }\n }\n } finally {\n reader.cancel();\n }\n\n throw streamError(\"Connection closed before receiving 'done' message\");\n}\n\nexport function buildHeaders(token: string, teamId?: string): Record<string, string> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n if (teamId) {\n headers[\"X-Team-Id\"] = teamId;\n }\n return headers;\n}\n","export type OutputMode = \"json\" | \"pretty\";\n\nexport function detectOutputMode(flags: {\n json?: boolean;\n}): OutputMode {\n if (flags.json !== undefined) {\n return flags.json ? \"json\" : \"pretty\";\n }\n // Auto-detect: JSON when piped, pretty in TTY\n return process.stdout.isTTY ? \"pretty\" : \"json\";\n}\n\nexport function outputResult(mode: OutputMode, data: unknown): void {\n if (mode === \"json\") {\n process.stdout.write(JSON.stringify(data) + \"\\n\");\n }\n // Pretty mode output is handled inline by commands using chalk/ora\n}\n\nexport function outputError(\n mode: OutputMode,\n error: { code: string; message: string }\n): void {\n if (mode === \"json\") {\n process.stdout.write(\n JSON.stringify({ success: false, error }) + \"\\n\"\n );\n }\n // Pretty mode errors are handled inline by commands\n}\n","import ora, { type Ora } from \"ora\";\nimport type { OutputMode } from \"./formatter.js\";\n\nexport class ProgressReporter {\n #spinner: Ora | null = null;\n #mode: OutputMode;\n #startTime: number = 0;\n #verbose: boolean;\n\n constructor(mode: OutputMode, verbose: boolean = false) {\n this.#mode = mode;\n this.#verbose = verbose;\n }\n\n start(message: string): void {\n this.#startTime = Date.now();\n if (this.#mode === \"pretty\") {\n this.#spinner = ora(message).start();\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"started\", message }) + \"\\n\");\n }\n }\n\n update(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.text = `${message} ${elapsed}`;\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"progress\", message }) + \"\\n\");\n }\n }\n\n succeed(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.succeed(`${message} ${elapsed}`);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"done\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n fail(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n this.#spinner.fail(message);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"error\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n #elapsed(): string {\n const ms = Date.now() - this.#startTime;\n const seconds = Math.floor(ms / 1000);\n if (seconds < 60) return `(${seconds}s)`;\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `(${minutes}m ${secs}s)`;\n }\n}\n","import chalk from \"chalk\";\n\nexport function printSuccess(message: string): void {\n console.log(chalk.green(\"✓\") + \" \" + message);\n}\n\nexport function printError(message: string): void {\n console.error(chalk.red(\"✗\") + \" \" + message);\n}\n\nexport function printInfo(message: string): void {\n console.log(chalk.blue(\"ℹ\") + \" \" + message);\n}\n\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(\"⚠\") + \" \" + message);\n}\n\nexport function printKeyValue(key: string, value: string): void {\n console.log(` ${chalk.gray(key + \":\")} ${value}`);\n}\n\nexport function printSessionResult(result: {\n sessionId: string;\n playgroundUrl?: string;\n tokenUsage?: number;\n}): void {\n console.log();\n printSuccess(\"Playground created successfully!\");\n printKeyValue(\"Session ID\", result.sessionId);\n if (result.playgroundUrl) {\n printKeyValue(\"Playground\", chalk.cyan.underline(result.playgroundUrl));\n }\n if (result.tokenUsage) {\n printKeyValue(\"Token usage\", result.tokenUsage.toLocaleString());\n }\n console.log();\n}\n\nexport function printDeployResult(result: {\n url?: string;\n packageUrl?: string;\n packageName?: string;\n packageVersion?: string;\n}): void {\n console.log();\n printSuccess(\"Published successfully!\");\n if (result.url) {\n printKeyValue(\"Live URL\", chalk.cyan.underline(result.url));\n }\n if (result.packageName) {\n printKeyValue(\"Package\", result.packageName);\n printKeyValue(\"Version\", result.packageVersion ?? \"\");\n if (result.packageUrl) {\n printKeyValue(\"URL\", chalk.cyan.underline(result.packageUrl));\n }\n }\n console.log();\n}\n\nexport function printFilesWritten(outputDir: string, count: number): void {\n console.log();\n printSuccess(`${count} files written to ${chalk.cyan(outputDir)}`);\n console.log();\n}\n","/**\n * Parse a Figma URL to extract fileKey and nodeId.\n *\n * Supported formats:\n * - https://www.figma.com/file/ABC123/FileName?node-id=42-15\n * - https://www.figma.com/design/ABC123/FileName?node-id=42-15\n * - https://figma.com/file/ABC123/FileName?node-id=42%3A15\n * - Just a fileKey string\n */\nexport function parseFigmaUrl(input: string): {\n fileKey: string;\n nodeId?: string;\n} {\n // If it doesn't look like a URL, treat as a raw file key\n if (!input.includes(\"figma.com\")) {\n return { fileKey: input };\n }\n\n try {\n const url = new URL(input);\n const pathParts = url.pathname.split(\"/\").filter(Boolean);\n\n // Expected format: /file/KEY/name or /design/KEY/name\n const typeIndex = pathParts.findIndex(\n (p) => p === \"file\" || p === \"design\"\n );\n if (typeIndex === -1 || typeIndex + 1 >= pathParts.length) {\n throw new Error(\"Could not find file key in Figma URL\");\n }\n\n const fileKey = pathParts[typeIndex + 1];\n const nodeIdParam = url.searchParams.get(\"node-id\");\n\n let nodeId: string | undefined;\n if (nodeIdParam) {\n // Convert dash format (42-15) to colon format (42:15)\n nodeId = nodeIdParam.replace(/-/g, \":\");\n }\n\n return { fileKey, nodeId };\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"file key\")) {\n throw err;\n }\n throw new Error(`Invalid Figma URL: ${input}`);\n }\n}\n\n/**\n * Normalize a node ID: convert dash format to colon format.\n * \"42-15\" -> \"42:15\"\n */\nexport function normalizeNodeId(nodeId: string): string {\n return nodeId.replace(/-/g, \":\");\n}\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { callMCPTool } from \"../api/mcp-client.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { printDeployResult } from \"../output/pretty.js\";\nimport { validationError, CliError } from \"../api/errors.js\";\n\nexport const publishCommand = new Command(\"publish\")\n .description(\"Deploy playground to live URL or npm package (1-3 min)\")\n .argument(\"<sessionId>\", \"Session ID from create command\")\n .option(\"--mode <mode>\", \"webapp | designSystem\", \"webapp\")\n .option(\"--package-name <name>\", \"NPM package name (designSystem mode)\")\n .option(\"--package-version <version>\", \"NPM package version (designSystem mode)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL\", \"https://public-api.animaapp.com\")\n .action(async (sessionId: string, opts) => {\n const mode = detectOutputMode(opts);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n if (![\"webapp\", \"designSystem\"].includes(opts.mode)) {\n throw validationError(\n `Invalid mode \"${opts.mode}\". Must be webapp or designSystem.`\n );\n }\n\n if (opts.mode === \"designSystem\" && !opts.packageName) {\n throw validationError(\"--package-name is required for designSystem mode\");\n }\n\n const auth = resolveAuth();\n\n const args: Record<string, unknown> = {\n sessionId,\n mode: opts.mode,\n };\n if (opts.packageName) args.packageName = opts.packageName;\n if (opts.packageVersion) args.packageVersion = opts.packageVersion;\n\n progress.start(`Publishing as ${opts.mode}...`);\n\n const result = (await callMCPTool(\n opts.apiUrl,\n auth.token,\n auth.teamId,\n \"playground-publish\",\n args\n )) as Record<string, unknown>;\n\n if (!result.success) {\n throw new CliError(\n \"API_ERROR\",\n (result.error as string) || (result.reason as string) || \"Publish failed\",\n 1,\n result\n );\n }\n\n progress.succeed(\"Published!\");\n\n if (mode === \"pretty\") {\n printDeployResult({\n url: result.liveUrl as string | undefined,\n packageUrl: result.packageUrl as string | undefined,\n packageName: result.packageName as string | undefined,\n packageVersion: result.packageVersion as string | undefined,\n });\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n ...(result.liveUrl ? { liveUrl: result.liveUrl, subdomain: result.subdomain } : {}),\n ...(result.packageName\n ? {\n packageName: result.packageName,\n packageVersion: result.packageVersion,\n packageUrl: result.packageUrl,\n }\n : {}),\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { apiError, streamError } from \"./errors.js\";\n\ntype MCPToolCallRequest = {\n jsonrpc: \"2.0\";\n id: number;\n method: \"tools/call\";\n params: {\n name: string;\n arguments: Record<string, unknown>;\n };\n};\n\ntype MCPToolCallResponse = {\n jsonrpc: \"2.0\";\n id: number;\n result?: {\n content: Array<{ type: string; text: string }>;\n };\n error?: {\n code: number;\n message: string;\n };\n};\n\nexport async function callMCPTool(\n apiBaseUrl: string,\n token: string,\n teamId: string | undefined,\n toolName: string,\n args: Record<string, unknown>\n): Promise<unknown> {\n const request: MCPToolCallRequest = {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: {\n name: toolName,\n arguments: args,\n },\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n Authorization: `Bearer ${token}`,\n };\n if (teamId) {\n headers[\"X-Team-Id\"] = teamId;\n }\n\n const response = await fetch(`${apiBaseUrl}/v1/mcp`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw apiError(`MCP request failed (${response.status}): ${errorText}`);\n }\n\n const contentType = response.headers.get(\"content-type\") || \"\";\n\n // Handle SSE response — the MCP endpoint streams SSE, final message contains the JSON-RPC result\n if (contentType.includes(\"text/event-stream\")) {\n return parseMCPSSEResponse(response);\n }\n\n // Plain JSON response\n const data = (await response.json()) as MCPToolCallResponse;\n return extractMCPResult(data);\n}\n\nasync function parseMCPSSEResponse(\n response: Response\n): Promise<unknown> {\n if (!response.body) {\n throw streamError(\"Response body is null\");\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let lastData: MCPToolCallResponse | null = null;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.trim() || line.startsWith(\":\")) continue;\n\n if (line.startsWith(\"data: \")) {\n try {\n const parsed = JSON.parse(line.slice(6));\n // Keep track of any JSON-RPC response\n if (parsed.jsonrpc === \"2.0\") {\n lastData = parsed;\n }\n } catch {\n // Ignore non-JSON SSE data lines\n }\n }\n }\n }\n } finally {\n reader.cancel();\n }\n\n if (!lastData) {\n throw apiError(\"MCP SSE stream ended without a JSON-RPC response\");\n }\n\n return extractMCPResult(lastData);\n}\n\nfunction extractMCPResult(data: MCPToolCallResponse): unknown {\n if (data.error) {\n throw apiError(`MCP tool error: ${data.error.message}`);\n }\n\n if (!data.result?.content?.length) {\n throw apiError(\"MCP tool returned empty result\");\n }\n\n const textContent = data.result.content.find((c) => c.type === \"text\");\n if (!textContent) {\n throw apiError(\"MCP tool returned no text content\");\n }\n\n try {\n return JSON.parse(textContent.text);\n } catch {\n return textContent.text;\n }\n}\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { streamGeneration, buildHeaders } from \"../api/client.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { printFilesWritten } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { writeFilesToDisk } from \"../utils/files.js\";\nimport { validationError, CliError } from \"../api/errors.js\";\n\nconst DEFAULT_API_URL = \"https://public-api.animaapp.com\";\n\nexport const codegenCommand = new Command(\"codegen\")\n .description(\"Convert Figma design to code files (no playground)\")\n .requiredOption(\"--file-key <key>\", \"Figma file key or URL\")\n .option(\"--nodes <nodes>\", \"Figma node IDs, comma-separated\")\n .option(\"--figma-token <token>\", \"Figma personal access token (or set FIGMA_TOKEN env var)\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./generated\")\n .option(\"--framework <fw>\", \"react | html\", \"react\")\n .option(\"--styling <style>\", \"tailwind | css | plain_css | css_modules | inline_styles\", \"tailwind\")\n .option(\"--language <lang>\", \"typescript | javascript\")\n .option(\"--ui-library <lib>\", \"mui | antd | shadcn | clean_react\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n: string) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n\n if (nodesId.length === 0) {\n throw validationError(\n \"No node IDs provided. Use --nodes or include node-id in the Figma URL.\"\n );\n }\n\n const auth = resolveAuth();\n\n // Resolve Figma token: flag > env var > stored credentials > error\n const figmaToken = opts.figmaToken || auth.figmaToken;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n const headers = buildHeaders(auth.token, auth.teamId);\n\n // Default language to typescript when framework is react\n const language = opts.language ?? (opts.framework === \"react\" ? \"typescript\" : undefined);\n\n const requestBody: Record<string, unknown> = {\n fileKey,\n nodesId,\n figmaToken,\n framework: opts.framework,\n language,\n styling: opts.styling,\n uiLibrary: opts.uiLibrary,\n };\n\n progress.start(\"Generating code from Figma...\");\n\n const result = await streamGeneration(\n `${opts.apiUrl}/v1/codegen`,\n requestBody,\n headers,\n {\n onQueueing: () => progress.update(\"Queued, waiting...\"),\n onStart: (sid) => progress.update(`Started (${sid.slice(0, 8)}...)...`),\n onProgress: (msgs) => {\n const running = msgs.find((m) => m.status === \"running\");\n if (running) progress.update(running.title);\n },\n onGeneratingCode: (pct) => progress.update(`Generating code (${pct}%)...`),\n onCompleted: () => progress.update(\"Writing files...\"),\n },\n parseInt(opts.timeout, 10)\n );\n\n const count = writeFilesToDisk(result.files, opts.output);\n\n progress.succeed(`Generated ${count} files`);\n\n if (mode === \"pretty\") {\n printFilesWritten(opts.output, count);\n } else {\n outputResult(mode, {\n success: true,\n output: opts.output,\n fileCount: count,\n sessionId: result.sessionId,\n tokenUsage: result.tokenUsage,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\n/**\n * Write generated files to disk.\n * Handles both code (text) and binary (base64-encoded) files.\n */\nexport function writeFilesToDisk(\n files: AnimaFiles,\n outputDir: string\n): number {\n // Create output directory\n fs.mkdirSync(outputDir, { recursive: true });\n\n let count = 0;\n\n for (const [filePath, fileContent] of Object.entries(files)) {\n const fullPath = path.join(outputDir, filePath);\n\n // Create parent directories\n const dirPath = path.dirname(fullPath);\n fs.mkdirSync(dirPath, { recursive: true });\n\n if (fileContent.isBinary) {\n const buffer = Buffer.from(fileContent.content, \"base64\");\n fs.writeFileSync(fullPath, buffer);\n } else {\n fs.writeFileSync(fullPath, fileContent.content, \"utf-8\");\n }\n\n count++;\n }\n\n return count;\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport { createWriteStream } from \"node:fs\";\nimport { Readable } from \"node:stream\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { callMCPTool } from \"../api/mcp-client.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { printFilesWritten } from \"../output/pretty.js\";\nimport { parsePlaygroundUrl } from \"../utils/download.js\";\nimport { CliError, apiError } from \"../api/errors.js\";\n\nconst DEFAULT_API_URL = \"https://public-api.animaapp.com\";\n\nexport const downloadCommand = new Command(\"download\")\n .description(\"Download project from an Anima playground\")\n .argument(\"<playgroundUrl>\", \"Playground URL or session ID\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./downloaded\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (playgroundUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const sessionId = parsePlaygroundUrl(playgroundUrl);\n const auth = resolveAuth();\n\n progress.start(\"Requesting download...\");\n\n const result = (await callMCPTool(\n opts.apiUrl,\n auth.token,\n auth.teamId,\n \"project-download_from_playground\",\n { playgroundUrl: `https://dev.animaapp.com/chat/${sessionId}` }\n )) as Record<string, unknown>;\n\n if (!result.success) {\n throw apiError(\n (result.error as string) || \"Download failed\",\n result\n );\n }\n\n const downloadUrl = result.downloadUrl as string;\n const fileCount = result.fileCount as number;\n\n if (!downloadUrl) {\n throw apiError(\"No download URL returned\");\n }\n\n progress.update(`Downloading zip (${fileCount} files)...`);\n\n // Download the zip file\n const zipPath = path.join(opts.output, \"__download.zip\");\n fs.mkdirSync(opts.output, { recursive: true });\n\n const zipResponse = await fetch(downloadUrl);\n if (!zipResponse.ok || !zipResponse.body) {\n throw apiError(`Failed to download zip: ${zipResponse.status}`);\n }\n\n await pipeline(\n Readable.fromWeb(zipResponse.body as any),\n createWriteStream(zipPath)\n );\n\n progress.update(\"Extracting...\");\n\n // Extract using tar (macOS/Linux have it, handles zip with unzip)\n const { execSync } = await import(\"node:child_process\");\n try {\n execSync(`unzip -o -q \"${zipPath}\" -d \"${opts.output}\"`, {\n stdio: \"pipe\",\n });\n } catch {\n // Fallback: try tar\n execSync(`tar -xf \"${zipPath}\" -C \"${opts.output}\"`, {\n stdio: \"pipe\",\n });\n }\n\n // Remove the zip\n fs.unlinkSync(zipPath);\n\n // Count extracted files\n const count = countFiles(opts.output);\n\n progress.succeed(`Downloaded ${count} files`);\n\n if (mode === \"pretty\") {\n printFilesWritten(opts.output, count);\n } else {\n outputResult(mode, {\n success: true,\n output: opts.output,\n fileCount: count,\n sessionId,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\nfunction countFiles(dir: string): number {\n let count = 0;\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n count += countFiles(path.join(dir, entry.name));\n } else {\n count++;\n }\n }\n return count;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport { createGunzip } from \"node:zlib\";\nimport { Readable } from \"node:stream\";\n\n/**\n * Download a file from a URL and save to disk.\n */\nexport async function downloadFile(\n url: string,\n outputPath: string\n): Promise<void> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Download failed (${response.status}): ${url}`);\n }\n\n const dirPath = path.dirname(outputPath);\n fs.mkdirSync(dirPath, { recursive: true });\n\n const fileStream = fs.createWriteStream(outputPath);\n const body = response.body;\n if (!body) throw new Error(\"No response body\");\n\n await pipeline(Readable.fromWeb(body as any), fileStream);\n}\n\n/**\n * Parse a playground URL to extract the session ID.\n * Supported formats:\n * - https://dev.animaapp.com/chat/SESSION_ID\n * - Just a session ID string\n */\nexport function parsePlaygroundUrl(input: string): string {\n if (!input.includes(\"/\")) {\n return input;\n }\n\n try {\n const url = new URL(input);\n const parts = url.pathname.split(\"/\").filter(Boolean);\n // Expected: /chat/SESSION_ID\n const chatIndex = parts.indexOf(\"chat\");\n if (chatIndex !== -1 && chatIndex + 1 < parts.length) {\n return parts[chatIndex + 1];\n }\n // Fallback: last path segment\n return parts[parts.length - 1];\n } catch {\n // Not a URL, treat as session ID\n return input;\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { writeCredentials, deleteCredentials, readCredentials, getCredentialsPath, extractTeamIdFromJWT } from \"../auth/store.js\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { loginWithBrowser } from \"../auth/oauth.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printSuccess, printError, printKeyValue, printInfo } from \"../output/pretty.js\";\nimport { CliError } from \"../api/errors.js\";\n\nconst DEFAULT_API_URL = \"https://public-api.animaapp.com\";\n\nexport const authCommand = new Command(\"auth\")\n .description(\"Manage authentication\")\n .option(\"--token <token>\", \"Store Anima API token\")\n .option(\"--figma-token <token>\", \"Store Figma personal access token\")\n .option(\"--team-id <teamId>\", \"Team ID to associate with token\")\n .option(\"--login\", \"Login via browser OAuth flow\")\n .option(\"--status\", \"Show current auth status\")\n .option(\"--logout\", \"Clear stored credentials\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n\n try {\n if (opts.token || opts.figmaToken) {\n const toSave: Record<string, string> = {};\n\n if (opts.token) {\n toSave.token = opts.token;\n toSave.teamId = opts.teamId ?? extractTeamIdFromJWT(opts.token) ?? \"\";\n }\n if (opts.figmaToken) {\n toSave.figmaToken = opts.figmaToken;\n }\n\n writeCredentials(toSave);\n\n if (mode === \"pretty\") {\n printSuccess(\"Credentials saved to \" + getCredentialsPath());\n if (opts.token) {\n printKeyValue(\"Anima token\", \"saved\");\n if (toSave.teamId) printKeyValue(\"Team ID\", toSave.teamId);\n }\n if (opts.figmaToken) {\n printKeyValue(\"Figma token\", \"saved\");\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"token_saved\",\n path: getCredentialsPath(),\n ...(opts.token ? { teamId: toSave.teamId } : {}),\n ...(opts.figmaToken ? { figmaToken: true } : {}),\n });\n }\n return;\n }\n\n if (opts.login) {\n if (mode === \"pretty\") {\n printInfo(\"Opening browser for authentication...\");\n }\n const result = await loginWithBrowser();\n if (mode === \"pretty\") {\n printSuccess(\"Authenticated successfully!\");\n printKeyValue(\"Token\", result.token.slice(0, 8) + \"...\");\n if (result.teamId) printKeyValue(\"Team ID\", result.teamId);\n } else {\n outputResult(mode, { success: true, action: \"logged_in\" });\n }\n return;\n }\n\n if (opts.logout) {\n const deleted = deleteCredentials();\n if (mode === \"pretty\") {\n if (deleted) {\n printSuccess(\"Credentials cleared\");\n } else {\n printInfo(\"No stored credentials found\");\n }\n } else {\n outputResult(mode, { success: true, action: \"logged_out\", hadCredentials: deleted });\n }\n return;\n }\n\n if (opts.status) {\n try {\n const auth = resolveAuth();\n const creds = readCredentials();\n const sourceName = auth.source === \"env\" ? \"ANIMA_API_TOKEN env var\" : getCredentialsPath();\n const hasFigma = !!(process.env.FIGMA_TOKEN || creds?.figmaToken);\n if (mode === \"pretty\") {\n printSuccess(\"Token configured\");\n printKeyValue(\"Source\", sourceName);\n printKeyValue(\"Anima token\", auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4));\n if (auth.teamId) printKeyValue(\"Team ID\", auth.teamId);\n printKeyValue(\"Figma token\", hasFigma ? \"configured\" : \"not set (needed for codegen/f2c)\");\n } else {\n outputResult(mode, {\n success: true,\n source: auth.source,\n tokenPreview: auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4),\n teamId: auth.teamId,\n figmaToken: hasFigma,\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n } else {\n throw err;\n }\n }\n return;\n }\n\n // No flag: show help\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"Auth commands:\");\n console.log(` ${chalk.cyan(\"anima auth --token <T>\")} Save Anima API token`);\n console.log(` ${chalk.cyan(\"anima auth --figma-token <T>\")} Save Figma token`);\n console.log(` ${chalk.cyan(\"anima auth --token <T> --figma-token <T>\")} Save both at once`);\n console.log(` ${chalk.cyan(\"anima auth --login\")} Login via browser`);\n console.log(` ${chalk.cyan(\"anima auth --status\")} Check auth status`);\n console.log(` ${chalk.cyan(\"anima auth --logout\")} Clear all credentials`);\n console.log();\n console.log(` Anima token: ${chalk.cyan.underline(\"https://dev.animaapp.com\")} > Settings > API Keys`);\n console.log(` Figma token: ${chalk.cyan.underline(\"https://www.figma.com\")} > Settings > Personal access tokens`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n message: \"Use --token, --login, --status, or --logout\",\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import http from \"node:http\";\nimport open from \"open\";\nimport { writeCredentials } from \"./store.js\";\n\nconst OAUTH_PORT = 19284;\nconst OAUTH_BASE = \"https://dev.animaapp.com\";\n\nexport async function loginWithBrowser(): Promise<{\n token: string;\n teamId?: string;\n}> {\n return new Promise((resolve, reject) => {\n const server = http.createServer((req, res) => {\n const url = new URL(req.url!, `http://localhost:${OAUTH_PORT}`);\n\n if (url.pathname === \"/callback\") {\n const token = url.searchParams.get(\"token\");\n const teamId = url.searchParams.get(\"teamId\") ?? undefined;\n\n if (!token) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(\n \"<html><body><h1>Error</h1><p>No token received. Please try again.</p></body></html>\"\n );\n server.close();\n reject(new Error(\"No token received from OAuth flow\"));\n return;\n }\n\n writeCredentials({ token, teamId });\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(\n \"<html><body><h1>Authenticated!</h1><p>You can close this window and return to the terminal.</p></body></html>\"\n );\n\n server.close();\n resolve({ token, teamId });\n }\n });\n\n server.listen(OAUTH_PORT, () => {\n const authUrl = `${OAUTH_BASE}/cli-auth?redirect=http://localhost:${OAUTH_PORT}/callback`;\n open(authUrl);\n });\n\n server.on(\"error\", (err) => {\n reject(\n new Error(`Failed to start OAuth callback server: ${err.message}`)\n );\n });\n\n // Timeout after 5 minutes\n setTimeout(() => {\n server.close();\n reject(new Error(\"OAuth login timed out after 5 minutes\"));\n }, 300_000);\n });\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","fs","path","DEFAULT_API_URL","Command","Command","fs","path","pipeline","Readable","fs","path","DEFAULT_API_URL","Command","path","fs","pipeline","Readable","Command","chalk","DEFAULT_API_URL","Command","chalk","Command"]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@animaapp/cli",
3
+ "version": "0.2.0",
4
+ "description": "Generate production-ready apps from prompts, URLs, or Figma designs",
5
+ "type": "module",
6
+ "bin": {
7
+ "anima": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "engines": {
13
+ "node": ">=18"
14
+ },
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "dev": "tsup --watch",
18
+ "test": "vitest run",
19
+ "test:watch": "vitest",
20
+ "typecheck": "tsc --noEmit",
21
+ "lint": "eslint src/",
22
+ "lint:fix": "eslint src/ --fix",
23
+ "clean": "rm -rf dist"
24
+ },
25
+ "dependencies": {
26
+ "chalk": "^5.3.0",
27
+ "commander": "^12.1.0",
28
+ "open": "^10.1.0",
29
+ "ora": "^8.1.1",
30
+ "zod": "^3.23.8"
31
+ },
32
+ "devDependencies": {
33
+ "@changesets/cli": "^2.29.8",
34
+ "@types/node": "^20.14.0",
35
+ "tsup": "^8.1.0",
36
+ "typescript": "^5.5.0",
37
+ "vitest": "^2.1.0"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "keywords": [
43
+ "anima",
44
+ "figma",
45
+ "code-generation",
46
+ "design-to-code",
47
+ "prompt-to-code",
48
+ "cli"
49
+ ],
50
+ "license": "MIT",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/AnimaApp/anima-cli.git"
54
+ }
55
+ }