mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Signed-off-by: Tyler Longwell <tlongwell@block.xyz> Co-authored-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Tyler Longwell <tlongwell@block.xyz> Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1cc3ha7z055mu0rwwu7806t2wt8mj3pvu0uv5mfp2c50dahaqhczshdalg6 <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1jmc9dt2lyvzu3h0kxlwxt5zg4fxp9476awyxw6gwxn72g6cw7exqs64whm <96f056ad5f2305c8ddf637dc65d048aa4c12d7daeb8867690e34fca46b0ef64c@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
272 lines
6.8 KiB
TypeScript
272 lines
6.8 KiB
TypeScript
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<string, unknown>;
|
|
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<string, unknown>;
|
|
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<Workflow[]> {
|
|
const raw = await invokeTauri<RawWorkflow[]>("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<Workflow[]> {
|
|
const raw = await invokeTauri<RawWorkflow[]>("get_channels_workflows", {
|
|
channelIds,
|
|
});
|
|
return raw.map(fromRawWorkflow);
|
|
}
|
|
|
|
export async function getWorkflow(workflowId: string): Promise<Workflow> {
|
|
const raw = await invokeTauri<RawWorkflow>("get_workflow", { workflowId });
|
|
return fromRawWorkflow(raw);
|
|
}
|
|
|
|
export async function createWorkflow(
|
|
channelId: string,
|
|
yamlDefinition: string,
|
|
): Promise<WorkflowSaveResult> {
|
|
const raw = await invokeTauri<RawWorkflowSaveResponse>("create_workflow", {
|
|
channelId,
|
|
yamlDefinition,
|
|
});
|
|
return fromRawWorkflowSave(raw);
|
|
}
|
|
|
|
export async function updateWorkflow(
|
|
workflowId: string,
|
|
yamlDefinition: string,
|
|
): Promise<WorkflowSaveResult> {
|
|
const raw = await invokeTauri<RawWorkflowSaveResponse>("update_workflow", {
|
|
workflowId,
|
|
yamlDefinition,
|
|
});
|
|
return fromRawWorkflowSave(raw);
|
|
}
|
|
|
|
export async function deleteWorkflow(workflowId: string): Promise<void> {
|
|
await invokeTauri("delete_workflow", { workflowId });
|
|
}
|
|
|
|
export async function getWorkflowRuns(
|
|
workflowId: string,
|
|
limit?: number,
|
|
): Promise<WorkflowRun[]> {
|
|
const raw = await invokeTauri<RawWorkflowRun[]>("get_workflow_runs", {
|
|
workflowId,
|
|
limit: limit ?? null,
|
|
});
|
|
return raw.map(fromRawWorkflowRun);
|
|
}
|
|
|
|
export async function getRunApprovals(
|
|
workflowId: string,
|
|
runId: string,
|
|
): Promise<WorkflowApproval[]> {
|
|
const raw = await invokeTauri<RawWorkflowApproval[]>("get_run_approvals", {
|
|
workflowId,
|
|
runId,
|
|
});
|
|
return raw.map(fromRawApproval);
|
|
}
|
|
|
|
export async function triggerWorkflow(
|
|
workflowId: string,
|
|
): Promise<TriggerWorkflowResponse> {
|
|
const raw = await invokeTauri<RawTriggerWorkflowResponse>(
|
|
"trigger_workflow",
|
|
{ workflowId },
|
|
);
|
|
return fromRawTriggerResponse(raw);
|
|
}
|
|
|
|
export async function grantApproval(
|
|
token: string,
|
|
note?: string,
|
|
): Promise<ApprovalActionResponse> {
|
|
const raw = await invokeTauri<RawApprovalActionResponse>("grant_approval", {
|
|
token,
|
|
note: note ?? null,
|
|
});
|
|
return fromRawApprovalResponse(raw);
|
|
}
|
|
|
|
export async function denyApproval(
|
|
token: string,
|
|
note?: string,
|
|
): Promise<ApprovalActionResponse> {
|
|
const raw = await invokeTauri<RawApprovalActionResponse>("deny_approval", {
|
|
token,
|
|
note: note ?? null,
|
|
});
|
|
return fromRawApprovalResponse(raw);
|
|
}
|