import type { CommandContext } from "@stricli/core"; import { buildApplication, buildCommand, buildRouteMap } from "@stricli/core"; import type { PapyrusClient } from "../client.ts"; import { runStricliToString } from "./stricli-run.ts"; type GraphProjectionClient = Pick; interface GraphProjectionContext extends CommandContext { readonly client: GraphProjectionClient; readonly json: boolean; } function parseBatchJson(value: string): Record { const parsed = JSON.parse(value) as unknown; if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("--batch-json must be a JSON object"); return parsed as Record; } const applyCommand = buildCommand({ func: async function (this: GraphProjectionContext, flags: { batchJson: Record }) { const result = await this.client.call, unknown>("graph_projection.apply", flags.batchJson); this.process.stdout.write(this.json ? JSON.stringify(result) : JSON.stringify(result, null, 2)); }, parameters: { flags: { batchJson: { brief: "JSON-encoded projection batch to apply", kind: "parsed", parse: parseBatchJson, placeholder: "json", }, }, }, docs: { brief: "Apply a projection batch", }, }); const checkpointCommand = buildCommand({ func: async function (this: GraphProjectionContext, flags: { producerId: string }) { const result = await this.client.call, unknown>("graph_projection.checkpoint", { producer_id: flags.producerId, }); if (this.json) { this.process.stdout.write(JSON.stringify(result)); return; } this.process.stdout.write( result === null ? `No projection checkpoint for producer "${flags.producerId}".` : JSON.stringify(result, null, 2), ); }, parameters: { flags: { producerId: { brief: "Producer id to look up the checkpoint for", kind: "parsed", parse: String, placeholder: "id", }, }, }, docs: { brief: "Look up a producer's projection checkpoint", }, }); const app = buildApplication( buildRouteMap({ routes: { apply: applyCommand, checkpoint: checkpointCommand }, docs: { brief: "Graph projection operations" }, }), { name: "graph-projection", scanner: { caseStyle: "allow-kebab-for-camel" } }, ); export async function runGraphProjectionCli(args: string[], client: GraphProjectionClient): Promise { const json = args.includes("--json"); const positional = args.filter((arg) => arg !== "--json"); return runStricliToString(app, positional, { client, json }); }