Files
formbricks/apps/web/modules/workflows/lib/api-client.ts
T
Javi Aguilar d3c04876bf Squashed commit of the following:
commit 0ab6c07139dc603749e9d07dc971dac9800c0c75
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 20:36:56 2026 +0200

    fix to stop running pnpm install when dev server stops

commit c5bf0f30b3d2b44607b9be3e79f343463f7302ce
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 20:17:50 2026 +0200

    docs(workbench): emphasize token-efficient context gathering

commit e0bd91b3b8f65ec03e8c29d57fd66163bce01493
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 20:15:57 2026 +0200

    chore(workbench): add review gates, validator, and rename skills

    - Add human review gate lines to milestones, plans, templates, and require completion before downstream work.
    - Add workbench/scripts/validate-workbench.mjs to check structure, required sections, links, review gates, and placeholders.
    - Rename create-milestone, create-plan, document-decision, and generate-changelog skills under a workbench- prefix and symlink skills/ into .claude, .codex, and .cursor.
    - Update AGENTS.md, GUIDE.md, README.md, and checkpoints with review-gate rules, validator usage, and checkpoint proportionality guidance.

commit 370ade8fdaab98778f1ceb499ec604270c0d156d
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 19:48:12 2026 +0200

    chore: improve workflow dir structure and add skills

commit ab1f17004f1d60c91ae9f1618f360864dca36cb4
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 18:38:44 2026 +0200

    feat(workflows): add workspace runs page, create-workflow dialog,  improve loading states

    - Add /workspaces/[id]/workflows/runs page listing runs across all
      workflows, backed by new GET /api/v3/workflows/runs endpoint.
    - Replace inline "new workflow" action with a dialog capturing name and
      optional description; persist description on Workflow model and v3
      API.
    - Add loading skeletons for workflow list, builder, and runs pages, and
      a Beta badge in the main navigation workflows group.

commit c16872f7f59983a8fb04ce8d1704016c8d0d69f2
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 05:35:31 2026 +0200

    fix(a11y): avoid layout shift with loading button state

commit 872c8ecdfbf0ba5db4beea3e383731f791b06520
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 05:35:08 2026 +0200

    feat(workflows): polish builder/list and rename "active" to "enabled"

    - Rename WorkflowStatus enum value from "active" to "enabled" across DB, schema, types, API, and locales.
    - Extract workflow builder editor state to Jotai atoms.
    - Add list row dropdown with delete dialog and unique-name on create.
    - Add snap-to-grid, reorganize, and status pill to the canvas.

commit 4b5d679b0d936cd5b8fc200352288b0c641afd6a
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 04:20:53 2026 +0200

    feat(workflows): implement initial PoC of the MVP

commit a2f8eb4b25bd1a3042bc96a886d7d669b104a9e3
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 02:58:53 2026 +0200

    docs(workbench): complete 001-000 workflows PoC readiness

commit ef78ba5d2e3bc8b40c32b9966556554f430b51e2
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 02:26:23 2026 +0200

    docs(workbench): reframe workflows MVP as PoC and add 001-010 vertical slice plan

commit fa17580ca8c9be31500118b56daf1652bef5e077
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Fri May 22 02:07:39 2026 +0200

    docs(workbench): add workflows MVP blueprint, milestone, plans, and research

commit 8d3163f8fe8af7c8d85a4dec8af0d87ae5e8c460
Author: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Date:   Thu May 21 22:13:47 2026 +0200

    chore: add workbench blueprint, cowork, and guidelines scaffolding
2026-05-22 20:45:12 +02:00

164 lines
4.4 KiB
TypeScript

