fix(web): use local workflow response types

The workflow routes were importing types that do not exist in the generated
OpenAPI client. Define the workflow endpoint response shapes locally so the
web app typechecks against the actual server responses.
This commit is contained in:
Bryan Helmkamp 2026-04-07 14:48:19 -04:00
parent 3dcf2ad04b
commit 888370cddc
No known key found for this signature in database
4 changed files with 39 additions and 5 deletions

View file

@ -0,0 +1,32 @@
import type { PaginationMeta, RunSettings } from "@qltysh/fabro-api-client";
export interface WorkflowScheduleSummary {
expression: string;
next_run?: string | null;
}
export interface WorkflowLastRunSummary {
ran_at?: string | null;
}
export interface WorkflowListItem {
name: string;
slug: string;
filename: string;
last_run?: WorkflowLastRunSummary | null;
schedule?: WorkflowScheduleSummary | null;
}
export interface PaginatedWorkflowListResponse {
data: WorkflowListItem[];
pagination?: PaginationMeta;
}
export interface WorkflowDetailResponse {
name: string;
slug: string;
description: string;
filename: string;
settings: RunSettings;
graph: string;
}

View file

@ -7,7 +7,8 @@ import { useTheme } from "../lib/theme";
import { getGraphTheme } from "../lib/graph-theme";
import { apiJson } from "../api";
import { formatDurationSecs } from "../lib/format";
import type { PaginatedRunStageList, PaginatedRunList, WorkflowDetail } from "@qltysh/fabro-api-client";
import type { PaginatedRunStageList, PaginatedRunList } from "@qltysh/fabro-api-client";
import type { WorkflowDetailResponse } from "../lib/workflow-api";
export const handle = { wide: true };
@ -35,7 +36,7 @@ export async function loader({ request, params }: any) {
let graphDot: string | null = null;
if (run) {
try {
const workflow = await apiJson<WorkflowDetail>(`/workflows/${run.workflow}`, { request });
const workflow = await apiJson<WorkflowDetailResponse>(`/workflows/${run.workflow}`, { request });
graphDot = workflow.graph;
} catch {
// workflow not found — leave graphDot null

View file

@ -1,7 +1,8 @@
import { ChevronRightIcon } from "@heroicons/react/20/solid";
import { Link, Outlet, useLocation, useParams } from "react-router";
import { apiJson } from "../api";
import type { WorkflowDetail as ApiWorkflowDetail, RunSettings } from "@qltysh/fabro-api-client";
import type { RunSettings } from "@qltysh/fabro-api-client";
import type { WorkflowDetailResponse as ApiWorkflowDetail } from "../lib/workflow-api";
export interface WorkflowEntry {
name: string;

View file

@ -15,7 +15,7 @@ import {
import { Link } from "react-router";
import { apiJson } from "../api";
import { timeAgo, timeUntil } from "../lib/time";
import type { PaginatedWorkflowList } from "@qltysh/fabro-api-client";
import type { PaginatedWorkflowListResponse } from "../lib/workflow-api";
export function meta({}: any) {
return [{ title: "Workflows — Fabro" }];
@ -105,7 +105,7 @@ interface WorkflowData {
}
export async function loader({ request }: any) {
const { data: apiWorkflows } = await apiJson<PaginatedWorkflowList>("/workflows", { request });
const { data: apiWorkflows } = await apiJson<PaginatedWorkflowListResponse>("/workflows", { request });
const workflows: WorkflowData[] = apiWorkflows.map((w) => ({
name: w.name,
slug: w.slug,