import { invokeTauri } from "@/shared/api/tauri"; import type { ApprovalActionResponse, TriggerWorkflowResponse, Workflow, WorkflowApproval, WorkflowRun, WorkflowSaveResult, TraceEntry, } from "@/shared/api/types"; // ── Raw types (snake_case from backend) ─────────────────────────────────── type RawWorkflow = { id: string; name: string; owner_pubkey: string; channel_id: string | null; definition: Record; status: Workflow["status"]; created_at: number; updated_at: number; }; type RawWorkflowSaveResponse = RawWorkflow & { webhook_secret?: string | null; }; type RawTraceEntry = { step_id: string; status: string; output?: Record; started_at?: number | null; completed_at?: number | null; error?: string | null; }; type RawWorkflowRun = { id: string; workflow_id: string; status: WorkflowRun["status"]; current_step: number | null; execution_trace: RawTraceEntry[]; started_at: number | null; completed_at: number | null; error_message: string | null; created_at: number; }; type RawWorkflowApproval = { token: string; workflow_id: string; run_id: string; step_id: string; step_index: number; approver_spec: string; status: WorkflowApproval["status"]; approver_pubkey: string | null; note: string | null; expires_at: string; created_at: number; }; type RawTriggerWorkflowResponse = { run_id: string; workflow_id: string; status: string; }; type RawApprovalActionResponse = { token: string; status: string; run_id: string; workflow_id: string; }; // ── Conversion functions ────────────────────────────────────────────────── function fromRawWorkflow(raw: RawWorkflow): Workflow { return { id: raw.id, name: raw.name, ownerPubkey: raw.owner_pubkey, channelId: raw.channel_id, definition: raw.definition, status: raw.status, createdAt: raw.created_at, updatedAt: raw.updated_at, }; } function fromRawWorkflowSave(raw: RawWorkflowSaveResponse): WorkflowSaveResult { return { workflow: fromRawWorkflow(raw), webhookSecret: raw.webhook_secret ?? null, }; } function fromRawTraceEntry(raw: RawTraceEntry): TraceEntry { return { stepId: raw.step_id, status: raw.status, output: raw.output ?? {}, startedAt: raw.started_at ?? null, completedAt: raw.completed_at ?? null, error: raw.error ?? null, }; } function fromRawWorkflowRun(raw: RawWorkflowRun): WorkflowRun { return { id: raw.id, workflowId: raw.workflow_id, status: raw.status, currentStep: raw.current_step, executionTrace: raw.execution_trace.map(fromRawTraceEntry), startedAt: raw.started_at, completedAt: raw.completed_at, errorMessage: raw.error_message, createdAt: raw.created_at, }; } export function fromRawApproval(raw: RawWorkflowApproval): WorkflowApproval { return { token: raw.token, workflowId: raw.workflow_id, runId: raw.run_id, stepId: raw.step_id, stepIndex: raw.step_index, approverSpec: raw.approver_spec, status: raw.status, approverPubkey: raw.approver_pubkey, note: raw.note, expiresAt: raw.expires_at, createdAt: raw.created_at, }; } function fromRawTriggerResponse( raw: RawTriggerWorkflowResponse, ): TriggerWorkflowResponse { return { runId: raw.run_id, workflowId: raw.workflow_id, status: raw.status, }; } function fromRawApprovalResponse( raw: RawApprovalActionResponse, ): ApprovalActionResponse { return { token: raw.token, status: raw.status, runId: raw.run_id, workflowId: raw.workflow_id, }; } // ── Tauri invoke wrappers ───────────────────────────────────────────────── export async function getChannelWorkflows( channelId: string, ): Promise { const raw = await invokeTauri("get_channel_workflows", { channelId, }); return raw.map(fromRawWorkflow); } /** * Fetch workflows across many channels in a single relay round-trip. * * Replaces the per-channel `Promise.all(getChannelWorkflows)` fanout on the * Workflows overview: the backend `#h` filter matches any listed channel, and * each returned workflow carries its own `channelId` so callers can group. */ export async function getChannelsWorkflows( channelIds: string[], ): Promise { const raw = await invokeTauri("get_channels_workflows", { channelIds, }); return raw.map(fromRawWorkflow); } export async function getWorkflow(workflowId: string): Promise { const raw = await invokeTauri("get_workflow", { workflowId }); return fromRawWorkflow(raw); } export async function createWorkflow( channelId: string, yamlDefinition: string, ): Promise { const raw = await invokeTauri("create_workflow", { channelId, yamlDefinition, }); return fromRawWorkflowSave(raw); } export async function updateWorkflow( workflowId: string, yamlDefinition: string, ): Promise { const raw = await invokeTauri("update_workflow", { workflowId, yamlDefinition, }); return fromRawWorkflowSave(raw); } export async function deleteWorkflow(workflowId: string): Promise { await invokeTauri("delete_workflow", { workflowId }); } export async function getWorkflowRuns( workflowId: string, limit?: number, ): Promise { const raw = await invokeTauri("get_workflow_runs", { workflowId, limit: limit ?? null, }); return raw.map(fromRawWorkflowRun); } export async function getRunApprovals( workflowId: string, runId: string, ): Promise { const raw = await invokeTauri("get_run_approvals", { workflowId, runId, }); return raw.map(fromRawApproval); } export async function triggerWorkflow( workflowId: string, ): Promise { const raw = await invokeTauri( "trigger_workflow", { workflowId }, ); return fromRawTriggerResponse(raw); } export async function grantApproval( token: string, note?: string, ): Promise { const raw = await invokeTauri("grant_approval", { token, note: note ?? null, }); return fromRawApprovalResponse(raw); } export async function denyApproval( token: string, note?: string, ): Promise { const raw = await invokeTauri("deny_approval", { token, note: note ?? null, }); return fromRawApprovalResponse(raw); }