import { defineCommand } from "citty"; import { apiRequest, type ApiRequestInit } from "../lib/api"; import { toTable } from "../lib/format"; export type OperationsApiRequest = ( path: string, init?: ApiRequestInit, ) => Promise; type Operation = { metadata: { name: string; creationTimestamp: string }; spec: { workspaceId: string; action: string }; status: { state: string; startedAt?: string; finishedAt?: string; result?: unknown; error?: { code: string; message: string }; }; }; function operationPath(workspace?: string): string { return workspace ? `/operations?${new URLSearchParams({ workspaceId: workspace })}` : "/operations"; } function renderOperations(items: Operation[]): string { if (items.length === 0) return "No operations"; return toTable( items.map((operation) => ({ id: operation.metadata.name, workspace: operation.spec.workspaceId, action: operation.spec.action, state: operation.status.state, created: operation.metadata.creationTimestamp, finished: operation.status.finishedAt, })), ); } export async function listOperations( workspace?: string, request: OperationsApiRequest = apiRequest, ): Promise { const response = await request<{ items: Operation[] }>( operationPath(workspace), ); return renderOperations(response.items); } export async function getOperation( id: string, request: OperationsApiRequest = apiRequest, ): Promise { const operation = await request( `/operations/${encodeURIComponent(id)}`, ); const output = [renderOperations([operation])]; if (operation.status.error) { output.push( `Error: ${operation.status.error.code}: ${operation.status.error.message}`, ); } if (operation.status.result !== undefined) { output.push(`Result: ${JSON.stringify(operation.status.result)}`); } return output.join("\n"); } const list = defineCommand({ meta: { name: "ls", description: "List operations" }, args: { workspace: { type: "string", alias: "w", description: "Filter by workspace", }, }, async run({ args }) { console.log(await listOperations(args.workspace ?? args._[0])); }, }); const get = defineCommand({ meta: { name: "get", description: "Get an operation" }, async run({ args }) { const id = String(args._[0] ?? "").trim(); if (!id) throw new Error("Operation ID is required"); console.log(await getOperation(id)); }, }); export const operations = defineCommand({ meta: { name: "operations", description: "Inspect server operations" }, subCommands: { get, ls: list }, });