"use client";
import type { TWorkflowDefinition, TWorkflowRunStatus, TWorkflowStatus } from "@formbricks/types/workflows";
import { parseV3ApiError } from "@/modules/api/lib/v3-client";
import type { TWorkflow, TWorkflowRun } from "../types/workflows";
type TListResponse<T> = {
data: T[];
meta: {
limit: number;
nextCursor: string | null;
};
};
type TItemResponse<T> = {
data: T;
};
const parseJsonResponse = async <T>(response: Response): Promise<T> => {
if (!response.ok) {
throw await parseV3ApiError(response);
}
return (await response.json()) as T;
};
export const listWorkflows = async ({
workspaceId,
status,
}: {
workspaceId: string;
status?: TWorkflowStatus;
}): Promise<TListResponse<TWorkflow>> => {
const params = new URLSearchParams({ workspaceId });
if (status) {
params.set("status", status);
}
const response = await fetch(`/api/v3/workflows?${params.toString()}`, {
cache: "no-store",
});
return await parseJsonResponse<TListResponse<TWorkflow>>(response);
};
export const createWorkflow = async ({
workspaceId,
name,
description,
definition,
}: {
workspaceId: string;
name: string;
description?: string | null;
definition: TWorkflowDefinition;
}): Promise<TWorkflow> => {
const response = await fetch("/api/v3/workflows", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ workspaceId, name, description, definition }),
});
const result = await parseJsonResponse<TItemResponse<TWorkflow>>(response);
return result.data;
};
export const getWorkflow = async (workflowId: string): Promise<TWorkflow> => {
const response = await fetch(`/api/v3/workflows/${workflowId}`, {
cache: "no-store",
});
const result = await parseJsonResponse<TItemResponse<TWorkflow>>(response);
return result.data;
};
export const updateWorkflow = async ({
workflowId,
name,
description,
definition,
}: {
workflowId: string;
name?: string;
description?: string | null;
definition?: TWorkflowDefinition;
}): Promise<TWorkflow> => {
const response = await fetch(`/api/v3/workflows/${workflowId}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name, description, definition }),
});
const result = await parseJsonResponse<TItemResponse<TWorkflow>>(response);
return result.data;
};
export const deleteWorkflow = async (workflowId: string): Promise<{ id: string }> => {
const response = await fetch(`/api/v3/workflows/${workflowId}`, {
method: "DELETE",
});
const result = await parseJsonResponse<TItemResponse<{ id: string }>>(response);
return result.data;
};
export const enableWorkflow = async (workflowId: string): Promise<TWorkflow> => {
const response = await fetch(`/api/v3/workflows/${workflowId}/enable`, {
method: "POST",
});
const result = await parseJsonResponse<TItemResponse<TWorkflow>>(response);
return result.data;
};
export const disableWorkflow = async (workflowId: string): Promise<TWorkflow> => {
const response = await fetch(`/api/v3/workflows/${workflowId}/disable`, {
method: "POST",
});
const result = await parseJsonResponse<TItemResponse<TWorkflow>>(response);
return result.data;
};
export const listWorkflowRuns = async ({
workflowId,
status,
}: {
workflowId: string;
status?: TWorkflowRunStatus;
}): Promise<TListResponse<TWorkflowRun>> => {
const params = new URLSearchParams();
if (status) {
params.set("status", status);
}
const response = await fetch(`/api/v3/workflows/${workflowId}/runs?${params.toString()}`, {
cache: "no-store",
});
return await parseJsonResponse<TListResponse<TWorkflowRun>>(response);
};
export const listWorkspaceWorkflowRuns = async ({
workspaceId,
status,
}: {
workspaceId: string;
status?: TWorkflowRunStatus;
}): Promise<TListResponse<TWorkflowRun>> => {
const params = new URLSearchParams({ workspaceId });
if (status) {
params.set("status", status);
}
const response = await fetch(`/api/v3/workflows/runs?${params.toString()}`, {
cache: "no-store",
});
return await parseJsonResponse<TListResponse<TWorkflowRun>>(response);
};
export const getWorkflowRun = async (workflowId: string, runId: string): Promise<TWorkflowRun> => {
const response = await fetch(`/api/v3/workflows/${workflowId}/runs/${runId}`, {
cache: "no-store",
});
const result = await parseJsonResponse<TItemResponse<TWorkflowRun>>(response);
return result.data;
};