mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-24 08:00:37 +00:00
feat: add automation api bindings
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import type { Automation, AutomationWrite } from "@/lib/api/models/app/automations/Automation";
|
||||
import Request from "../../Request";
|
||||
|
||||
export default async function createAutomation(w: AutomationWrite): Promise<{ automation: Automation }> {
|
||||
return await Request<{ automation: Automation }>({
|
||||
method: "POST",
|
||||
url: "/automations",
|
||||
data: w,
|
||||
authorization: true,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import Request from "../../Request";
|
||||
|
||||
export default async function deleteAutomation(id: string): Promise<{ deleted: boolean }> {
|
||||
return await Request<{ deleted: boolean }>({
|
||||
method: "DELETE",
|
||||
url: `/automations/${id}`,
|
||||
authorization: true,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { Automation } from "@/lib/api/models/app/automations/Automation";
|
||||
import Request from "../../Request";
|
||||
|
||||
export default async function getAutomation(id: string): Promise<{ automation: Automation }> {
|
||||
return await Request<{ automation: Automation }>({
|
||||
method: "GET",
|
||||
url: `/automations/${id}`,
|
||||
authorization: true,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { Automation } from "@/lib/api/models/app/automations/Automation";
|
||||
import Request from "../../Request";
|
||||
|
||||
export default async function listAutomations(): Promise<{ automations: Automation[] }> {
|
||||
return await Request<{ automations: Automation[] }>({
|
||||
method: "GET",
|
||||
url: "/automations",
|
||||
authorization: true,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { Automation, AutomationWrite } from "@/lib/api/models/app/automations/Automation";
|
||||
import Request from "../../Request";
|
||||
|
||||
export default async function updateAutomation(id: string, w: AutomationWrite): Promise<{ automation: Automation }> {
|
||||
return await Request<{ automation: Automation }>({
|
||||
method: "PATCH",
|
||||
url: `/automations/${id}`,
|
||||
data: w,
|
||||
authorization: true,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import getAutomation from "@/lib/api/client/app/automations/getAutomation";
|
||||
|
||||
export function useAutomation(id: string, enabled = true) {
|
||||
return useQuery({
|
||||
queryKey: ["automations", id],
|
||||
queryFn: () => getAutomation(id),
|
||||
enabled: enabled && !!id,
|
||||
staleTime: 15_000,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import createAutomation from "@/lib/api/client/app/automations/createAutomation";
|
||||
import updateAutomation from "@/lib/api/client/app/automations/updateAutomation";
|
||||
import deleteAutomation from "@/lib/api/client/app/automations/deleteAutomation";
|
||||
import type { AutomationWrite } from "@/lib/api/models/app/automations/Automation";
|
||||
|
||||
export function useCreateAutomation() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (w: AutomationWrite) => createAutomation(w),
|
||||
onSuccess: () => void qc.invalidateQueries({ queryKey: ["automations"] }),
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateAutomation() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ id, w }: { id: string; w: AutomationWrite }) => updateAutomation(id, w),
|
||||
onSuccess: (_res, vars) => {
|
||||
void qc.invalidateQueries({ queryKey: ["automations"] });
|
||||
void qc.invalidateQueries({ queryKey: ["automations", vars.id] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteAutomation() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => deleteAutomation(id),
|
||||
onSuccess: () => void qc.invalidateQueries({ queryKey: ["automations"] }),
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import listAutomations from "@/lib/api/client/app/automations/listAutomations";
|
||||
|
||||
export function useAutomations() {
|
||||
return useQuery({
|
||||
queryKey: ["automations"],
|
||||
queryFn: listAutomations,
|
||||
staleTime: 15_000,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { IntegrationAction } from "@/lib/api/models/app/integrations/Integration";
|
||||
|
||||
// One action node of an automation: run `action` on `connection_id` with config.
|
||||
export interface AutomationStep {
|
||||
id?: string;
|
||||
connection_id: string;
|
||||
action: IntegrationAction;
|
||||
config?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
// An automation = one trigger event -> a set of action steps. Execution reuses
|
||||
// the integration event-subscription dispatcher (each step is a subscription).
|
||||
export interface Automation {
|
||||
id: string;
|
||||
organization_id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
trigger_event: string;
|
||||
filter?: Record<string, unknown>;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
steps: AutomationStep[];
|
||||
}
|
||||
|
||||
// Create/update payload from the flow builder.
|
||||
export interface AutomationWrite {
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
trigger_event: string;
|
||||
filter?: Record<string, unknown>;
|
||||
steps: AutomationStep[];
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// Trigger + action vocabulary the Automations flow builder renders from. Kept in
|
||||
// sync with the backend's subscribable events (catalog crmEvents/notifyEvents)
|
||||
// and the per-provider action handlers.
|
||||
|
||||
import { EVENT_LABELS } from "@/lib/api/models/app/integrations/Integration";
|
||||
|
||||
// Warmbly events that can trigger an automation. Order = how they're listed.
|
||||
export const TRIGGER_EVENTS: string[] = [
|
||||
"campaign.reply_received",
|
||||
"meeting.booked",
|
||||
"meeting.rescheduled",
|
||||
"meeting.canceled",
|
||||
"campaign.email_bounced",
|
||||
"campaign.unsubscribed",
|
||||
"warmup.health_changed",
|
||||
"deliverability.complaint",
|
||||
];
|
||||
|
||||
export function triggerLabel(ev: string): string {
|
||||
return EVENT_LABELS[ev] ?? ev;
|
||||
}
|
||||
|
||||
// Human labels for the provider action handlers (the action a step performs).
|
||||
export const ACTION_LABELS: Record<string, string> = {
|
||||
"slack.notify": "Send a Slack message",
|
||||
"discord.notify": "Send a Discord message",
|
||||
"hubspot.upsert_contact": "Create / update HubSpot contact",
|
||||
"pipedrive.upsert_person": "Create / update Pipedrive person",
|
||||
"salesforce.upsert_contact": "Create / update Salesforce contact",
|
||||
"close.upsert_lead": "Create / update Close lead",
|
||||
"webhook.ping": "Send a webhook",
|
||||
};
|
||||
|
||||
export function actionLabel(a: string): string {
|
||||
return ACTION_LABELS[a] ?? a;
|
||||
}
|
||||
|
||||
// Per-action config field needs, so the node editor shows the right inputs.
|
||||
export function actionNeedsChannel(action: string): boolean {
|
||||
return action === "slack.notify";
|
||||
}
|
||||
export function actionNeedsURL(action: string): boolean {
|
||||
return action === "webhook.ping";
|
||||
}
|
||||
// Notify-style actions accept an optional custom message template.
|
||||
export function actionSupportsTemplate(action: string): boolean {
|
||||
return action === "slack.notify" || action === "discord.notify" || action === "webhook.ping";
|
||||
}
|
||||
|
||||
// Only the reply trigger carries intent / confidence filters.
|
||||
export function triggerSupportsIntentFilter(ev: string): boolean {
|
||||
return ev === "campaign.reply_received";
|
||||
}
|
||||
Reference in New Issue
Block a user