import { $ } from "bun"; /** * Get the Cloudflare account ID from wrangler whoami */ export async function getAccountId(): Promise { const result = await $`wrangler whoami`.quiet(); if (result.exitCode !== 0) { throw new Error("Failed to get account ID. Are you authenticated?"); } const output = result.stdout.toString(); // wrangler whoami outputs a table like: // │ Account Name │ 26927580508a6da4ea3169bdc5c23418 │ const match = output.match(/│[^│]+│\s*([a-f0-9]{32})\s*│/); if (!match?.[1]) { throw new Error("Could not parse account ID from wrangler whoami"); } return match[1]; } /** * Check if a worker exists by attempting to list its deployments */ export async function checkWorkerExists(name: string): Promise { const result = await $`wrangler deployments list --name ${name}`.nothrow().quiet(); return result.exitCode === 0; } /** * Delete a worker with force flag (no confirmation) */ export async function deleteWorker(name: string): Promise { const result = await $`wrangler delete --name ${name} --force`.nothrow().quiet(); if (result.exitCode !== 0) { const stderr = result.stderr.toString().trim(); throw new Error(stderr || `Failed to delete worker ${name}`); } } /** * Export a D1 database to a SQL file */ export async function exportDatabase(dbName: string, outputPath: string): Promise { const result = await $`wrangler d1 export ${dbName} --output ${outputPath}`.nothrow().quiet(); if (result.exitCode !== 0) { throw new Error(`Failed to export database ${dbName} to ${outputPath}`); } } /** * Delete a D1 database without confirmation */ export async function deleteDatabase(dbName: string): Promise { const result = await $`wrangler d1 delete ${dbName} --skip-confirmation`.nothrow().quiet(); if (result.exitCode !== 0) { throw new Error(`Failed to delete database ${dbName}`); } } /** * List D1 databases for the current account */ export async function listD1Databases(): Promise> { const result = await $`wrangler d1 list --json`.nothrow().quiet(); if (result.exitCode !== 0) { const stderr = result.stderr.toString().trim(); throw new Error(stderr || "Failed to list D1 databases"); } try { const output = result.stdout.toString().trim(); const parsed = JSON.parse(output); if (Array.isArray(parsed)) return parsed; if (Array.isArray(parsed?.result)) return parsed.result; if (Array.isArray(parsed?.databases)) return parsed.databases; } catch { // Fall through to empty list } return []; } /** * List all workers for the current account * Parses the output of `wrangler deployments list` to extract worker names */ export async function listWorkers(): Promise { const result = await $`wrangler deployments list`.nothrow().quiet(); if (result.exitCode !== 0) { throw new Error("Failed to list workers"); } const output = result.stdout.toString(); const workers: string[] = []; // Parse the table output to extract worker names // Format is typically: │ Worker Name │ ... const lines = output.split("\n"); for (const line of lines) { // Match worker name from table rows (not headers or separators) const match = line.match(/│\s*([a-zA-Z0-9_-]+)\s*│/); if (match?.[1] && !match[1].match(/^(Worker|Name|─+)$/i)) { workers.push(match[1]); } } return workers; }