98 lines
2.6 KiB
TypeScript
98 lines
2.6 KiB
TypeScript
import { defineCommand } from "citty";
|
|
import { apiRequest, type ApiRequestInit } from "../lib/api";
|
|
import { toTable } from "../lib/format";
|
|
|
|
export type OperationsApiRequest = <T>(
|
|
path: string,
|
|
init?: ApiRequestInit,
|
|
) => Promise<T>;
|
|
|
|
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<string> {
|
|
const response = await request<{ items: Operation[] }>(
|
|
operationPath(workspace),
|
|
);
|
|
return renderOperations(response.items);
|
|
}
|
|
|
|
export async function getOperation(
|
|
id: string,
|
|
request: OperationsApiRequest = apiRequest,
|
|
): Promise<string> {
|
|
const operation = await request<Operation>(
|
|
`/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 },
|
|
});
|