feat: v2
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
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 },
|
||||
});
|
||||
Reference in New Issue
Block a user