@vocoder/cli 0.1.14 → 0.1.16
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/bin.mjs +158 -50
- package/dist/bin.mjs.map +1 -1
- package/package.json +1 -1
package/dist/bin.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bin.ts","../src/commands/init.ts","../src/utils/auth-store.ts","../src/utils/github-connect.ts","../src/utils/local-server.ts","../src/utils/api.ts","../src/utils/git-identity.ts","../src/utils/project-create.ts","../src/utils/locale-search.ts","../src/utils/branch-select.ts","../src/utils/workspace.ts","../src/commands/logout.ts","../src/commands/sync.ts","../src/utils/branch.ts","../src/utils/config.ts","../src/commands/whoami.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { init } from './commands/init.js';\nimport { logout } from './commands/logout.js';\nimport { sync } from './commands/sync.js';\nimport { whoami } from './commands/whoami.js';\n\n\n/**\n * Collector function for repeated CLI options\n * Allows multiple --include or --exclude flags\n */\nfunction collect(value: string, previous: string[] = []): string[] {\n return previous.concat([value]);\n}\n\nasync function runCommand(command: (options: any) => Promise<number>, options: any): Promise<void> {\n const exitCode = await command(options);\n // Force exit so open stdin handles from readline/clack don't stall the process.\n process.exit(exitCode);\n}\n\nconst program = new Command();\n\nprogram\n .name('vocoder')\n .description('Vocoder CLI - Project setup and string extraction')\n .version('0.1.5');\n\nprogram\n .command('init')\n .description('Authenticate and provision Vocoder for this project')\n .option('--api-url <url>', 'Override Vocoder API URL')\n .option('--yes', 'Allow overwriting existing local config values')\n .option('--ci', 'Non-interactive mode: print auth URL to stdout, skip browser open')\n .option('--project-name <name>', 'Starter project name to create')\n .option('--source-locale <locale>', 'Source locale for the starter project')\n .option('--target-locales <list>', 'Comma-separated target locales (e.g. es,fr,de)')\n .action((options) => runCommand(init, options));\n\nprogram\n .command('sync')\n .description('Extract strings and sync translations')\n .option('--branch <branch>', 'Override detected branch')\n .option('--mode <mode>', 'Sync mode: auto, required, best-effort', 'auto')\n .option('--max-wait <ms>', 'Max wait for translations (ms)')\n .option('--force', 'Force re-extraction even if no changes')\n .option('--dry-run', 'Preview without syncing')\n .option('--no-fallback', 'Disable fallback to cached translations')\n .option('--include <pattern>', 'Include glob pattern', collect, [])\n .option('--exclude <pattern>', 'Exclude glob pattern', collect, [])\n .option('--verbose', 'Detailed output')\n .action((options) => {\n const translated: Record<string, unknown> = { ...options };\n if (options.maxWait) translated.maxWaitMs = Number(options.maxWait);\n if (options.fallback === false) translated.noFallback = true;\n return runCommand(sync, translated);\n });\n\nprogram\n .command('logout')\n .description('Log out and remove stored credentials')\n .option('--api-url <url>', 'Override Vocoder API URL')\n .action((options) => runCommand(logout, options));\n\nprogram\n .command('whoami')\n .description('Show the currently authenticated user')\n .option('--api-url <url>', 'Override Vocoder API URL')\n .action((options) => runCommand(whoami, options));\n\nprogram.parse(process.argv);\n","import * as p from '@clack/prompts';\n\nimport {\n buildInstallCommand,\n detectLocalEcosystem,\n getPackagesToInstall,\n} from '../utils/detect-local.js';\nimport { clearAuthData, readAuthData, writeAuthData } from '../utils/auth-store.js';\nimport { runGitHubDiscoveryFlow, runGitHubInstallFlow, selectGitHubInstallation } from '../utils/github-connect.js';\n\nimport type { InitOptions } from '../types.js';\nimport { VocoderAPI, VocoderAPIError } from '../utils/api.js';\nimport chalk from 'chalk';\nimport { execSync } from 'node:child_process';\nimport { getSetupSnippets } from '../utils/setup-snippets.js';\nimport { config as loadEnv } from 'dotenv';\nimport { resolveGitContext } from '../utils/git-identity.js';\nimport { runProjectAppCreate, runProjectCreate } from '../utils/project-create.js';\nimport { selectWorkspace } from '../utils/workspace.js';\nimport { spawn } from 'node:child_process';\nimport { startCallbackServer } from '../utils/local-server.js';\n\nloadEnv();\n\nconst SUBSCRIPTION_SETTINGS_PATH = '/dashboard/workspace/settings?tab=subscription';\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n if (!process.stdout.isTTY || process.env.CI === 'true') {\n return false;\n }\n\n let command: string;\n let args: string[];\n\n if (process.platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (process.platform === 'win32') {\n command = 'rundll32';\n args = ['url.dll,FileProtocolHandler', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n return await new Promise<boolean>((resolve) => {\n try {\n const child = spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n\n let settled = false;\n child.once('spawn', () => {\n if (settled) return;\n settled = true;\n child.unref();\n resolve(true);\n });\n child.once('error', () => {\n if (settled) return;\n settled = true;\n resolve(false);\n });\n setTimeout(() => {\n if (settled) return;\n settled = true;\n resolve(false);\n }, 300);\n } catch {\n resolve(false);\n }\n });\n}\n\nfunction isPlanLimitFailure(message?: string): boolean {\n if (!message) return false;\n return /limit|upgrade/i.test(message);\n}\n\nfunction getSubscriptionSettingsUrl(apiUrl: string): string {\n return new URL(SUBSCRIPTION_SETTINGS_PATH, apiUrl).toString();\n}\n\nfunction printPlanLimitMessage(apiUrl: string, message: string): void {\n p.log.error(`You are over your plan limits.\\n ${message}`);\n p.log.info(`Manage subscription: ${getSubscriptionSettingsUrl(apiUrl)}`);\n}\n\ninterface ScaffoldParams {\n projectName: string;\n organizationName: string;\n sourceLocale: string;\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n}\n\nfunction runScaffold(params: ScaffoldParams): void {\n const { projectName, organizationName, sourceLocale, branchTriggers } = params;\n\n p.log.info(`Project: ${chalk.bold(projectName)}`);\n p.log.info(`Workspace: ${chalk.bold(organizationName)}`);\n\n const detection = detectLocalEcosystem();\n\n if (detection.ecosystem) {\n const frameworkLabel = detection.framework ?? detection.ecosystem;\n const pmLabel = detection.packageManager;\n p.log.info(`Detected: ${chalk.bold(frameworkLabel)} (${pmLabel})`);\n }\n\n const packagesToInstall = getPackagesToInstall(detection);\n if (packagesToInstall.length > 0) {\n const installCmd = buildInstallCommand(detection.packageManager, packagesToInstall);\n p.log.info('');\n const installSpinner = p.spinner();\n installSpinner.start(`Installing ${packagesToInstall.join(', ')}...`);\n\n try {\n execSync(installCmd, { stdio: 'pipe', cwd: process.cwd() });\n installSpinner.stop(`Installed ${packagesToInstall.join(', ')}`);\n } catch {\n installSpinner.stop('Package installation failed');\n p.log.warn(`Run manually: ${chalk.cyan(installCmd)}`);\n }\n } else if (detection.ecosystem) {\n p.log.info(`Packages: ${chalk.green('already installed')}`);\n }\n\n const snippets = getSetupSnippets({\n framework: detection.framework,\n ecosystem: detection.ecosystem,\n sourceLocale,\n branchTriggers,\n });\n\n let stepNum = 1;\n\n if (snippets.pluginStep) {\n p.log.message('');\n p.log.step(`${chalk.bold(`Step ${stepNum}:`)} Add the plugin to ${chalk.cyan(snippets.pluginStep.file)}`);\n printCodeBlock(snippets.pluginStep.code);\n stepNum++;\n }\n\n if (snippets.providerStep) {\n p.log.step(`${chalk.bold(`Step ${stepNum}:`)} Add the provider to ${chalk.cyan(snippets.providerStep.file)}`);\n printCodeBlock(snippets.providerStep.code);\n stepNum++;\n }\n\n p.log.step(`${chalk.bold(`Step ${stepNum}:`)} Wrap translatable strings`);\n printCodeBlock(snippets.wrapStep.code);\n\n p.log.message('');\n for (const line of snippets.whatsNext.split('\\n')) {\n p.log.success(line);\n }\n}\n\nfunction printMcpSetup(apiKey: string): void {\n const addCommand = `claude mcp add --scope project --transport stdio \\\\\\n --env VOCODER_API_KEY=${apiKey} \\\\\\n vocoder -- npx -y @vocoder/mcp`;\n\n const teamConfig = JSON.stringify(\n {\n mcpServers: {\n vocoder: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@vocoder/mcp'],\n env: { VOCODER_API_KEY: '${env:VOCODER_API_KEY}' },\n },\n },\n },\n null,\n 2,\n );\n\n p.log.message('');\n p.log.message(chalk.bold('Use Vocoder with Claude Code'));\n p.log.message('Run this to add the MCP server to your project:');\n p.log.message('');\n printCodeBlock(addCommand);\n p.log.message('');\n p.log.message('To share with your team, commit ' + chalk.cyan('.mcp.json') + ' with an env var reference');\n p.log.message('so each developer supplies their own key:');\n p.log.message('');\n printCodeBlock(teamConfig);\n p.log.message('');\n p.log.message(chalk.gray('Setup instructions: https://vocoder.app/docs/mcp'));\n}\n\nfunction printCodeBlock(code: string): void {\n const lines = code.split('\\n');\n const maxLen = lines.reduce((max: number, line: string) => Math.max(max, line.length), 0);\n const bar = chalk.gray('│');\n const pad = (s: string) => s + ' '.repeat(maxLen - s.length);\n\n process.stdout.write(`${chalk.gray('│')}\\n`);\n process.stdout.write(`${chalk.gray('│')} ${chalk.gray('┌' + '─'.repeat(maxLen + 2) + '┐')}\\n`);\n for (const line of lines) {\n process.stdout.write(`${chalk.gray('│')} ${bar} ${pad(line)} ${bar}\\n`);\n }\n process.stdout.write(`${chalk.gray('│')} ${chalk.gray('└' + '─'.repeat(maxLen + 2) + '┘')}\\n`);\n}\n\n// ── Auth helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Verify a stored auth token against the API.\n * Returns user info on success, null if the token is invalid/expired.\n * Always clears the stored token on failure.\n *\n * Returns `{ userGone: true }` when the server confirms the user no longer\n * exists (404) — callers should treat this as a first-time setup, not a reauth.\n */\nasync function verifyStoredToken(\n api: VocoderAPI,\n token: string,\n): Promise<{ userId: string; email: string; name: string | null } | { userGone: true } | null> {\n try {\n return await api.getCliUserInfo(token);\n } catch (err) {\n clearAuthData();\n // 404 = user record deleted — treat as first-time, not reauth\n if (err instanceof VocoderAPIError && err.status === 404) {\n return { userGone: true };\n }\n return null;\n }\n}\n\n/**\n * Run the browser authentication flow.\n * Returns `{ token, userInfo, organizationId? }` on success, or null if cancelled.\n * When `organizationId` is set, the GitHub App was installed in the same browser\n * trip — the caller should skip workspace selection and GitHub connect.\n *\n * @param reauth - When true, the user has an expired token and already has a workspace.\n * Use verificationUrl (auth/cli page) instead of installUrl so we don't create a\n * duplicate workspace. The direct-to-GitHub install URL is only for first-time setup.\n */\nasync function runAuthFlow(\n api: VocoderAPI,\n options: InitOptions,\n reauth = false,\n repoCanonical?: string,\n): Promise<{ token: string; userId: string; email: string; name: string | null; organizationId?: string; discoveryReady?: boolean } | null> {\n // Try to start a local callback server for instant token delivery.\n // In --ci mode the browser step is handled externally, so skip the callback\n // server and go straight to polling — simpler and testable.\n let server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n if (!options.ci) {\n try {\n server = await startCallbackServer();\n } catch {\n // Port conflict or other issue — fall back to polling\n }\n }\n\n const session = await api.startCliAuthSession(server?.port, repoCanonical);\n // Re-auth: user already has a workspace — use verificationUrl (auth/cli page)\n // so we don't trigger a new GitHub App install and create a duplicate workspace.\n // First-time: use installUrl to combine Vocoder auth + App install in one trip.\n const browserUrl = reauth\n ? session.verificationUrl\n : (session.installUrl ?? session.verificationUrl);\n const expiresAt = new Date(session.expiresAt).getTime();\n\n if (options.ci) {\n // Machine-readable output for automated test harnesses.\n // Parsed by e2e/helpers/cli.ts: /^VOCODER_AUTH_URL: (.+)$/m\n process.stdout.write(`VOCODER_AUTH_URL: ${browserUrl}\\n`);\n // Also emit the session ID separately so tests can expire/complete sessions\n process.stdout.write(`VOCODER_SESSION_ID: ${session.sessionId}\\n`);\n } else if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {\n if (reauth) {\n // Re-auth: token expired, just sign in — no install choice needed\n if (!options.yes) {\n const shouldOpen = await p.confirm({ message: 'Open your browser to sign in again?' });\n if (p.isCancel(shouldOpen)) {\n server?.close();\n p.cancel('Setup cancelled.');\n return null;\n }\n if (!shouldOpen) {\n p.log.info('Open the URL above manually in your browser to continue.');\n } else {\n const opened = await tryOpenBrowser(browserUrl);\n if (!opened) {\n p.note(browserUrl, 'Sign In');\n p.log.info('Open the URL above manually to continue.');\n }\n }\n } else {\n await tryOpenBrowser(browserUrl);\n }\n } else {\n // First-time setup: let user choose install vs link existing\n let isLinkFlow = false;\n if (!options.yes) {\n const connectChoice = await p.select<string>({\n message: 'Vocoder needs to be installed on your GitHub account to get started',\n options: [\n { value: 'install', label: 'Install GitHub App', hint: 'recommended' },\n { value: 'link', label: 'Already installed? Link your account' },\n ],\n });\n\n if (p.isCancel(connectChoice)) {\n server?.close();\n p.cancel('Setup cancelled.');\n return null;\n }\n\n isLinkFlow = connectChoice === 'link';\n }\n\n // For \"link\": get the OAuth-only URL from the server (no install page shown)\n let urlToOpen = browserUrl;\n if (isLinkFlow) {\n try {\n const linkSession = await api.startCliGitHubLinkSession(\n session.sessionId,\n server?.port,\n );\n urlToOpen = linkSession.oauthUrl;\n } catch {\n // Fall back to install URL if link-start fails\n urlToOpen = browserUrl;\n }\n }\n\n // Open browser immediately — no separate confirm needed\n const opened = await tryOpenBrowser(urlToOpen);\n if (!opened) {\n // Only show URL as a fallback if auto-open fails\n p.log.warn('Could not open your browser automatically.');\n p.note(urlToOpen, 'GitHub');\n p.log.info('Open the URL above to continue.');\n }\n }\n }\n\n const authSpinner = p.spinner();\n authSpinner.start('Waiting for GitHub authorization...');\n\n let rawToken: string | null = null;\n let callbackOrganizationId: string | undefined;\n let callbackDiscoveryReady = false;\n\n if (server) {\n // Fast path: wait for the localhost callback\n try {\n const deadline = Math.min(expiresAt, Date.now() + 10 * 60 * 1000);\n const timeoutMs = deadline - Date.now();\n const params = await Promise.race([\n server.waitForCallback(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), timeoutMs)),\n ]);\n\n if (params && typeof params.token === 'string') {\n rawToken = params.token;\n if (typeof params.organizationId === 'string' && params.organizationId) {\n callbackOrganizationId = params.organizationId;\n }\n // Link flow: callback signals discovery results are cached\n if (params.discovery_ready === '1') {\n callbackDiscoveryReady = true;\n }\n }\n } catch {\n // Fall through to polling\n } finally {\n server.close();\n }\n }\n\n if (!rawToken) {\n // Polling fallback\n while (Date.now() < expiresAt) {\n const result = await api.pollCliAuthSession(session.sessionId);\n\n if (result.status === 'complete') {\n rawToken = result.token;\n if (result.organizationId) {\n callbackOrganizationId = result.organizationId;\n }\n break;\n }\n\n if (result.status === 'failed') {\n authSpinner.stop();\n p.log.error(result.reason);\n return null;\n }\n\n // Still pending — wait 2s before next poll\n await sleep(2000);\n }\n }\n\n if (!rawToken) {\n authSpinner.stop();\n p.log.error('The authentication link expired. Run `vocoder init` again.');\n return null;\n }\n\n // Validate the token and get user info\n const userInfo = await api.getCliUserInfo(rawToken);\n authSpinner.stop(`Authenticated as ${chalk.bold(userInfo.email)}`);\n\n return { token: rawToken, ...userInfo, organizationId: callbackOrganizationId, discoveryReady: callbackDiscoveryReady };\n}\n\n// ── Main command ─────────────────────────────────────────────────────────────\n\nexport async function init(options: InitOptions = {}): Promise<number> {\n const apiUrl = options.apiUrl || process.env.VOCODER_API_URL || 'https://vocoder.app';\n\n p.intro('Vocoder Setup');\n\n try {\n // ── Detect git context ──────────────────────────────────────────────────\n const gitContext = resolveGitContext();\n const identity = gitContext.identity;\n\n if (gitContext.warnings.length > 0) {\n for (const warning of gitContext.warnings) {\n p.log.warn(warning);\n }\n }\n\n // ── Fast lookup: does a project already exist for this repo? ────────────\n // No spinner — this is a fast DB read and we don't want an empty ◇ on miss.\n let existingAppsForRepo: Array<{\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n }> = [];\n let repoProjectId: string | null = null;\n let repoProjectName: string | null = null;\n\n if (identity) {\n const anonApi = new VocoderAPI({ apiUrl, apiKey: '' });\n const lookup = await anonApi.lookupProjectByRepo({\n repoCanonical: identity.repoCanonical,\n scopePath: identity.repoScopePath,\n });\n\n // Exact match: this scope is already configured — scaffold and exit.\n if (lookup.exactMatch) {\n const { exactMatch } = lookup;\n runScaffold({\n projectName: exactMatch.projectName,\n organizationName: exactMatch.organizationName,\n sourceLocale: exactMatch.sourceLocale ?? 'en',\n branchTriggers: exactMatch.branchTriggers ?? [{ pattern: 'main', triggers: ['push'] }],\n });\n p.outro(\"Vocoder is already set up for this repository.\");\n return 0;\n }\n\n // Whole-repo app exists: covers this repo from any directory — scaffold.\n if (lookup.hasWholeRepoApp) {\n const wholeRepo = lookup.existingApps.find((a) => a.scopePath === '');\n if (wholeRepo) {\n runScaffold({\n projectName: wholeRepo.projectName,\n organizationName: wholeRepo.organizationName,\n sourceLocale: 'en',\n branchTriggers: [{ pattern: 'main', triggers: ['push'] }],\n });\n p.outro(\"Vocoder is already set up for this repository.\");\n return 0;\n }\n }\n\n // Other scoped apps exist: this repo has a project but not for this scope.\n // Store for display + validation in the app directory prompt.\n if (lookup.existingApps.length > 0) {\n existingAppsForRepo = lookup.existingApps;\n // All apps belong to the same project (one project per repo)\n repoProjectId = lookup.existingApps[0]?.projectId ?? null;\n repoProjectName = lookup.existingApps[0]?.projectName ?? null;\n }\n }\n\n // ── Auth: check stored token, prompt if missing ─────────────────────────\n const api = new VocoderAPI({ apiUrl, apiKey: '' });\n let userToken: string;\n let userEmail: string;\n let userName: string | null;\n\n // organizationId is set when auth+GitHub install completed in one browser trip\n let authOrganizationId: string | undefined;\n // discoveryReady is set when auth completed via link-start OAuth (no install)\n let authDiscoveryReady = false;\n\n const stored = readAuthData();\n if (stored && stored.apiUrl === apiUrl) {\n const verified = await verifyStoredToken(api, stored.token);\n\n if (verified && !('userGone' in verified)) {\n p.log.success(`Authenticated as ${chalk.bold(verified.email)}`);\n userToken = stored.token;\n userEmail = verified.email;\n userName = verified.name;\n } else {\n // userGone = user deleted from DB → full first-time flow (installUrl)\n // null = token expired → reauth via verificationUrl\n const isFirstTime = verified !== null && 'userGone' in verified;\n if (isFirstTime) {\n p.log.warn('Account not found — starting fresh setup');\n } else {\n p.log.warn('Stored credentials expired — signing in again');\n }\n const authResult = await runAuthFlow(api, options, /* reauth */ !isFirstTime, identity?.repoCanonical);\n if (!authResult) return 1;\n userToken = authResult.token;\n userEmail = authResult.email;\n userName = authResult.name;\n authOrganizationId = authResult.organizationId;\n authDiscoveryReady = authResult.discoveryReady ?? false;\n\n writeAuthData({\n token: userToken,\n apiUrl,\n userId: authResult.userId,\n email: userEmail,\n name: userName,\n createdAt: new Date().toISOString(),\n });\n }\n } else {\n const authResult = await runAuthFlow(api, options, false, identity?.repoCanonical);\n if (!authResult) return 1;\n userToken = authResult.token;\n userEmail = authResult.email;\n userName = authResult.name;\n authOrganizationId = authResult.organizationId;\n\n writeAuthData({\n token: userToken,\n apiUrl,\n userId: authResult.userId,\n email: userEmail,\n name: userName,\n createdAt: new Date().toISOString(),\n });\n }\n\n // ── Workspace selection ─────────────────────────────────────────────────────\n let selectedWorkspaceId: string;\n let selectedWorkspaceName: string;\n\n if (authOrganizationId) {\n // Install path: auth+install completed in one browser trip, workspace already created.\n const workspaceData = await api.listWorkspaces(userToken);\n const ws = workspaceData.workspaces.find((w) => w.id === authOrganizationId);\n selectedWorkspaceId = authOrganizationId;\n selectedWorkspaceName = ws?.name ?? userEmail;\n p.log.success(`Connected as ${chalk.bold(userEmail)} — workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n // Always check for cached discovery results first. The cache expires in\n // 5 minutes so returning users (no recent link flow) fall through cleanly.\n const discoveryResult = await api.getCliGitHubDiscovery(userToken).catch(() => null);\n const cachedInstallations = discoveryResult?.installations ?? [];\n\n if (cachedInstallations.length > 0) {\n // Warn if none of the discovered installations belong to the org that\n // owns the current repo — the binding won't be created even if setup succeeds.\n if (identity?.repoCanonical) {\n const repoOwner = identity.repoCanonical.split(':')[1]?.split('/')[0]?.toLowerCase();\n if (repoOwner) {\n const hasMatchingAccount = cachedInstallations.some(\n (i) => i.accountLogin.toLowerCase() === repoOwner,\n );\n if (!hasMatchingAccount) {\n p.log.warn(\n `None of your GitHub App installations belong to \"${repoOwner}\", ` +\n `the account that owns this repository.\\n` +\n ` The project will be created but translations won't trigger automatically.\\n` +\n ` To fix: install the Vocoder GitHub App on \"${repoOwner}\" instead.`,\n );\n }\n }\n }\n\n // Auto-select when there's exactly one valid (non-suspended, unclaimed) installation\n const validInstallations = cachedInstallations.filter(\n (i) => !i.isSuspended && !i.conflictLabel,\n );\n\n let selectedInstallationId: number | string | null = null;\n\n if (validInstallations.length === 1 && cachedInstallations.length === 1) {\n // Single installation — claim silently, no prompt needed\n selectedInstallationId = validInstallations[0]!.installationId;\n } else {\n selectedInstallationId = await selectGitHubInstallation(\n cachedInstallations.map((inst) => ({\n installationId: inst.installationId,\n accountLogin: inst.accountLogin,\n accountType: inst.accountType,\n isSuspended: inst.isSuspended,\n conflictLabel: inst.conflictLabel,\n })),\n false,\n );\n }\n\n if (selectedInstallationId === null || selectedInstallationId === 'install_new') {\n p.cancel('Setup cancelled. Re-run `vocoder init` and choose Install GitHub App.');\n return 1;\n }\n\n const claimResult = await api.claimCliGitHubInstallation(userToken, {\n installationId: String(selectedInstallationId),\n organizationId: null,\n });\n selectedWorkspaceId = claimResult.organizationId;\n selectedWorkspaceName = claimResult.organizationName;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n // ── Repo-aware workspace resolution ──────────────────────────────────────\n const workspaceData = await api.listWorkspaces(userToken, {\n repo: identity?.repoCanonical,\n });\n\n const repoCanonical = identity?.repoCanonical ?? null;\n // Workspaces whose GitHub installation covers the current repo\n const covering = repoCanonical\n ? workspaceData.workspaces.filter((w) => w.coversRepo === true)\n : [];\n // Workspaces that have any GitHub connection (may not cover this repo)\n const connected = workspaceData.workspaces.filter((w) => w.hasGitHubConnection);\n\n if (repoCanonical && covering.length === 1) {\n // ── Scenario 1: exactly one workspace covers this repo — auto-select ──\n const ws = covering[0]!;\n selectedWorkspaceId = ws.id;\n selectedWorkspaceName = ws.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\n } else if (repoCanonical && covering.length > 1) {\n // ── Scenario 2: multiple workspaces cover this repo — let user pick ──\n const choice = await p.select<string>({\n message: 'Select workspace for this repo',\n options: covering.map((w) => ({\n value: w.id,\n label: `${w.name} ${chalk.dim(`(${w.projectCount} project${w.projectCount !== 1 ? 's' : ''})`)}`,\n })),\n });\n if (p.isCancel(choice)) { p.cancel('Setup cancelled.'); return 1; }\n const ws = covering.find((w) => w.id === choice)!;\n selectedWorkspaceId = ws.id;\n selectedWorkspaceName = ws.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\n } else if (repoCanonical && covering.length === 0 && connected.length > 0) {\n // ── Scenario 3: connected workspaces exist but none cover this repo ──\n const shortRepo = repoCanonical.split(':')[1] ?? repoCanonical;\n p.log.warn(\n `${chalk.bold(shortRepo)} isn't accessible from your Vocoder installation.\\n` +\n ` Grant access to this repository or install on the account that owns it.`,\n );\n\n const fixOptions: Array<{ value: string; label: string }> = [];\n for (const ws of connected) {\n if (ws.installationConfigureUrl) {\n fixOptions.push({\n value: `grant:${ws.id}`,\n label: `Configure ${chalk.bold(ws.connectionLabel ?? ws.name)}'s GitHub App installation`,\n });\n }\n }\n fixOptions.push({\n value: 'install_new',\n label: `Install on a different GitHub account ${chalk.dim('(creates a new personal workspace)')}`,\n });\n fixOptions.push({ value: 'cancel', label: 'Cancel' });\n\n const fix = await p.select<string>({\n message: 'How would you like to fix this?',\n options: fixOptions,\n });\n\n if (p.isCancel(fix) || fix === 'cancel') {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n if (fix.startsWith('grant:')) {\n const ws = connected.find((w) => `grant:${w.id}` === fix)!;\n await tryOpenBrowser(ws.installationConfigureUrl!);\n p.cancel(\n `Grant access to ${chalk.bold(shortRepo)} in your browser,\\n` +\n ` then re-run ${chalk.bold('vocoder init')}.`,\n );\n return 1;\n }\n\n // install_new: full install → creates new workspace covering the new account\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) {\n p.log.error('GitHub App installation did not complete. Run `vocoder init` again.');\n return 1;\n }\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\n } else {\n // ── Fallback: no repo context or first-time user — standard select ────\n if (workspaceData.workspaces.length === 1 && !workspaceData.canCreateWorkspace) {\n const ws = workspaceData.workspaces[0]!;\n selectedWorkspaceId = ws.id;\n selectedWorkspaceName = ws.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n\n const workspaceResult = await selectWorkspace(workspaceData);\n\n if (workspaceResult.action === 'cancelled') {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n if (workspaceResult.action === 'use') {\n selectedWorkspaceId = workspaceResult.workspace.id;\n selectedWorkspaceName = workspaceResult.workspace.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n // ── New workspace: GitHub connect flow ────────────────────────────────\n const connectChoice = await p.select<string>({\n message: 'Connect your new workspace to GitHub',\n options: [\n { value: 'install', label: 'Install the Vocoder GitHub App' },\n { value: 'link', label: 'Link an existing installation' },\n ],\n });\n\n if (p.isCancel(connectChoice)) {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n if (connectChoice === 'install') {\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) {\n p.log.error('GitHub App installation did not complete. Run `vocoder init` again.');\n return 1;\n }\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n const installations = await runGitHubDiscoveryFlow({ api, userToken, yes: options.yes });\n if (!installations) return 1;\n\n if (installations.length === 0) {\n p.log.warn('No GitHub installations found. Install the Vocoder GitHub App first.');\n const installNow = await p.confirm({ message: 'Open GitHub to install the App?' });\n if (p.isCancel(installNow) || !installNow) return 1;\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) return 1;\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n } else {\n const selectedInstallationId = await selectGitHubInstallation(\n installations.map((inst) => ({\n installationId: inst.installationId,\n accountLogin: inst.accountLogin,\n accountType: inst.accountType,\n isSuspended: inst.isSuspended,\n conflictLabel: inst.conflictLabel,\n })),\n true,\n );\n\n if (selectedInstallationId === null) { p.cancel('Setup cancelled.'); return 1; }\n\n if (selectedInstallationId === 'install_new') {\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) return 1;\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n } else {\n const claimResult = await api.claimCliGitHubInstallation(userToken, {\n installationId: String(selectedInstallationId),\n organizationId: null,\n });\n selectedWorkspaceId = claimResult.organizationId;\n selectedWorkspaceName = claimResult.organizationName;\n }\n }\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n }\n } // closes new workspace else\n } // closes auto-select else\n } // closes main scenario if/else chain\n } // closes cachedInstallations else\n } // closes if (authOrganizationId) else\n\n // ── Add-app path: repo already has a project with scoped apps ───────────────\n // Skip plan limit check — we're adding a ProjectApp to an existing project,\n // not creating a new one. Run the project config prompts then call\n // POST /api/cli/project/apps.\n if (repoProjectId && repoProjectName && existingAppsForRepo.length > 0) {\n p.log.info(\n `${chalk.bold(repoProjectName)} is already set up for this repo.\\n` +\n ` Configured apps: ${existingAppsForRepo\n .map((a) => chalk.cyan(a.scopePath || '(entire repo)'))\n .join(', ')}`,\n );\n\n const appResult = await runProjectAppCreate({\n api,\n userToken,\n projectId: repoProjectId,\n projectName: repoProjectName,\n organizationName: selectedWorkspaceName,\n repoCanonical: identity?.repoCanonical,\n defaultScopePath: identity?.repoScopePath,\n existingApps: existingAppsForRepo,\n });\n\n if (!appResult) {\n p.log.error('App setup failed. Run `vocoder init` again.');\n return 1;\n }\n\n runScaffold({\n projectName: appResult.projectName,\n organizationName: selectedWorkspaceName,\n sourceLocale: appResult.sourceLocale,\n branchTriggers: appResult.branchTriggers,\n });\n p.outro(\"You're all set.\");\n return 0;\n }\n\n // ── Plan limit pre-flight ────────────────────────────────────────────────────\n try {\n const wsCheck = await api.listWorkspaces(userToken);\n const ws = wsCheck.workspaces.find((w) => w.id === selectedWorkspaceId);\n if (ws && ws.maxProjects !== -1 && ws.projectCount >= ws.maxProjects) {\n p.log.warn(\n `Project limit reached — ${ws.projectCount}/${ws.maxProjects} on your ${chalk.bold(ws.planId)} plan.`,\n );\n\n const limitAction = await p.select<string>({\n message: 'What would you like to do?',\n options: [\n { value: 'upgrade', label: 'Upgrade plan' },\n { value: 'cancel', label: 'Cancel' },\n ],\n });\n\n if (p.isCancel(limitAction) || limitAction === 'cancel') {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n await tryOpenBrowser(`${apiUrl}${SUBSCRIPTION_SETTINGS_PATH}`);\n p.cancel('Upgrade your plan in the browser, then re-run `vocoder init`.');\n return 1;\n }\n } catch {\n // Non-fatal\n }\n\n // ── Project configuration ────────────────────────────────────────────────────\n const projectResult = await runProjectCreate({\n api,\n userToken,\n organizationId: selectedWorkspaceId,\n defaultName: identity?.repoCanonical\n ? identity.repoCanonical.split('/').pop()\n : undefined,\n defaultSourceLocale: 'en',\n repoCanonical: identity?.repoCanonical,\n defaultBranches: ['main'],\n defaultScopePath: identity?.repoScopePath,\n });\n\n\n if (!projectResult) {\n p.log.error('Project creation failed. Run `vocoder init` again.');\n return 1;\n }\n\n // Warn if the current repo isn't accessible to the GitHub App installation.\n // This means translations won't trigger on push until the App is granted access.\n if (!projectResult.repositoryBound && identity?.repoCanonical) {\n p.log.warn(\n `This repository isn't accessible to your GitHub App installation.\\n` +\n `Translations won't run automatically until you grant access.\\n\\n` +\n ` To fix: go to your GitHub App installation settings and add this\\n` +\n ` repository to the allowed list, or switch to \"All repositories\".\\n` +\n (projectResult.configureUrl\n ? `\\n ${chalk.dim(projectResult.configureUrl)}\\n`\n : ''),\n );\n }\n\n // ── Scaffold + MCP setup ─────────────────────────────────────────────────────\n runScaffold({\n projectName: projectResult.projectName,\n organizationName: selectedWorkspaceName,\n sourceLocale: projectResult.sourceLocale,\n branchTriggers: projectResult.branchTriggers,\n });\n\n printMcpSetup(projectResult.apiKey);\n\n p.outro(\"You're all set.\");\n return 0;\n } catch (error) {\n if (error instanceof Error) {\n if (isPlanLimitFailure(error.message)) {\n printPlanLimitMessage(apiUrl, error.message);\n return 1;\n }\n p.log.error(`Error: ${error.message}`);\n } else {\n p.log.error('Unknown setup error');\n }\n\n return 1;\n }\n}\n","import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nexport interface AuthData {\n token: string;\n apiUrl: string;\n userId: string;\n email: string;\n name: string | null;\n createdAt: string;\n}\n\nfunction getAuthFilePath(): string {\n return join(homedir(), '.config', 'vocoder', 'auth.json');\n}\n\nexport function readAuthData(): AuthData | null {\n const filePath = getAuthFilePath();\n try {\n const raw = readFileSync(filePath, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== 'object') return null;\n const data = parsed as Partial<AuthData>;\n if (\n typeof data.token !== 'string' ||\n typeof data.apiUrl !== 'string' ||\n typeof data.userId !== 'string' ||\n typeof data.email !== 'string' ||\n typeof data.createdAt !== 'string'\n ) {\n return null;\n }\n return {\n token: data.token,\n apiUrl: data.apiUrl,\n userId: data.userId,\n email: data.email,\n name: typeof data.name === 'string' ? data.name : null,\n createdAt: data.createdAt,\n };\n } catch {\n return null;\n }\n}\n\nexport function writeAuthData(data: AuthData): void {\n const filePath = getAuthFilePath();\n const dir = dirname(filePath);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n writeFileSync(filePath, JSON.stringify(data, null, 2), { mode: 0o600 });\n}\n\nexport function clearAuthData(): void {\n const filePath = getAuthFilePath();\n try {\n unlinkSync(filePath);\n } catch {\n // Already gone — that's fine\n }\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\nimport { spawn } from 'node:child_process';\nimport type { VocoderAPI } from './api.js';\nimport { startCallbackServer } from './local-server.js';\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n if (!process.stdout.isTTY || process.env.CI === 'true') {\n return false;\n }\n\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 = 'rundll32';\n args = ['url.dll,FileProtocolHandler', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n return new Promise<boolean>((resolve) => {\n try {\n const child = spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n\n let settled = false;\n child.once('spawn', () => {\n if (settled) return;\n settled = true;\n child.unref();\n resolve(true);\n });\n child.once('error', () => {\n if (settled) return;\n settled = true;\n resolve(false);\n });\n setTimeout(() => {\n if (settled) return;\n settled = true;\n resolve(false);\n }, 300);\n } catch {\n resolve(false);\n }\n });\n}\n\nexport interface GitHubConnectResult {\n organizationId: string;\n organizationName: string;\n connectionLabel: string;\n}\n\n/**\n * Run the full GitHub App install flow for a new workspace.\n * Opens the browser to the GitHub App install page and waits for completion.\n *\n * Returns `null` if the user cancelled or an error occurred.\n */\nexport async function runGitHubInstallFlow(params: {\n api: VocoderAPI;\n userToken: string;\n organizationId?: string;\n yes?: boolean;\n}): Promise<GitHubConnectResult | null> {\n // Try to start a local callback server for instant notification\n let server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n try {\n server = await startCallbackServer();\n } catch {\n // Fall through — the user can re-run if something goes wrong\n }\n\n const { installUrl } = await params.api.startCliGitHubInstall(params.userToken, {\n organizationId: params.organizationId,\n callbackPort: server?.port,\n });\n\n p.log.info('Opening GitHub to install the Vocoder App...');\n p.note(installUrl, 'Install URL');\n\n if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {\n const shouldOpen = params.yes\n ? true\n : await p.confirm({ message: 'Open in your browser?' });\n\n if (p.isCancel(shouldOpen)) {\n server?.close();\n return null;\n }\n\n if (shouldOpen) {\n const opened = await tryOpenBrowser(installUrl);\n if (!opened) {\n p.log.info('Could not open a browser automatically. Use the URL above.');\n }\n }\n }\n\n const connectSpinner = p.spinner();\n connectSpinner.start('Waiting for GitHub App installation...');\n\n if (server) {\n try {\n const params_timeout = 15 * 60 * 1000; // 15 minutes\n const callbackParams = await Promise.race([\n server.waitForCallback(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), params_timeout)),\n ]);\n\n server.close();\n\n if (!callbackParams) {\n connectSpinner.stop('GitHub App installation timed out');\n p.log.error('The installation flow timed out. Run `vocoder init` again.');\n return null;\n }\n\n if (callbackParams.error) {\n connectSpinner.stop('GitHub App installation failed');\n p.log.error(callbackParams.error);\n return null;\n }\n\n const { organizationId, connectionLabel, workspace_created } = callbackParams;\n\n if (!organizationId || !connectionLabel) {\n connectSpinner.stop('GitHub App installation incomplete');\n p.log.error('Missing organization or connection data from callback.');\n return null;\n }\n\n connectSpinner.stop(`Connected to GitHub as ${chalk.bold(connectionLabel)}`);\n\n // Fetch the org name\n const orgName = workspace_created ? connectionLabel : organizationId;\n return {\n organizationId,\n organizationName: orgName,\n connectionLabel,\n };\n } catch {\n server.close();\n connectSpinner.stop('GitHub App installation failed');\n return null;\n }\n }\n\n // No local server — there's no polling fallback for install; just wait\n connectSpinner.stop('Could not detect GitHub App installation automatically');\n p.log.warn('Complete the installation in your browser, then run `vocoder init` again.');\n return null;\n}\n\n/**\n * Run the GitHub OAuth discovery flow to find existing installations.\n * Returns the list of installations with conflict labels, or null on cancellation/error.\n */\nexport async function runGitHubDiscoveryFlow(params: {\n api: VocoderAPI;\n userToken: string;\n organizationId?: string;\n yes?: boolean;\n}): Promise<Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n}> | null> {\n // Try local callback server\n let server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n try {\n server = await startCallbackServer();\n } catch {\n // Fall through\n }\n\n const { oauthUrl } = await params.api.startCliGitHubOAuth(params.userToken, {\n organizationId: params.organizationId,\n callbackPort: server?.port,\n });\n\n p.log.info('Opening GitHub to authorize your account...');\n p.note('Complete authorization in your browser.');\n\n if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {\n const shouldOpen = params.yes\n ? true\n : await p.confirm({ message: 'Open in your browser?' });\n\n if (p.isCancel(shouldOpen)) {\n server?.close();\n return null;\n }\n\n if (shouldOpen) {\n const opened = await tryOpenBrowser(oauthUrl);\n if (!opened) {\n p.log.info(`Could not open browser automatically. Visit: ${oauthUrl}`);\n }\n }\n }\n\n const oauthSpinner = p.spinner();\n oauthSpinner.start('Waiting for GitHub authorization...');\n\n if (server) {\n try {\n const timeoutMs = 10 * 60 * 1000;\n const callbackParams = await Promise.race([\n server.waitForCallback(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), timeoutMs)),\n ]);\n\n server.close();\n\n if (!callbackParams) {\n oauthSpinner.stop('GitHub authorization timed out');\n return null;\n }\n\n if (callbackParams.error) {\n oauthSpinner.stop('GitHub authorization failed');\n p.log.error(callbackParams.error);\n return null;\n }\n } catch {\n server.close();\n oauthSpinner.stop('GitHub authorization failed');\n return null;\n }\n }\n\n oauthSpinner.stop('GitHub account authorized');\n\n // Fetch discovery results\n const discoveryResult = await params.api.getCliGitHubDiscovery(params.userToken);\n return discoveryResult.installations;\n}\n\ntype DiscoveredInstallation = {\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n};\n\n/**\n * Prompt the user to select a GitHub installation from discovery results.\n * Returns the selected installation ID, 'install_new' to trigger install flow,\n * or null on cancellation.\n */\nexport async function selectGitHubInstallation(\n installations: DiscoveredInstallation[],\n canInstallNew: boolean,\n): Promise<number | 'install_new' | null> {\n type SelectValue = string;\n\n const options: Array<{ value: SelectValue; label: string; hint?: string }> =\n installations.map((inst) => ({\n value: String(inst.installationId),\n label: inst.accountLogin,\n hint: [\n inst.accountType === 'Organization' ? 'organization' : 'personal',\n inst.conflictLabel ? `connected to ${inst.conflictLabel}` : '',\n inst.isSuspended ? 'suspended' : '',\n ]\n .filter(Boolean)\n .join(' · ') || undefined,\n }));\n\n if (canInstallNew) {\n options.push({\n value: 'install_new',\n label: `Install on a new account ${chalk.dim('(creates a new personal workspace)')}`,\n });\n }\n\n const selected = await p.select<SelectValue>({\n message: 'Select a GitHub installation',\n options,\n });\n\n if (p.isCancel(selected)) return null;\n if (selected === 'install_new') return 'install_new';\n\n return Number(selected);\n}\n","import { createServer } from 'node:http';\nimport { AddressInfo } from 'node:net';\nimport { URL } from 'node:url';\n\nexport interface LocalServerHandle {\n port: number;\n waitForCallback: () => Promise<Record<string, string>>;\n close: () => void;\n}\n\n/**\n * Starts a local HTTP server on a random available port.\n * Returns the port and a promise that resolves when the browser\n * redirects to /callback with query parameters.\n *\n * Used for the browser→CLI token handoff pattern:\n * 1. CLI passes `port` to the auth session start request\n * 2. After browser auth, vocoder.app redirects to localhost:<port>/callback?token=...\n * 3. `waitForCallback()` resolves with the query params\n */\nexport function startCallbackServer(): Promise<LocalServerHandle> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let callbackResolve: ((params: Record<string, string>) => void) | null = null;\n let callbackReject: ((err: Error) => void) | null = null;\n\n const callbackPromise = new Promise<Record<string, string>>((res, rej) => {\n callbackResolve = res;\n callbackReject = rej;\n });\n\n const server = createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end();\n return;\n }\n\n let pathname: string;\n let params: Record<string, string>;\n\n try {\n const parsed = new URL(req.url, 'http://localhost');\n pathname = parsed.pathname;\n params = Object.fromEntries(parsed.searchParams.entries());\n } catch {\n res.writeHead(400);\n res.end('Bad request');\n return;\n }\n\n if (pathname !== '/callback') {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<!DOCTYPE html><html><head><title>Authenticated</title></head>' +\n '<body style=\"font-family:sans-serif;text-align:center;padding:3rem;\">' +\n '<h2>Authenticated</h2>' +\n '<p>Return to your terminal to continue. You can close this tab.</p>' +\n '</body></html>',\n );\n\n if (callbackResolve) {\n callbackResolve(params);\n callbackResolve = null;\n }\n\n setImmediate(() => server.close());\n });\n\n server.on('error', (err) => {\n if (!settled) {\n settled = true;\n if (callbackReject) callbackReject(err);\n reject(err);\n }\n });\n\n // Bind to a random port on localhost only\n server.listen(0, '127.0.0.1', () => {\n if (settled) return;\n settled = true;\n\n const port = (server.address() as AddressInfo).port;\n\n resolve({\n port,\n waitForCallback: () => callbackPromise,\n close: () => server.close(),\n });\n });\n });\n}\n","import type {\n APIProjectConfig,\n InitStartResponse,\n InitStatusResponse,\n\tLimitErrorResponse,\n\tLocalConfig,\n\tRequestedSyncMode,\n\tRepoIdentityPayload,\n\tSyncPolicyErrorResponse,\n\tTranslationBatchResponse,\n\tTranslationSnapshotResponse,\n\tTranslationStringEntry,\n\tTranslationStatusResponse,\n} from '../types.js';\n\nfunction isLimitErrorResponse(value: unknown): value is LimitErrorResponse {\n if (!value || typeof value !== 'object') {\n return false;\n }\n\n const candidate = value as Partial<LimitErrorResponse>;\n return (\n typeof candidate.errorCode === 'string' &&\n typeof candidate.limitType === 'string' &&\n typeof candidate.planId === 'string' &&\n typeof candidate.current === 'number' &&\n typeof candidate.required === 'number' &&\n typeof candidate.upgradeUrl === 'string' &&\n typeof candidate.message === 'string'\n );\n}\n\nfunction isSyncPolicyErrorResponse(value: unknown): value is SyncPolicyErrorResponse {\n if (!value || typeof value !== 'object') {\n return false;\n }\n\n const candidate = value as Partial<SyncPolicyErrorResponse>;\n return (\n (candidate.errorCode === 'BRANCH_NOT_ALLOWED' ||\n candidate.errorCode === 'PROJECT_REPOSITORY_MISMATCH') &&\n typeof candidate.message === 'string'\n );\n}\n\nfunction extractErrorMessage(payload: unknown, fallback: string): string {\n if (!payload || typeof payload !== 'object') {\n return fallback;\n }\n\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.message === 'string') {\n return candidate.message;\n }\n\n if (typeof candidate.error === 'string') {\n return candidate.error;\n }\n\n return fallback;\n}\n\nfunction parsePayload(raw: string): unknown {\n if (raw.length === 0) {\n return null;\n }\n\n // HTML responses (e.g. Next.js error pages) are never valid API payloads.\n // Wrapping raw HTML as the error message causes it to leak into the TUI.\n const trimmed = raw.trimStart();\n if (trimmed.startsWith('<!DOCTYPE') || trimmed.startsWith('<html')) {\n return { message: 'Unexpected response from server (received HTML). Check your network connection or try again.' };\n }\n\n try {\n return JSON.parse(raw);\n } catch {\n return { message: raw };\n }\n}\n\nasync function readPayload(response: {\n text?: () => Promise<string>;\n json?: () => Promise<unknown>;\n}): Promise<unknown> {\n if (typeof response.text === 'function') {\n const raw = await response.text();\n return parsePayload(raw);\n }\n\n if (typeof response.json === 'function') {\n return response.json();\n }\n\n return null;\n}\n\nexport class VocoderAPIError extends Error {\n readonly status: number;\n readonly payload: unknown;\n readonly limitError: LimitErrorResponse | null;\n readonly syncPolicyError: SyncPolicyErrorResponse | null;\n\n constructor(params: {\n message: string;\n status: number;\n payload: unknown;\n limitError?: LimitErrorResponse | null;\n syncPolicyError?: SyncPolicyErrorResponse | null;\n }) {\n super(params.message);\n this.name = 'VocoderAPIError';\n this.status = params.status;\n this.payload = params.payload;\n this.limitError = params.limitError ?? null;\n this.syncPolicyError = params.syncPolicyError ?? null;\n }\n}\n\nexport class VocoderAPI {\n private apiUrl: string;\n private apiKey: string;\n\n constructor(config: LocalConfig) {\n this.apiUrl = config.apiUrl;\n this.apiKey = config.apiKey;\n }\n\n private async request<T>(\n path: string,\n init: RequestInit = {},\n errorPrefix?: string,\n ): Promise<T> {\n const response = await fetch(`${this.apiUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n ...(init.headers ?? {}),\n },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n const limitError = isLimitErrorResponse(payload) ? payload : null;\n const syncPolicyError = isSyncPolicyErrorResponse(payload) ? payload : null;\n const baseMessage = extractErrorMessage(payload, `Request failed with status ${response.status}`);\n throw new VocoderAPIError({\n message: errorPrefix ? `${errorPrefix}: ${baseMessage}` : baseMessage,\n status: response.status,\n payload,\n limitError,\n syncPolicyError,\n });\n }\n\n return payload as T;\n }\n\n /**\n * Fetch project configuration from API\n * Project is determined from the API key\n */\n\tasync getProjectConfig(): Promise<APIProjectConfig> {\n\t\tconst data = await this.request<{\n\t\t\tprojectName: string;\n\t\t\torganizationName: string;\n\t\t\tsourceLocale: string;\n\t\t\ttargetLocales: string[];\n\t\t\tbranchTriggers: Array<{ pattern: string; triggers: string[] }>;\n\t\t\tprimaryBranch?: string;\n\t\t\tsyncPolicy?: {\n\t\t\t\tblockingBranches?: string[];\n\t\t\t\tblockingMode?: \"required\" | \"best-effort\";\n\t\t\t\tnonBlockingMode?: \"required\" | \"best-effort\";\n\t\t\t\tdefaultMaxWaitMs?: number;\n\t\t\t};\n\t\t}>('/api/cli/config', {}, 'Failed to fetch project config');\n\n\t\treturn {\n\t\t\tprojectName: data.projectName,\n\t\t\torganizationName: data.organizationName,\n\t\t\tsourceLocale: data.sourceLocale,\n\t\t\ttargetLocales: data.targetLocales,\n\t\t\tbranchTriggers: data.branchTriggers ?? [],\n\t\t\tprimaryBranch: data.primaryBranch,\n\t\t\tsyncPolicy: {\n\t\t\t\tblockingBranches: data.syncPolicy?.blockingBranches ?? [\"main\", \"master\"],\n\t\t\t\tblockingMode: data.syncPolicy?.blockingMode ?? \"required\",\n\t\t\t\tnonBlockingMode: data.syncPolicy?.nonBlockingMode ?? \"best-effort\",\n\t\t\t\tdefaultMaxWaitMs: data.syncPolicy?.defaultMaxWaitMs ?? 60_000,\n\t\t\t},\n\t\t};\n\t}\n\n /**\n * Submit strings for translation\n * Project is determined from the API key\n */\n private stableTextKey(text: string): string {\n // FNV-1a 32-bit hash for deterministic fallback IDs\n let hash = 0x811c9dc5;\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return `SK_TEXT_${(hash >>> 0).toString(16).toUpperCase().padStart(8, '0')}`;\n }\n\n private normalizeStringEntries(\n entries: string[] | TranslationStringEntry[],\n ): TranslationStringEntry[] {\n if (entries.length === 0) {\n return [];\n }\n\n const first = entries[0];\n if (typeof first === 'string') {\n return (entries as string[]).map((text) => ({\n key: this.stableTextKey(text),\n text,\n }));\n }\n\n return (entries as TranslationStringEntry[]).map((entry, index) => ({\n key: entry.key || this.stableTextKey(`${entry.text}:${index}`),\n text: entry.text,\n ...(entry.context ? { context: entry.context } : {}),\n ...(entry.formality ? { formality: entry.formality } : {}),\n }));\n }\n\n\tasync submitTranslation(\n\t\tbranch: string,\n\t\tentries: string[] | TranslationStringEntry[],\n\t\ttargetLocales: string[],\n\t\toptions?: {\n\t\t\trequestedMode?: RequestedSyncMode;\n\t\t\trequestedMaxWaitMs?: number;\n\t\t\tclientRunId?: string;\n\t\t},\n\t\trepoIdentity?: RepoIdentityPayload,\n\t): Promise<TranslationBatchResponse> {\n const stringEntries = this.normalizeStringEntries(entries);\n const strings = stringEntries.map((entry) => entry.text);\n\n // Compute hash of sorted strings for fast comparison\n const crypto = await import('crypto');\n const sortedStrings = [...strings].sort();\n const stringsHash = crypto\n .createHash('sha256')\n .update(JSON.stringify(sortedStrings))\n .digest('hex');\n\n return this.request<TranslationBatchResponse>('/api/cli/sync', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n\t body: JSON.stringify({\n\t branch,\n\t stringEntries,\n\t targetLocales,\n\t stringsHash,\n\t ...(options?.requestedMode ? { requestedMode: options.requestedMode } : {}),\n\t ...(typeof options?.requestedMaxWaitMs === 'number'\n\t ? { requestedMaxWaitMs: options.requestedMaxWaitMs }\n\t : {}),\n\t ...(options?.clientRunId ? { clientRunId: options.clientRunId } : {}),\n\t ...(repoIdentity?.repoCanonical ? { repoCanonical: repoIdentity.repoCanonical } : {}),\n\t ...(repoIdentity?.repoScopePath !== undefined\n\t ? { repoScopePath: repoIdentity.repoScopePath }\n : {}),\n }),\n }, 'Translation submission failed');\n }\n\n /**\n * Check translation status\n */\n\tasync getTranslationStatus(\n\t\tbatchId: string,\n\t): Promise<TranslationStatusResponse> {\n\t\treturn this.request<TranslationStatusResponse>(\n\t\t\t`/api/cli/sync/status/${batchId}`,\n\t\t\t{},\n\t\t\t'Failed to check translation status',\n\t\t);\n\t}\n\n\tasync getTranslationSnapshot(params: {\n\t\tbranch: string;\n\t\ttargetLocales: string[];\n\t}): Promise<TranslationSnapshotResponse> {\n\t\tconst search = new URLSearchParams();\n\t\tsearch.set('branch', params.branch);\n\t\tfor (const locale of params.targetLocales) {\n\t\t\tsearch.append('targetLocale', locale);\n\t\t}\n\n\t\treturn this.request<TranslationSnapshotResponse>(\n\t\t\t`/api/cli/sync/snapshot?${search.toString()}`,\n\t\t\t{},\n\t\t\t'Failed to fetch translation snapshot',\n\t\t);\n\t}\n\n /**\n * Wait for translation to complete with polling\n */\n async waitForCompletion(\n batchId: string,\n timeout: number = 60000,\n onProgress?: (progress: number) => void,\n ): Promise<{\n translations: Record<string, Record<string, string>>;\n localeMetadata?: Record<string, { nativeName: string; dir?: 'rtl' }>;\n }> {\n const startTime = Date.now();\n const pollInterval = 1000; // Poll every second\n\n while (Date.now() - startTime < timeout) {\n const status = await this.getTranslationStatus(batchId);\n\n // Call progress callback\n if (onProgress) {\n onProgress(status.progress);\n }\n\n if (status.status === 'COMPLETED') {\n if (!status.translations) {\n throw new Error('Translation completed but no translations returned');\n }\n return {\n translations: status.translations,\n localeMetadata: status.localeMetadata,\n };\n }\n\n if (status.status === 'FAILED') {\n throw new Error(\n `Translation failed: ${status.errorMessage || 'Unknown error'}`,\n );\n }\n\n // Wait before polling again\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new Error(`Translation timeout after ${timeout}ms`);\n }\n\n async startInitSession(input: {\n projectName?: string;\n sourceLocale?: string;\n targetLocales?: string[];\n repoCanonical?: string;\n repoScopePath?: string;\n }): Promise<InitStartResponse> {\n const response = await fetch(`${this.apiUrl}/api/cli/init/start`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start init session (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as InitStartResponse;\n }\n\n async getInitSessionStatus(params: {\n sessionId: string;\n pollToken: string;\n }): Promise<InitStatusResponse> {\n const response = await fetch(\n `${this.apiUrl}/api/cli/init/status/${params.sessionId}`,\n {\n headers: {\n Authorization: `Bearer ${params.pollToken}`,\n },\n },\n );\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to get init status (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as InitStatusResponse;\n }\n\n // ── CLI Auth endpoints (no project API key needed) ──────────────────────────\n\n /**\n * Start a CLI auth session. Returns `{ sessionId, verificationUrl, expiresAt }`.\n * `sessionId` is the raw poll token — keep it secret, used for polling.\n */\n async startCliAuthSession(callbackPort?: number, repoCanonical?: string): Promise<{\n sessionId: string;\n verificationUrl: string;\n installUrl?: string;\n expiresAt: string;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/auth/start`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...(callbackPort != null ? { callbackPort } : {}),\n ...(repoCanonical ? { repoCanonical } : {}),\n }),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start auth session (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { sessionId: string; verificationUrl: string; installUrl?: string; expiresAt: string };\n }\n\n /**\n * Poll for CLI auth session completion.\n * Returns `{ token }` on success, throws on failure/expiry.\n * The server returns HTTP 202 while still pending.\n */\n async pollCliAuthSession(pollToken: string): Promise<\n | { status: 'pending' }\n | { status: 'complete'; token: string; organizationId?: string }\n | { status: 'failed'; reason: string }\n > {\n const response = await fetch(\n `${this.apiUrl}/api/cli/auth/session?session=${encodeURIComponent(pollToken)}`,\n );\n\n const payload = await readPayload(response);\n\n if (response.status === 202) {\n return { status: 'pending' };\n }\n\n if (response.status === 410) {\n return {\n status: 'failed',\n reason: extractErrorMessage(payload, 'Auth session expired or failed'),\n };\n }\n\n if (!response.ok) {\n return {\n status: 'failed',\n reason: extractErrorMessage(payload, `Auth session error (${response.status})`),\n };\n }\n\n const result = payload as { token?: string; organizationId?: string };\n if (!result.token) {\n return { status: 'failed', reason: 'No token in response' };\n }\n\n return {\n status: 'complete',\n token: result.token,\n ...(result.organizationId ? { organizationId: result.organizationId } : {}),\n };\n }\n\n /**\n * Validate a CLI user token and return the authenticated user's info.\n * Used by the CLI to verify stored credentials on startup.\n */\n async getCliUserInfo(userToken: string): Promise<{\n userId: string;\n email: string;\n name: string | null;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/auth/me`, {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Token validation failed (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { userId: string; email: string; name: string | null };\n }\n\n /**\n * Revoke the given CLI user token server-side.\n */\n async revokeCliToken(userToken: string): Promise<void> {\n const response = await fetch(`${this.apiUrl}/api/cli/auth/token`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n if (!response.ok) {\n const payload = await readPayload(response);\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Token revocation failed (${response.status})`),\n status: response.status,\n payload,\n });\n }\n }\n\n // ── Workspaces ────────────────────────────────────────────────────────────────\n\n async listWorkspaces(\n userToken: string,\n params?: { repo?: string },\n ): Promise<{\n workspaces: Array<{\n id: string;\n name: string;\n planId: string;\n maxProjects: number;\n projectCount: number;\n hasGitHubConnection: boolean;\n connectionLabel: string | null;\n /** null when no `repo` param was provided */\n coversRepo: boolean | null;\n installationConfigureUrl: string | null;\n }>;\n canCreateWorkspace: boolean;\n }> {\n const url = new URL(`${this.apiUrl}/api/cli/workspaces`);\n if (params?.repo) url.searchParams.set('repo', params.repo);\n\n const response = await fetch(url.toString(), {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to list workspaces (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n workspaces: Array<{\n id: string;\n name: string;\n planId: string;\n maxProjects: number;\n projectCount: number;\n hasGitHubConnection: boolean;\n connectionLabel: string | null;\n coversRepo: boolean | null;\n installationConfigureUrl: string | null;\n }>;\n canCreateWorkspace: boolean;\n };\n }\n\n async listProjects(\n userToken: string,\n organizationId: string,\n ): Promise<\n Array<{\n id: string;\n name: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n }>\n > {\n const url = new URL(`${this.apiUrl}/api/cli/projects`);\n url.searchParams.set('organizationId', organizationId);\n\n const response = await fetch(url.toString(), {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to list projects (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n const result = payload as { projects: Array<{\n id: string;\n name: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n }> };\n return result.projects;\n }\n\n // ── CLI GitHub endpoints ──────────────────────────────────────────────────────\n\n async startCliGitHubInstall(\n userToken: string,\n params: { organizationId?: string; callbackPort?: number },\n ): Promise<{ installUrl: string }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/install/start`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${userToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start GitHub install (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { installUrl: string };\n }\n\n /**\n * Start the \"link existing installation\" discovery flow.\n * Unlike startCliGitHubOAuth, this requires no bearer token — the Vocoder\n * account is created from the OAuth code in the callback.\n */\n async startCliGitHubLinkSession(\n sessionId: string,\n callbackPort?: number,\n ): Promise<{ oauthUrl: string }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/oauth/link-start`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sessionId, ...(callbackPort != null ? { callbackPort } : {}) }),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start GitHub link session (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { oauthUrl: string };\n }\n\n async startCliGitHubOAuth(\n userToken: string,\n params: { organizationId?: string; callbackPort?: number },\n ): Promise<{ oauthUrl: string }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/oauth/start`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${userToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start GitHub OAuth (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { oauthUrl: string };\n }\n\n async getCliGitHubDiscovery(userToken: string): Promise<{\n installations: Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n }>;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/discovery`, {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to fetch GitHub discovery (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n installations: Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n }>;\n };\n }\n\n async claimCliGitHubInstallation(\n userToken: string,\n params: { installationId: string; organizationId: string | null },\n ): Promise<{\n organizationId: string;\n organizationName: string;\n connectionLabel: string;\n repoCount: number;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/claim`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${userToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to claim GitHub installation (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n organizationId: string;\n organizationName: string;\n connectionLabel: string;\n repoCount: number;\n };\n }\n\n // ── Locales ───────────────────────────────────────────────────────────────────\n\n async listLocales(userToken: string): Promise<Array<{ code: string; name: string; nativeName?: string }>> {\n const response = await fetch(`${this.apiUrl}/api/cli/locales`, {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to list locales (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n const result = payload as { locales: Array<{ code: string; name: string; nativeName?: string }> };\n return result.locales;\n }\n\n // ── Project creation ──────────────────────────────────────────────────────────\n\n async createProject(\n userToken: string,\n params: {\n organizationId: string;\n name: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n scopePaths: string[];\n repoCanonical?: string;\n },\n ): Promise<{\n projectId: string;\n projectName: string;\n apiKey: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repositoryBound: boolean;\n configureUrl?: string;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/projects`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${userToken}`,\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to create project (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n projectId: string;\n projectName: string;\n apiKey: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repositoryBound: boolean;\n configureUrl?: string;\n };\n }\n\n // ── Project lookup ────────────────────────────────────────────────────────────\n\n /**\n * Look up all project apps for a given repo. Returns info about exact matches,\n * existing apps in other scopes, and whether a whole-repo app exists.\n * No auth required.\n */\n async lookupProjectByRepo(params: {\n repoCanonical: string;\n scopePath: string;\n }): Promise<{\n exactMatch: {\n projectId: string;\n projectName: string;\n organizationName: string;\n sourceLocale?: string;\n branchTriggers?: Array<{ pattern: string; triggers: string[] }>;\n } | null;\n existingApps: Array<{\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n }>;\n hasWholeRepoApp: boolean;\n }> {\n try {\n const response = await fetch(`${this.apiUrl}/api/cli/init/lookup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n repo: params.repoCanonical,\n scopePath: params.scopePath,\n }),\n });\n\n if (!response.ok) {\n return { exactMatch: null, existingApps: [], hasWholeRepoApp: false };\n }\n\n return (await response.json()) as {\n exactMatch: {\n projectId: string;\n projectName: string;\n organizationName: string;\n sourceLocale?: string;\n branchTriggers?: Array<{ pattern: string; triggers: string[] }>;\n } | null;\n existingApps: Array<{\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n }>;\n hasWholeRepoApp: boolean;\n };\n } catch {\n return { exactMatch: null, existingApps: [], hasWholeRepoApp: false };\n }\n }\n\n /**\n * Add a new ProjectApp to an existing project (monorepo: new app directory).\n * Does not check plan limits — no new project is created.\n */\n async createProjectApp(\n userToken: string,\n params: {\n projectId: string;\n scopePath: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repoCanonical: string;\n },\n ): Promise<{\n appId: string;\n projectId: string;\n projectName: string;\n apiKey: string;\n scopePath: string;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/project/apps`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${userToken}`,\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to create project app (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n appId: string;\n projectId: string;\n projectName: string;\n apiKey: string;\n scopePath: string;\n };\n }\n}\n","import { execSync } from 'child_process';\nimport { relative, resolve } from 'path';\n\nexport type GitRepositoryIdentity = {\n repoCanonical: string;\n repoScopePath: string;\n};\n\nexport type GitContext = {\n identity: GitRepositoryIdentity | null;\n warnings: string[];\n};\n\nfunction safeExec(command: string): string | null {\n try {\n const output = execSync(command, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'ignore'],\n }).trim();\n return output.length > 0 ? output : null;\n } catch {\n return null;\n }\n}\n\nfunction normalizePath(pathname: string): string | null {\n const cleaned = pathname\n .replace(/^\\/+/, '')\n .replace(/\\.git$/i, '')\n .trim();\n\n if (!cleaned || !cleaned.includes('/')) {\n return null;\n }\n\n return cleaned;\n}\n\nfunction parseRemoteUrl(remoteUrl: string): {\n host: string;\n ownerRepoPath: string;\n} | null {\n const trimmed = remoteUrl.trim();\n if (!trimmed) {\n return null;\n }\n\n // SCP-like syntax: git@github.com:owner/repo.git\n if (!trimmed.includes('://')) {\n const scpMatch = trimmed.match(/^(?:.+@)?([^:]+):(.+)$/);\n if (scpMatch) {\n const host = (scpMatch[1] || '').toLowerCase();\n const ownerRepoPath = normalizePath(scpMatch[2] || '');\n if (!host || !ownerRepoPath) {\n return null;\n }\n return { host, ownerRepoPath };\n }\n return null;\n }\n\n try {\n const parsed = new URL(trimmed);\n const host = parsed.hostname.toLowerCase();\n const ownerRepoPath = normalizePath(decodeURIComponent(parsed.pathname));\n if (!host || !ownerRepoPath) {\n return null;\n }\n return { host, ownerRepoPath };\n } catch {\n return null;\n }\n}\n\nfunction toCanonical(host: string, ownerRepoPath: string): string {\n if (host.includes('github.com')) {\n return `github:${ownerRepoPath.toLowerCase()}`;\n }\n if (host.includes('gitlab.com')) {\n return `gitlab:${ownerRepoPath.toLowerCase()}`;\n }\n if (host.includes('bitbucket.org')) {\n return `bitbucket:${ownerRepoPath.toLowerCase()}`;\n }\n return `git:${host}/${ownerRepoPath.toLowerCase()}`;\n}\n\nexport function resolveGitRepositoryIdentity(): GitRepositoryIdentity | null {\n const remoteUrl = safeExec('git config --get remote.origin.url');\n if (!remoteUrl) {\n return null;\n }\n\n const parsed = parseRemoteUrl(remoteUrl);\n if (!parsed) {\n return null;\n }\n\n const repositoryRoot = safeExec('git rev-parse --show-toplevel');\n const currentDirectory = process.cwd();\n let repoScopePath = '';\n if (repositoryRoot) {\n const relativePath = relative(resolve(repositoryRoot), resolve(currentDirectory))\n .replace(/\\\\/g, '/')\n .trim();\n\n if (relativePath && relativePath !== '.' && !relativePath.startsWith('..')) {\n repoScopePath = relativePath;\n }\n }\n\n return {\n repoCanonical: toCanonical(parsed.host, parsed.ownerRepoPath),\n repoScopePath,\n };\n}\n\nexport function resolveGitContext(): GitContext {\n const warnings: string[] = [];\n const identity = resolveGitRepositoryIdentity();\n\n if (!identity) {\n warnings.push(\n 'Could not detect git remote origin. Repo binding will be skipped until sync can detect it.',\n );\n }\n\n return { identity, warnings };\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\nimport type { VocoderAPI } from './api.js';\nimport type { LocaleOption } from './locale-search.js';\nimport { searchMultiSelectLocales, searchSelectLocale } from './locale-search.js';\nimport { detectGitBranches, filterableBranchSelect } from './branch-select.js';\n\nexport interface ExistingApp {\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n}\n\nexport interface ProjectCreateParams {\n api: VocoderAPI;\n userToken: string;\n organizationId: string;\n /** Default project name (repo name or directory name) */\n defaultName?: string;\n /** Pre-detected source locale, e.g. \"en\" */\n defaultSourceLocale?: string;\n /** Repo canonical for binding the project, e.g. \"github:owner/repo\" */\n repoCanonical?: string;\n /** Default target branches */\n defaultBranches?: string[];\n /**\n * Auto-detected scope path (CWD relative to git root).\n * Non-empty when running from a subdirectory of the repo — monorepo use case.\n * e.g. \"apps/web\"\n */\n defaultScopePath?: string;\n}\n\nexport interface ProjectAppCreateParams {\n api: VocoderAPI;\n userToken: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n repoCanonical?: string;\n defaultScopePath?: string;\n /** Existing apps to display and validate against */\n existingApps: ExistingApp[];\n}\n\nexport interface ProjectAppCreateResult {\n projectId: string;\n projectName: string;\n apiKey: string;\n scopePath: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n}\n\nexport interface ProjectCreateResult {\n projectId: string;\n projectName: string;\n apiKey: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repositoryBound: boolean;\n configureUrl?: string;\n}\n\n/** All locales — used for target language selection. */\nfunction buildLocaleOptions(\n locales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n return locales.map((l) => ({\n bcp47: l.code,\n label: `${l.name} — ${l.code}`,\n }));\n}\n\n/**\n * Deduplicated language list — used for source language selection.\n * Groups locales by language family (prefix before first hyphen) and keeps one\n * representative per family, preferring the shortest/base code (e.g. \"en\" over\n * \"en-US\"). This prevents showing \"English\", \"English (American)\", \"English\n * (British)\" as three separate choices when the user just means \"English\".\n */\nfunction buildLanguageOptions(\n locales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n const byFamily = new Map<string, LocaleOption>();\n\n for (const l of locales) {\n const family = l.code.split('-')[0]!.toLowerCase();\n const opt: LocaleOption = { bcp47: l.code, label: `${l.name} — ${l.code}` };\n const existing = byFamily.get(family);\n // Prefer base code (shorter, no region suffix) over regional variants\n if (!existing || l.code.length < existing.bcp47.length) {\n byFamily.set(family, opt);\n }\n }\n\n return Array.from(byFamily.values());\n}\n\n/**\n * Run the full project configuration TUI: prompts for name, source locale,\n * target locales, and target branches, then calls POST /api/cli/projects.\n *\n * Returns the created project info (including API key), or null if cancelled.\n */\nexport async function runProjectCreate(\n params: ProjectCreateParams,\n): Promise<ProjectCreateResult | null> {\n const { api, userToken, organizationId, repoCanonical } = params;\n\n // ── Project name ────────────────────────────────────────────────────────────\n // Use the detected repo name automatically — no prompt needed.\n const projectName = (params.defaultName ?? 'my-project').trim();\n p.log.success(`Project: ${chalk.bold(projectName)}`);\n\n // ── Fetch available locales ─────────────────────────────────────────────────\n let rawLocales: Array<{ code: string; name: string; nativeName?: string }>;\n try {\n rawLocales = await api.listLocales(userToken);\n } catch {\n p.log.error('Failed to fetch supported locales. Check your connection and try again.');\n return null;\n }\n\n // Source: deduplicated by language family (e.g. just \"English — en\", not all variants)\n const languageOptions = buildLanguageOptions(rawLocales);\n // Target: all locales (regional variants matter for translation targets)\n const localeOptions = buildLocaleOptions(rawLocales);\n\n // ── Scope path (monorepo) ───────────────────────────────────────────────────\n let scopePath: string;\n if (params.defaultScopePath) {\n // Auto-detected from CWD — confirm silently, same pattern as project name.\n scopePath = params.defaultScopePath;\n p.log.success(`App directory: ${chalk.bold(scopePath)}`);\n } else {\n const rawScope = await p.text({\n message: 'App directory (leave blank for the entire repo)',\n placeholder: 'e.g. apps/web, packages/frontend',\n initialValue: '',\n validate(value) {\n const v = value.trim();\n if (!v) return;\n if (v.startsWith('/')) return 'Use a relative path, not an absolute path';\n if (v.includes('..')) return 'Path must not contain \"..\"';\n },\n });\n if (p.isCancel(rawScope)) return null;\n scopePath = ((rawScope as string | undefined) ?? '').trim();\n }\n\n // ── Source locale ───────────────────────────────────────────────────────────\n const sourceLocale = await searchSelectLocale(\n languageOptions,\n 'Source language (the language your code is written in)',\n params.defaultSourceLocale ?? 'en',\n );\n\n if (sourceLocale === null) return null;\n\n // ── Target locales ──────────────────────────────────────────────────────────\n // Exclude the exact source locale; regional variants (e.g. en-GB when source=en) remain available\n const targetOptions = localeOptions.filter((opt) => opt.bcp47 !== sourceLocale);\n\n const targetLocales = await searchMultiSelectLocales(\n targetOptions,\n 'Target languages (languages to translate into)',\n );\n\n if (targetLocales === null) return null;\n\n if (targetLocales.length === 0) {\n p.log.warn('No target languages selected — you can add them later from the dashboard.');\n }\n\n // ── Target branches + triggers ──────────────────────────────────────────────\n // Select branches first, then ask how translations should be triggered on them.\n // The two prompts together produce a branchTriggers array.\n const detected = detectGitBranches();\n const initialBranches = params.defaultBranches?.length\n ? params.defaultBranches\n : [detected.defaultBranch];\n\n let selectedBranches: string[] = [];\n {\n let initial = initialBranches;\n while (selectedBranches.length === 0) {\n const result = await filterableBranchSelect({\n message: 'Target branches',\n branches: detected.branches,\n defaultBranch: detected.defaultBranch,\n initialValues: initial,\n });\n if (result === null) return null;\n if (result.length === 0) {\n p.log.warn('At least one branch is required. Please select at least one.');\n initial = [detected.defaultBranch];\n } else {\n selectedBranches = result;\n }\n }\n }\n\n const triggerChoice = await p.select<string>({\n message: 'When should translations run?',\n options: [\n { value: 'push', label: 'On push to target branches' },\n { value: 'pull_request', label: 'On pull requests' },\n { value: 'push_and_pr', label: 'On push and pull requests' },\n { value: 'manual', label: 'Manual only', hint: 'use vocoder sync or trigger from dashboard' },\n ],\n });\n if (p.isCancel(triggerChoice)) return null;\n\n const triggersForBranch =\n triggerChoice === 'push_and_pr'\n ? ['push', 'pull_request']\n : [(triggerChoice as string)];\n\n // Each selected branch gets the same trigger set (uniform mode for init;\n // per-branch overrides are available in project settings after setup).\n const branchTriggers = selectedBranches.map((pattern) => ({\n pattern,\n triggers: triggersForBranch,\n }));\n\n // ── Create project ──────────────────────────────────────────────────────────\n try {\n const result = await api.createProject(userToken, {\n organizationId,\n name: projectName,\n sourceLocale,\n targetLocales,\n branchTriggers,\n scopePaths: scopePath ? [scopePath] : [],\n repoCanonical,\n });\n\n p.log.success(`Project ${chalk.bold(result.projectName)} created!`);\n return result;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n p.log.error(`Failed to create project: ${message}`);\n return null;\n }\n}\n\n/**\n * Configure and create a new ProjectApp under an existing project.\n * Used when the repo already has a project (monorepo: adding a new app directory).\n * No plan limit check runs — only a new ProjectApp is created, not a new Project.\n */\nexport async function runProjectAppCreate(\n params: ProjectAppCreateParams,\n): Promise<ProjectAppCreateResult | null> {\n const { api, userToken, projectId, projectName, repoCanonical } = params;\n const existingScopes = new Set(params.existingApps.map((a) => a.scopePath));\n\n // ── Fetch available locales ─────────────────────────────────────────────────\n let rawLocales: Array<{ code: string; name: string; nativeName?: string }>;\n try {\n rawLocales = await api.listLocales(userToken);\n } catch {\n p.log.error('Failed to fetch supported locales. Check your connection and try again.');\n return null;\n }\n\n const languageOptions = buildLanguageOptions(rawLocales);\n const localeOptions = buildLocaleOptions(rawLocales);\n\n // ── App directory ───────────────────────────────────────────────────────────\n let scopePath: string;\n if (params.defaultScopePath && !existingScopes.has(params.defaultScopePath)) {\n // Auto-detected scope is new — confirm silently.\n scopePath = params.defaultScopePath;\n p.log.success(`App directory: ${chalk.bold(scopePath)}`);\n } else {\n // Show existing apps so the user knows what's already configured.\n if (params.existingApps.length > 0) {\n const configuredList = params.existingApps\n .map((a) => chalk.dim(a.scopePath || '(entire repo)'))\n .join(', ');\n p.log.info(`Already configured: ${configuredList}`);\n }\n\n const hasWholeRepoApp = existingScopes.has('');\n\n const rawScope = await p.text({\n message: 'App directory for this new app',\n placeholder: 'e.g. apps/backend',\n initialValue: params.defaultScopePath ?? '',\n validate(value) {\n const v = value.trim();\n if (!v && hasWholeRepoApp) return 'This project already covers the entire repo.';\n if (!v) return 'App directory is required when other apps already exist.';\n if (v.startsWith('/')) return 'Use a relative path, not an absolute path.';\n if (v.includes('..')) return 'Path must not contain \"..\".';\n if (existingScopes.has(v)) return `\"${v}\" is already configured. Choose a different directory.`;\n },\n });\n if (p.isCancel(rawScope)) return null;\n scopePath = ((rawScope as string | undefined) ?? '').trim();\n }\n\n // ── Source locale ───────────────────────────────────────────────────────────\n const sourceLocale = await searchSelectLocale(\n languageOptions,\n 'Source language',\n 'en',\n );\n if (sourceLocale === null) return null;\n\n // ── Target locales ──────────────────────────────────────────────────────────\n const targetOptions = localeOptions.filter((opt) => opt.bcp47 !== sourceLocale);\n const targetLocales = await searchMultiSelectLocales(\n targetOptions,\n 'Target languages',\n );\n if (targetLocales === null) return null;\n if (targetLocales.length === 0) {\n p.log.warn('No target languages selected — you can add them later from the dashboard.');\n }\n\n // ── Translation triggers ────────────────────────────────────────────────────\n const triggerChoice = await p.select<string>({\n message: 'When should translations run?',\n options: [\n { value: 'push', label: 'On push to target branches' },\n { value: 'pull_request', label: 'On pull requests' },\n { value: 'push_and_pr', label: 'On push and pull requests' },\n { value: 'manual', label: 'Manual only', hint: 'use vocoder sync or trigger from dashboard' },\n ],\n });\n if (p.isCancel(triggerChoice)) return null;\n\n const triggersForBranch =\n triggerChoice === 'push_and_pr' ? ['push', 'pull_request'] : [triggerChoice as string];\n\n // ── Target branches ─────────────────────────────────────────────────────────\n const detected = detectGitBranches();\n let selectedBranches: string[] = [];\n {\n let initial = [detected.defaultBranch];\n while (selectedBranches.length === 0) {\n const result = await filterableBranchSelect({\n message: 'Target branches',\n branches: detected.branches,\n defaultBranch: detected.defaultBranch,\n initialValues: initial,\n });\n if (result === null) return null;\n if (result.length === 0) {\n p.log.warn('At least one branch is required.');\n initial = [detected.defaultBranch];\n } else {\n selectedBranches = result;\n }\n }\n }\n\n const branchTriggers = selectedBranches.map((pattern) => ({\n pattern,\n triggers: triggersForBranch,\n }));\n\n // ── Create the ProjectApp ───────────────────────────────────────────────────\n try {\n const result = await api.createProjectApp(userToken, {\n projectId,\n scopePath,\n sourceLocale,\n targetLocales,\n branchTriggers,\n repoCanonical: repoCanonical ?? '',\n });\n\n p.log.success(`App ${chalk.bold(scopePath)} added to ${chalk.bold(projectName)}!`);\n return {\n projectId: result.projectId,\n projectName: result.projectName,\n apiKey: result.apiKey,\n scopePath: result.scopePath,\n sourceLocale,\n targetLocales,\n branchTriggers,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n p.log.error(`Failed to add app: ${message}`);\n return null;\n }\n}\n","import { Prompt, isCancel } from '@clack/core';\nimport * as p from '@clack/prompts';\nimport chalk from 'chalk';\n\nexport interface LocaleOption {\n bcp47: string;\n /** Human-readable label, e.g. \"English — en\" */\n label: string;\n}\n\n// ── Symbols (match @clack/prompts style) ──────────────────────────────────────\n\nconst S_BAR = '│';\nconst S_BAR_END = '└';\nconst S_ACTIVE = '◆';\nconst S_SUBMIT = '◆';\nconst S_CANCEL = '■';\nconst S_ERROR = '▲';\n\nconst noColor = process.env.NO_COLOR === '1' || process.env.FORCE_COLOR === '0';\nconst dim = (s: string) => noColor ? s : chalk.gray(s);\nconst cyan = (s: string) => noColor ? s : chalk.cyan(s);\nconst grn = (s: string) => noColor ? s : chalk.green(s);\nconst ylw = (s: string) => noColor ? s : chalk.yellow(s);\nconst red = (s: string) => noColor ? s : chalk.red(s);\nconst bld = (s: string) => noColor ? s : chalk.bold(s);\n\nfunction symbol(state: string): string {\n switch (state) {\n case 'submit': return grn(S_SUBMIT);\n case 'cancel': return red(S_CANCEL);\n case 'error': return ylw(S_ERROR);\n default: return cyan(S_ACTIVE);\n }\n}\n\n// ── Filter ────────────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 12;\n\nfunction filterLocales(options: LocaleOption[], query: string): LocaleOption[] {\n if (!query.trim()) return options;\n const lower = query.toLowerCase();\n return options.filter(\n (o) => o.bcp47.toLowerCase().includes(lower) || o.label.toLowerCase().includes(lower),\n );\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nfunction buildList(\n filtered: LocaleOption[],\n cursor: number,\n scrollOffset: number,\n selected: Set<string> | null, // null = single-select\n): string {\n const isMulti = selected !== null;\n const end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n const visibleLines: string[] = [];\n\n for (let i = scrollOffset; i < end; i++) {\n const opt = filtered[i]!;\n const isCursor = i === cursor;\n const isChecked = isMulti && selected!.has(opt.bcp47);\n\n const icon = isMulti\n ? (isChecked ? (isCursor ? grn('◼') : '◼') : (isCursor ? grn('◻') : dim('◻')))\n : (isCursor ? grn('●') : dim('○'));\n\n visibleLines.push(`${cyan(S_BAR)} ${icon} ${isCursor ? bld(opt.label) : opt.label}`);\n }\n\n const hidden = filtered.length - (end - scrollOffset);\n if (hidden > 0) visibleLines.push(dim(`${S_BAR} ${hidden} more — keep typing to narrow`));\n if (filtered.length === 0) visibleLines.push(dim(`${S_BAR} No matches`));\n if (isMulti && selected!.size > 0) {\n visibleLines.push(dim(`${S_BAR} ${selected!.size} selected — Enter to confirm`));\n }\n\n return visibleLines.join('\\n');\n}\n\n// ── Core prompt factory ───────────────────────────────────────────────────────\n\nasync function runFilterablePrompt(opts: {\n message: string;\n options: LocaleOption[];\n multi: boolean;\n initialValue?: string;\n initialValues?: string[];\n}): Promise<string | string[] | null> {\n const { message, options, multi } = opts;\n\n let filter = '';\n let cursor = 0;\n let scrollOffset = 0;\n const selected = new Set<string>(multi ? (opts.initialValues ?? []) : []);\n\n if (!multi && opts.initialValue) {\n const idx = options.findIndex((o) => o.bcp47 === opts.initialValue);\n if (idx >= 0) cursor = idx;\n }\n\n const getFiltered = () => filterLocales(options, filter);\n\n // Keep cursor in bounds and scroll window centred\n const clampCursor = (filtered: LocaleOption[]) => {\n if (cursor >= filtered.length) cursor = Math.max(0, filtered.length - 1);\n if (cursor < scrollOffset) scrollOffset = cursor;\n if (cursor >= scrollOffset + MAX_VISIBLE) scrollOffset = cursor - MAX_VISIBLE + 1;\n if (scrollOffset < 0) scrollOffset = 0;\n };\n\n // @clack/core Prompt: render() returns the ENTIRE frame; clack handles\n // re-rendering (cursor movement + diff) automatically.\n // Using `any` cast to pass `trackValue=false` (2nd constructor arg).\n const prompt = new (Prompt as any)(\n {\n initialValue: !multi ? (options[cursor]?.bcp47 ?? null) : null,\n validate() {\n const f = getFiltered();\n if (multi && selected.size === 0) return 'At least one target language is required.';\n if (!multi && !f[cursor]) return 'Please select a language.';\n return undefined;\n },\n render(this: { state: string; error: string; value: unknown }) {\n const filtered = getFiltered();\n clampCursor(filtered);\n\n const hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n const hint = filter.length > 0\n ? filter\n : dim('type to filter, ↑↓ navigate' + (multi ? ', space select' : ''));\n\n switch (this.state) {\n case 'submit': {\n const val = multi\n ? Array.from(selected).map((id) => options.find((o) => o.bcp47 === id)?.label ?? id).join(', ')\n : options.find((o) => o.bcp47 === (this.value as string))?.label ?? '';\n return `${hdr}${dim(S_BAR)} ${bld(val || dim('none'))}`;\n }\n case 'cancel':\n return `${hdr}${dim(S_BAR)}`;\n case 'error':\n return [\n hdr.trimEnd(),\n `${ylw(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, multi ? selected : null),\n `${ylw(S_BAR_END)} ${ylw(this.error)}`,\n '',\n ].join('\\n');\n default:\n return [\n hdr.trimEnd(),\n `${cyan(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, multi ? selected : null),\n `${cyan(S_BAR_END)}`,\n '',\n ].join('\\n');\n }\n },\n },\n false, // trackValue=false — we manage value manually\n ) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n // Character input → update filter\n prompt.on('key', (key: string | undefined) => {\n if (!key || key === ' ') return; // space handled by cursor event\n const cp = key.codePointAt(0) ?? 0;\n if (cp === 0x7f || cp === 0x08) { // backspace\n filter = filter.slice(0, -1);\n cursor = 0; scrollOffset = 0;\n } else if (cp >= 32 && cp !== 127) {\n filter += key;\n cursor = 0; scrollOffset = 0;\n }\n });\n\n // Navigation + toggle\n prompt.on('cursor', (action: string | undefined) => {\n const filtered = getFiltered();\n switch (action) {\n case 'up': cursor = Math.max(0, cursor - 1); break;\n case 'down': cursor = Math.min(Math.max(filtered.length - 1, 0), cursor + 1); break;\n case 'space':\n if (multi) {\n const opt = filtered[cursor];\n if (opt) {\n if (selected.has(opt.bcp47)) selected.delete(opt.bcp47);\n else selected.add(opt.bcp47);\n }\n }\n break;\n }\n // Sync prompt.value for single-select so submit gets the right value\n if (!multi) {\n const opt = getFiltered()[cursor];\n (prompt as any).value = opt?.bcp47 ?? null;\n }\n });\n\n // Before submit resolves, set value to the selected items (multi) or current cursor (single)\n prompt.on('finalize', () => {\n if ((prompt as any).state === 'submit') {\n if (multi) {\n (prompt as any).value = Array.from(selected);\n } else {\n const f = getFiltered();\n (prompt as any).value = f[cursor]?.bcp47 ?? null;\n }\n }\n });\n\n const result = await prompt.prompt();\n\n if (isCancel(result)) return null;\n return result as string | string[];\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport async function searchSelectLocale(\n options: LocaleOption[],\n message: string,\n initialValue?: string,\n): Promise<string | null> {\n const result = await runFilterablePrompt({ message, options, multi: false, initialValue });\n return typeof result === 'string' ? result : null;\n}\n\nexport async function searchMultiSelectLocales(\n options: LocaleOption[],\n message: string,\n initialValues?: string[],\n): Promise<string[] | null> {\n const result = await runFilterablePrompt({ message, options, multi: true, initialValues });\n if (result === null) return null;\n const picks = result as string[];\n // Validate already prevents empty on first try; this handles the retry path\n if (picks.length === 0) {\n p.log.warn('At least one target language is required. Please select at least one.');\n return searchMultiSelectLocales(options, message, initialValues);\n }\n return picks;\n}\n","import { Prompt, isCancel } from '@clack/core';\nimport chalk from 'chalk';\nimport { execSync } from 'node:child_process';\n\n// ── Symbols ───────────────────────────────────────────────────────────────────\n\nconst S_BAR = '│';\nconst S_BAR_END = '└';\nconst S_ACTIVE = '◆';\nconst S_SUBMIT = '◆';\nconst S_CANCEL = '■';\nconst S_ERROR = '▲';\n\nconst noColor = process.env.NO_COLOR === '1' || process.env.FORCE_COLOR === '0';\nconst dim = (s: string) => noColor ? s : chalk.gray(s);\nconst cyan = (s: string) => noColor ? s : chalk.cyan(s);\nconst grn = (s: string) => noColor ? s : chalk.green(s);\nconst ylw = (s: string) => noColor ? s : chalk.yellow(s);\nconst red = (s: string) => noColor ? s : chalk.red(s);\nconst bld = (s: string) => noColor ? s : chalk.bold(s);\n\nfunction symbol(state: string): string {\n switch (state) {\n case 'submit': return grn(S_SUBMIT);\n case 'cancel': return red(S_CANCEL);\n case 'error': return ylw(S_ERROR);\n default: return cyan(S_ACTIVE);\n }\n}\n\n// ── Git detection ─────────────────────────────────────────────────────────────\n\nexport interface DetectedBranches {\n branches: string[];\n defaultBranch: string;\n}\n\nexport function detectGitBranches(cwd?: string): DetectedBranches {\n const workDir = cwd ?? process.cwd();\n try {\n // Local branches\n const localOut = execSync('git branch', { cwd: workDir, stdio: 'pipe' }).toString();\n const localBranches = localOut.split('\\n')\n .filter(Boolean)\n .map((b) => b.replace(/^\\*?\\s*/, '').trim())\n .filter(Boolean);\n\n // Remote branches (strip \"origin/\" prefix, skip HEAD pointer)\n let remoteBranches: string[] = [];\n try {\n const remoteOut = execSync('git branch -r', { cwd: workDir, stdio: 'pipe' }).toString();\n remoteBranches = remoteOut.split('\\n')\n .map((b) => b.trim())\n .filter((b) => b && !b.includes('HEAD'))\n .map((b) => b.replace(/^[^/]+\\//, '')); // strip \"origin/\" (or any remote name)\n } catch { /* no remote */ }\n\n const branches = [...new Set([...localBranches, ...remoteBranches])].sort();\n\n // Default branch: ask git for origin's HEAD (local cache, no network call).\n // Falls back to 'main' if the remote HEAD isn't cached.\n let defaultBranch = 'main';\n try {\n const ref = execSync('git symbolic-ref refs/remotes/origin/HEAD', { cwd: workDir, stdio: 'pipe' })\n .toString().trim();\n // ref = \"refs/remotes/origin/main\"\n defaultBranch = ref.split('/').pop() ?? 'main';\n } catch { /* HEAD not cached — run \"git remote set-head origin --auto\" to fix */ }\n\n return {\n branches: branches.length > 0 ? branches : [defaultBranch],\n defaultBranch,\n };\n } catch {\n return { branches: ['main'], defaultBranch: 'main' };\n }\n}\n\n// ── Validation ────────────────────────────────────────────────────────────────\n\nconst INVALID_CHARS = /[\\s?^~:[\\]\\\\]/;\n\nexport function validateBranchPattern(pattern: string): string | null {\n const t = pattern.trim();\n if (!t) return 'Pattern cannot be empty';\n if (INVALID_CHARS.test(t)) return 'Invalid characters — avoid spaces, ?, ^, ~, :, [, ], \\\\';\n if (t.startsWith('/') || t.endsWith('/')) return 'Cannot start or end with /';\n if (t.includes('//')) return 'Cannot contain //';\n return null;\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 10;\nconst ADD_PATTERN_VALUE = '__add__';\n\ninterface BranchItem {\n value: string;\n label: string;\n isCustom?: boolean;\n}\n\nfunction buildItems(\n branches: string[],\n defaultBranch: string,\n customPatterns: string[],\n): BranchItem[] {\n const items: BranchItem[] = branches.map((b) => ({\n value: b,\n label: b === defaultBranch ? `${b} (default branch)` : b,\n }));\n for (const pt of customPatterns) {\n if (!branches.includes(pt)) {\n items.push({ value: pt, label: pt, isCustom: true });\n }\n }\n return items;\n}\n\nfunction filterItems(items: BranchItem[], query: string): BranchItem[] {\n if (!query.trim()) return items;\n const lower = query.toLowerCase();\n return items.filter((i) => i.value.toLowerCase().includes(lower));\n}\n\nfunction buildList(\n filtered: BranchItem[],\n cursor: number,\n scrollOffset: number,\n selected: Set<string>,\n filter: string,\n customPatterns: string[],\n addCursor: boolean,\n): string {\n const lines: string[] = [];\n const end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n\n for (let i = scrollOffset; i < end; i++) {\n const item = filtered[i]!;\n const isCursor = i === cursor && !addCursor;\n const isChecked = selected.has(item.value);\n\n const icon = isChecked\n ? (isCursor ? grn('◼') : '◼')\n : (isCursor ? grn('◻') : dim('◻'));\n\n let label = item.isCustom ? `${item.label} ${dim('(custom)')}` : item.label;\n if (isCursor) label = bld(label);\n\n lines.push(`${cyan(S_BAR)} ${icon} ${label}`);\n }\n\n // \"Add pattern\" option\n const trimmed = filter.trim();\n const allItems = [...filtered]; // simplified: just check filtered\n const isNewPattern =\n trimmed.length > 0 &&\n !allItems.some((i) => i.value === trimmed) &&\n !customPatterns.includes(trimmed);\n\n if (isNewPattern) {\n const err = validateBranchPattern(trimmed);\n const icon = addCursor ? grn('◻') : dim('◻');\n const label = err\n ? `${ylw('+')} ${dim(`\"${trimmed}\" — ${err}`)}`\n : `${grn('+')} Add \"${trimmed}\" as branch pattern`;\n lines.push(`${cyan(S_BAR)} ${icon} ${label}`);\n } else if (filtered.length === 0 && trimmed.length === 0) {\n lines.push(dim(`${S_BAR} No branches detected`));\n }\n\n const hidden = filtered.length - (end - scrollOffset);\n if (hidden > 0) lines.push(dim(`${S_BAR} ${hidden} more`));\n if (selected.size > 0) lines.push(dim(`${S_BAR} ${selected.size} selected — Enter to confirm`));\n\n return lines.join('\\n');\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport async function filterableBranchSelect(params: {\n message: string;\n branches: string[];\n defaultBranch: string;\n initialValues?: string[];\n}): Promise<string[] | null> {\n const { message, branches, defaultBranch } = params;\n\n let filter = '';\n let cursor = 0;\n let scrollOffset = 0;\n let addCursor = false;\n const customPatterns: string[] = [];\n const selected = new Set<string>(params.initialValues ?? [defaultBranch]);\n\n const getItems = () => buildItems(branches, defaultBranch, customPatterns);\n const getFiltered = () => filterItems(getItems(), filter);\n\n const isNewPattern = () => {\n const t = filter.trim();\n if (!t) return false;\n return !getItems().some((i) => i.value === t) && !customPatterns.includes(t);\n };\n\n const clampCursor = (filtered: BranchItem[]) => {\n const hasAdd = isNewPattern();\n const max = filtered.length - 1 + (hasAdd ? 1 : 0);\n if (cursor > max && !addCursor) cursor = Math.max(0, max);\n if (!addCursor) {\n if (cursor < scrollOffset) scrollOffset = cursor;\n if (cursor >= scrollOffset + MAX_VISIBLE) scrollOffset = cursor - MAX_VISIBLE + 1;\n if (scrollOffset < 0) scrollOffset = 0;\n }\n };\n\n const prompt = new (Prompt as any)(\n {\n validate() {\n if (selected.size === 0) return 'At least one branch is required.';\n return undefined;\n },\n render(this: { state: string; error: string }) {\n const filtered = getFiltered();\n clampCursor(filtered);\n\n const hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n const hint = filter.length > 0\n ? filter\n : dim('type to filter or add pattern, ↑↓ navigate, space select');\n\n switch (this.state) {\n case 'submit': {\n const summary = selected.size > 0\n ? bld(Array.from(selected).join(', '))\n : dim('none');\n return `${hdr}${dim(S_BAR)} ${summary}`;\n }\n case 'cancel':\n return `${hdr}${dim(S_BAR)}`;\n case 'error':\n return [\n hdr.trimEnd(),\n `${ylw(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor),\n `${ylw(S_BAR_END)} ${ylw(this.error)}`,\n '',\n ].join('\\n');\n default:\n return [\n hdr.trimEnd(),\n `${cyan(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor),\n `${cyan(S_BAR_END)}`,\n '',\n ].join('\\n');\n }\n },\n },\n false,\n ) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n prompt.on('key', (key: string | undefined) => {\n if (!key || key === ' ') return;\n const cp = key.codePointAt(0) ?? 0;\n if (cp === 0x7f || cp === 0x08) {\n filter = filter.slice(0, -1);\n cursor = 0; scrollOffset = 0; addCursor = false;\n } else if (cp >= 32 && cp !== 127) {\n filter += key;\n cursor = 0; scrollOffset = 0; addCursor = false;\n }\n });\n\n prompt.on('cursor', (action: string | undefined) => {\n const filtered = getFiltered();\n const hasAdd = isNewPattern();\n\n switch (action) {\n case 'up':\n if (addCursor) { addCursor = false; cursor = Math.max(0, filtered.length - 1); }\n else cursor = Math.max(0, cursor - 1);\n break;\n case 'down':\n if (!addCursor && cursor >= filtered.length - 1 && hasAdd) addCursor = true;\n else if (!addCursor) cursor = Math.min(filtered.length - 1, cursor + 1);\n break;\n case 'space':\n if (addCursor) {\n const t = filter.trim();\n const err = validateBranchPattern(t);\n if (!err) {\n customPatterns.push(t);\n selected.add(t);\n filter = '';\n cursor = 0; scrollOffset = 0; addCursor = false;\n }\n } else {\n const item = filtered[cursor];\n if (item) {\n if (selected.has(item.value)) selected.delete(item.value);\n else selected.add(item.value);\n }\n }\n break;\n }\n });\n\n prompt.on('finalize', () => {\n if ((prompt as any).state === 'submit') {\n (prompt as any).value = Array.from(selected);\n }\n });\n\n const result = await prompt.prompt();\n if (isCancel(result)) return null;\n return result as string[];\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\n\nexport interface WorkspaceInfo {\n id: string;\n name: string;\n planId: string;\n projectCount: number;\n hasGitHubConnection: boolean;\n connectionLabel: string | null;\n}\n\nexport interface WorkspaceListResult {\n workspaces: WorkspaceInfo[];\n canCreateWorkspace: boolean;\n}\n\nexport type WorkspaceSelection =\n | { action: 'use'; workspace: WorkspaceInfo }\n | { action: 'create' }\n | { action: 'cancelled' };\n\nfunction workspaceLabel(ws: WorkspaceInfo): string {\n const parts: string[] = [ws.name];\n const meta: string[] = [];\n\n if (ws.projectCount === 1) {\n meta.push('1 project');\n } else if (ws.projectCount > 1) {\n meta.push(`${ws.projectCount} projects`);\n }\n\n if (ws.connectionLabel) {\n meta.push(`GitHub: ${ws.connectionLabel}`);\n }\n\n if (meta.length > 0) {\n parts.push(chalk.dim(`(${meta.join(', ')})`));\n }\n\n return parts.join(' ');\n}\n\n/**\n * Prompt the user to select a workspace or create a new one.\n * Returns a `WorkspaceSelection` describing what the user chose.\n */\nexport async function selectWorkspace(\n result: WorkspaceListResult,\n): Promise<WorkspaceSelection> {\n const { workspaces, canCreateWorkspace } = result;\n\n if (workspaces.length === 0) {\n // No workspaces — must create\n return { action: 'create' };\n }\n\n type SelectValue = string | 'create';\n\n const options: Array<{ value: SelectValue; label: string; hint?: string }> =\n workspaces.map((ws) => ({\n value: ws.id,\n label: ws.name,\n hint:\n [\n ws.projectCount > 0 ? `${ws.projectCount} project${ws.projectCount !== 1 ? 's' : ''}` : '',\n ws.connectionLabel ? `GitHub: ${ws.connectionLabel}` : '',\n ]\n .filter(Boolean)\n .join(' · ') || undefined,\n }));\n\n if (canCreateWorkspace) {\n options.push({ value: 'create', label: 'Create new workspace' });\n }\n\n const selected = await p.select<SelectValue>({\n message: 'Select workspace',\n options,\n });\n\n if (p.isCancel(selected)) {\n return { action: 'cancelled' };\n }\n\n if (selected === 'create') {\n return { action: 'create' };\n }\n\n const workspace = workspaces.find((ws) => ws.id === selected);\n if (!workspace) {\n return { action: 'cancelled' };\n }\n\n return { action: 'use', workspace };\n}\n","import * as p from '@clack/prompts';\nimport { VocoderAPI } from '../utils/api.js';\nimport { clearAuthData, readAuthData } from '../utils/auth-store.js';\n\nexport interface LogoutOptions {\n apiUrl?: string;\n}\n\nexport async function logout(options: LogoutOptions = {}): Promise<number> {\n const stored = readAuthData();\n\n if (!stored) {\n p.log.info('Not currently authenticated.');\n return 0;\n }\n\n const apiUrl = options.apiUrl ?? stored.apiUrl ?? 'https://vocoder.app';\n const api = new VocoderAPI({ apiUrl, apiKey: '' });\n\n try {\n await api.revokeCliToken(stored.token);\n } catch {\n // Ignore errors — we still clear local data even if the server call fails\n }\n\n clearAuthData();\n p.log.success(`Logged out (was ${stored.email})`);\n return 0;\n}\n","import * as p from '@clack/prompts';\n\nimport type {\n EffectiveSyncMode,\n ExtractedString,\n LimitErrorResponse,\n ProjectConfig,\n RequestedSyncMode,\n SyncPolicyConfig,\n TranslateOptions,\n TranslationStringEntry,\n} from '../types.js';\nimport { VocoderAPI, VocoderAPIError } from '../utils/api.js';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { detectBranch, isTargetBranch } from '../utils/branch.js';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { getMergedConfig, validateLocalConfig } from '../utils/config.js';\n\nimport { StringExtractor } from '../utils/extract.js';\nimport chalk from 'chalk';\nimport { join } from 'path';\nimport { resolveGitRepositoryIdentity } from '../utils/git-identity.js';\n\ntype LocaleMetadataMap = Record<string, { nativeName: string; dir?: 'rtl' }>;\ntype TranslationMap = Record<string, Record<string, string>>;\ntype TranslationArtifactSource = 'fresh' | 'local-cache' | 'api-snapshot';\n\ntype TranslationArtifacts = {\n source: TranslationArtifactSource;\n translations: TranslationMap;\n localeMetadata?: LocaleMetadataMap;\n snapshotBatchId?: string;\n completedAt?: string | null;\n cacheBranch?: string;\n};\n\ntype LocalSnapshotCache = {\n version: 1;\n branch: string;\n sourceLocale: string;\n targetLocales: string[];\n savedAt: string;\n snapshotBatchId?: string;\n completedAt?: string | null;\n localeMetadata?: LocaleMetadataMap;\n translations: TranslationMap;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseLocaleMetadata(value: unknown): LocaleMetadataMap | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n\n const metadata: LocaleMetadataMap = {};\n for (const [locale, rawValue] of Object.entries(value)) {\n if (!isRecord(rawValue)) {\n continue;\n }\n\n const nativeName = rawValue.nativeName;\n if (typeof nativeName !== 'string' || nativeName.trim().length === 0) {\n continue;\n }\n\n const entry: { nativeName: string; dir?: 'rtl' } = { nativeName };\n if (rawValue.dir === 'rtl') {\n entry.dir = 'rtl';\n }\n\n metadata[locale] = entry;\n }\n\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction parseTranslations(value: unknown): TranslationMap | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const translations: TranslationMap = {};\n\n for (const [locale, localeValue] of Object.entries(value)) {\n if (!isRecord(localeValue)) {\n continue;\n }\n\n const localeTranslations: Record<string, string> = {};\n for (const [source, translated] of Object.entries(localeValue)) {\n if (typeof translated === 'string') {\n localeTranslations[source] = translated;\n }\n }\n\n translations[locale] = localeTranslations;\n }\n\n return Object.keys(translations).length > 0 ? translations : null;\n}\n\nfunction getCacheFilePath(projectRoot: string, branch: string): string {\n const slug = branch\n .replace(/[^a-zA-Z0-9._-]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 40);\n const branchHash = createHash('sha1').update(branch).digest('hex').slice(0, 12);\n const filename = `${slug || 'branch'}-${branchHash}.json`;\n return join(projectRoot, 'node_modules', '.vocoder', 'cache', 'sync', filename);\n}\n\nfunction readLocalSnapshotCache(params: {\n projectRoot: string;\n branch: string;\n}): TranslationArtifacts | null {\n const candidateBranches = params.branch === 'main'\n ? ['main']\n : [params.branch, 'main'];\n\n for (const candidateBranch of candidateBranches) {\n const cacheFilePath = getCacheFilePath(params.projectRoot, candidateBranch);\n\n if (!existsSync(cacheFilePath)) {\n continue;\n }\n\n try {\n const raw = readFileSync(cacheFilePath, 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n if (!isRecord(parsed)) {\n continue;\n }\n\n const translations = parseTranslations(parsed.translations);\n if (!translations) {\n continue;\n }\n\n const localeMetadata = parseLocaleMetadata(parsed.localeMetadata);\n\n return {\n source: 'local-cache',\n translations,\n localeMetadata,\n snapshotBatchId:\n typeof parsed.snapshotBatchId === 'string'\n ? parsed.snapshotBatchId\n : undefined,\n completedAt:\n typeof parsed.completedAt === 'string' ? parsed.completedAt : null,\n cacheBranch: candidateBranch,\n };\n } catch {\n continue;\n }\n }\n\n return null;\n}\n\nfunction writeLocalSnapshotCache(params: {\n projectRoot: string;\n branch: string;\n sourceLocale: string;\n targetLocales: string[];\n translations: TranslationMap;\n localeMetadata?: LocaleMetadataMap;\n snapshotBatchId?: string;\n completedAt?: string | null;\n}): string {\n const cacheFilePath = getCacheFilePath(params.projectRoot, params.branch);\n mkdirSync(join(params.projectRoot, 'node_modules', '.vocoder', 'cache', 'sync'), {\n recursive: true,\n });\n\n const payload: LocalSnapshotCache = {\n version: 1,\n branch: params.branch,\n sourceLocale: params.sourceLocale,\n targetLocales: params.targetLocales,\n savedAt: new Date().toISOString(),\n ...(params.snapshotBatchId ? { snapshotBatchId: params.snapshotBatchId } : {}),\n ...(params.completedAt ? { completedAt: params.completedAt } : {}),\n ...(params.localeMetadata ? { localeMetadata: params.localeMetadata } : {}),\n translations: params.translations,\n };\n\n writeFileSync(cacheFilePath, JSON.stringify(payload, null, 2), 'utf-8');\n return cacheFilePath;\n}\n\nfunction resolveEffectiveModeFromPolicy(params: {\n branch: string;\n requestedMode: RequestedSyncMode;\n policy: SyncPolicyConfig;\n}): EffectiveSyncMode {\n const { requestedMode, policy, branch } = params;\n\n let mode: EffectiveSyncMode;\n if (requestedMode === 'auto') {\n const isBlockingBranch = isTargetBranch(branch, policy.blockingBranches);\n mode = isBlockingBranch ? policy.blockingMode : policy.nonBlockingMode;\n } else {\n mode = requestedMode;\n }\n\n return mode;\n}\n\nfunction resolveWaitTimeoutMs(params: {\n requestedMaxWaitMs?: number;\n policyDefaultMaxWaitMs?: number;\n fallbackTimeoutMs: number;\n}): number {\n if (\n typeof params.requestedMaxWaitMs === 'number' &&\n Number.isFinite(params.requestedMaxWaitMs) &&\n params.requestedMaxWaitMs > 0\n ) {\n return Math.floor(params.requestedMaxWaitMs);\n }\n\n if (\n typeof params.policyDefaultMaxWaitMs === 'number' &&\n Number.isFinite(params.policyDefaultMaxWaitMs) &&\n params.policyDefaultMaxWaitMs > 0\n ) {\n return Math.floor(params.policyDefaultMaxWaitMs);\n }\n\n return params.fallbackTimeoutMs;\n}\n\nfunction normalizeTranslations(params: {\n sourceLocale: string;\n targetLocales: string[];\n sourceStrings: string[];\n translations: TranslationMap;\n}): TranslationMap {\n const merged: TranslationMap = {};\n\n for (const [locale, values] of Object.entries(params.translations)) {\n merged[locale] = { ...values };\n }\n\n const expectedLocales = [\n params.sourceLocale,\n ...params.targetLocales.filter((locale) => locale !== params.sourceLocale),\n ];\n\n for (const locale of expectedLocales) {\n if (!merged[locale]) {\n merged[locale] = {};\n }\n }\n\n if (!merged[params.sourceLocale]) {\n merged[params.sourceLocale] = {};\n }\n\n for (const sourceText of params.sourceStrings) {\n if (!(sourceText in merged[params.sourceLocale]!)) {\n merged[params.sourceLocale]![sourceText] = sourceText;\n }\n }\n\n return merged;\n}\n\nexport function getLimitErrorGuidance(limitError: LimitErrorResponse): string[] {\n if (limitError.limitType === 'providers') {\n return [\n 'Provider setup required.',\n 'Add a DeepL API key in Dashboard -> Workspace Settings -> Providers.',\n `Open settings: ${limitError.upgradeUrl}`,\n ];\n }\n\n if (limitError.limitType === 'translation_chars') {\n return [\n 'Monthly translation character limit reached.',\n `Used this month: ${limitError.current.toLocaleString()} chars`,\n `Requested after sync: ${limitError.required.toLocaleString()} chars`,\n `Upgrade plan: ${limitError.upgradeUrl}`,\n ];\n }\n\n if (limitError.limitType === 'source_strings') {\n return [\n 'Active source string limit reached.',\n `Current active strings: ${limitError.current.toLocaleString()}`,\n `Required for this sync: ${limitError.required.toLocaleString()}`,\n `Upgrade plan: ${limitError.upgradeUrl}`,\n ];\n }\n\n return [\n `Plan: ${limitError.planId}`,\n `Current: ${limitError.current}`,\n `Required: ${limitError.required}`,\n `Upgrade: ${limitError.upgradeUrl}`,\n ];\n}\n\nfunction getSyncPolicyErrorGuidance(\n error: NonNullable<VocoderAPIError['syncPolicyError']>,\n): string[] {\n if (error.errorCode === 'BRANCH_NOT_ALLOWED') {\n const lines = ['This branch is not allowed for this project.'];\n if (error.branch) {\n lines.push(`Current branch: ${error.branch}`);\n }\n // targetBranches removed — configure branches in project settings\n lines.push('Update your project target branches in the dashboard if needed.');\n return lines;\n }\n\n const lines = ['This project is bound to a different repository.'];\n if (error.boundRepoLabel) {\n lines.push(`Bound repository: ${error.boundRepoLabel}`);\n }\n if (error.boundScopePath) {\n lines.push(`Bound scope: ${error.boundScopePath}`);\n }\n lines.push(\n 'Run `vocoder init` from the correct repository or create a separate project.',\n );\n return lines;\n}\n\nfunction mergeContext(\n current: string | undefined,\n incoming: string | undefined,\n): string | undefined {\n if (!incoming) return current;\n if (!current) return incoming;\n if (current === incoming) return current;\n\n const merged = new Set(\n [...current.split(' | '), ...incoming.split(' | ')]\n .map((part) => part.trim())\n .filter(Boolean),\n );\n return Array.from(merged).join(' | ');\n}\n\nfunction buildStringEntries(\n extractedStrings: ExtractedString[],\n): TranslationStringEntry[] {\n const byText = new Map<string, TranslationStringEntry>();\n\n for (const str of extractedStrings) {\n const existing = byText.get(str.text);\n if (!existing) {\n byText.set(str.text, {\n key: str.key,\n text: str.text,\n ...(str.context ? { context: str.context } : {}),\n ...(str.formality ? { formality: str.formality } : {}),\n });\n continue;\n }\n\n existing.context = mergeContext(existing.context, str.context);\n\n if (!existing.formality && str.formality) {\n existing.formality = str.formality;\n } else if (\n existing.formality &&\n str.formality &&\n existing.formality !== str.formality\n ) {\n existing.formality = 'auto';\n }\n\n if (str.key < existing.key) {\n existing.key = str.key;\n }\n }\n\n return Array.from(byText.values());\n}\n\nasync function fetchApiSnapshot(api: VocoderAPI, params: {\n branch: string;\n targetLocales: string[];\n}): Promise<TranslationArtifacts | null> {\n const snapshot = await api.getTranslationSnapshot({\n branch: params.branch,\n targetLocales: params.targetLocales,\n });\n\n if (snapshot.status !== 'FOUND' || !snapshot.translations) {\n return null;\n }\n\n return {\n source: 'api-snapshot',\n translations: snapshot.translations,\n localeMetadata: snapshot.localeMetadata,\n snapshotBatchId: snapshot.snapshotBatchId,\n completedAt: snapshot.completedAt,\n };\n}\n\n/**\n * Main sync command\n */\nexport async function sync(options: TranslateOptions = {}): Promise<number> {\n const startTime = Date.now();\n const projectRoot = process.cwd();\n\n p.intro('Vocoder Sync');\n\n const spinner = p.spinner();\n\n try {\n spinner.start('Detecting branch');\n const branch = detectBranch(options.branch);\n spinner.stop(`Branch: ${chalk.cyan(branch)}`);\n\n spinner.start('Loading project configuration');\n\n const mergedConfig = await getMergedConfig(options, options.verbose);\n const localConfig = {\n apiKey: mergedConfig.apiKey || '',\n apiUrl: mergedConfig.apiUrl || 'https://vocoder.app',\n };\n validateLocalConfig(localConfig);\n\n const api = new VocoderAPI(localConfig);\n const apiConfig = await api.getProjectConfig();\n\n const requestedMode = mergedConfig.mode;\n const waitTimeoutMs = resolveWaitTimeoutMs({\n requestedMaxWaitMs: mergedConfig.maxWaitMs,\n policyDefaultMaxWaitMs: apiConfig.syncPolicy.defaultMaxWaitMs,\n fallbackTimeoutMs: 60_000,\n });\n\n const config: ProjectConfig = {\n ...localConfig,\n ...apiConfig,\n extractionPattern: mergedConfig.extractionPattern,\n excludePattern: mergedConfig.excludePattern,\n timeout: waitTimeoutMs,\n };\n\n spinner.stop('Project configuration loaded');\n\n if (!options.force && !isTargetBranch(branch, config.targetBranches)) {\n p.log.warn(\n `Skipping translations (${chalk.cyan(branch)} is not a target branch)`,\n );\n p.log.info(`Target branches: ${config.targetBranches.join(', ')}`);\n p.log.info('Use --force to translate anyway');\n p.outro('');\n return 0;\n }\n\n const patternsDisplay = Array.isArray(config.extractionPattern)\n ? config.extractionPattern.join(', ')\n : config.extractionPattern;\n\n spinner.start(`Extracting strings from ${patternsDisplay}`);\n const extractor = new StringExtractor();\n const extractedStrings = await extractor.extractFromProject(\n config.extractionPattern,\n projectRoot,\n config.excludePattern,\n );\n\n if (extractedStrings.length === 0) {\n spinner.stop('No translatable strings found');\n p.log.warn('Make sure you are wrapping translatable strings with Vocoder');\n p.outro('');\n return 0;\n }\n\n spinner.stop(\n `Extracted ${chalk.cyan(extractedStrings.length)} strings from ${chalk.cyan(patternsDisplay)}`,\n );\n\n if (options.verbose) {\n const sampleLines = extractedStrings\n .slice(0, 5)\n .map((s: ExtractedString) => ` \"${s.text}\" (${s.file}:${s.line})`);\n if (extractedStrings.length > 5) {\n sampleLines.push(` ... and ${extractedStrings.length - 5} more`);\n }\n p.note(sampleLines.join('\\n'), 'Sample strings');\n }\n\n if (options.dryRun) {\n p.note(\n [\n `Strings: ${extractedStrings.length}`,\n `Branch: ${branch}`,\n `Target locales: ${config.targetLocales.join(', ')}`,\n `Requested mode: ${requestedMode}`,\n `Max wait: ${waitTimeoutMs}ms`,\n `No fallback: ${mergedConfig.noFallback ? 'yes' : 'no'}`,\n ].join('\\n'),\n 'Dry run - would translate',\n );\n p.outro('No API calls made.');\n return 0;\n }\n\n const repoIdentity = resolveGitRepositoryIdentity();\n if (!repoIdentity && options.verbose) {\n p.log.warn(\n 'Could not detect git remote origin. Sync will continue without repo metadata.',\n );\n }\n\n const stringEntries = buildStringEntries(extractedStrings);\n const sourceStrings = stringEntries.map((entry) => entry.text);\n\n if (options.verbose && stringEntries.length !== extractedStrings.length) {\n p.log.info(\n `Deduped ${extractedStrings.length} extracted entries into ${stringEntries.length} unique source strings`,\n );\n }\n\n spinner.start('Submitting strings to Vocoder API');\n\n const batchResponse = await api.submitTranslation(\n branch,\n stringEntries,\n config.targetLocales,\n {\n requestedMode,\n requestedMaxWaitMs: waitTimeoutMs,\n clientRunId: randomUUID(),\n },\n repoIdentity ?? undefined,\n );\n\n spinner.stop(`Submitted to API - Batch ${chalk.cyan(batchResponse.batchId)}`);\n\n const effectiveMode = batchResponse.effectiveMode ??\n resolveEffectiveModeFromPolicy({\n branch,\n requestedMode,\n policy: config.syncPolicy,\n });\n\n if (options.verbose) {\n p.log.info(`Requested mode: ${requestedMode}`);\n p.log.info(`Effective mode: ${effectiveMode}`);\n p.log.info(`Wait timeout: ${waitTimeoutMs}ms`);\n if (batchResponse.queueStatus) {\n p.log.info(`Queue status: ${batchResponse.queueStatus}`);\n }\n }\n\n if (batchResponse.status === 'UP_TO_DATE' && batchResponse.noChanges) {\n p.log.success('No changes detected - strings are up to date');\n }\n\n p.log.info(`New strings: ${chalk.cyan(batchResponse.newStrings)}`);\n\n if (batchResponse.deletedStrings && batchResponse.deletedStrings > 0) {\n p.log.info(\n `Deleted strings: ${chalk.yellow(batchResponse.deletedStrings)} (archived)`,\n );\n }\n\n p.log.info(`Total strings: ${chalk.cyan(batchResponse.totalStrings)}`);\n\n if (batchResponse.newStrings === 0) {\n p.log.success('No new strings - using existing translations');\n } else {\n p.log.info(\n `Syncing to ${config.targetLocales.length} locales (${config.targetLocales.join(', ')})`,\n );\n\n if (batchResponse.estimatedTime) {\n p.log.info(`Estimated time: ~${batchResponse.estimatedTime}s`);\n }\n }\n\n let artifacts: TranslationArtifacts | null = null;\n if (batchResponse.translations) {\n artifacts = {\n source: 'fresh',\n translations: batchResponse.translations,\n };\n }\n\n let waitError: Error | null = null;\n if (!artifacts && (effectiveMode === 'required' || effectiveMode === 'best-effort')) {\n spinner.start(`Waiting for translations (max ${waitTimeoutMs}ms)`);\n\n let lastProgress = 0;\n try {\n const completion = await api.waitForCompletion(\n batchResponse.batchId,\n waitTimeoutMs,\n (progress) => {\n const percent = Math.round(progress * 100);\n if (percent > lastProgress) {\n spinner.message(`Translating... ${percent}%`);\n lastProgress = percent;\n }\n },\n );\n\n artifacts = {\n source: 'fresh',\n translations: completion.translations,\n localeMetadata: completion.localeMetadata,\n };\n spinner.stop('Translations complete');\n } catch (error) {\n spinner.stop('Translation wait incomplete');\n waitError = error instanceof Error ? error : new Error(String(error));\n\n if (effectiveMode === 'required') {\n throw waitError;\n }\n\n p.log.warn(`Best-effort wait ended early: ${waitError.message}`);\n }\n }\n\n if (!artifacts) {\n if (mergedConfig.noFallback) {\n throw new Error(\n 'Fresh translations are not available and fallback is disabled (--no-fallback).',\n );\n }\n\n spinner.start('Loading fallback translations');\n\n const localFallback = readLocalSnapshotCache({\n projectRoot,\n branch,\n });\n\n if (localFallback) {\n artifacts = localFallback;\n const cacheBranchLabel =\n localFallback.cacheBranch && localFallback.cacheBranch !== branch\n ? `${localFallback.cacheBranch} fallback`\n : localFallback.cacheBranch || branch;\n spinner.stop(`Using local cached snapshot (${cacheBranchLabel})`);\n } else {\n try {\n const apiSnapshot = await fetchApiSnapshot(api, {\n branch,\n targetLocales: config.targetLocales,\n });\n\n if (apiSnapshot) {\n artifacts = apiSnapshot;\n spinner.stop('Using latest completed API snapshot');\n } else {\n spinner.stop('No completed API snapshot available');\n }\n } catch (error) {\n spinner.stop('Failed to fetch API snapshot');\n if (options.verbose) {\n const message =\n error instanceof Error ? error.message : 'Unknown snapshot fetch error';\n p.log.warn(`Snapshot fetch error: ${message}`);\n }\n }\n }\n\n if (!artifacts) {\n if (waitError) {\n throw new Error(\n `No fallback snapshot available after wait failure: ${waitError.message}`,\n );\n }\n\n throw new Error(\n 'No fallback snapshot available. Try again shortly or run with --mode required.',\n );\n }\n }\n\n const finalTranslations = normalizeTranslations({\n sourceLocale: config.sourceLocale,\n targetLocales: config.targetLocales,\n sourceStrings,\n translations: artifacts.translations,\n });\n\n try {\n const cachePath = writeLocalSnapshotCache({\n projectRoot,\n branch,\n sourceLocale: config.sourceLocale,\n targetLocales: config.targetLocales,\n translations: finalTranslations,\n localeMetadata: artifacts.localeMetadata,\n snapshotBatchId:\n artifacts.snapshotBatchId ??\n (artifacts.source === 'fresh'\n ? batchResponse.batchId\n : batchResponse.latestCompletedBatchId),\n completedAt:\n artifacts.completedAt ??\n (artifacts.source === 'fresh' ? new Date().toISOString() : null),\n });\n\n if (options.verbose) {\n p.log.info(`Cached snapshot: ${cachePath}`);\n }\n } catch (error) {\n if (options.verbose) {\n const message =\n error instanceof Error ? error.message : 'Unknown cache write error';\n p.log.warn(`Failed to write local snapshot cache: ${message}`);\n }\n }\n\n if (artifacts.source !== 'fresh') {\n const sourceLabel =\n artifacts.source === 'local-cache'\n ? 'local cached snapshot'\n : 'completed API snapshot';\n p.log.warn(\n `Using ${sourceLabel}. New strings may appear after the background sync completes.`,\n );\n }\n\n const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n p.outro(`Sync complete! (${duration}s)`);\n\n p.log.info('Translations will be injected at build time by @vocoder/unplugin.');\n p.log.info('Just use <VocoderProvider> and <T> — no manual imports needed.');\n return 0;\n } catch (error) {\n spinner.stop();\n\n if (error instanceof VocoderAPIError && error.syncPolicyError) {\n p.log.error(error.syncPolicyError.message);\n const guidance = getSyncPolicyErrorGuidance(error.syncPolicyError);\n for (const line of guidance) {\n p.log.info(line);\n }\n return 1;\n }\n\n if (error instanceof VocoderAPIError && error.limitError) {\n const { limitError } = error;\n p.log.error(limitError.message);\n const guidance = getLimitErrorGuidance(limitError);\n for (const line of guidance) {\n p.log.info(line);\n }\n return 1;\n }\n\n if (error instanceof Error) {\n p.log.error(error.message);\n\n if (error.message.includes('VOCODER_API_KEY')) {\n p.log.warn('VOCODER_API_KEY is only needed for `vocoder sync` (CLI push).');\n p.log.info(' Create one at: https://vocoder.app/dashboard');\n p.log.info(' Then: export VOCODER_API_KEY=\"vc_...\" or add it to .env');\n p.log.info('');\n p.log.info(' Note: If you use @vocoder/unplugin, `vocoder sync` is optional.');\n p.log.info(' Translations are fetched automatically at build time.');\n } else if (error.message.includes('git branch')) {\n p.log.warn('Run from a git repository, or use:');\n p.log.info(' vocoder sync --branch main');\n }\n\n if (options.verbose) {\n p.log.info(`Full error: ${error.stack ?? error}`);\n }\n }\n\n return 1;\n }\n}\n","import { execSync } from 'child_process';\n\nconst REGEX_SPECIAL_CHARS = /[.+?^${}()|[\\]\\\\]/g;\n\nfunction escapeRegexChar(value: string): string {\n return value.replace(REGEX_SPECIAL_CHARS, '\\\\$&');\n}\n\n/**\n * Detects the current git branch from multiple sources in priority order:\n * 1. Explicit --branch flag (passed as parameter)\n * 2. CI environment variables (GitHub Actions, Vercel, Netlify, etc.)\n * 3. Git command (local development)\n *\n * @param override - Optional branch name to override detection\n * @returns The current branch name\n */\nexport function detectBranch(override?: string): string {\n // 1. Explicit override (from --branch flag)\n if (override) {\n return override;\n }\n\n // 2. CI environment variables\n const envBranch =\n process.env.GITHUB_HEAD_REF || // GitHub Actions (PR source branch)\n process.env.GITHUB_REF_NAME || // GitHub Actions (push)\n process.env.VERCEL_GIT_COMMIT_REF || // Vercel\n process.env.BRANCH || // Netlify\n process.env.CF_PAGES_BRANCH || // Cloudflare Pages\n process.env.CI_COMMIT_REF_NAME || // GitLab CI\n process.env.BITBUCKET_BRANCH || // Bitbucket Pipelines\n process.env.CIRCLE_BRANCH || // CircleCI\n process.env.RENDER_GIT_BRANCH; // Render\n\n if (envBranch) {\n return envBranch;\n }\n\n // 3. Git command (local development)\n try {\n const branch = execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'ignore'],\n }).trim();\n\n return branch;\n } catch (error) {\n throw new Error(\n 'Failed to detect git branch. Make sure you are in a git repository or set the --branch flag.',\n );\n }\n}\n\n/**\n * Checks if the current branch is a target branch that should trigger translations\n *\n * @param currentBranch - The current branch name\n * @param targetBranches - List of branches that should trigger translations\n * @returns True if the branch should trigger translations\n */\nexport function isTargetBranch(\n currentBranch: string,\n targetBranches: string[],\n): boolean {\n return targetBranches.some((pattern) =>\n matchBranchPattern(currentBranch, pattern),\n );\n}\n\nexport function matchBranchPattern(branch: string, pattern: string): boolean {\n const trimmedPattern = pattern.trim();\n if (!trimmedPattern) {\n return false;\n }\n\n let regexSource = '^';\n for (let i = 0; i < trimmedPattern.length; i += 1) {\n const char = trimmedPattern[i];\n if (!char) {\n continue;\n }\n\n if (char === '*') {\n const next = trimmedPattern[i + 1];\n if (next === '*') {\n regexSource += '.*';\n i += 1;\n } else {\n regexSource += '[^/]*';\n }\n continue;\n }\n\n regexSource += escapeRegexChar(char);\n }\n regexSource += '$';\n\n return new RegExp(regexSource).test(branch);\n}\n","import type { LocalConfig, RequestedSyncMode, TranslateOptions } from '../types.js';\n\nimport chalk from 'chalk';\nimport { config as loadEnv } from 'dotenv';\n\n// Load .env file if present\nloadEnv();\n\n/**\n * Validates the local configuration\n */\nexport function validateLocalConfig(config: LocalConfig): void {\n if (!config.apiKey || config.apiKey.length === 0) {\n throw new Error('VOCODER_API_KEY is required. Set it in your .env file.');\n }\n\n if (!config.apiKey.startsWith('vc_')) {\n throw new Error('Invalid API key format. Expected format: vc_...');\n }\n\n if (!config.apiUrl || !config.apiUrl.startsWith('http')) {\n throw new Error('Invalid API URL');\n }\n}\n\n/**\n * Merge configuration from all sources with priority:\n * 1. CLI flags (highest priority)\n * 2. Environment variables\n * 3. Defaults (lowest priority)\n *\n * @param cliOptions - Options from CLI flags\n * @param verbose - Whether to log config sources\n * @returns Merged configuration with source information\n */\nexport async function getMergedConfig(\n cliOptions: TranslateOptions,\n verbose: boolean = false,\n _startDir?: string\n): Promise<{\n extractionPattern: string[];\n excludePattern: string[];\n apiKey?: string;\n apiUrl?: string;\n mode: RequestedSyncMode;\n maxWaitMs?: number;\n noFallback: boolean;\n configSources: {\n extractionPattern: string;\n excludePattern: string;\n apiKey: string;\n apiUrl: string;\n mode: string;\n maxWaitMs: string;\n noFallback: string;\n };\n}> {\n const configSources = {\n extractionPattern: 'default',\n excludePattern: 'default',\n apiKey: 'environment',\n apiUrl: 'default',\n mode: 'default',\n maxWaitMs: 'default',\n noFallback: 'default',\n };\n\n // 1. Defaults\n const defaults = {\n extractionPattern: ['src/**/*.{tsx,jsx,ts,js}'],\n excludePattern: [] as string[],\n apiUrl: 'https://vocoder.app',\n };\n\n // 2. Environment variables\n const envExtractionPattern = process.env.VOCODER_EXTRACTION_PATTERN;\n const envApiUrl = process.env.VOCODER_API_URL;\n const envSyncMode = process.env.VOCODER_SYNC_MODE;\n const envSyncMaxWaitMs = process.env.VOCODER_SYNC_MAX_WAIT_MS;\n const envSyncNoFallback = process.env.VOCODER_SYNC_NO_FALLBACK;\n\n // 3. Merge with priority: CLI > env > defaults\n\n // Extract patterns (include)\n let extractionPattern: string[];\n if (cliOptions.include && cliOptions.include.length > 0) {\n extractionPattern = cliOptions.include;\n configSources.extractionPattern = 'CLI flag';\n } else if (envExtractionPattern) {\n extractionPattern = [envExtractionPattern];\n configSources.extractionPattern = 'environment';\n } else {\n extractionPattern = defaults.extractionPattern;\n }\n\n // Exclude patterns\n let excludePattern: string[];\n if (cliOptions.exclude && cliOptions.exclude.length > 0) {\n excludePattern = cliOptions.exclude;\n configSources.excludePattern = 'CLI flag';\n } else {\n excludePattern = defaults.excludePattern;\n }\n\n // API key (from env)\n let apiKey: string | undefined;\n if (process.env.VOCODER_API_KEY) {\n apiKey = process.env.VOCODER_API_KEY;\n configSources.apiKey = 'environment';\n }\n\n // API URL\n let apiUrl: string;\n if (envApiUrl) {\n apiUrl = envApiUrl;\n configSources.apiUrl = 'environment';\n } else {\n apiUrl = defaults.apiUrl;\n }\n\n const modeCandidates = ['auto', 'required', 'best-effort'] as const;\n let mode: RequestedSyncMode = 'auto';\n if (cliOptions.mode && modeCandidates.includes(cliOptions.mode)) {\n mode = cliOptions.mode;\n configSources.mode = 'CLI flag';\n } else if (envSyncMode && modeCandidates.includes(envSyncMode as RequestedSyncMode)) {\n mode = envSyncMode as RequestedSyncMode;\n configSources.mode = 'environment';\n }\n\n let maxWaitMs: number | undefined;\n if (typeof cliOptions.maxWaitMs === 'number' && Number.isFinite(cliOptions.maxWaitMs) && cliOptions.maxWaitMs > 0) {\n maxWaitMs = Math.floor(cliOptions.maxWaitMs);\n configSources.maxWaitMs = 'CLI flag';\n } else if (envSyncMaxWaitMs) {\n const parsed = Number.parseInt(envSyncMaxWaitMs, 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n maxWaitMs = parsed;\n configSources.maxWaitMs = 'environment';\n }\n }\n\n let noFallback = false;\n if (typeof cliOptions.noFallback === 'boolean') {\n noFallback = cliOptions.noFallback;\n configSources.noFallback = 'CLI flag';\n } else if (envSyncNoFallback) {\n noFallback = ['1', 'true', 'yes', 'on'].includes(envSyncNoFallback.toLowerCase());\n configSources.noFallback = 'environment';\n }\n\n // Log config sources in verbose mode\n if (verbose) {\n console.log(chalk.dim('\\n Configuration sources:'));\n console.log(chalk.dim(` Include patterns: ${configSources.extractionPattern}`));\n if (excludePattern.length > 0) {\n console.log(chalk.dim(` Exclude patterns: ${configSources.excludePattern}`));\n }\n console.log(chalk.dim(` API key: ${configSources.apiKey}`));\n console.log(chalk.dim(` API URL: ${configSources.apiUrl}\\n`));\n console.log(chalk.dim(` Sync mode: ${configSources.mode}`));\n if (maxWaitMs) {\n console.log(chalk.dim(` Max wait: ${configSources.maxWaitMs}`));\n }\n console.log(chalk.dim(` No fallback: ${configSources.noFallback}\\n`));\n }\n\n return {\n extractionPattern,\n excludePattern,\n apiKey,\n apiUrl,\n mode,\n maxWaitMs,\n noFallback,\n configSources,\n };\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\nimport { VocoderAPI } from '../utils/api.js';\nimport { readAuthData } from '../utils/auth-store.js';\n\nexport interface WhoamiOptions {\n apiUrl?: string;\n}\n\nexport async function whoami(options: WhoamiOptions = {}): Promise<number> {\n const stored = readAuthData();\n\n if (!stored) {\n p.log.info('Not logged in. Run `vocoder init` to authenticate.');\n return 1;\n }\n\n const apiUrl = options.apiUrl ?? stored.apiUrl ?? 'https://vocoder.app';\n const api = new VocoderAPI({ apiUrl, apiKey: '' });\n\n try {\n const info = await api.getCliUserInfo(stored.token);\n p.log.info(`Logged in as ${chalk.bold(info.email)}`);\n if (info.name) {\n p.log.info(`Name: ${info.name}`);\n }\n p.log.info(`API: ${apiUrl}`);\n return 0;\n } catch {\n p.log.error('Stored credentials are invalid or expired. Run `vocoder init` to re-authenticate.');\n return 1;\n }\n}\n"],"mappings":"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","names":["p","URL","resolve","resolve","init","text","resolve","chalk","execSync","p","chalk","isCancel","p","chalk","Prompt","isCancel","chalk","execSync","S_BAR","S_BAR_END","S_ACTIVE","S_SUBMIT","S_CANCEL","S_ERROR","noColor","dim","cyan","grn","ylw","red","bld","symbol","MAX_VISIBLE","buildList","MAX_VISIBLE","grn","dim","bld","cyan","S_BAR","ylw","Prompt","symbol","S_BAR_END","isCancel","chalk","p","chalk","spawn","resolve","tryOpenBrowser","spawn","chalk","execSync","p","p","execSync","mkdirSync","readFileSync","writeFileSync","chalk","loadEnv","chalk","join","join","readFileSync","mkdirSync","writeFileSync","lines","spinner","chalk","p","chalk","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/bin.ts","../src/commands/init.ts","../src/utils/auth-store.ts","../src/utils/github-connect.ts","../src/utils/local-server.ts","../src/utils/api.ts","../src/utils/git-identity.ts","../src/utils/project-create.ts","../src/utils/locale-search.ts","../src/utils/branch-select.ts","../src/utils/workspace.ts","../src/commands/logout.ts","../src/commands/sync.ts","../src/utils/branch.ts","../src/utils/config.ts","../src/commands/whoami.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { init } from './commands/init.js';\nimport { logout } from './commands/logout.js';\nimport { sync } from './commands/sync.js';\nimport { whoami } from './commands/whoami.js';\n\n\n/**\n * Collector function for repeated CLI options\n * Allows multiple --include or --exclude flags\n */\nfunction collect(value: string, previous: string[] = []): string[] {\n return previous.concat([value]);\n}\n\nasync function runCommand(command: (options: any) => Promise<number>, options: any): Promise<void> {\n const exitCode = await command(options);\n // Force exit so open stdin handles from readline/clack don't stall the process.\n process.exit(exitCode);\n}\n\nconst program = new Command();\n\nprogram\n .name('vocoder')\n .description('Vocoder CLI - Project setup and string extraction')\n .version('0.1.5');\n\nprogram\n .command('init')\n .description('Authenticate and provision Vocoder for this project')\n .option('--api-url <url>', 'Override Vocoder API URL')\n .option('--yes', 'Allow overwriting existing local config values')\n .option('--ci', 'Non-interactive mode: print auth URL to stdout, skip browser open')\n .option('--project-name <name>', 'Starter project name to create')\n .option('--source-locale <locale>', 'Source locale for the starter project')\n .option('--target-locales <list>', 'Comma-separated target locales (e.g. es,fr,de)')\n .action((options) => runCommand(init, options));\n\nprogram\n .command('sync')\n .description('Extract strings and sync translations')\n .option('--branch <branch>', 'Override detected branch')\n .option('--mode <mode>', 'Sync mode: auto, required, best-effort', 'auto')\n .option('--max-wait <ms>', 'Max wait for translations (ms)')\n .option('--force', 'Force re-extraction even if no changes')\n .option('--dry-run', 'Preview without syncing')\n .option('--no-fallback', 'Disable fallback to cached translations')\n .option('--include <pattern>', 'Include glob pattern', collect, [])\n .option('--exclude <pattern>', 'Exclude glob pattern', collect, [])\n .option('--verbose', 'Detailed output')\n .action((options) => {\n const translated: Record<string, unknown> = { ...options };\n if (options.maxWait) translated.maxWaitMs = Number(options.maxWait);\n if (options.fallback === false) translated.noFallback = true;\n return runCommand(sync, translated);\n });\n\nprogram\n .command('logout')\n .description('Log out and remove stored credentials')\n .option('--api-url <url>', 'Override Vocoder API URL')\n .action((options) => runCommand(logout, options));\n\nprogram\n .command('whoami')\n .description('Show the currently authenticated user')\n .option('--api-url <url>', 'Override Vocoder API URL')\n .action((options) => runCommand(whoami, options));\n\nprogram.parse(process.argv);\n","import * as p from '@clack/prompts';\n\nimport {\n buildInstallCommand,\n detectLocalEcosystem,\n getPackagesToInstall,\n} from '../utils/detect-local.js';\nimport { clearAuthData, readAuthData, writeAuthData } from '../utils/auth-store.js';\nimport { runGitHubDiscoveryFlow, runGitHubInstallFlow, selectGitHubInstallation } from '../utils/github-connect.js';\n\nimport type { InitOptions } from '../types.js';\nimport { VocoderAPI, VocoderAPIError } from '../utils/api.js';\nimport chalk from 'chalk';\nimport { execSync } from 'node:child_process';\nimport { getSetupSnippets } from '../utils/setup-snippets.js';\nimport { config as loadEnv } from 'dotenv';\nimport { resolveGitContext } from '../utils/git-identity.js';\nimport { runProjectAppCreate, runProjectCreate } from '../utils/project-create.js';\nimport { selectWorkspace } from '../utils/workspace.js';\nimport { spawn } from 'node:child_process';\nimport { startCallbackServer } from '../utils/local-server.js';\n\nloadEnv();\n\nconst SUBSCRIPTION_SETTINGS_PATH = '/dashboard/workspace/settings?tab=subscription';\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n if (!process.stdout.isTTY || process.env.CI === 'true') {\n return false;\n }\n\n let command: string;\n let args: string[];\n\n if (process.platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (process.platform === 'win32') {\n command = 'rundll32';\n args = ['url.dll,FileProtocolHandler', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n return await new Promise<boolean>((resolve) => {\n try {\n const child = spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n\n let settled = false;\n child.once('spawn', () => {\n if (settled) return;\n settled = true;\n child.unref();\n resolve(true);\n });\n child.once('error', () => {\n if (settled) return;\n settled = true;\n resolve(false);\n });\n setTimeout(() => {\n if (settled) return;\n settled = true;\n resolve(false);\n }, 300);\n } catch {\n resolve(false);\n }\n });\n}\n\nfunction isPlanLimitFailure(message?: string): boolean {\n if (!message) return false;\n return /limit|upgrade/i.test(message);\n}\n\nfunction getSubscriptionSettingsUrl(apiUrl: string): string {\n return new URL(SUBSCRIPTION_SETTINGS_PATH, apiUrl).toString();\n}\n\nfunction printPlanLimitMessage(apiUrl: string, message: string): void {\n p.log.error(`You are over your plan limits.\\n ${message}`);\n p.log.info(`Manage subscription: ${getSubscriptionSettingsUrl(apiUrl)}`);\n}\n\ninterface ScaffoldParams {\n projectName: string;\n organizationName: string;\n sourceLocale: string;\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n}\n\nfunction runScaffold(params: ScaffoldParams): void {\n const { projectName, organizationName, sourceLocale, branchTriggers } = params;\n\n p.log.info(`Project: ${chalk.bold(projectName)}`);\n p.log.info(`Workspace: ${chalk.bold(organizationName)}`);\n\n const detection = detectLocalEcosystem();\n\n if (detection.ecosystem) {\n const frameworkLabel = detection.framework ?? detection.ecosystem;\n const pmLabel = detection.packageManager;\n p.log.info(`Detected: ${chalk.bold(frameworkLabel)} (${pmLabel})`);\n }\n\n const packagesToInstall = getPackagesToInstall(detection);\n if (packagesToInstall.length > 0) {\n const installCmd = buildInstallCommand(detection.packageManager, packagesToInstall);\n p.log.info('');\n const installSpinner = p.spinner();\n installSpinner.start(`Installing ${packagesToInstall.join(', ')}...`);\n\n try {\n execSync(installCmd, { stdio: 'pipe', cwd: process.cwd() });\n installSpinner.stop(`Installed ${packagesToInstall.join(', ')}`);\n } catch {\n installSpinner.stop('Package installation failed');\n p.log.warn(`Run manually: ${chalk.cyan(installCmd)}`);\n }\n } else if (detection.ecosystem) {\n p.log.info(`Packages: ${chalk.green('already installed')}`);\n }\n\n const snippets = getSetupSnippets({\n framework: detection.framework,\n ecosystem: detection.ecosystem,\n sourceLocale,\n branchTriggers,\n });\n\n let stepNum = 1;\n\n if (snippets.pluginStep) {\n p.log.message('');\n p.log.step(`${chalk.bold(`Step ${stepNum}:`)} Add the plugin to ${chalk.cyan(snippets.pluginStep.file)}`);\n printCodeBlock(snippets.pluginStep.code);\n stepNum++;\n }\n\n if (snippets.providerStep) {\n p.log.step(`${chalk.bold(`Step ${stepNum}:`)} Add the provider to ${chalk.cyan(snippets.providerStep.file)}`);\n printCodeBlock(snippets.providerStep.code);\n stepNum++;\n }\n\n p.log.step(`${chalk.bold(`Step ${stepNum}:`)} Wrap translatable strings`);\n printCodeBlock(snippets.wrapStep.code);\n\n p.log.message('');\n for (const line of snippets.whatsNext.split('\\n')) {\n p.log.success(line);\n }\n}\n\nfunction printMcpSetup(apiKey: string): void {\n const addCommand = `claude mcp add --scope project --transport stdio \\\\\\n --env VOCODER_API_KEY=${apiKey} \\\\\\n vocoder -- npx -y @vocoder/mcp`;\n\n const teamConfig = JSON.stringify(\n {\n mcpServers: {\n vocoder: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@vocoder/mcp'],\n env: { VOCODER_API_KEY: '${env:VOCODER_API_KEY}' },\n },\n },\n },\n null,\n 2,\n );\n\n p.log.message('');\n p.log.message(chalk.bold('Use Vocoder with Claude Code'));\n p.log.message('Run this to add the MCP server to your project:');\n p.log.message('');\n printCodeBlock(addCommand);\n p.log.message('');\n p.log.message('To share with your team, commit ' + chalk.cyan('.mcp.json') + ' with an env var reference');\n p.log.message('so each developer supplies their own key:');\n p.log.message('');\n printCodeBlock(teamConfig);\n p.log.message('');\n p.log.message(chalk.gray('Setup instructions: https://vocoder.app/docs/mcp'));\n}\n\nfunction printCodeBlock(code: string): void {\n const lines = code.split('\\n');\n const maxLen = lines.reduce((max: number, line: string) => Math.max(max, line.length), 0);\n const bar = chalk.gray('│');\n const pad = (s: string) => s + ' '.repeat(maxLen - s.length);\n\n process.stdout.write(`${chalk.gray('│')}\\n`);\n process.stdout.write(`${chalk.gray('│')} ${chalk.gray('┌' + '─'.repeat(maxLen + 2) + '┐')}\\n`);\n for (const line of lines) {\n process.stdout.write(`${chalk.gray('│')} ${bar} ${pad(line)} ${bar}\\n`);\n }\n process.stdout.write(`${chalk.gray('│')} ${chalk.gray('└' + '─'.repeat(maxLen + 2) + '┘')}\\n`);\n}\n\n// ── Auth helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Verify a stored auth token against the API.\n * Returns user info on success, null if the token is invalid/expired.\n * Always clears the stored token on failure.\n *\n * Returns `{ userGone: true }` when the server confirms the user no longer\n * exists (404) — callers should treat this as a first-time setup, not a reauth.\n */\nasync function verifyStoredToken(\n api: VocoderAPI,\n token: string,\n): Promise<{ userId: string; email: string; name: string | null } | { userGone: true } | null> {\n try {\n return await api.getCliUserInfo(token);\n } catch (err) {\n clearAuthData();\n // 404 = user record deleted — treat as first-time, not reauth\n if (err instanceof VocoderAPIError && err.status === 404) {\n return { userGone: true };\n }\n return null;\n }\n}\n\n/**\n * Run the browser authentication flow.\n * Returns `{ token, userInfo, organizationId? }` on success, or null if cancelled.\n * When `organizationId` is set, the GitHub App was installed in the same browser\n * trip — the caller should skip workspace selection and GitHub connect.\n *\n * @param reauth - When true, the user has an expired token and already has a workspace.\n * Use verificationUrl (auth/cli page) instead of installUrl so we don't create a\n * duplicate workspace. The direct-to-GitHub install URL is only for first-time setup.\n */\nasync function runAuthFlow(\n api: VocoderAPI,\n options: InitOptions,\n reauth = false,\n repoCanonical?: string,\n): Promise<{ token: string; userId: string; email: string; name: string | null; organizationId?: string; discoveryReady?: boolean } | null> {\n // Try to start a local callback server for instant token delivery.\n // In --ci mode the browser step is handled externally, so skip the callback\n // server and go straight to polling — simpler and testable.\n let server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n if (!options.ci) {\n try {\n server = await startCallbackServer();\n } catch {\n // Port conflict or other issue — fall back to polling\n }\n }\n\n const session = await api.startCliAuthSession(server?.port, repoCanonical);\n // Re-auth: user already has a workspace — use verificationUrl (auth/cli page)\n // so we don't trigger a new GitHub App install and create a duplicate workspace.\n // First-time: use installUrl to combine Vocoder auth + App install in one trip.\n const browserUrl = reauth\n ? session.verificationUrl\n : (session.installUrl ?? session.verificationUrl);\n const expiresAt = new Date(session.expiresAt).getTime();\n\n if (options.ci) {\n // Machine-readable output for automated test harnesses.\n // Parsed by e2e/helpers/cli.ts: /^VOCODER_AUTH_URL: (.+)$/m\n process.stdout.write(`VOCODER_AUTH_URL: ${browserUrl}\\n`);\n // Also emit the session ID separately so tests can expire/complete sessions\n process.stdout.write(`VOCODER_SESSION_ID: ${session.sessionId}\\n`);\n } else if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {\n if (reauth) {\n // Re-auth: token expired, just sign in — no install choice needed\n if (!options.yes) {\n const shouldOpen = await p.confirm({ message: 'Open your browser to sign in again?' });\n if (p.isCancel(shouldOpen)) {\n server?.close();\n p.cancel('Setup cancelled.');\n return null;\n }\n if (!shouldOpen) {\n p.log.info('Open the URL above manually in your browser to continue.');\n } else {\n const opened = await tryOpenBrowser(browserUrl);\n if (!opened) {\n p.note(browserUrl, 'Sign In');\n p.log.info('Open the URL above manually to continue.');\n }\n }\n } else {\n await tryOpenBrowser(browserUrl);\n }\n } else {\n // First-time setup: let user choose install vs link existing\n let isLinkFlow = false;\n if (!options.yes) {\n const connectChoice = await p.select<string>({\n message: 'Vocoder needs to be installed on your GitHub account to get started',\n options: [\n { value: 'install', label: 'Install GitHub App', hint: 'recommended' },\n { value: 'link', label: 'Already installed? Link your account' },\n ],\n });\n\n if (p.isCancel(connectChoice)) {\n server?.close();\n p.cancel('Setup cancelled.');\n return null;\n }\n\n isLinkFlow = connectChoice === 'link';\n }\n\n // For \"link\": get the OAuth-only URL from the server (no install page shown)\n let urlToOpen = browserUrl;\n if (isLinkFlow) {\n try {\n const linkSession = await api.startCliGitHubLinkSession(\n session.sessionId,\n server?.port,\n );\n urlToOpen = linkSession.oauthUrl;\n } catch {\n // Fall back to install URL if link-start fails\n urlToOpen = browserUrl;\n }\n }\n\n // Open browser immediately — no separate confirm needed\n const opened = await tryOpenBrowser(urlToOpen);\n if (!opened) {\n // Only show URL as a fallback if auto-open fails\n p.log.warn('Could not open your browser automatically.');\n p.note(urlToOpen, 'GitHub');\n p.log.info('Open the URL above to continue.');\n }\n }\n }\n\n const authSpinner = p.spinner();\n authSpinner.start('Waiting for GitHub authorization...');\n\n let rawToken: string | null = null;\n let callbackOrganizationId: string | undefined;\n let callbackDiscoveryReady = false;\n\n if (server) {\n // Fast path: wait for the localhost callback\n try {\n const deadline = Math.min(expiresAt, Date.now() + 10 * 60 * 1000);\n const timeoutMs = deadline - Date.now();\n const params = await Promise.race([\n server.waitForCallback(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), timeoutMs)),\n ]);\n\n if (params && typeof params.token === 'string') {\n rawToken = params.token;\n if (typeof params.organizationId === 'string' && params.organizationId) {\n callbackOrganizationId = params.organizationId;\n }\n // Link flow: callback signals discovery results are cached\n if (params.discovery_ready === '1') {\n callbackDiscoveryReady = true;\n }\n }\n } catch {\n // Fall through to polling\n } finally {\n server.close();\n }\n }\n\n if (!rawToken) {\n // Polling fallback\n while (Date.now() < expiresAt) {\n const result = await api.pollCliAuthSession(session.sessionId);\n\n if (result.status === 'complete') {\n rawToken = result.token;\n if (result.organizationId) {\n callbackOrganizationId = result.organizationId;\n }\n break;\n }\n\n if (result.status === 'failed') {\n authSpinner.stop();\n p.log.error(result.reason);\n return null;\n }\n\n // Still pending — wait 2s before next poll\n await sleep(2000);\n }\n }\n\n if (!rawToken) {\n authSpinner.stop();\n p.log.error('The authentication link expired. Run `vocoder init` again.');\n return null;\n }\n\n // Validate the token and get user info\n const userInfo = await api.getCliUserInfo(rawToken);\n authSpinner.stop(`Authenticated as ${chalk.bold(userInfo.email)}`);\n\n return { token: rawToken, ...userInfo, organizationId: callbackOrganizationId, discoveryReady: callbackDiscoveryReady };\n}\n\n// ── Main command ─────────────────────────────────────────────────────────────\n\nexport async function init(options: InitOptions = {}): Promise<number> {\n const apiUrl = options.apiUrl || process.env.VOCODER_API_URL || 'https://vocoder.app';\n\n p.intro('Vocoder Setup');\n\n try {\n // ── Detect git context ──────────────────────────────────────────────────\n const gitContext = resolveGitContext();\n const identity = gitContext.identity;\n\n if (gitContext.warnings.length > 0) {\n for (const warning of gitContext.warnings) {\n p.log.warn(warning);\n }\n }\n\n // ── Fast lookup: does a project already exist for this repo? ────────────\n // No spinner — this is a fast DB read and we don't want an empty ◇ on miss.\n let existingAppsForRepo: Array<{\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n }> = [];\n let repoProjectId: string | null = null;\n let repoProjectName: string | null = null;\n\n if (identity) {\n const anonApi = new VocoderAPI({ apiUrl, apiKey: '' });\n const lookup = await anonApi.lookupProjectByRepo({\n repoCanonical: identity.repoCanonical,\n scopePath: identity.repoScopePath,\n });\n\n // Exact match: this scope is already configured — scaffold and exit.\n if (lookup.exactMatch) {\n const { exactMatch } = lookup;\n runScaffold({\n projectName: exactMatch.projectName,\n organizationName: exactMatch.organizationName,\n sourceLocale: exactMatch.sourceLocale ?? 'en',\n branchTriggers: exactMatch.branchTriggers ?? [{ pattern: 'main', triggers: ['push'] }],\n });\n p.outro(\"Vocoder is already set up for this repository.\");\n return 0;\n }\n\n // Whole-repo app exists: covers this repo from any directory — scaffold.\n if (lookup.hasWholeRepoApp) {\n const wholeRepo = lookup.existingApps.find((a) => a.scopePath === '');\n if (wholeRepo) {\n runScaffold({\n projectName: wholeRepo.projectName,\n organizationName: wholeRepo.organizationName,\n sourceLocale: 'en',\n branchTriggers: [{ pattern: 'main', triggers: ['push'] }],\n });\n p.outro(\"Vocoder is already set up for this repository.\");\n return 0;\n }\n }\n\n // Other scoped apps exist: this repo has a project but not for this scope.\n // Store for display + validation in the app directory prompt.\n if (lookup.existingApps.length > 0) {\n existingAppsForRepo = lookup.existingApps;\n // All apps belong to the same project (one project per repo)\n repoProjectId = lookup.existingApps[0]?.projectId ?? null;\n repoProjectName = lookup.existingApps[0]?.projectName ?? null;\n }\n }\n\n // ── Auth: check stored token, prompt if missing ─────────────────────────\n const api = new VocoderAPI({ apiUrl, apiKey: '' });\n let userToken: string;\n let userEmail: string;\n let userName: string | null;\n\n // organizationId is set when auth+GitHub install completed in one browser trip\n let authOrganizationId: string | undefined;\n // discoveryReady is set when auth completed via link-start OAuth (no install)\n let authDiscoveryReady = false;\n\n const stored = readAuthData();\n if (stored && stored.apiUrl === apiUrl) {\n const verified = await verifyStoredToken(api, stored.token);\n\n if (verified && !('userGone' in verified)) {\n p.log.success(`Authenticated as ${chalk.bold(verified.email)}`);\n userToken = stored.token;\n userEmail = verified.email;\n userName = verified.name;\n } else {\n // userGone = user deleted from DB → full first-time flow (installUrl)\n // null = token expired → reauth via verificationUrl\n const isFirstTime = verified !== null && 'userGone' in verified;\n if (isFirstTime) {\n p.log.warn('Account not found — starting fresh setup');\n } else {\n p.log.warn('Stored credentials expired — signing in again');\n }\n const authResult = await runAuthFlow(api, options, /* reauth */ !isFirstTime, identity?.repoCanonical);\n if (!authResult) return 1;\n userToken = authResult.token;\n userEmail = authResult.email;\n userName = authResult.name;\n authOrganizationId = authResult.organizationId;\n authDiscoveryReady = authResult.discoveryReady ?? false;\n\n writeAuthData({\n token: userToken,\n apiUrl,\n userId: authResult.userId,\n email: userEmail,\n name: userName,\n createdAt: new Date().toISOString(),\n });\n }\n } else {\n const authResult = await runAuthFlow(api, options, false, identity?.repoCanonical);\n if (!authResult) return 1;\n userToken = authResult.token;\n userEmail = authResult.email;\n userName = authResult.name;\n authOrganizationId = authResult.organizationId;\n\n writeAuthData({\n token: userToken,\n apiUrl,\n userId: authResult.userId,\n email: userEmail,\n name: userName,\n createdAt: new Date().toISOString(),\n });\n }\n\n // ── Workspace selection ─────────────────────────────────────────────────────\n let selectedWorkspaceId: string;\n let selectedWorkspaceName: string;\n\n if (authOrganizationId) {\n // Install path: auth+install completed in one browser trip, workspace already created.\n const workspaceData = await api.listWorkspaces(userToken);\n const ws = workspaceData.workspaces.find((w) => w.id === authOrganizationId);\n selectedWorkspaceId = authOrganizationId;\n selectedWorkspaceName = ws?.name ?? userEmail;\n p.log.success(`Connected as ${chalk.bold(userEmail)} — workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n // Always check for cached discovery results first. The cache expires in\n // 5 minutes so returning users (no recent link flow) fall through cleanly.\n const discoveryResult = await api.getCliGitHubDiscovery(userToken).catch(() => null);\n const cachedInstallations = discoveryResult?.installations ?? [];\n\n if (cachedInstallations.length > 0) {\n // Warn if none of the discovered installations belong to the org that\n // owns the current repo — the binding won't be created even if setup succeeds.\n if (identity?.repoCanonical) {\n const repoOwner = identity.repoCanonical.split(':')[1]?.split('/')[0]?.toLowerCase();\n if (repoOwner) {\n const hasMatchingAccount = cachedInstallations.some(\n (i) => i.accountLogin.toLowerCase() === repoOwner,\n );\n if (!hasMatchingAccount) {\n p.log.warn(\n `None of your GitHub App installations belong to \"${repoOwner}\", ` +\n `the account that owns this repository.\\n` +\n ` The project will be created but translations won't trigger automatically.\\n` +\n ` To fix: install the Vocoder GitHub App on \"${repoOwner}\" instead.`,\n );\n }\n }\n }\n\n // Auto-select when there's exactly one valid (non-suspended, unclaimed) installation\n const validInstallations = cachedInstallations.filter(\n (i) => !i.isSuspended && !i.conflictLabel,\n );\n\n let selectedInstallationId: number | string | null = null;\n\n if (validInstallations.length === 1 && cachedInstallations.length === 1) {\n // Single installation — claim silently, no prompt needed\n selectedInstallationId = validInstallations[0]!.installationId;\n } else {\n selectedInstallationId = await selectGitHubInstallation(\n cachedInstallations.map((inst) => ({\n installationId: inst.installationId,\n accountLogin: inst.accountLogin,\n accountType: inst.accountType,\n isSuspended: inst.isSuspended,\n conflictLabel: inst.conflictLabel,\n })),\n false,\n );\n }\n\n if (selectedInstallationId === null || selectedInstallationId === 'install_new') {\n p.cancel('Setup cancelled. Re-run `vocoder init` and choose Install GitHub App.');\n return 1;\n }\n\n const claimResult = await api.claimCliGitHubInstallation(userToken, {\n installationId: String(selectedInstallationId),\n organizationId: null,\n });\n selectedWorkspaceId = claimResult.organizationId;\n selectedWorkspaceName = claimResult.organizationName;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n // ── Repo-aware workspace resolution ──────────────────────────────────────\n const workspaceData = await api.listWorkspaces(userToken, {\n repo: identity?.repoCanonical,\n });\n\n const repoCanonical = identity?.repoCanonical ?? null;\n // Workspaces whose GitHub installation covers the current repo\n const covering = repoCanonical\n ? workspaceData.workspaces.filter((w) => w.coversRepo === true)\n : [];\n // Workspaces that have any GitHub connection (may not cover this repo)\n const connected = workspaceData.workspaces.filter((w) => w.hasGitHubConnection);\n\n if (repoCanonical && covering.length === 1) {\n // ── Scenario 1: exactly one workspace covers this repo — auto-select ──\n const ws = covering[0]!;\n selectedWorkspaceId = ws.id;\n selectedWorkspaceName = ws.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\n } else if (repoCanonical && covering.length > 1) {\n // ── Scenario 2: multiple workspaces cover this repo — let user pick ──\n const choice = await p.select<string>({\n message: 'Select workspace for this repo',\n options: covering.map((w) => ({\n value: w.id,\n label: `${w.name} ${chalk.dim(`(${w.projectCount} project${w.projectCount !== 1 ? 's' : ''})`)}`,\n })),\n });\n if (p.isCancel(choice)) { p.cancel('Setup cancelled.'); return 1; }\n const ws = covering.find((w) => w.id === choice)!;\n selectedWorkspaceId = ws.id;\n selectedWorkspaceName = ws.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\n } else if (repoCanonical && covering.length === 0 && connected.length > 0) {\n // ── Scenario 3: connected workspaces exist but none cover this repo ──\n const shortRepo = repoCanonical.split(':')[1] ?? repoCanonical;\n p.log.warn(\n `${chalk.bold(shortRepo)} isn't accessible from your Vocoder installation.\\n` +\n ` Grant access to this repository or install on the account that owns it.`,\n );\n\n const fixOptions: Array<{ value: string; label: string }> = [];\n for (const ws of connected) {\n if (ws.installationConfigureUrl) {\n fixOptions.push({\n value: `grant:${ws.id}`,\n label: `Configure ${chalk.bold(ws.connectionLabel ?? ws.name)}'s GitHub App installation`,\n });\n }\n }\n fixOptions.push({\n value: 'install_new',\n label: `Install on a different GitHub account ${chalk.dim('(creates a new personal workspace)')}`,\n });\n fixOptions.push({ value: 'cancel', label: 'Cancel' });\n\n const fix = await p.select<string>({\n message: 'How would you like to fix this?',\n options: fixOptions,\n });\n\n if (p.isCancel(fix) || fix === 'cancel') {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n if (fix.startsWith('grant:')) {\n const ws = connected.find((w) => `grant:${w.id}` === fix)!;\n await tryOpenBrowser(ws.installationConfigureUrl!);\n p.cancel(\n `Grant access to ${chalk.bold(shortRepo)} in your browser,\\n` +\n ` then re-run ${chalk.bold('vocoder init')}.`,\n );\n return 1;\n }\n\n // install_new: full install → creates new workspace covering the new account\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) {\n p.log.error('GitHub App installation did not complete. Run `vocoder init` again.');\n return 1;\n }\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\n } else {\n // ── Fallback: no repo context or first-time user — standard select ────\n if (workspaceData.workspaces.length === 1 && !workspaceData.canCreateWorkspace) {\n const ws = workspaceData.workspaces[0]!;\n selectedWorkspaceId = ws.id;\n selectedWorkspaceName = ws.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n\n const workspaceResult = await selectWorkspace(workspaceData);\n\n if (workspaceResult.action === 'cancelled') {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n if (workspaceResult.action === 'use') {\n selectedWorkspaceId = workspaceResult.workspace.id;\n selectedWorkspaceName = workspaceResult.workspace.name;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n // ── New workspace: GitHub connect flow ────────────────────────────────\n const connectChoice = await p.select<string>({\n message: 'Connect your new workspace to GitHub',\n options: [\n { value: 'install', label: 'Install the Vocoder GitHub App' },\n { value: 'link', label: 'Link an existing installation' },\n ],\n });\n\n if (p.isCancel(connectChoice)) {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n if (connectChoice === 'install') {\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) {\n p.log.error('GitHub App installation did not complete. Run `vocoder init` again.');\n return 1;\n }\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n } else {\n const installations = await runGitHubDiscoveryFlow({ api, userToken, yes: options.yes });\n if (!installations) return 1;\n\n if (installations.length === 0) {\n p.log.warn('No GitHub installations found. Install the Vocoder GitHub App first.');\n const installNow = await p.confirm({ message: 'Open GitHub to install the App?' });\n if (p.isCancel(installNow) || !installNow) return 1;\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) return 1;\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n } else {\n const selectedInstallationId = await selectGitHubInstallation(\n installations.map((inst) => ({\n installationId: inst.installationId,\n accountLogin: inst.accountLogin,\n accountType: inst.accountType,\n isSuspended: inst.isSuspended,\n conflictLabel: inst.conflictLabel,\n })),\n true,\n );\n\n if (selectedInstallationId === null) { p.cancel('Setup cancelled.'); return 1; }\n\n if (selectedInstallationId === 'install_new') {\n const connectResult = await runGitHubInstallFlow({ api, userToken, yes: options.yes });\n if (!connectResult) return 1;\n selectedWorkspaceId = connectResult.organizationId;\n selectedWorkspaceName = connectResult.organizationName;\n } else {\n const claimResult = await api.claimCliGitHubInstallation(userToken, {\n installationId: String(selectedInstallationId),\n organizationId: null,\n });\n selectedWorkspaceId = claimResult.organizationId;\n selectedWorkspaceName = claimResult.organizationName;\n }\n }\n p.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n }\n } // closes new workspace else\n } // closes auto-select else\n } // closes main scenario if/else chain\n } // closes cachedInstallations else\n } // closes if (authOrganizationId) else\n\n // ── Add-app path: repo already has a project with scoped apps ───────────────\n // Skip plan limit check — we're adding a ProjectApp to an existing project,\n // not creating a new one. Run the project config prompts then call\n // POST /api/cli/project/apps.\n if (repoProjectId && repoProjectName && existingAppsForRepo.length > 0) {\n p.log.info(\n `${chalk.bold(repoProjectName)} is already set up for this repo.\\n` +\n ` Configured apps: ${existingAppsForRepo\n .map((a) => chalk.cyan(a.scopePath || '(entire repo)'))\n .join(', ')}`,\n );\n\n const appResult = await runProjectAppCreate({\n api,\n userToken,\n projectId: repoProjectId,\n projectName: repoProjectName,\n organizationName: selectedWorkspaceName,\n repoCanonical: identity?.repoCanonical,\n defaultScopePath: identity?.repoScopePath,\n existingApps: existingAppsForRepo,\n });\n\n if (!appResult) {\n p.log.error('App setup failed. Run `vocoder init` again.');\n return 1;\n }\n\n runScaffold({\n projectName: appResult.projectName,\n organizationName: selectedWorkspaceName,\n sourceLocale: appResult.sourceLocale,\n branchTriggers: appResult.branchTriggers,\n });\n p.outro(\"You're all set.\");\n return 0;\n }\n\n // ── Plan limit pre-flight ────────────────────────────────────────────────────\n try {\n const wsCheck = await api.listWorkspaces(userToken);\n const ws = wsCheck.workspaces.find((w) => w.id === selectedWorkspaceId);\n if (ws && ws.maxProjects !== -1 && ws.projectCount >= ws.maxProjects) {\n p.log.warn(\n `Project limit reached — ${ws.projectCount}/${ws.maxProjects} on your ${chalk.bold(ws.planId)} plan.`,\n );\n\n // If we're in a known repo, offer to connect an existing project to it.\n // This handles the case where the project exists but the repo binding\n // is missing (e.g. was lost in a migration or never created).\n const hasRepoContext = !!identity?.repoCanonical;\n\n const options: Array<{ value: string; label: string }> = [];\n if (hasRepoContext) {\n options.push({\n value: 'connect',\n label: 'Connect this repo to an existing project',\n });\n }\n options.push({ value: 'upgrade', label: 'Upgrade plan' });\n options.push({ value: 'cancel', label: 'Cancel' });\n\n const limitAction = await p.select<string>({\n message: 'What would you like to do?',\n options,\n });\n\n if (p.isCancel(limitAction) || limitAction === 'cancel') {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n if (limitAction === 'upgrade') {\n await tryOpenBrowser(`${apiUrl}${SUBSCRIPTION_SETTINGS_PATH}`);\n p.cancel('Upgrade your plan in the browser, then re-run `vocoder init`.');\n return 1;\n }\n\n // connect: list projects in this workspace, pick one, create ProjectApp binding\n const existingProjects = await api.listProjects(userToken, selectedWorkspaceId);\n if (existingProjects.length === 0) {\n p.log.error('No projects found in this workspace.');\n return 1;\n }\n\n const chosenId = await p.select<string>({\n message: 'Which project should this repo be connected to?',\n options: existingProjects.map((proj) => ({\n value: proj.id,\n label: proj.name,\n })),\n });\n\n if (p.isCancel(chosenId)) {\n p.cancel('Setup cancelled.');\n return 1;\n }\n\n const chosen = existingProjects.find((proj) => proj.id === chosenId)!;\n\n const appResult = await runProjectAppCreate({\n api,\n userToken,\n projectId: chosen.id,\n projectName: chosen.name,\n organizationName: selectedWorkspaceName,\n repoCanonical: identity?.repoCanonical,\n defaultScopePath: identity?.repoScopePath,\n existingApps: [],\n });\n\n if (!appResult) {\n p.log.error('Setup failed. Run `vocoder init` again.');\n return 1;\n }\n\n runScaffold({\n projectName: appResult.projectName,\n organizationName: selectedWorkspaceName,\n sourceLocale: appResult.sourceLocale,\n branchTriggers: appResult.branchTriggers,\n });\n p.outro(\"You're all set.\");\n return 0;\n }\n } catch {\n // Non-fatal\n }\n\n // ── Project configuration ────────────────────────────────────────────────────\n const projectResult = await runProjectCreate({\n api,\n userToken,\n organizationId: selectedWorkspaceId,\n defaultName: identity?.repoCanonical\n ? identity.repoCanonical.split('/').pop()\n : undefined,\n defaultSourceLocale: 'en',\n repoCanonical: identity?.repoCanonical,\n defaultBranches: ['main'],\n defaultScopePath: identity?.repoScopePath,\n });\n\n\n if (!projectResult) {\n p.log.error('Project creation failed. Run `vocoder init` again.');\n return 1;\n }\n\n // Warn if the current repo isn't accessible to the GitHub App installation.\n // This means translations won't trigger on push until the App is granted access.\n if (!projectResult.repositoryBound && identity?.repoCanonical) {\n p.log.warn(\n `This repository isn't accessible to your GitHub App installation.\\n` +\n `Translations won't run automatically until you grant access.\\n\\n` +\n ` To fix: go to your GitHub App installation settings and add this\\n` +\n ` repository to the allowed list, or switch to \"All repositories\".\\n` +\n (projectResult.configureUrl\n ? `\\n ${chalk.dim(projectResult.configureUrl)}\\n`\n : ''),\n );\n }\n\n // ── Scaffold + MCP setup ─────────────────────────────────────────────────────\n runScaffold({\n projectName: projectResult.projectName,\n organizationName: selectedWorkspaceName,\n sourceLocale: projectResult.sourceLocale,\n branchTriggers: projectResult.branchTriggers,\n });\n\n printMcpSetup(projectResult.apiKey);\n\n p.outro(\"You're all set.\");\n return 0;\n } catch (error) {\n if (error instanceof Error) {\n if (isPlanLimitFailure(error.message)) {\n printPlanLimitMessage(apiUrl, error.message);\n return 1;\n }\n p.log.error(`Error: ${error.message}`);\n } else {\n p.log.error('Unknown setup error');\n }\n\n return 1;\n }\n}\n","import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nexport interface AuthData {\n token: string;\n apiUrl: string;\n userId: string;\n email: string;\n name: string | null;\n createdAt: string;\n}\n\nfunction getAuthFilePath(): string {\n return join(homedir(), '.config', 'vocoder', 'auth.json');\n}\n\nexport function readAuthData(): AuthData | null {\n const filePath = getAuthFilePath();\n try {\n const raw = readFileSync(filePath, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== 'object') return null;\n const data = parsed as Partial<AuthData>;\n if (\n typeof data.token !== 'string' ||\n typeof data.apiUrl !== 'string' ||\n typeof data.userId !== 'string' ||\n typeof data.email !== 'string' ||\n typeof data.createdAt !== 'string'\n ) {\n return null;\n }\n return {\n token: data.token,\n apiUrl: data.apiUrl,\n userId: data.userId,\n email: data.email,\n name: typeof data.name === 'string' ? data.name : null,\n createdAt: data.createdAt,\n };\n } catch {\n return null;\n }\n}\n\nexport function writeAuthData(data: AuthData): void {\n const filePath = getAuthFilePath();\n const dir = dirname(filePath);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n writeFileSync(filePath, JSON.stringify(data, null, 2), { mode: 0o600 });\n}\n\nexport function clearAuthData(): void {\n const filePath = getAuthFilePath();\n try {\n unlinkSync(filePath);\n } catch {\n // Already gone — that's fine\n }\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\nimport { spawn } from 'node:child_process';\nimport type { VocoderAPI } from './api.js';\nimport { startCallbackServer } from './local-server.js';\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n if (!process.stdout.isTTY || process.env.CI === 'true') {\n return false;\n }\n\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 = 'rundll32';\n args = ['url.dll,FileProtocolHandler', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n return new Promise<boolean>((resolve) => {\n try {\n const child = spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n\n let settled = false;\n child.once('spawn', () => {\n if (settled) return;\n settled = true;\n child.unref();\n resolve(true);\n });\n child.once('error', () => {\n if (settled) return;\n settled = true;\n resolve(false);\n });\n setTimeout(() => {\n if (settled) return;\n settled = true;\n resolve(false);\n }, 300);\n } catch {\n resolve(false);\n }\n });\n}\n\nexport interface GitHubConnectResult {\n organizationId: string;\n organizationName: string;\n connectionLabel: string;\n}\n\n/**\n * Run the full GitHub App install flow for a new workspace.\n * Opens the browser to the GitHub App install page and waits for completion.\n *\n * Returns `null` if the user cancelled or an error occurred.\n */\nexport async function runGitHubInstallFlow(params: {\n api: VocoderAPI;\n userToken: string;\n organizationId?: string;\n yes?: boolean;\n}): Promise<GitHubConnectResult | null> {\n // Try to start a local callback server for instant notification\n let server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n try {\n server = await startCallbackServer();\n } catch {\n // Fall through — the user can re-run if something goes wrong\n }\n\n const { installUrl } = await params.api.startCliGitHubInstall(params.userToken, {\n organizationId: params.organizationId,\n callbackPort: server?.port,\n });\n\n p.log.info('Opening GitHub to install the Vocoder App...');\n p.note(installUrl, 'Install URL');\n\n if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {\n const shouldOpen = params.yes\n ? true\n : await p.confirm({ message: 'Open in your browser?' });\n\n if (p.isCancel(shouldOpen)) {\n server?.close();\n return null;\n }\n\n if (shouldOpen) {\n const opened = await tryOpenBrowser(installUrl);\n if (!opened) {\n p.log.info('Could not open a browser automatically. Use the URL above.');\n }\n }\n }\n\n const connectSpinner = p.spinner();\n connectSpinner.start('Waiting for GitHub App installation...');\n\n if (server) {\n try {\n const params_timeout = 15 * 60 * 1000; // 15 minutes\n const callbackParams = await Promise.race([\n server.waitForCallback(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), params_timeout)),\n ]);\n\n server.close();\n\n if (!callbackParams) {\n connectSpinner.stop('GitHub App installation timed out');\n p.log.error('The installation flow timed out. Run `vocoder init` again.');\n return null;\n }\n\n if (callbackParams.error) {\n connectSpinner.stop('GitHub App installation failed');\n p.log.error(callbackParams.error);\n return null;\n }\n\n const { organizationId, connectionLabel, workspace_created } = callbackParams;\n\n if (!organizationId || !connectionLabel) {\n connectSpinner.stop('GitHub App installation incomplete');\n p.log.error('Missing organization or connection data from callback.');\n return null;\n }\n\n connectSpinner.stop(`Connected to GitHub as ${chalk.bold(connectionLabel)}`);\n\n // Fetch the org name\n const orgName = workspace_created ? connectionLabel : organizationId;\n return {\n organizationId,\n organizationName: orgName,\n connectionLabel,\n };\n } catch {\n server.close();\n connectSpinner.stop('GitHub App installation failed');\n return null;\n }\n }\n\n // No local server — there's no polling fallback for install; just wait\n connectSpinner.stop('Could not detect GitHub App installation automatically');\n p.log.warn('Complete the installation in your browser, then run `vocoder init` again.');\n return null;\n}\n\n/**\n * Run the GitHub OAuth discovery flow to find existing installations.\n * Returns the list of installations with conflict labels, or null on cancellation/error.\n */\nexport async function runGitHubDiscoveryFlow(params: {\n api: VocoderAPI;\n userToken: string;\n organizationId?: string;\n yes?: boolean;\n}): Promise<Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n}> | null> {\n // Try local callback server\n let server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n try {\n server = await startCallbackServer();\n } catch {\n // Fall through\n }\n\n const { oauthUrl } = await params.api.startCliGitHubOAuth(params.userToken, {\n organizationId: params.organizationId,\n callbackPort: server?.port,\n });\n\n p.log.info('Opening GitHub to authorize your account...');\n p.note('Complete authorization in your browser.');\n\n if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {\n const shouldOpen = params.yes\n ? true\n : await p.confirm({ message: 'Open in your browser?' });\n\n if (p.isCancel(shouldOpen)) {\n server?.close();\n return null;\n }\n\n if (shouldOpen) {\n const opened = await tryOpenBrowser(oauthUrl);\n if (!opened) {\n p.log.info(`Could not open browser automatically. Visit: ${oauthUrl}`);\n }\n }\n }\n\n const oauthSpinner = p.spinner();\n oauthSpinner.start('Waiting for GitHub authorization...');\n\n if (server) {\n try {\n const timeoutMs = 10 * 60 * 1000;\n const callbackParams = await Promise.race([\n server.waitForCallback(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), timeoutMs)),\n ]);\n\n server.close();\n\n if (!callbackParams) {\n oauthSpinner.stop('GitHub authorization timed out');\n return null;\n }\n\n if (callbackParams.error) {\n oauthSpinner.stop('GitHub authorization failed');\n p.log.error(callbackParams.error);\n return null;\n }\n } catch {\n server.close();\n oauthSpinner.stop('GitHub authorization failed');\n return null;\n }\n }\n\n oauthSpinner.stop('GitHub account authorized');\n\n // Fetch discovery results\n const discoveryResult = await params.api.getCliGitHubDiscovery(params.userToken);\n return discoveryResult.installations;\n}\n\ntype DiscoveredInstallation = {\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n};\n\n/**\n * Prompt the user to select a GitHub installation from discovery results.\n * Returns the selected installation ID, 'install_new' to trigger install flow,\n * or null on cancellation.\n */\nexport async function selectGitHubInstallation(\n installations: DiscoveredInstallation[],\n canInstallNew: boolean,\n): Promise<number | 'install_new' | null> {\n type SelectValue = string;\n\n const options: Array<{ value: SelectValue; label: string; hint?: string }> =\n installations.map((inst) => ({\n value: String(inst.installationId),\n label: inst.accountLogin,\n hint: [\n inst.accountType === 'Organization' ? 'organization' : 'personal',\n inst.conflictLabel ? `connected to ${inst.conflictLabel}` : '',\n inst.isSuspended ? 'suspended' : '',\n ]\n .filter(Boolean)\n .join(' · ') || undefined,\n }));\n\n if (canInstallNew) {\n options.push({\n value: 'install_new',\n label: `Install on a new account ${chalk.dim('(creates a new personal workspace)')}`,\n });\n }\n\n const selected = await p.select<SelectValue>({\n message: 'Select a GitHub installation',\n options,\n });\n\n if (p.isCancel(selected)) return null;\n if (selected === 'install_new') return 'install_new';\n\n return Number(selected);\n}\n","import { createServer } from 'node:http';\nimport { AddressInfo } from 'node:net';\nimport { URL } from 'node:url';\n\nexport interface LocalServerHandle {\n port: number;\n waitForCallback: () => Promise<Record<string, string>>;\n close: () => void;\n}\n\n/**\n * Starts a local HTTP server on a random available port.\n * Returns the port and a promise that resolves when the browser\n * redirects to /callback with query parameters.\n *\n * Used for the browser→CLI token handoff pattern:\n * 1. CLI passes `port` to the auth session start request\n * 2. After browser auth, vocoder.app redirects to localhost:<port>/callback?token=...\n * 3. `waitForCallback()` resolves with the query params\n */\nexport function startCallbackServer(): Promise<LocalServerHandle> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let callbackResolve: ((params: Record<string, string>) => void) | null = null;\n let callbackReject: ((err: Error) => void) | null = null;\n\n const callbackPromise = new Promise<Record<string, string>>((res, rej) => {\n callbackResolve = res;\n callbackReject = rej;\n });\n\n const server = createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end();\n return;\n }\n\n let pathname: string;\n let params: Record<string, string>;\n\n try {\n const parsed = new URL(req.url, 'http://localhost');\n pathname = parsed.pathname;\n params = Object.fromEntries(parsed.searchParams.entries());\n } catch {\n res.writeHead(400);\n res.end('Bad request');\n return;\n }\n\n if (pathname !== '/callback') {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<!DOCTYPE html><html><head><title>Authenticated</title></head>' +\n '<body style=\"font-family:sans-serif;text-align:center;padding:3rem;\">' +\n '<h2>Authenticated</h2>' +\n '<p>Return to your terminal to continue. You can close this tab.</p>' +\n '</body></html>',\n );\n\n if (callbackResolve) {\n callbackResolve(params);\n callbackResolve = null;\n }\n\n setImmediate(() => server.close());\n });\n\n server.on('error', (err) => {\n if (!settled) {\n settled = true;\n if (callbackReject) callbackReject(err);\n reject(err);\n }\n });\n\n // Bind to a random port on localhost only\n server.listen(0, '127.0.0.1', () => {\n if (settled) return;\n settled = true;\n\n const port = (server.address() as AddressInfo).port;\n\n resolve({\n port,\n waitForCallback: () => callbackPromise,\n close: () => server.close(),\n });\n });\n });\n}\n","import type {\n APIProjectConfig,\n InitStartResponse,\n InitStatusResponse,\n\tLimitErrorResponse,\n\tLocalConfig,\n\tRequestedSyncMode,\n\tRepoIdentityPayload,\n\tSyncPolicyErrorResponse,\n\tTranslationBatchResponse,\n\tTranslationSnapshotResponse,\n\tTranslationStringEntry,\n\tTranslationStatusResponse,\n} from '../types.js';\n\nfunction isLimitErrorResponse(value: unknown): value is LimitErrorResponse {\n if (!value || typeof value !== 'object') {\n return false;\n }\n\n const candidate = value as Partial<LimitErrorResponse>;\n return (\n typeof candidate.errorCode === 'string' &&\n typeof candidate.limitType === 'string' &&\n typeof candidate.planId === 'string' &&\n typeof candidate.current === 'number' &&\n typeof candidate.required === 'number' &&\n typeof candidate.upgradeUrl === 'string' &&\n typeof candidate.message === 'string'\n );\n}\n\nfunction isSyncPolicyErrorResponse(value: unknown): value is SyncPolicyErrorResponse {\n if (!value || typeof value !== 'object') {\n return false;\n }\n\n const candidate = value as Partial<SyncPolicyErrorResponse>;\n return (\n (candidate.errorCode === 'BRANCH_NOT_ALLOWED' ||\n candidate.errorCode === 'PROJECT_REPOSITORY_MISMATCH') &&\n typeof candidate.message === 'string'\n );\n}\n\nfunction extractErrorMessage(payload: unknown, fallback: string): string {\n if (!payload || typeof payload !== 'object') {\n return fallback;\n }\n\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.message === 'string') {\n return candidate.message;\n }\n\n if (typeof candidate.error === 'string') {\n return candidate.error;\n }\n\n return fallback;\n}\n\nfunction parsePayload(raw: string): unknown {\n if (raw.length === 0) {\n return null;\n }\n\n // HTML responses (e.g. Next.js error pages) are never valid API payloads.\n // Wrapping raw HTML as the error message causes it to leak into the TUI.\n const trimmed = raw.trimStart();\n if (trimmed.startsWith('<!DOCTYPE') || trimmed.startsWith('<html')) {\n return { message: 'Unexpected response from server (received HTML). Check your network connection or try again.' };\n }\n\n try {\n return JSON.parse(raw);\n } catch {\n return { message: raw };\n }\n}\n\nasync function readPayload(response: {\n text?: () => Promise<string>;\n json?: () => Promise<unknown>;\n}): Promise<unknown> {\n if (typeof response.text === 'function') {\n const raw = await response.text();\n return parsePayload(raw);\n }\n\n if (typeof response.json === 'function') {\n return response.json();\n }\n\n return null;\n}\n\nexport class VocoderAPIError extends Error {\n readonly status: number;\n readonly payload: unknown;\n readonly limitError: LimitErrorResponse | null;\n readonly syncPolicyError: SyncPolicyErrorResponse | null;\n\n constructor(params: {\n message: string;\n status: number;\n payload: unknown;\n limitError?: LimitErrorResponse | null;\n syncPolicyError?: SyncPolicyErrorResponse | null;\n }) {\n super(params.message);\n this.name = 'VocoderAPIError';\n this.status = params.status;\n this.payload = params.payload;\n this.limitError = params.limitError ?? null;\n this.syncPolicyError = params.syncPolicyError ?? null;\n }\n}\n\nexport class VocoderAPI {\n private apiUrl: string;\n private apiKey: string;\n\n constructor(config: LocalConfig) {\n this.apiUrl = config.apiUrl;\n this.apiKey = config.apiKey;\n }\n\n private async request<T>(\n path: string,\n init: RequestInit = {},\n errorPrefix?: string,\n ): Promise<T> {\n const response = await fetch(`${this.apiUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n ...(init.headers ?? {}),\n },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n const limitError = isLimitErrorResponse(payload) ? payload : null;\n const syncPolicyError = isSyncPolicyErrorResponse(payload) ? payload : null;\n const baseMessage = extractErrorMessage(payload, `Request failed with status ${response.status}`);\n throw new VocoderAPIError({\n message: errorPrefix ? `${errorPrefix}: ${baseMessage}` : baseMessage,\n status: response.status,\n payload,\n limitError,\n syncPolicyError,\n });\n }\n\n return payload as T;\n }\n\n /**\n * Fetch project configuration from API\n * Project is determined from the API key\n */\n\tasync getProjectConfig(): Promise<APIProjectConfig> {\n\t\tconst data = await this.request<{\n\t\t\tprojectName: string;\n\t\t\torganizationName: string;\n\t\t\tsourceLocale: string;\n\t\t\ttargetLocales: string[];\n\t\t\tbranchTriggers: Array<{ pattern: string; triggers: string[] }>;\n\t\t\tprimaryBranch?: string;\n\t\t\tsyncPolicy?: {\n\t\t\t\tblockingBranches?: string[];\n\t\t\t\tblockingMode?: \"required\" | \"best-effort\";\n\t\t\t\tnonBlockingMode?: \"required\" | \"best-effort\";\n\t\t\t\tdefaultMaxWaitMs?: number;\n\t\t\t};\n\t\t}>('/api/cli/config', {}, 'Failed to fetch project config');\n\n\t\treturn {\n\t\t\tprojectName: data.projectName,\n\t\t\torganizationName: data.organizationName,\n\t\t\tsourceLocale: data.sourceLocale,\n\t\t\ttargetLocales: data.targetLocales,\n\t\t\tbranchTriggers: data.branchTriggers ?? [],\n\t\t\tprimaryBranch: data.primaryBranch,\n\t\t\tsyncPolicy: {\n\t\t\t\tblockingBranches: data.syncPolicy?.blockingBranches ?? [\"main\", \"master\"],\n\t\t\t\tblockingMode: data.syncPolicy?.blockingMode ?? \"required\",\n\t\t\t\tnonBlockingMode: data.syncPolicy?.nonBlockingMode ?? \"best-effort\",\n\t\t\t\tdefaultMaxWaitMs: data.syncPolicy?.defaultMaxWaitMs ?? 60_000,\n\t\t\t},\n\t\t};\n\t}\n\n /**\n * Submit strings for translation\n * Project is determined from the API key\n */\n private stableTextKey(text: string): string {\n // FNV-1a 32-bit hash for deterministic fallback IDs\n let hash = 0x811c9dc5;\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return `SK_TEXT_${(hash >>> 0).toString(16).toUpperCase().padStart(8, '0')}`;\n }\n\n private normalizeStringEntries(\n entries: string[] | TranslationStringEntry[],\n ): TranslationStringEntry[] {\n if (entries.length === 0) {\n return [];\n }\n\n const first = entries[0];\n if (typeof first === 'string') {\n return (entries as string[]).map((text) => ({\n key: this.stableTextKey(text),\n text,\n }));\n }\n\n return (entries as TranslationStringEntry[]).map((entry, index) => ({\n key: entry.key || this.stableTextKey(`${entry.text}:${index}`),\n text: entry.text,\n ...(entry.context ? { context: entry.context } : {}),\n ...(entry.formality ? { formality: entry.formality } : {}),\n }));\n }\n\n\tasync submitTranslation(\n\t\tbranch: string,\n\t\tentries: string[] | TranslationStringEntry[],\n\t\ttargetLocales: string[],\n\t\toptions?: {\n\t\t\trequestedMode?: RequestedSyncMode;\n\t\t\trequestedMaxWaitMs?: number;\n\t\t\tclientRunId?: string;\n\t\t},\n\t\trepoIdentity?: RepoIdentityPayload,\n\t): Promise<TranslationBatchResponse> {\n const stringEntries = this.normalizeStringEntries(entries);\n const strings = stringEntries.map((entry) => entry.text);\n\n // Compute hash of sorted strings for fast comparison\n const crypto = await import('crypto');\n const sortedStrings = [...strings].sort();\n const stringsHash = crypto\n .createHash('sha256')\n .update(JSON.stringify(sortedStrings))\n .digest('hex');\n\n return this.request<TranslationBatchResponse>('/api/cli/sync', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n\t body: JSON.stringify({\n\t branch,\n\t stringEntries,\n\t targetLocales,\n\t stringsHash,\n\t ...(options?.requestedMode ? { requestedMode: options.requestedMode } : {}),\n\t ...(typeof options?.requestedMaxWaitMs === 'number'\n\t ? { requestedMaxWaitMs: options.requestedMaxWaitMs }\n\t : {}),\n\t ...(options?.clientRunId ? { clientRunId: options.clientRunId } : {}),\n\t ...(repoIdentity?.repoCanonical ? { repoCanonical: repoIdentity.repoCanonical } : {}),\n\t ...(repoIdentity?.repoScopePath !== undefined\n\t ? { repoScopePath: repoIdentity.repoScopePath }\n : {}),\n }),\n }, 'Translation submission failed');\n }\n\n /**\n * Check translation status\n */\n\tasync getTranslationStatus(\n\t\tbatchId: string,\n\t): Promise<TranslationStatusResponse> {\n\t\treturn this.request<TranslationStatusResponse>(\n\t\t\t`/api/cli/sync/status/${batchId}`,\n\t\t\t{},\n\t\t\t'Failed to check translation status',\n\t\t);\n\t}\n\n\tasync getTranslationSnapshot(params: {\n\t\tbranch: string;\n\t\ttargetLocales: string[];\n\t}): Promise<TranslationSnapshotResponse> {\n\t\tconst search = new URLSearchParams();\n\t\tsearch.set('branch', params.branch);\n\t\tfor (const locale of params.targetLocales) {\n\t\t\tsearch.append('targetLocale', locale);\n\t\t}\n\n\t\treturn this.request<TranslationSnapshotResponse>(\n\t\t\t`/api/cli/sync/snapshot?${search.toString()}`,\n\t\t\t{},\n\t\t\t'Failed to fetch translation snapshot',\n\t\t);\n\t}\n\n /**\n * Wait for translation to complete with polling\n */\n async waitForCompletion(\n batchId: string,\n timeout: number = 60000,\n onProgress?: (progress: number) => void,\n ): Promise<{\n translations: Record<string, Record<string, string>>;\n localeMetadata?: Record<string, { nativeName: string; dir?: 'rtl' }>;\n }> {\n const startTime = Date.now();\n const pollInterval = 1000; // Poll every second\n\n while (Date.now() - startTime < timeout) {\n const status = await this.getTranslationStatus(batchId);\n\n // Call progress callback\n if (onProgress) {\n onProgress(status.progress);\n }\n\n if (status.status === 'COMPLETED') {\n if (!status.translations) {\n throw new Error('Translation completed but no translations returned');\n }\n return {\n translations: status.translations,\n localeMetadata: status.localeMetadata,\n };\n }\n\n if (status.status === 'FAILED') {\n throw new Error(\n `Translation failed: ${status.errorMessage || 'Unknown error'}`,\n );\n }\n\n // Wait before polling again\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new Error(`Translation timeout after ${timeout}ms`);\n }\n\n async startInitSession(input: {\n projectName?: string;\n sourceLocale?: string;\n targetLocales?: string[];\n repoCanonical?: string;\n repoScopePath?: string;\n }): Promise<InitStartResponse> {\n const response = await fetch(`${this.apiUrl}/api/cli/init/start`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start init session (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as InitStartResponse;\n }\n\n async getInitSessionStatus(params: {\n sessionId: string;\n pollToken: string;\n }): Promise<InitStatusResponse> {\n const response = await fetch(\n `${this.apiUrl}/api/cli/init/status/${params.sessionId}`,\n {\n headers: {\n Authorization: `Bearer ${params.pollToken}`,\n },\n },\n );\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to get init status (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as InitStatusResponse;\n }\n\n // ── CLI Auth endpoints (no project API key needed) ──────────────────────────\n\n /**\n * Start a CLI auth session. Returns `{ sessionId, verificationUrl, expiresAt }`.\n * `sessionId` is the raw poll token — keep it secret, used for polling.\n */\n async startCliAuthSession(callbackPort?: number, repoCanonical?: string): Promise<{\n sessionId: string;\n verificationUrl: string;\n installUrl?: string;\n expiresAt: string;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/auth/start`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...(callbackPort != null ? { callbackPort } : {}),\n ...(repoCanonical ? { repoCanonical } : {}),\n }),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start auth session (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { sessionId: string; verificationUrl: string; installUrl?: string; expiresAt: string };\n }\n\n /**\n * Poll for CLI auth session completion.\n * Returns `{ token }` on success, throws on failure/expiry.\n * The server returns HTTP 202 while still pending.\n */\n async pollCliAuthSession(pollToken: string): Promise<\n | { status: 'pending' }\n | { status: 'complete'; token: string; organizationId?: string }\n | { status: 'failed'; reason: string }\n > {\n const response = await fetch(\n `${this.apiUrl}/api/cli/auth/session?session=${encodeURIComponent(pollToken)}`,\n );\n\n const payload = await readPayload(response);\n\n if (response.status === 202) {\n return { status: 'pending' };\n }\n\n if (response.status === 410) {\n return {\n status: 'failed',\n reason: extractErrorMessage(payload, 'Auth session expired or failed'),\n };\n }\n\n if (!response.ok) {\n return {\n status: 'failed',\n reason: extractErrorMessage(payload, `Auth session error (${response.status})`),\n };\n }\n\n const result = payload as { token?: string; organizationId?: string };\n if (!result.token) {\n return { status: 'failed', reason: 'No token in response' };\n }\n\n return {\n status: 'complete',\n token: result.token,\n ...(result.organizationId ? { organizationId: result.organizationId } : {}),\n };\n }\n\n /**\n * Validate a CLI user token and return the authenticated user's info.\n * Used by the CLI to verify stored credentials on startup.\n */\n async getCliUserInfo(userToken: string): Promise<{\n userId: string;\n email: string;\n name: string | null;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/auth/me`, {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Token validation failed (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { userId: string; email: string; name: string | null };\n }\n\n /**\n * Revoke the given CLI user token server-side.\n */\n async revokeCliToken(userToken: string): Promise<void> {\n const response = await fetch(`${this.apiUrl}/api/cli/auth/token`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n if (!response.ok) {\n const payload = await readPayload(response);\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Token revocation failed (${response.status})`),\n status: response.status,\n payload,\n });\n }\n }\n\n // ── Workspaces ────────────────────────────────────────────────────────────────\n\n async listWorkspaces(\n userToken: string,\n params?: { repo?: string },\n ): Promise<{\n workspaces: Array<{\n id: string;\n name: string;\n planId: string;\n maxProjects: number;\n projectCount: number;\n hasGitHubConnection: boolean;\n connectionLabel: string | null;\n /** null when no `repo` param was provided */\n coversRepo: boolean | null;\n installationConfigureUrl: string | null;\n }>;\n canCreateWorkspace: boolean;\n }> {\n const url = new URL(`${this.apiUrl}/api/cli/workspaces`);\n if (params?.repo) url.searchParams.set('repo', params.repo);\n\n const response = await fetch(url.toString(), {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to list workspaces (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n workspaces: Array<{\n id: string;\n name: string;\n planId: string;\n maxProjects: number;\n projectCount: number;\n hasGitHubConnection: boolean;\n connectionLabel: string | null;\n coversRepo: boolean | null;\n installationConfigureUrl: string | null;\n }>;\n canCreateWorkspace: boolean;\n };\n }\n\n async listProjects(\n userToken: string,\n organizationId: string,\n ): Promise<\n Array<{\n id: string;\n name: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n }>\n > {\n const url = new URL(`${this.apiUrl}/api/cli/projects`);\n url.searchParams.set('organizationId', organizationId);\n\n const response = await fetch(url.toString(), {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to list projects (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n const result = payload as { projects: Array<{\n id: string;\n name: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n }> };\n return result.projects;\n }\n\n // ── CLI GitHub endpoints ──────────────────────────────────────────────────────\n\n async startCliGitHubInstall(\n userToken: string,\n params: { organizationId?: string; callbackPort?: number },\n ): Promise<{ installUrl: string }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/install/start`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${userToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start GitHub install (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { installUrl: string };\n }\n\n /**\n * Start the \"link existing installation\" discovery flow.\n * Unlike startCliGitHubOAuth, this requires no bearer token — the Vocoder\n * account is created from the OAuth code in the callback.\n */\n async startCliGitHubLinkSession(\n sessionId: string,\n callbackPort?: number,\n ): Promise<{ oauthUrl: string }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/oauth/link-start`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sessionId, ...(callbackPort != null ? { callbackPort } : {}) }),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start GitHub link session (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { oauthUrl: string };\n }\n\n async startCliGitHubOAuth(\n userToken: string,\n params: { organizationId?: string; callbackPort?: number },\n ): Promise<{ oauthUrl: string }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/oauth/start`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${userToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to start GitHub OAuth (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as { oauthUrl: string };\n }\n\n async getCliGitHubDiscovery(userToken: string): Promise<{\n installations: Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n }>;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/discovery`, {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to fetch GitHub discovery (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n installations: Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n isSuspended: boolean;\n conflictLabel: string | null;\n }>;\n };\n }\n\n async claimCliGitHubInstallation(\n userToken: string,\n params: { installationId: string; organizationId: string | null },\n ): Promise<{\n organizationId: string;\n organizationName: string;\n connectionLabel: string;\n repoCount: number;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/github/claim`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${userToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to claim GitHub installation (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n organizationId: string;\n organizationName: string;\n connectionLabel: string;\n repoCount: number;\n };\n }\n\n // ── Locales ───────────────────────────────────────────────────────────────────\n\n async listLocales(userToken: string): Promise<Array<{ code: string; name: string; nativeName?: string }>> {\n const response = await fetch(`${this.apiUrl}/api/cli/locales`, {\n headers: { Authorization: `Bearer ${userToken}` },\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to list locales (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n const result = payload as { locales: Array<{ code: string; name: string; nativeName?: string }> };\n return result.locales;\n }\n\n // ── Project creation ──────────────────────────────────────────────────────────\n\n async createProject(\n userToken: string,\n params: {\n organizationId: string;\n name: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n scopePaths: string[];\n repoCanonical?: string;\n },\n ): Promise<{\n projectId: string;\n projectName: string;\n apiKey: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repositoryBound: boolean;\n configureUrl?: string;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/projects`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${userToken}`,\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to create project (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n projectId: string;\n projectName: string;\n apiKey: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repositoryBound: boolean;\n configureUrl?: string;\n };\n }\n\n // ── Project lookup ────────────────────────────────────────────────────────────\n\n /**\n * Look up all project apps for a given repo. Returns info about exact matches,\n * existing apps in other scopes, and whether a whole-repo app exists.\n * No auth required.\n */\n async lookupProjectByRepo(params: {\n repoCanonical: string;\n scopePath: string;\n }): Promise<{\n exactMatch: {\n projectId: string;\n projectName: string;\n organizationName: string;\n sourceLocale?: string;\n branchTriggers?: Array<{ pattern: string; triggers: string[] }>;\n } | null;\n existingApps: Array<{\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n }>;\n hasWholeRepoApp: boolean;\n }> {\n try {\n const response = await fetch(`${this.apiUrl}/api/cli/init/lookup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n repo: params.repoCanonical,\n scopePath: params.scopePath,\n }),\n });\n\n if (!response.ok) {\n return { exactMatch: null, existingApps: [], hasWholeRepoApp: false };\n }\n\n return (await response.json()) as {\n exactMatch: {\n projectId: string;\n projectName: string;\n organizationName: string;\n sourceLocale?: string;\n branchTriggers?: Array<{ pattern: string; triggers: string[] }>;\n } | null;\n existingApps: Array<{\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n }>;\n hasWholeRepoApp: boolean;\n };\n } catch {\n return { exactMatch: null, existingApps: [], hasWholeRepoApp: false };\n }\n }\n\n /**\n * Add a new ProjectApp to an existing project (monorepo: new app directory).\n * Does not check plan limits — no new project is created.\n */\n async createProjectApp(\n userToken: string,\n params: {\n projectId: string;\n scopePath: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repoCanonical: string;\n },\n ): Promise<{\n appId: string;\n projectId: string;\n projectName: string;\n apiKey: string;\n scopePath: string;\n }> {\n const response = await fetch(`${this.apiUrl}/api/cli/project/apps`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${userToken}`,\n },\n body: JSON.stringify(params),\n });\n\n const payload = await readPayload(response);\n\n if (!response.ok) {\n throw new VocoderAPIError({\n message: extractErrorMessage(payload, `Failed to create project app (${response.status})`),\n status: response.status,\n payload,\n });\n }\n\n return payload as {\n appId: string;\n projectId: string;\n projectName: string;\n apiKey: string;\n scopePath: string;\n };\n }\n}\n","import { execSync } from 'child_process';\nimport { relative, resolve } from 'path';\n\nexport type GitRepositoryIdentity = {\n repoCanonical: string;\n repoScopePath: string;\n};\n\nexport type GitContext = {\n identity: GitRepositoryIdentity | null;\n warnings: string[];\n};\n\nfunction safeExec(command: string): string | null {\n try {\n const output = execSync(command, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'ignore'],\n }).trim();\n return output.length > 0 ? output : null;\n } catch {\n return null;\n }\n}\n\nfunction normalizePath(pathname: string): string | null {\n const cleaned = pathname\n .replace(/^\\/+/, '')\n .replace(/\\.git$/i, '')\n .trim();\n\n if (!cleaned || !cleaned.includes('/')) {\n return null;\n }\n\n return cleaned;\n}\n\nfunction parseRemoteUrl(remoteUrl: string): {\n host: string;\n ownerRepoPath: string;\n} | null {\n const trimmed = remoteUrl.trim();\n if (!trimmed) {\n return null;\n }\n\n // SCP-like syntax: git@github.com:owner/repo.git\n if (!trimmed.includes('://')) {\n const scpMatch = trimmed.match(/^(?:.+@)?([^:]+):(.+)$/);\n if (scpMatch) {\n const host = (scpMatch[1] || '').toLowerCase();\n const ownerRepoPath = normalizePath(scpMatch[2] || '');\n if (!host || !ownerRepoPath) {\n return null;\n }\n return { host, ownerRepoPath };\n }\n return null;\n }\n\n try {\n const parsed = new URL(trimmed);\n const host = parsed.hostname.toLowerCase();\n const ownerRepoPath = normalizePath(decodeURIComponent(parsed.pathname));\n if (!host || !ownerRepoPath) {\n return null;\n }\n return { host, ownerRepoPath };\n } catch {\n return null;\n }\n}\n\nfunction toCanonical(host: string, ownerRepoPath: string): string {\n if (host.includes('github.com')) {\n return `github:${ownerRepoPath.toLowerCase()}`;\n }\n if (host.includes('gitlab.com')) {\n return `gitlab:${ownerRepoPath.toLowerCase()}`;\n }\n if (host.includes('bitbucket.org')) {\n return `bitbucket:${ownerRepoPath.toLowerCase()}`;\n }\n return `git:${host}/${ownerRepoPath.toLowerCase()}`;\n}\n\nexport function resolveGitRepositoryIdentity(): GitRepositoryIdentity | null {\n const remoteUrl = safeExec('git config --get remote.origin.url');\n if (!remoteUrl) {\n return null;\n }\n\n const parsed = parseRemoteUrl(remoteUrl);\n if (!parsed) {\n return null;\n }\n\n const repositoryRoot = safeExec('git rev-parse --show-toplevel');\n const currentDirectory = process.cwd();\n let repoScopePath = '';\n if (repositoryRoot) {\n const relativePath = relative(resolve(repositoryRoot), resolve(currentDirectory))\n .replace(/\\\\/g, '/')\n .trim();\n\n if (relativePath && relativePath !== '.' && !relativePath.startsWith('..')) {\n repoScopePath = relativePath;\n }\n }\n\n return {\n repoCanonical: toCanonical(parsed.host, parsed.ownerRepoPath),\n repoScopePath,\n };\n}\n\nexport function resolveGitContext(): GitContext {\n const warnings: string[] = [];\n const identity = resolveGitRepositoryIdentity();\n\n if (!identity) {\n warnings.push(\n 'Could not detect git remote origin. Repo binding will be skipped until sync can detect it.',\n );\n }\n\n return { identity, warnings };\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\nimport type { VocoderAPI } from './api.js';\nimport type { LocaleOption } from './locale-search.js';\nimport { searchMultiSelectLocales, searchSelectLocale } from './locale-search.js';\nimport { detectGitBranches, filterableBranchSelect } from './branch-select.js';\n\nexport interface ExistingApp {\n scopePath: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n}\n\nexport interface ProjectCreateParams {\n api: VocoderAPI;\n userToken: string;\n organizationId: string;\n /** Default project name (repo name or directory name) */\n defaultName?: string;\n /** Pre-detected source locale, e.g. \"en\" */\n defaultSourceLocale?: string;\n /** Repo canonical for binding the project, e.g. \"github:owner/repo\" */\n repoCanonical?: string;\n /** Default target branches */\n defaultBranches?: string[];\n /**\n * Auto-detected scope path (CWD relative to git root).\n * Non-empty when running from a subdirectory of the repo — monorepo use case.\n * e.g. \"apps/web\"\n */\n defaultScopePath?: string;\n}\n\nexport interface ProjectAppCreateParams {\n api: VocoderAPI;\n userToken: string;\n projectId: string;\n projectName: string;\n organizationName: string;\n repoCanonical?: string;\n defaultScopePath?: string;\n /** Existing apps to display and validate against */\n existingApps: ExistingApp[];\n}\n\nexport interface ProjectAppCreateResult {\n projectId: string;\n projectName: string;\n apiKey: string;\n scopePath: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n}\n\nexport interface ProjectCreateResult {\n projectId: string;\n projectName: string;\n apiKey: string;\n sourceLocale: string;\n targetLocales: string[];\n branchTriggers: Array<{ pattern: string; triggers: string[] }>;\n repositoryBound: boolean;\n configureUrl?: string;\n}\n\n/** All locales — used for target language selection. */\nfunction buildLocaleOptions(\n locales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n return locales.map((l) => ({\n bcp47: l.code,\n label: `${l.name} — ${l.code}`,\n }));\n}\n\n/**\n * Deduplicated language list — used for source language selection.\n * Groups locales by language family (prefix before first hyphen) and keeps one\n * representative per family, preferring the shortest/base code (e.g. \"en\" over\n * \"en-US\"). This prevents showing \"English\", \"English (American)\", \"English\n * (British)\" as three separate choices when the user just means \"English\".\n */\nfunction buildLanguageOptions(\n locales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n const byFamily = new Map<string, LocaleOption>();\n\n for (const l of locales) {\n const family = l.code.split('-')[0]!.toLowerCase();\n const opt: LocaleOption = { bcp47: l.code, label: `${l.name} — ${l.code}` };\n const existing = byFamily.get(family);\n // Prefer base code (shorter, no region suffix) over regional variants\n if (!existing || l.code.length < existing.bcp47.length) {\n byFamily.set(family, opt);\n }\n }\n\n return Array.from(byFamily.values());\n}\n\n/**\n * Run the full project configuration TUI: prompts for name, source locale,\n * target locales, and target branches, then calls POST /api/cli/projects.\n *\n * Returns the created project info (including API key), or null if cancelled.\n */\nexport async function runProjectCreate(\n params: ProjectCreateParams,\n): Promise<ProjectCreateResult | null> {\n const { api, userToken, organizationId, repoCanonical } = params;\n\n // ── Project name ────────────────────────────────────────────────────────────\n // Use the detected repo name automatically — no prompt needed.\n const projectName = (params.defaultName ?? 'my-project').trim();\n p.log.success(`Project: ${chalk.bold(projectName)}`);\n\n // ── Fetch available locales ─────────────────────────────────────────────────\n let rawLocales: Array<{ code: string; name: string; nativeName?: string }>;\n try {\n rawLocales = await api.listLocales(userToken);\n } catch {\n p.log.error('Failed to fetch supported locales. Check your connection and try again.');\n return null;\n }\n\n // Source: deduplicated by language family (e.g. just \"English — en\", not all variants)\n const languageOptions = buildLanguageOptions(rawLocales);\n // Target: all locales (regional variants matter for translation targets)\n const localeOptions = buildLocaleOptions(rawLocales);\n\n // ── Scope path (monorepo) ───────────────────────────────────────────────────\n let scopePath: string;\n if (params.defaultScopePath) {\n // Auto-detected from CWD — confirm silently, same pattern as project name.\n scopePath = params.defaultScopePath;\n p.log.success(`App directory: ${chalk.bold(scopePath)}`);\n } else {\n const rawScope = await p.text({\n message: 'App directory (leave blank for the entire repo)',\n placeholder: 'e.g. apps/web, packages/frontend',\n initialValue: '',\n validate(value) {\n const v = value.trim();\n if (!v) return;\n if (v.startsWith('/')) return 'Use a relative path, not an absolute path';\n if (v.includes('..')) return 'Path must not contain \"..\"';\n },\n });\n if (p.isCancel(rawScope)) return null;\n scopePath = ((rawScope as string | undefined) ?? '').trim();\n }\n\n // ── Source locale ───────────────────────────────────────────────────────────\n const sourceLocale = await searchSelectLocale(\n languageOptions,\n 'Source language (the language your code is written in)',\n params.defaultSourceLocale ?? 'en',\n );\n\n if (sourceLocale === null) return null;\n\n // ── Target locales ──────────────────────────────────────────────────────────\n // Exclude the exact source locale; regional variants (e.g. en-GB when source=en) remain available\n const targetOptions = localeOptions.filter((opt) => opt.bcp47 !== sourceLocale);\n\n const targetLocales = await searchMultiSelectLocales(\n targetOptions,\n 'Target languages (languages to translate into)',\n );\n\n if (targetLocales === null) return null;\n\n if (targetLocales.length === 0) {\n p.log.warn('No target languages selected — you can add them later from the dashboard.');\n }\n\n // ── Branch triggers — per-trigger selection ────────────────────────────────\n // Ask which branches should fire for each trigger type. Branches can appear\n // in both push and PR (they get both triggers). Manual is mutually exclusive:\n // a branch cannot be both automatic (push/PR) and manual-only.\n const detected = detectGitBranches();\n const initialBranches = params.defaultBranches?.length\n ? params.defaultBranches\n : [detected.defaultBranch];\n\n // Step 1: push (required)\n let pushBranches: string[] = [];\n {\n let initial = initialBranches;\n while (pushBranches.length === 0) {\n const result = await filterableBranchSelect({\n message: 'Translate on push — which branches?',\n branches: detected.branches,\n defaultBranch: detected.defaultBranch,\n initialValues: initial,\n });\n if (result === null) return null;\n if (result.length === 0) {\n p.log.warn('At least one branch is required. Please select at least one.');\n initial = [detected.defaultBranch];\n } else {\n pushBranches = result;\n }\n }\n }\n\n // Step 2: pull requests (optional, can overlap with push)\n const prResult = await filterableBranchSelect({\n message: 'Translate on pull requests — which branches? (optional)',\n branches: detected.branches,\n defaultBranch: detected.defaultBranch,\n initialValues: [],\n optional: true,\n });\n if (prResult === null) return null;\n const prBranches = prResult;\n\n // Step 3: manual-only (optional, mutually exclusive from push + PR)\n const autoSet = new Set([...pushBranches, ...prBranches]);\n const manualResult = await filterableBranchSelect({\n message: `Manual-only branches — translate via \\`vocoder sync\\` only (optional)`,\n branches: detected.branches.filter((b) => !autoSet.has(b)),\n defaultBranch: detected.defaultBranch,\n initialValues: [],\n optional: true,\n });\n if (manualResult === null) return null;\n\n // Strip any manual branches that overlap with push/PR (manual is exclusive)\n const manualBranches = manualResult.filter((b) => {\n if (autoSet.has(b)) {\n p.log.warn(`\"${b}\" is already configured for automatic translation — skipping from manual.`);\n return false;\n }\n return true;\n });\n\n // Validate: at least one branch total\n if (pushBranches.length === 0 && prBranches.length === 0 && manualBranches.length === 0) {\n p.log.error('At least one branch must be configured.');\n return null;\n }\n\n // Merge: branches in both push and PR get both triggers\n const triggerMap = new Map<string, Set<string>>();\n for (const b of pushBranches) {\n if (!triggerMap.has(b)) triggerMap.set(b, new Set());\n triggerMap.get(b)!.add('push');\n }\n for (const b of prBranches) {\n if (!triggerMap.has(b)) triggerMap.set(b, new Set());\n triggerMap.get(b)!.add('pull_request');\n }\n for (const b of manualBranches) {\n triggerMap.set(b, new Set(['manual']));\n }\n\n const branchTriggers = Array.from(triggerMap.entries()).map(([pattern, triggers]) => ({\n pattern,\n triggers: Array.from(triggers),\n }));\n\n // ── Create project ──────────────────────────────────────────────────────────\n try {\n const result = await api.createProject(userToken, {\n organizationId,\n name: projectName,\n sourceLocale,\n targetLocales,\n branchTriggers,\n scopePaths: scopePath ? [scopePath] : [],\n repoCanonical,\n });\n\n p.log.success(`Project ${chalk.bold(result.projectName)} created!`);\n return result;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n p.log.error(`Failed to create project: ${message}`);\n return null;\n }\n}\n\n/**\n * Configure and create a new ProjectApp under an existing project.\n * Used when the repo already has a project (monorepo: adding a new app directory).\n * No plan limit check runs — only a new ProjectApp is created, not a new Project.\n */\nexport async function runProjectAppCreate(\n params: ProjectAppCreateParams,\n): Promise<ProjectAppCreateResult | null> {\n const { api, userToken, projectId, projectName, repoCanonical } = params;\n const existingScopes = new Set(params.existingApps.map((a) => a.scopePath));\n\n // ── Fetch available locales ─────────────────────────────────────────────────\n let rawLocales: Array<{ code: string; name: string; nativeName?: string }>;\n try {\n rawLocales = await api.listLocales(userToken);\n } catch {\n p.log.error('Failed to fetch supported locales. Check your connection and try again.');\n return null;\n }\n\n const languageOptions = buildLanguageOptions(rawLocales);\n const localeOptions = buildLocaleOptions(rawLocales);\n\n // ── App directory ───────────────────────────────────────────────────────────\n let scopePath: string;\n if (params.defaultScopePath && !existingScopes.has(params.defaultScopePath)) {\n // Auto-detected scope is new — confirm silently.\n scopePath = params.defaultScopePath;\n p.log.success(`App directory: ${chalk.bold(scopePath)}`);\n } else {\n // Show existing apps so the user knows what's already configured.\n if (params.existingApps.length > 0) {\n const configuredList = params.existingApps\n .map((a) => chalk.dim(a.scopePath || '(entire repo)'))\n .join(', ');\n p.log.info(`Already configured: ${configuredList}`);\n }\n\n const hasWholeRepoApp = existingScopes.has('');\n\n const rawScope = await p.text({\n message: 'App directory for this new app',\n placeholder: 'e.g. apps/backend',\n initialValue: params.defaultScopePath ?? '',\n validate(value) {\n const v = value.trim();\n if (!v && hasWholeRepoApp) return 'This project already covers the entire repo.';\n if (!v) return 'App directory is required when other apps already exist.';\n if (v.startsWith('/')) return 'Use a relative path, not an absolute path.';\n if (v.includes('..')) return 'Path must not contain \"..\".';\n if (existingScopes.has(v)) return `\"${v}\" is already configured. Choose a different directory.`;\n },\n });\n if (p.isCancel(rawScope)) return null;\n scopePath = ((rawScope as string | undefined) ?? '').trim();\n }\n\n // ── Source locale ───────────────────────────────────────────────────────────\n const sourceLocale = await searchSelectLocale(\n languageOptions,\n 'Source language',\n 'en',\n );\n if (sourceLocale === null) return null;\n\n // ── Target locales ──────────────────────────────────────────────────────────\n const targetOptions = localeOptions.filter((opt) => opt.bcp47 !== sourceLocale);\n const targetLocales = await searchMultiSelectLocales(\n targetOptions,\n 'Target languages',\n );\n if (targetLocales === null) return null;\n if (targetLocales.length === 0) {\n p.log.warn('No target languages selected — you can add them later from the dashboard.');\n }\n\n // ── Branch triggers — per-trigger selection (same logic as runProjectCreate) ─\n const detectedApp = detectGitBranches();\n\n let appPushBranches: string[] = [];\n {\n let initial = [detectedApp.defaultBranch];\n while (appPushBranches.length === 0) {\n const result = await filterableBranchSelect({\n message: 'Translate on push — which branches?',\n branches: detectedApp.branches,\n defaultBranch: detectedApp.defaultBranch,\n initialValues: initial,\n });\n if (result === null) return null;\n if (result.length === 0) {\n p.log.warn('At least one branch is required.');\n initial = [detectedApp.defaultBranch];\n } else {\n appPushBranches = result;\n }\n }\n }\n\n const appPrResult = await filterableBranchSelect({\n message: 'Translate on pull requests — which branches? (optional)',\n branches: detectedApp.branches,\n defaultBranch: detectedApp.defaultBranch,\n initialValues: [],\n optional: true,\n });\n if (appPrResult === null) return null;\n\n const appAutoSet = new Set([...appPushBranches, ...appPrResult]);\n const appManualResult = await filterableBranchSelect({\n message: 'Manual-only branches (optional)',\n branches: detectedApp.branches.filter((b) => !appAutoSet.has(b)),\n defaultBranch: detectedApp.defaultBranch,\n initialValues: [],\n optional: true,\n });\n if (appManualResult === null) return null;\n\n const appManualBranches = appManualResult.filter((b) => {\n if (appAutoSet.has(b)) {\n p.log.warn(`\"${b}\" is already configured for automatic translation — skipping from manual.`);\n return false;\n }\n return true;\n });\n\n const appTriggerMap = new Map<string, Set<string>>();\n for (const b of appPushBranches) {\n if (!appTriggerMap.has(b)) appTriggerMap.set(b, new Set());\n appTriggerMap.get(b)!.add('push');\n }\n for (const b of appPrResult) {\n if (!appTriggerMap.has(b)) appTriggerMap.set(b, new Set());\n appTriggerMap.get(b)!.add('pull_request');\n }\n for (const b of appManualBranches) {\n appTriggerMap.set(b, new Set(['manual']));\n }\n\n const branchTriggers = Array.from(appTriggerMap.entries()).map(([pattern, triggers]) => ({\n pattern,\n triggers: Array.from(triggers),\n }));\n\n // ── Create the ProjectApp ───────────────────────────────────────────────────\n try {\n const result = await api.createProjectApp(userToken, {\n projectId,\n scopePath,\n sourceLocale,\n targetLocales,\n branchTriggers,\n repoCanonical: repoCanonical ?? '',\n });\n\n p.log.success(`App ${chalk.bold(scopePath)} added to ${chalk.bold(projectName)}!`);\n return {\n projectId: result.projectId,\n projectName: result.projectName,\n apiKey: result.apiKey,\n scopePath: result.scopePath,\n sourceLocale,\n targetLocales,\n branchTriggers,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n p.log.error(`Failed to add app: ${message}`);\n return null;\n }\n}\n","import { Prompt, isCancel } from '@clack/core';\nimport * as p from '@clack/prompts';\nimport chalk from 'chalk';\n\nexport interface LocaleOption {\n bcp47: string;\n /** Human-readable label, e.g. \"English — en\" */\n label: string;\n}\n\n// ── Symbols (match @clack/prompts style) ──────────────────────────────────────\n\nconst S_BAR = '│';\nconst S_BAR_END = '└';\nconst S_ACTIVE = '◆';\nconst S_SUBMIT = '◆';\nconst S_CANCEL = '■';\nconst S_ERROR = '▲';\n\nconst noColor = process.env.NO_COLOR === '1' || process.env.FORCE_COLOR === '0';\nconst dim = (s: string) => noColor ? s : chalk.gray(s);\nconst cyan = (s: string) => noColor ? s : chalk.cyan(s);\nconst grn = (s: string) => noColor ? s : chalk.green(s);\nconst ylw = (s: string) => noColor ? s : chalk.yellow(s);\nconst red = (s: string) => noColor ? s : chalk.red(s);\nconst bld = (s: string) => noColor ? s : chalk.bold(s);\n\nfunction symbol(state: string): string {\n switch (state) {\n case 'submit': return grn(S_SUBMIT);\n case 'cancel': return red(S_CANCEL);\n case 'error': return ylw(S_ERROR);\n default: return cyan(S_ACTIVE);\n }\n}\n\n// ── Filter ────────────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 12;\n\nfunction filterLocales(options: LocaleOption[], query: string): LocaleOption[] {\n if (!query.trim()) return options;\n const lower = query.toLowerCase();\n return options.filter(\n (o) => o.bcp47.toLowerCase().includes(lower) || o.label.toLowerCase().includes(lower),\n );\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nfunction buildList(\n filtered: LocaleOption[],\n cursor: number,\n scrollOffset: number,\n selected: Set<string> | null, // null = single-select\n): string {\n const isMulti = selected !== null;\n const end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n const visibleLines: string[] = [];\n\n for (let i = scrollOffset; i < end; i++) {\n const opt = filtered[i]!;\n const isCursor = i === cursor;\n const isChecked = isMulti && selected!.has(opt.bcp47);\n\n const icon = isMulti\n ? (isChecked ? (isCursor ? grn('◼') : '◼') : (isCursor ? grn('◻') : dim('◻')))\n : (isCursor ? grn('●') : dim('○'));\n\n visibleLines.push(`${cyan(S_BAR)} ${icon} ${isCursor ? bld(opt.label) : opt.label}`);\n }\n\n const hidden = filtered.length - (end - scrollOffset);\n if (hidden > 0) visibleLines.push(dim(`${S_BAR} ${hidden} more — keep typing to narrow`));\n if (filtered.length === 0) visibleLines.push(dim(`${S_BAR} No matches`));\n if (isMulti && selected!.size > 0) {\n visibleLines.push(dim(`${S_BAR} ${selected!.size} selected — Enter to confirm`));\n }\n\n return visibleLines.join('\\n');\n}\n\n// ── Core prompt factory ───────────────────────────────────────────────────────\n\nasync function runFilterablePrompt(opts: {\n message: string;\n options: LocaleOption[];\n multi: boolean;\n initialValue?: string;\n initialValues?: string[];\n}): Promise<string | string[] | null> {\n const { message, options, multi } = opts;\n\n let filter = '';\n let cursor = 0;\n let scrollOffset = 0;\n const selected = new Set<string>(multi ? (opts.initialValues ?? []) : []);\n\n if (!multi && opts.initialValue) {\n const idx = options.findIndex((o) => o.bcp47 === opts.initialValue);\n if (idx >= 0) cursor = idx;\n }\n\n const getFiltered = () => filterLocales(options, filter);\n\n // Keep cursor in bounds and scroll window centred\n const clampCursor = (filtered: LocaleOption[]) => {\n if (cursor >= filtered.length) cursor = Math.max(0, filtered.length - 1);\n if (cursor < scrollOffset) scrollOffset = cursor;\n if (cursor >= scrollOffset + MAX_VISIBLE) scrollOffset = cursor - MAX_VISIBLE + 1;\n if (scrollOffset < 0) scrollOffset = 0;\n };\n\n // @clack/core Prompt: render() returns the ENTIRE frame; clack handles\n // re-rendering (cursor movement + diff) automatically.\n // Using `any` cast to pass `trackValue=false` (2nd constructor arg).\n const prompt = new (Prompt as any)(\n {\n initialValue: !multi ? (options[cursor]?.bcp47 ?? null) : null,\n validate() {\n const f = getFiltered();\n if (multi && selected.size === 0) return 'At least one target language is required.';\n if (!multi && !f[cursor]) return 'Please select a language.';\n return undefined;\n },\n render(this: { state: string; error: string; value: unknown }) {\n const filtered = getFiltered();\n clampCursor(filtered);\n\n const hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n const hint = filter.length > 0\n ? filter\n : dim('type to filter, ↑↓ navigate' + (multi ? ', space select' : ''));\n\n switch (this.state) {\n case 'submit': {\n const val = multi\n ? Array.from(selected).map((id) => options.find((o) => o.bcp47 === id)?.label ?? id).join(', ')\n : options.find((o) => o.bcp47 === (this.value as string))?.label ?? '';\n return `${hdr}${dim(S_BAR)} ${bld(val || dim('none'))}`;\n }\n case 'cancel':\n return `${hdr}${dim(S_BAR)}`;\n case 'error':\n return [\n hdr.trimEnd(),\n `${ylw(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, multi ? selected : null),\n `${ylw(S_BAR_END)} ${ylw(this.error)}`,\n '',\n ].join('\\n');\n default:\n return [\n hdr.trimEnd(),\n `${cyan(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, multi ? selected : null),\n `${cyan(S_BAR_END)}`,\n '',\n ].join('\\n');\n }\n },\n },\n false, // trackValue=false — we manage value manually\n ) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n // Character input → update filter\n prompt.on('key', (key: string | undefined) => {\n if (!key || key === ' ') return; // space handled by cursor event\n const cp = key.codePointAt(0) ?? 0;\n if (cp === 0x7f || cp === 0x08) { // backspace\n filter = filter.slice(0, -1);\n cursor = 0; scrollOffset = 0;\n } else if (cp >= 32 && cp !== 127) {\n filter += key;\n cursor = 0; scrollOffset = 0;\n }\n });\n\n // Navigation + toggle\n prompt.on('cursor', (action: string | undefined) => {\n const filtered = getFiltered();\n switch (action) {\n case 'up': cursor = Math.max(0, cursor - 1); break;\n case 'down': cursor = Math.min(Math.max(filtered.length - 1, 0), cursor + 1); break;\n case 'space':\n if (multi) {\n const opt = filtered[cursor];\n if (opt) {\n if (selected.has(opt.bcp47)) selected.delete(opt.bcp47);\n else selected.add(opt.bcp47);\n }\n }\n break;\n }\n // Sync prompt.value for single-select so submit gets the right value\n if (!multi) {\n const opt = getFiltered()[cursor];\n (prompt as any).value = opt?.bcp47 ?? null;\n }\n });\n\n // Before submit resolves, set value to the selected items (multi) or current cursor (single)\n prompt.on('finalize', () => {\n if ((prompt as any).state === 'submit') {\n if (multi) {\n (prompt as any).value = Array.from(selected);\n } else {\n const f = getFiltered();\n (prompt as any).value = f[cursor]?.bcp47 ?? null;\n }\n }\n });\n\n const result = await prompt.prompt();\n\n if (isCancel(result)) return null;\n return result as string | string[];\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport async function searchSelectLocale(\n options: LocaleOption[],\n message: string,\n initialValue?: string,\n): Promise<string | null> {\n const result = await runFilterablePrompt({ message, options, multi: false, initialValue });\n return typeof result === 'string' ? result : null;\n}\n\nexport async function searchMultiSelectLocales(\n options: LocaleOption[],\n message: string,\n initialValues?: string[],\n): Promise<string[] | null> {\n const result = await runFilterablePrompt({ message, options, multi: true, initialValues });\n if (result === null) return null;\n const picks = result as string[];\n // Validate already prevents empty on first try; this handles the retry path\n if (picks.length === 0) {\n p.log.warn('At least one target language is required. Please select at least one.');\n return searchMultiSelectLocales(options, message, initialValues);\n }\n return picks;\n}\n","import { Prompt, isCancel } from '@clack/core';\nimport chalk from 'chalk';\nimport { execSync } from 'node:child_process';\n\n// ── Symbols ───────────────────────────────────────────────────────────────────\n\nconst S_BAR = '│';\nconst S_BAR_END = '└';\nconst S_ACTIVE = '◆';\nconst S_SUBMIT = '◆';\nconst S_CANCEL = '■';\nconst S_ERROR = '▲';\n\nconst noColor = process.env.NO_COLOR === '1' || process.env.FORCE_COLOR === '0';\nconst dim = (s: string) => noColor ? s : chalk.gray(s);\nconst cyan = (s: string) => noColor ? s : chalk.cyan(s);\nconst grn = (s: string) => noColor ? s : chalk.green(s);\nconst ylw = (s: string) => noColor ? s : chalk.yellow(s);\nconst red = (s: string) => noColor ? s : chalk.red(s);\nconst bld = (s: string) => noColor ? s : chalk.bold(s);\n\nfunction symbol(state: string): string {\n switch (state) {\n case 'submit': return grn(S_SUBMIT);\n case 'cancel': return red(S_CANCEL);\n case 'error': return ylw(S_ERROR);\n default: return cyan(S_ACTIVE);\n }\n}\n\n// ── Git detection ─────────────────────────────────────────────────────────────\n\nexport interface DetectedBranches {\n branches: string[];\n defaultBranch: string;\n}\n\nexport function detectGitBranches(cwd?: string): DetectedBranches {\n const workDir = cwd ?? process.cwd();\n try {\n // Local branches\n const localOut = execSync('git branch', { cwd: workDir, stdio: 'pipe' }).toString();\n const localBranches = localOut.split('\\n')\n .filter(Boolean)\n .map((b) => b.replace(/^\\*?\\s*/, '').trim())\n .filter(Boolean);\n\n // Remote branches (strip \"origin/\" prefix, skip HEAD pointer)\n let remoteBranches: string[] = [];\n try {\n const remoteOut = execSync('git branch -r', { cwd: workDir, stdio: 'pipe' }).toString();\n remoteBranches = remoteOut.split('\\n')\n .map((b) => b.trim())\n .filter((b) => b && !b.includes('HEAD'))\n .map((b) => b.replace(/^[^/]+\\//, '')); // strip \"origin/\" (or any remote name)\n } catch { /* no remote */ }\n\n const branches = [...new Set([...localBranches, ...remoteBranches])].sort();\n\n // Default branch: ask git for origin's HEAD (local cache, no network call).\n // Falls back to 'main' if the remote HEAD isn't cached.\n let defaultBranch = 'main';\n try {\n const ref = execSync('git symbolic-ref refs/remotes/origin/HEAD', { cwd: workDir, stdio: 'pipe' })\n .toString().trim();\n // ref = \"refs/remotes/origin/main\"\n defaultBranch = ref.split('/').pop() ?? 'main';\n } catch { /* HEAD not cached — run \"git remote set-head origin --auto\" to fix */ }\n\n return {\n branches: branches.length > 0 ? branches : [defaultBranch],\n defaultBranch,\n };\n } catch {\n return { branches: ['main'], defaultBranch: 'main' };\n }\n}\n\n// ── Validation ────────────────────────────────────────────────────────────────\n\nconst INVALID_CHARS = /[\\s?^~:[\\]\\\\]/;\n\nexport function validateBranchPattern(pattern: string): string | null {\n const t = pattern.trim();\n if (!t) return 'Pattern cannot be empty';\n if (INVALID_CHARS.test(t)) return 'Invalid characters — avoid spaces, ?, ^, ~, :, [, ], \\\\';\n if (t.startsWith('/') || t.endsWith('/')) return 'Cannot start or end with /';\n if (t.includes('//')) return 'Cannot contain //';\n return null;\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 10;\nconst ADD_PATTERN_VALUE = '__add__';\n\ninterface BranchItem {\n value: string;\n label: string;\n isCustom?: boolean;\n}\n\nfunction buildItems(\n branches: string[],\n defaultBranch: string,\n customPatterns: string[],\n): BranchItem[] {\n const items: BranchItem[] = branches.map((b) => ({\n value: b,\n label: b === defaultBranch ? `${b} (default branch)` : b,\n }));\n for (const pt of customPatterns) {\n if (!branches.includes(pt)) {\n items.push({ value: pt, label: pt, isCustom: true });\n }\n }\n return items;\n}\n\nfunction filterItems(items: BranchItem[], query: string): BranchItem[] {\n if (!query.trim()) return items;\n const lower = query.toLowerCase();\n return items.filter((i) => i.value.toLowerCase().includes(lower));\n}\n\nfunction buildList(\n filtered: BranchItem[],\n cursor: number,\n scrollOffset: number,\n selected: Set<string>,\n filter: string,\n customPatterns: string[],\n addCursor: boolean,\n optional = false,\n): string {\n const lines: string[] = [];\n const end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n\n for (let i = scrollOffset; i < end; i++) {\n const item = filtered[i]!;\n const isCursor = i === cursor && !addCursor;\n const isChecked = selected.has(item.value);\n\n const icon = isChecked\n ? (isCursor ? grn('◼') : '◼')\n : (isCursor ? grn('◻') : dim('◻'));\n\n let label = item.isCustom ? `${item.label} ${dim('(custom)')}` : item.label;\n if (isCursor) label = bld(label);\n\n lines.push(`${cyan(S_BAR)} ${icon} ${label}`);\n }\n\n // \"Add pattern\" option\n const trimmed = filter.trim();\n const allItems = [...filtered]; // simplified: just check filtered\n const isNewPattern =\n trimmed.length > 0 &&\n !allItems.some((i) => i.value === trimmed) &&\n !customPatterns.includes(trimmed);\n\n if (isNewPattern) {\n const err = validateBranchPattern(trimmed);\n const icon = addCursor ? grn('◻') : dim('◻');\n const label = err\n ? `${ylw('+')} ${dim(`\"${trimmed}\" — ${err}`)}`\n : `${grn('+')} Add \"${trimmed}\" as branch pattern`;\n lines.push(`${cyan(S_BAR)} ${icon} ${label}`);\n } else if (filtered.length === 0 && trimmed.length === 0) {\n lines.push(dim(`${S_BAR} No branches detected`));\n }\n\n const hidden = filtered.length - (end - scrollOffset);\n if (hidden > 0) lines.push(dim(`${S_BAR} ${hidden} more`));\n if (selected.size > 0) {\n lines.push(dim(`${S_BAR} ${selected.size} selected — Enter to confirm`));\n } else if (optional) {\n lines.push(dim(`${S_BAR} Enter to skip`));\n }\n\n return lines.join('\\n');\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport async function filterableBranchSelect(params: {\n message: string;\n branches: string[];\n defaultBranch: string;\n initialValues?: string[];\n /** When true, empty selection is accepted (Enter = skip) */\n optional?: boolean;\n}): Promise<string[] | null> {\n const { message, branches, defaultBranch } = params;\n const optional = params.optional ?? false;\n\n let filter = '';\n let cursor = 0;\n let scrollOffset = 0;\n let addCursor = false;\n const customPatterns: string[] = [];\n const selected = new Set<string>(params.initialValues ?? [defaultBranch]);\n\n const getItems = () => buildItems(branches, defaultBranch, customPatterns);\n const getFiltered = () => filterItems(getItems(), filter);\n\n const isNewPattern = () => {\n const t = filter.trim();\n if (!t) return false;\n return !getItems().some((i) => i.value === t) && !customPatterns.includes(t);\n };\n\n const clampCursor = (filtered: BranchItem[]) => {\n const hasAdd = isNewPattern();\n const max = filtered.length - 1 + (hasAdd ? 1 : 0);\n if (cursor > max && !addCursor) cursor = Math.max(0, max);\n if (!addCursor) {\n if (cursor < scrollOffset) scrollOffset = cursor;\n if (cursor >= scrollOffset + MAX_VISIBLE) scrollOffset = cursor - MAX_VISIBLE + 1;\n if (scrollOffset < 0) scrollOffset = 0;\n }\n };\n\n const prompt = new (Prompt as any)(\n {\n validate() {\n if (!optional && selected.size === 0) return 'At least one branch is required.';\n return undefined;\n },\n render(this: { state: string; error: string }) {\n const filtered = getFiltered();\n clampCursor(filtered);\n\n const hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n const hint = filter.length > 0\n ? filter\n : dim('type to filter or add pattern, ↑↓ navigate, space select');\n\n switch (this.state) {\n case 'submit': {\n const summary = selected.size > 0\n ? bld(Array.from(selected).join(', '))\n : dim('none');\n return `${hdr}${dim(S_BAR)} ${summary}`;\n }\n case 'cancel':\n return `${hdr}${dim(S_BAR)}`;\n case 'error':\n return [\n hdr.trimEnd(),\n `${ylw(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor, optional),\n `${ylw(S_BAR_END)} ${ylw(this.error)}`,\n '',\n ].join('\\n');\n default:\n return [\n hdr.trimEnd(),\n `${cyan(S_BAR)} ${dim('/')} ${hint}`,\n buildList(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor, optional),\n `${cyan(S_BAR_END)}`,\n '',\n ].join('\\n');\n }\n },\n },\n false,\n ) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n prompt.on('key', (key: string | undefined) => {\n if (!key || key === ' ') return;\n const cp = key.codePointAt(0) ?? 0;\n if (cp === 0x7f || cp === 0x08) {\n filter = filter.slice(0, -1);\n cursor = 0; scrollOffset = 0; addCursor = false;\n } else if (cp >= 32 && cp !== 127) {\n filter += key;\n cursor = 0; scrollOffset = 0; addCursor = false;\n }\n });\n\n prompt.on('cursor', (action: string | undefined) => {\n const filtered = getFiltered();\n const hasAdd = isNewPattern();\n\n switch (action) {\n case 'up':\n if (addCursor) { addCursor = false; cursor = Math.max(0, filtered.length - 1); }\n else cursor = Math.max(0, cursor - 1);\n break;\n case 'down':\n if (!addCursor && cursor >= filtered.length - 1 && hasAdd) addCursor = true;\n else if (!addCursor) cursor = Math.min(filtered.length - 1, cursor + 1);\n break;\n case 'space':\n if (addCursor) {\n const t = filter.trim();\n const err = validateBranchPattern(t);\n if (!err) {\n customPatterns.push(t);\n selected.add(t);\n filter = '';\n cursor = 0; scrollOffset = 0; addCursor = false;\n }\n } else {\n const item = filtered[cursor];\n if (item) {\n if (selected.has(item.value)) selected.delete(item.value);\n else selected.add(item.value);\n }\n }\n break;\n }\n });\n\n prompt.on('finalize', () => {\n if ((prompt as any).state === 'submit') {\n (prompt as any).value = Array.from(selected);\n }\n });\n\n const result = await prompt.prompt();\n if (isCancel(result)) return null;\n return result as string[];\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\n\nexport interface WorkspaceInfo {\n id: string;\n name: string;\n planId: string;\n projectCount: number;\n hasGitHubConnection: boolean;\n connectionLabel: string | null;\n}\n\nexport interface WorkspaceListResult {\n workspaces: WorkspaceInfo[];\n canCreateWorkspace: boolean;\n}\n\nexport type WorkspaceSelection =\n | { action: 'use'; workspace: WorkspaceInfo }\n | { action: 'create' }\n | { action: 'cancelled' };\n\nfunction workspaceLabel(ws: WorkspaceInfo): string {\n const parts: string[] = [ws.name];\n const meta: string[] = [];\n\n if (ws.projectCount === 1) {\n meta.push('1 project');\n } else if (ws.projectCount > 1) {\n meta.push(`${ws.projectCount} projects`);\n }\n\n if (ws.connectionLabel) {\n meta.push(`GitHub: ${ws.connectionLabel}`);\n }\n\n if (meta.length > 0) {\n parts.push(chalk.dim(`(${meta.join(', ')})`));\n }\n\n return parts.join(' ');\n}\n\n/**\n * Prompt the user to select a workspace or create a new one.\n * Returns a `WorkspaceSelection` describing what the user chose.\n */\nexport async function selectWorkspace(\n result: WorkspaceListResult,\n): Promise<WorkspaceSelection> {\n const { workspaces, canCreateWorkspace } = result;\n\n if (workspaces.length === 0) {\n // No workspaces — must create\n return { action: 'create' };\n }\n\n type SelectValue = string | 'create';\n\n const options: Array<{ value: SelectValue; label: string; hint?: string }> =\n workspaces.map((ws) => ({\n value: ws.id,\n label: ws.name,\n hint:\n [\n ws.projectCount > 0 ? `${ws.projectCount} project${ws.projectCount !== 1 ? 's' : ''}` : '',\n ws.connectionLabel ? `GitHub: ${ws.connectionLabel}` : '',\n ]\n .filter(Boolean)\n .join(' · ') || undefined,\n }));\n\n if (canCreateWorkspace) {\n options.push({ value: 'create', label: 'Create new workspace' });\n }\n\n const selected = await p.select<SelectValue>({\n message: 'Select workspace',\n options,\n });\n\n if (p.isCancel(selected)) {\n return { action: 'cancelled' };\n }\n\n if (selected === 'create') {\n return { action: 'create' };\n }\n\n const workspace = workspaces.find((ws) => ws.id === selected);\n if (!workspace) {\n return { action: 'cancelled' };\n }\n\n return { action: 'use', workspace };\n}\n","import * as p from '@clack/prompts';\nimport { VocoderAPI } from '../utils/api.js';\nimport { clearAuthData, readAuthData } from '../utils/auth-store.js';\n\nexport interface LogoutOptions {\n apiUrl?: string;\n}\n\nexport async function logout(options: LogoutOptions = {}): Promise<number> {\n const stored = readAuthData();\n\n if (!stored) {\n p.log.info('Not currently authenticated.');\n return 0;\n }\n\n const apiUrl = options.apiUrl ?? stored.apiUrl ?? 'https://vocoder.app';\n const api = new VocoderAPI({ apiUrl, apiKey: '' });\n\n try {\n await api.revokeCliToken(stored.token);\n } catch {\n // Ignore errors — we still clear local data even if the server call fails\n }\n\n clearAuthData();\n p.log.success(`Logged out (was ${stored.email})`);\n return 0;\n}\n","import * as p from '@clack/prompts';\n\nimport type {\n EffectiveSyncMode,\n ExtractedString,\n LimitErrorResponse,\n ProjectConfig,\n RequestedSyncMode,\n SyncPolicyConfig,\n TranslateOptions,\n TranslationStringEntry,\n} from '../types.js';\nimport { VocoderAPI, VocoderAPIError } from '../utils/api.js';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { detectBranch, isTargetBranch } from '../utils/branch.js';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { getMergedConfig, validateLocalConfig } from '../utils/config.js';\n\nimport { StringExtractor } from '../utils/extract.js';\nimport chalk from 'chalk';\nimport { join } from 'path';\nimport { resolveGitRepositoryIdentity } from '../utils/git-identity.js';\n\ntype LocaleMetadataMap = Record<string, { nativeName: string; dir?: 'rtl' }>;\ntype TranslationMap = Record<string, Record<string, string>>;\ntype TranslationArtifactSource = 'fresh' | 'local-cache' | 'api-snapshot';\n\ntype TranslationArtifacts = {\n source: TranslationArtifactSource;\n translations: TranslationMap;\n localeMetadata?: LocaleMetadataMap;\n snapshotBatchId?: string;\n completedAt?: string | null;\n cacheBranch?: string;\n};\n\ntype LocalSnapshotCache = {\n version: 1;\n branch: string;\n sourceLocale: string;\n targetLocales: string[];\n savedAt: string;\n snapshotBatchId?: string;\n completedAt?: string | null;\n localeMetadata?: LocaleMetadataMap;\n translations: TranslationMap;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseLocaleMetadata(value: unknown): LocaleMetadataMap | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n\n const metadata: LocaleMetadataMap = {};\n for (const [locale, rawValue] of Object.entries(value)) {\n if (!isRecord(rawValue)) {\n continue;\n }\n\n const nativeName = rawValue.nativeName;\n if (typeof nativeName !== 'string' || nativeName.trim().length === 0) {\n continue;\n }\n\n const entry: { nativeName: string; dir?: 'rtl' } = { nativeName };\n if (rawValue.dir === 'rtl') {\n entry.dir = 'rtl';\n }\n\n metadata[locale] = entry;\n }\n\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction parseTranslations(value: unknown): TranslationMap | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const translations: TranslationMap = {};\n\n for (const [locale, localeValue] of Object.entries(value)) {\n if (!isRecord(localeValue)) {\n continue;\n }\n\n const localeTranslations: Record<string, string> = {};\n for (const [source, translated] of Object.entries(localeValue)) {\n if (typeof translated === 'string') {\n localeTranslations[source] = translated;\n }\n }\n\n translations[locale] = localeTranslations;\n }\n\n return Object.keys(translations).length > 0 ? translations : null;\n}\n\nfunction getCacheFilePath(projectRoot: string, branch: string): string {\n const slug = branch\n .replace(/[^a-zA-Z0-9._-]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 40);\n const branchHash = createHash('sha1').update(branch).digest('hex').slice(0, 12);\n const filename = `${slug || 'branch'}-${branchHash}.json`;\n return join(projectRoot, 'node_modules', '.vocoder', 'cache', 'sync', filename);\n}\n\nfunction readLocalSnapshotCache(params: {\n projectRoot: string;\n branch: string;\n}): TranslationArtifacts | null {\n const candidateBranches = params.branch === 'main'\n ? ['main']\n : [params.branch, 'main'];\n\n for (const candidateBranch of candidateBranches) {\n const cacheFilePath = getCacheFilePath(params.projectRoot, candidateBranch);\n\n if (!existsSync(cacheFilePath)) {\n continue;\n }\n\n try {\n const raw = readFileSync(cacheFilePath, 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n if (!isRecord(parsed)) {\n continue;\n }\n\n const translations = parseTranslations(parsed.translations);\n if (!translations) {\n continue;\n }\n\n const localeMetadata = parseLocaleMetadata(parsed.localeMetadata);\n\n return {\n source: 'local-cache',\n translations,\n localeMetadata,\n snapshotBatchId:\n typeof parsed.snapshotBatchId === 'string'\n ? parsed.snapshotBatchId\n : undefined,\n completedAt:\n typeof parsed.completedAt === 'string' ? parsed.completedAt : null,\n cacheBranch: candidateBranch,\n };\n } catch {\n continue;\n }\n }\n\n return null;\n}\n\nfunction writeLocalSnapshotCache(params: {\n projectRoot: string;\n branch: string;\n sourceLocale: string;\n targetLocales: string[];\n translations: TranslationMap;\n localeMetadata?: LocaleMetadataMap;\n snapshotBatchId?: string;\n completedAt?: string | null;\n}): string {\n const cacheFilePath = getCacheFilePath(params.projectRoot, params.branch);\n mkdirSync(join(params.projectRoot, 'node_modules', '.vocoder', 'cache', 'sync'), {\n recursive: true,\n });\n\n const payload: LocalSnapshotCache = {\n version: 1,\n branch: params.branch,\n sourceLocale: params.sourceLocale,\n targetLocales: params.targetLocales,\n savedAt: new Date().toISOString(),\n ...(params.snapshotBatchId ? { snapshotBatchId: params.snapshotBatchId } : {}),\n ...(params.completedAt ? { completedAt: params.completedAt } : {}),\n ...(params.localeMetadata ? { localeMetadata: params.localeMetadata } : {}),\n translations: params.translations,\n };\n\n writeFileSync(cacheFilePath, JSON.stringify(payload, null, 2), 'utf-8');\n return cacheFilePath;\n}\n\nfunction resolveEffectiveModeFromPolicy(params: {\n branch: string;\n requestedMode: RequestedSyncMode;\n policy: SyncPolicyConfig;\n}): EffectiveSyncMode {\n const { requestedMode, policy, branch } = params;\n\n let mode: EffectiveSyncMode;\n if (requestedMode === 'auto') {\n const isBlockingBranch = isTargetBranch(branch, policy.blockingBranches);\n mode = isBlockingBranch ? policy.blockingMode : policy.nonBlockingMode;\n } else {\n mode = requestedMode;\n }\n\n return mode;\n}\n\nfunction resolveWaitTimeoutMs(params: {\n requestedMaxWaitMs?: number;\n policyDefaultMaxWaitMs?: number;\n fallbackTimeoutMs: number;\n}): number {\n if (\n typeof params.requestedMaxWaitMs === 'number' &&\n Number.isFinite(params.requestedMaxWaitMs) &&\n params.requestedMaxWaitMs > 0\n ) {\n return Math.floor(params.requestedMaxWaitMs);\n }\n\n if (\n typeof params.policyDefaultMaxWaitMs === 'number' &&\n Number.isFinite(params.policyDefaultMaxWaitMs) &&\n params.policyDefaultMaxWaitMs > 0\n ) {\n return Math.floor(params.policyDefaultMaxWaitMs);\n }\n\n return params.fallbackTimeoutMs;\n}\n\nfunction normalizeTranslations(params: {\n sourceLocale: string;\n targetLocales: string[];\n sourceStrings: string[];\n translations: TranslationMap;\n}): TranslationMap {\n const merged: TranslationMap = {};\n\n for (const [locale, values] of Object.entries(params.translations)) {\n merged[locale] = { ...values };\n }\n\n const expectedLocales = [\n params.sourceLocale,\n ...params.targetLocales.filter((locale) => locale !== params.sourceLocale),\n ];\n\n for (const locale of expectedLocales) {\n if (!merged[locale]) {\n merged[locale] = {};\n }\n }\n\n if (!merged[params.sourceLocale]) {\n merged[params.sourceLocale] = {};\n }\n\n for (const sourceText of params.sourceStrings) {\n if (!(sourceText in merged[params.sourceLocale]!)) {\n merged[params.sourceLocale]![sourceText] = sourceText;\n }\n }\n\n return merged;\n}\n\nexport function getLimitErrorGuidance(limitError: LimitErrorResponse): string[] {\n if (limitError.limitType === 'providers') {\n return [\n 'Provider setup required.',\n 'Add a DeepL API key in Dashboard -> Workspace Settings -> Providers.',\n `Open settings: ${limitError.upgradeUrl}`,\n ];\n }\n\n if (limitError.limitType === 'translation_chars') {\n return [\n 'Monthly translation character limit reached.',\n `Used this month: ${limitError.current.toLocaleString()} chars`,\n `Requested after sync: ${limitError.required.toLocaleString()} chars`,\n `Upgrade plan: ${limitError.upgradeUrl}`,\n ];\n }\n\n if (limitError.limitType === 'source_strings') {\n return [\n 'Active source string limit reached.',\n `Current active strings: ${limitError.current.toLocaleString()}`,\n `Required for this sync: ${limitError.required.toLocaleString()}`,\n `Upgrade plan: ${limitError.upgradeUrl}`,\n ];\n }\n\n return [\n `Plan: ${limitError.planId}`,\n `Current: ${limitError.current}`,\n `Required: ${limitError.required}`,\n `Upgrade: ${limitError.upgradeUrl}`,\n ];\n}\n\nfunction getSyncPolicyErrorGuidance(\n error: NonNullable<VocoderAPIError['syncPolicyError']>,\n): string[] {\n if (error.errorCode === 'BRANCH_NOT_ALLOWED') {\n const lines = ['This branch is not allowed for this project.'];\n if (error.branch) {\n lines.push(`Current branch: ${error.branch}`);\n }\n // targetBranches removed — configure branches in project settings\n lines.push('Update your project target branches in the dashboard if needed.');\n return lines;\n }\n\n const lines = ['This project is bound to a different repository.'];\n if (error.boundRepoLabel) {\n lines.push(`Bound repository: ${error.boundRepoLabel}`);\n }\n if (error.boundScopePath) {\n lines.push(`Bound scope: ${error.boundScopePath}`);\n }\n lines.push(\n 'Run `vocoder init` from the correct repository or create a separate project.',\n );\n return lines;\n}\n\nfunction mergeContext(\n current: string | undefined,\n incoming: string | undefined,\n): string | undefined {\n if (!incoming) return current;\n if (!current) return incoming;\n if (current === incoming) return current;\n\n const merged = new Set(\n [...current.split(' | '), ...incoming.split(' | ')]\n .map((part) => part.trim())\n .filter(Boolean),\n );\n return Array.from(merged).join(' | ');\n}\n\nfunction buildStringEntries(\n extractedStrings: ExtractedString[],\n): TranslationStringEntry[] {\n const byText = new Map<string, TranslationStringEntry>();\n\n for (const str of extractedStrings) {\n const existing = byText.get(str.text);\n if (!existing) {\n byText.set(str.text, {\n key: str.key,\n text: str.text,\n ...(str.context ? { context: str.context } : {}),\n ...(str.formality ? { formality: str.formality } : {}),\n });\n continue;\n }\n\n existing.context = mergeContext(existing.context, str.context);\n\n if (!existing.formality && str.formality) {\n existing.formality = str.formality;\n } else if (\n existing.formality &&\n str.formality &&\n existing.formality !== str.formality\n ) {\n existing.formality = 'auto';\n }\n\n if (str.key < existing.key) {\n existing.key = str.key;\n }\n }\n\n return Array.from(byText.values());\n}\n\nasync function fetchApiSnapshot(api: VocoderAPI, params: {\n branch: string;\n targetLocales: string[];\n}): Promise<TranslationArtifacts | null> {\n const snapshot = await api.getTranslationSnapshot({\n branch: params.branch,\n targetLocales: params.targetLocales,\n });\n\n if (snapshot.status !== 'FOUND' || !snapshot.translations) {\n return null;\n }\n\n return {\n source: 'api-snapshot',\n translations: snapshot.translations,\n localeMetadata: snapshot.localeMetadata,\n snapshotBatchId: snapshot.snapshotBatchId,\n completedAt: snapshot.completedAt,\n };\n}\n\n/**\n * Main sync command\n */\nexport async function sync(options: TranslateOptions = {}): Promise<number> {\n const startTime = Date.now();\n const projectRoot = process.cwd();\n\n p.intro('Vocoder Sync');\n\n const spinner = p.spinner();\n\n try {\n spinner.start('Detecting branch');\n const branch = detectBranch(options.branch);\n spinner.stop(`Branch: ${chalk.cyan(branch)}`);\n\n spinner.start('Loading project configuration');\n\n const mergedConfig = await getMergedConfig(options, options.verbose);\n const localConfig = {\n apiKey: mergedConfig.apiKey || '',\n apiUrl: mergedConfig.apiUrl || 'https://vocoder.app',\n };\n validateLocalConfig(localConfig);\n\n const api = new VocoderAPI(localConfig);\n const apiConfig = await api.getProjectConfig();\n\n const requestedMode = mergedConfig.mode;\n const waitTimeoutMs = resolveWaitTimeoutMs({\n requestedMaxWaitMs: mergedConfig.maxWaitMs,\n policyDefaultMaxWaitMs: apiConfig.syncPolicy.defaultMaxWaitMs,\n fallbackTimeoutMs: 60_000,\n });\n\n const config: ProjectConfig = {\n ...localConfig,\n ...apiConfig,\n extractionPattern: mergedConfig.extractionPattern,\n excludePattern: mergedConfig.excludePattern,\n timeout: waitTimeoutMs,\n };\n\n spinner.stop('Project configuration loaded');\n\n if (!options.force && !isTargetBranch(branch, config.targetBranches)) {\n p.log.warn(\n `Skipping translations (${chalk.cyan(branch)} is not a target branch)`,\n );\n p.log.info(`Target branches: ${config.targetBranches.join(', ')}`);\n p.log.info('Use --force to translate anyway');\n p.outro('');\n return 0;\n }\n\n const patternsDisplay = Array.isArray(config.extractionPattern)\n ? config.extractionPattern.join(', ')\n : config.extractionPattern;\n\n spinner.start(`Extracting strings from ${patternsDisplay}`);\n const extractor = new StringExtractor();\n const extractedStrings = await extractor.extractFromProject(\n config.extractionPattern,\n projectRoot,\n config.excludePattern,\n );\n\n if (extractedStrings.length === 0) {\n spinner.stop('No translatable strings found');\n p.log.warn('Make sure you are wrapping translatable strings with Vocoder');\n p.outro('');\n return 0;\n }\n\n spinner.stop(\n `Extracted ${chalk.cyan(extractedStrings.length)} strings from ${chalk.cyan(patternsDisplay)}`,\n );\n\n if (options.verbose) {\n const sampleLines = extractedStrings\n .slice(0, 5)\n .map((s: ExtractedString) => ` \"${s.text}\" (${s.file}:${s.line})`);\n if (extractedStrings.length > 5) {\n sampleLines.push(` ... and ${extractedStrings.length - 5} more`);\n }\n p.note(sampleLines.join('\\n'), 'Sample strings');\n }\n\n if (options.dryRun) {\n p.note(\n [\n `Strings: ${extractedStrings.length}`,\n `Branch: ${branch}`,\n `Target locales: ${config.targetLocales.join(', ')}`,\n `Requested mode: ${requestedMode}`,\n `Max wait: ${waitTimeoutMs}ms`,\n `No fallback: ${mergedConfig.noFallback ? 'yes' : 'no'}`,\n ].join('\\n'),\n 'Dry run - would translate',\n );\n p.outro('No API calls made.');\n return 0;\n }\n\n const repoIdentity = resolveGitRepositoryIdentity();\n if (!repoIdentity && options.verbose) {\n p.log.warn(\n 'Could not detect git remote origin. Sync will continue without repo metadata.',\n );\n }\n\n const stringEntries = buildStringEntries(extractedStrings);\n const sourceStrings = stringEntries.map((entry) => entry.text);\n\n if (options.verbose && stringEntries.length !== extractedStrings.length) {\n p.log.info(\n `Deduped ${extractedStrings.length} extracted entries into ${stringEntries.length} unique source strings`,\n );\n }\n\n spinner.start('Submitting strings to Vocoder API');\n\n const batchResponse = await api.submitTranslation(\n branch,\n stringEntries,\n config.targetLocales,\n {\n requestedMode,\n requestedMaxWaitMs: waitTimeoutMs,\n clientRunId: randomUUID(),\n },\n repoIdentity ?? undefined,\n );\n\n spinner.stop(`Submitted to API - Batch ${chalk.cyan(batchResponse.batchId)}`);\n\n const effectiveMode = batchResponse.effectiveMode ??\n resolveEffectiveModeFromPolicy({\n branch,\n requestedMode,\n policy: config.syncPolicy,\n });\n\n if (options.verbose) {\n p.log.info(`Requested mode: ${requestedMode}`);\n p.log.info(`Effective mode: ${effectiveMode}`);\n p.log.info(`Wait timeout: ${waitTimeoutMs}ms`);\n if (batchResponse.queueStatus) {\n p.log.info(`Queue status: ${batchResponse.queueStatus}`);\n }\n }\n\n if (batchResponse.status === 'UP_TO_DATE' && batchResponse.noChanges) {\n p.log.success('No changes detected - strings are up to date');\n }\n\n p.log.info(`New strings: ${chalk.cyan(batchResponse.newStrings)}`);\n\n if (batchResponse.deletedStrings && batchResponse.deletedStrings > 0) {\n p.log.info(\n `Deleted strings: ${chalk.yellow(batchResponse.deletedStrings)} (archived)`,\n );\n }\n\n p.log.info(`Total strings: ${chalk.cyan(batchResponse.totalStrings)}`);\n\n if (batchResponse.newStrings === 0) {\n p.log.success('No new strings - using existing translations');\n } else {\n p.log.info(\n `Syncing to ${config.targetLocales.length} locales (${config.targetLocales.join(', ')})`,\n );\n\n if (batchResponse.estimatedTime) {\n p.log.info(`Estimated time: ~${batchResponse.estimatedTime}s`);\n }\n }\n\n let artifacts: TranslationArtifacts | null = null;\n if (batchResponse.translations) {\n artifacts = {\n source: 'fresh',\n translations: batchResponse.translations,\n };\n }\n\n let waitError: Error | null = null;\n if (!artifacts && (effectiveMode === 'required' || effectiveMode === 'best-effort')) {\n spinner.start(`Waiting for translations (max ${waitTimeoutMs}ms)`);\n\n let lastProgress = 0;\n try {\n const completion = await api.waitForCompletion(\n batchResponse.batchId,\n waitTimeoutMs,\n (progress) => {\n const percent = Math.round(progress * 100);\n if (percent > lastProgress) {\n spinner.message(`Translating... ${percent}%`);\n lastProgress = percent;\n }\n },\n );\n\n artifacts = {\n source: 'fresh',\n translations: completion.translations,\n localeMetadata: completion.localeMetadata,\n };\n spinner.stop('Translations complete');\n } catch (error) {\n spinner.stop('Translation wait incomplete');\n waitError = error instanceof Error ? error : new Error(String(error));\n\n if (effectiveMode === 'required') {\n throw waitError;\n }\n\n p.log.warn(`Best-effort wait ended early: ${waitError.message}`);\n }\n }\n\n if (!artifacts) {\n if (mergedConfig.noFallback) {\n throw new Error(\n 'Fresh translations are not available and fallback is disabled (--no-fallback).',\n );\n }\n\n spinner.start('Loading fallback translations');\n\n const localFallback = readLocalSnapshotCache({\n projectRoot,\n branch,\n });\n\n if (localFallback) {\n artifacts = localFallback;\n const cacheBranchLabel =\n localFallback.cacheBranch && localFallback.cacheBranch !== branch\n ? `${localFallback.cacheBranch} fallback`\n : localFallback.cacheBranch || branch;\n spinner.stop(`Using local cached snapshot (${cacheBranchLabel})`);\n } else {\n try {\n const apiSnapshot = await fetchApiSnapshot(api, {\n branch,\n targetLocales: config.targetLocales,\n });\n\n if (apiSnapshot) {\n artifacts = apiSnapshot;\n spinner.stop('Using latest completed API snapshot');\n } else {\n spinner.stop('No completed API snapshot available');\n }\n } catch (error) {\n spinner.stop('Failed to fetch API snapshot');\n if (options.verbose) {\n const message =\n error instanceof Error ? error.message : 'Unknown snapshot fetch error';\n p.log.warn(`Snapshot fetch error: ${message}`);\n }\n }\n }\n\n if (!artifacts) {\n if (waitError) {\n throw new Error(\n `No fallback snapshot available after wait failure: ${waitError.message}`,\n );\n }\n\n throw new Error(\n 'No fallback snapshot available. Try again shortly or run with --mode required.',\n );\n }\n }\n\n const finalTranslations = normalizeTranslations({\n sourceLocale: config.sourceLocale,\n targetLocales: config.targetLocales,\n sourceStrings,\n translations: artifacts.translations,\n });\n\n try {\n const cachePath = writeLocalSnapshotCache({\n projectRoot,\n branch,\n sourceLocale: config.sourceLocale,\n targetLocales: config.targetLocales,\n translations: finalTranslations,\n localeMetadata: artifacts.localeMetadata,\n snapshotBatchId:\n artifacts.snapshotBatchId ??\n (artifacts.source === 'fresh'\n ? batchResponse.batchId\n : batchResponse.latestCompletedBatchId),\n completedAt:\n artifacts.completedAt ??\n (artifacts.source === 'fresh' ? new Date().toISOString() : null),\n });\n\n if (options.verbose) {\n p.log.info(`Cached snapshot: ${cachePath}`);\n }\n } catch (error) {\n if (options.verbose) {\n const message =\n error instanceof Error ? error.message : 'Unknown cache write error';\n p.log.warn(`Failed to write local snapshot cache: ${message}`);\n }\n }\n\n if (artifacts.source !== 'fresh') {\n const sourceLabel =\n artifacts.source === 'local-cache'\n ? 'local cached snapshot'\n : 'completed API snapshot';\n p.log.warn(\n `Using ${sourceLabel}. New strings may appear after the background sync completes.`,\n );\n }\n\n const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n p.outro(`Sync complete! (${duration}s)`);\n\n p.log.info('Translations will be injected at build time by @vocoder/unplugin.');\n p.log.info('Just use <VocoderProvider> and <T> — no manual imports needed.');\n return 0;\n } catch (error) {\n spinner.stop();\n\n if (error instanceof VocoderAPIError && error.syncPolicyError) {\n p.log.error(error.syncPolicyError.message);\n const guidance = getSyncPolicyErrorGuidance(error.syncPolicyError);\n for (const line of guidance) {\n p.log.info(line);\n }\n return 1;\n }\n\n if (error instanceof VocoderAPIError && error.limitError) {\n const { limitError } = error;\n p.log.error(limitError.message);\n const guidance = getLimitErrorGuidance(limitError);\n for (const line of guidance) {\n p.log.info(line);\n }\n return 1;\n }\n\n if (error instanceof Error) {\n p.log.error(error.message);\n\n if (error.message.includes('VOCODER_API_KEY')) {\n p.log.warn('VOCODER_API_KEY is only needed for `vocoder sync` (CLI push).');\n p.log.info(' Create one at: https://vocoder.app/dashboard');\n p.log.info(' Then: export VOCODER_API_KEY=\"vc_...\" or add it to .env');\n p.log.info('');\n p.log.info(' Note: If you use @vocoder/unplugin, `vocoder sync` is optional.');\n p.log.info(' Translations are fetched automatically at build time.');\n } else if (error.message.includes('git branch')) {\n p.log.warn('Run from a git repository, or use:');\n p.log.info(' vocoder sync --branch main');\n }\n\n if (options.verbose) {\n p.log.info(`Full error: ${error.stack ?? error}`);\n }\n }\n\n return 1;\n }\n}\n","import { execSync } from 'child_process';\n\nconst REGEX_SPECIAL_CHARS = /[.+?^${}()|[\\]\\\\]/g;\n\nfunction escapeRegexChar(value: string): string {\n return value.replace(REGEX_SPECIAL_CHARS, '\\\\$&');\n}\n\n/**\n * Detects the current git branch from multiple sources in priority order:\n * 1. Explicit --branch flag (passed as parameter)\n * 2. CI environment variables (GitHub Actions, Vercel, Netlify, etc.)\n * 3. Git command (local development)\n *\n * @param override - Optional branch name to override detection\n * @returns The current branch name\n */\nexport function detectBranch(override?: string): string {\n // 1. Explicit override (from --branch flag)\n if (override) {\n return override;\n }\n\n // 2. CI environment variables\n const envBranch =\n process.env.GITHUB_HEAD_REF || // GitHub Actions (PR source branch)\n process.env.GITHUB_REF_NAME || // GitHub Actions (push)\n process.env.VERCEL_GIT_COMMIT_REF || // Vercel\n process.env.BRANCH || // Netlify\n process.env.CF_PAGES_BRANCH || // Cloudflare Pages\n process.env.CI_COMMIT_REF_NAME || // GitLab CI\n process.env.BITBUCKET_BRANCH || // Bitbucket Pipelines\n process.env.CIRCLE_BRANCH || // CircleCI\n process.env.RENDER_GIT_BRANCH; // Render\n\n if (envBranch) {\n return envBranch;\n }\n\n // 3. Git command (local development)\n try {\n const branch = execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'ignore'],\n }).trim();\n\n return branch;\n } catch (error) {\n throw new Error(\n 'Failed to detect git branch. Make sure you are in a git repository or set the --branch flag.',\n );\n }\n}\n\n/**\n * Checks if the current branch is a target branch that should trigger translations\n *\n * @param currentBranch - The current branch name\n * @param targetBranches - List of branches that should trigger translations\n * @returns True if the branch should trigger translations\n */\nexport function isTargetBranch(\n currentBranch: string,\n targetBranches: string[],\n): boolean {\n return targetBranches.some((pattern) =>\n matchBranchPattern(currentBranch, pattern),\n );\n}\n\nexport function matchBranchPattern(branch: string, pattern: string): boolean {\n const trimmedPattern = pattern.trim();\n if (!trimmedPattern) {\n return false;\n }\n\n let regexSource = '^';\n for (let i = 0; i < trimmedPattern.length; i += 1) {\n const char = trimmedPattern[i];\n if (!char) {\n continue;\n }\n\n if (char === '*') {\n const next = trimmedPattern[i + 1];\n if (next === '*') {\n regexSource += '.*';\n i += 1;\n } else {\n regexSource += '[^/]*';\n }\n continue;\n }\n\n regexSource += escapeRegexChar(char);\n }\n regexSource += '$';\n\n return new RegExp(regexSource).test(branch);\n}\n","import type { LocalConfig, RequestedSyncMode, TranslateOptions } from '../types.js';\n\nimport chalk from 'chalk';\nimport { config as loadEnv } from 'dotenv';\n\n// Load .env file if present\nloadEnv();\n\n/**\n * Validates the local configuration\n */\nexport function validateLocalConfig(config: LocalConfig): void {\n if (!config.apiKey || config.apiKey.length === 0) {\n throw new Error('VOCODER_API_KEY is required. Set it in your .env file.');\n }\n\n if (!config.apiKey.startsWith('vc_')) {\n throw new Error('Invalid API key format. Expected format: vc_...');\n }\n\n if (!config.apiUrl || !config.apiUrl.startsWith('http')) {\n throw new Error('Invalid API URL');\n }\n}\n\n/**\n * Merge configuration from all sources with priority:\n * 1. CLI flags (highest priority)\n * 2. Environment variables\n * 3. Defaults (lowest priority)\n *\n * @param cliOptions - Options from CLI flags\n * @param verbose - Whether to log config sources\n * @returns Merged configuration with source information\n */\nexport async function getMergedConfig(\n cliOptions: TranslateOptions,\n verbose: boolean = false,\n _startDir?: string\n): Promise<{\n extractionPattern: string[];\n excludePattern: string[];\n apiKey?: string;\n apiUrl?: string;\n mode: RequestedSyncMode;\n maxWaitMs?: number;\n noFallback: boolean;\n configSources: {\n extractionPattern: string;\n excludePattern: string;\n apiKey: string;\n apiUrl: string;\n mode: string;\n maxWaitMs: string;\n noFallback: string;\n };\n}> {\n const configSources = {\n extractionPattern: 'default',\n excludePattern: 'default',\n apiKey: 'environment',\n apiUrl: 'default',\n mode: 'default',\n maxWaitMs: 'default',\n noFallback: 'default',\n };\n\n // 1. Defaults\n const defaults = {\n extractionPattern: ['src/**/*.{tsx,jsx,ts,js}'],\n excludePattern: [] as string[],\n apiUrl: 'https://vocoder.app',\n };\n\n // 2. Environment variables\n const envExtractionPattern = process.env.VOCODER_EXTRACTION_PATTERN;\n const envApiUrl = process.env.VOCODER_API_URL;\n const envSyncMode = process.env.VOCODER_SYNC_MODE;\n const envSyncMaxWaitMs = process.env.VOCODER_SYNC_MAX_WAIT_MS;\n const envSyncNoFallback = process.env.VOCODER_SYNC_NO_FALLBACK;\n\n // 3. Merge with priority: CLI > env > defaults\n\n // Extract patterns (include)\n let extractionPattern: string[];\n if (cliOptions.include && cliOptions.include.length > 0) {\n extractionPattern = cliOptions.include;\n configSources.extractionPattern = 'CLI flag';\n } else if (envExtractionPattern) {\n extractionPattern = [envExtractionPattern];\n configSources.extractionPattern = 'environment';\n } else {\n extractionPattern = defaults.extractionPattern;\n }\n\n // Exclude patterns\n let excludePattern: string[];\n if (cliOptions.exclude && cliOptions.exclude.length > 0) {\n excludePattern = cliOptions.exclude;\n configSources.excludePattern = 'CLI flag';\n } else {\n excludePattern = defaults.excludePattern;\n }\n\n // API key (from env)\n let apiKey: string | undefined;\n if (process.env.VOCODER_API_KEY) {\n apiKey = process.env.VOCODER_API_KEY;\n configSources.apiKey = 'environment';\n }\n\n // API URL\n let apiUrl: string;\n if (envApiUrl) {\n apiUrl = envApiUrl;\n configSources.apiUrl = 'environment';\n } else {\n apiUrl = defaults.apiUrl;\n }\n\n const modeCandidates = ['auto', 'required', 'best-effort'] as const;\n let mode: RequestedSyncMode = 'auto';\n if (cliOptions.mode && modeCandidates.includes(cliOptions.mode)) {\n mode = cliOptions.mode;\n configSources.mode = 'CLI flag';\n } else if (envSyncMode && modeCandidates.includes(envSyncMode as RequestedSyncMode)) {\n mode = envSyncMode as RequestedSyncMode;\n configSources.mode = 'environment';\n }\n\n let maxWaitMs: number | undefined;\n if (typeof cliOptions.maxWaitMs === 'number' && Number.isFinite(cliOptions.maxWaitMs) && cliOptions.maxWaitMs > 0) {\n maxWaitMs = Math.floor(cliOptions.maxWaitMs);\n configSources.maxWaitMs = 'CLI flag';\n } else if (envSyncMaxWaitMs) {\n const parsed = Number.parseInt(envSyncMaxWaitMs, 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n maxWaitMs = parsed;\n configSources.maxWaitMs = 'environment';\n }\n }\n\n let noFallback = false;\n if (typeof cliOptions.noFallback === 'boolean') {\n noFallback = cliOptions.noFallback;\n configSources.noFallback = 'CLI flag';\n } else if (envSyncNoFallback) {\n noFallback = ['1', 'true', 'yes', 'on'].includes(envSyncNoFallback.toLowerCase());\n configSources.noFallback = 'environment';\n }\n\n // Log config sources in verbose mode\n if (verbose) {\n console.log(chalk.dim('\\n Configuration sources:'));\n console.log(chalk.dim(` Include patterns: ${configSources.extractionPattern}`));\n if (excludePattern.length > 0) {\n console.log(chalk.dim(` Exclude patterns: ${configSources.excludePattern}`));\n }\n console.log(chalk.dim(` API key: ${configSources.apiKey}`));\n console.log(chalk.dim(` API URL: ${configSources.apiUrl}\\n`));\n console.log(chalk.dim(` Sync mode: ${configSources.mode}`));\n if (maxWaitMs) {\n console.log(chalk.dim(` Max wait: ${configSources.maxWaitMs}`));\n }\n console.log(chalk.dim(` No fallback: ${configSources.noFallback}\\n`));\n }\n\n return {\n extractionPattern,\n excludePattern,\n apiKey,\n apiUrl,\n mode,\n maxWaitMs,\n noFallback,\n configSources,\n };\n}\n","import * as p from '@clack/prompts';\nimport chalk from 'chalk';\nimport { VocoderAPI } from '../utils/api.js';\nimport { readAuthData } from '../utils/auth-store.js';\n\nexport interface WhoamiOptions {\n apiUrl?: string;\n}\n\nexport async function whoami(options: WhoamiOptions = {}): Promise<number> {\n const stored = readAuthData();\n\n if (!stored) {\n p.log.info('Not logged in. Run `vocoder init` to authenticate.');\n return 1;\n }\n\n const apiUrl = options.apiUrl ?? stored.apiUrl ?? 'https://vocoder.app';\n const api = new VocoderAPI({ apiUrl, apiKey: '' });\n\n try {\n const info = await api.getCliUserInfo(stored.token);\n p.log.info(`Logged in as ${chalk.bold(info.email)}`);\n if (info.name) {\n p.log.info(`Name: ${info.name}`);\n }\n p.log.info(`API: ${apiUrl}`);\n return 0;\n } catch {\n p.log.error('Stored credentials are invalid or expired. Run `vocoder init` to re-authenticate.');\n return 1;\n }\n}\n"],"mappings":"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","names":["p","URL","resolve","resolve","init","text","resolve","chalk","execSync","p","chalk","isCancel","p","chalk","Prompt","isCancel","chalk","execSync","S_BAR","S_BAR_END","S_ACTIVE","S_SUBMIT","S_CANCEL","S_ERROR","noColor","dim","cyan","grn","ylw","red","bld","symbol","MAX_VISIBLE","buildList","MAX_VISIBLE","grn","dim","bld","cyan","S_BAR","ylw","Prompt","symbol","S_BAR_END","isCancel","chalk","p","chalk","spawn","resolve","tryOpenBrowser","spawn","chalk","execSync","options","p","p","execSync","mkdirSync","readFileSync","writeFileSync","chalk","loadEnv","chalk","join","join","readFileSync","mkdirSync","writeFileSync","lines","spinner","chalk","p","chalk","chalk"]}
|