pr_01m47d15m3e54sn21z27rpy5n9/apps/web/app/lib/webhooks.server.ts

62 lines2,568 bytesCodeBlame
1import type { Hook, HookDelivery, HookOwner, User, Viewer } from "@g1t/contracts";
2
3import { webhooks } from "./services.server";
4import { unwrap } from "./session.server";
5
6/** What a webhooks page shows: the webhooks, and one's deliveries if it is open. */
7export type WebhooksData = {
8 hooks: Hook[];
9 open: string | null;
10 deliveries: HookDelivery[];
11};
12
13export async function loadWebhooks(owner: HookOwner, viewer: Viewer, request: Request): Promise<WebhooksData> {
14 const hooks = unwrap(await webhooks.list(viewer, owner));
15 const wanted = new URL(request.url).searchParams.get("hook");
16 const open = hooks.find((hook) => hook.id === wanted)?.id ?? null;
17 const deliveries = open ? unwrap(await webhooks.deliveries(viewer, owner, open)) : [];
18 return { hooks, open, deliveries };
19}
20
21/** What a webhooks form asked for, done. */
22export type WebhooksAction = {
23 error?: string;
24 /** A webhook just made, and its secret if g1t made it: shown once. */
25 created?: { hook: Hook; secret: string | null };
26 /** The latest delivery a ping or redelivery made. */
27 sent?: HookDelivery;
28};
29
30export async function actOnWebhooks(owner: HookOwner, actor: User, form: FormData): Promise<WebhooksAction> {
31 const id = String(form.get("id") ?? "");
32 switch (form.get("intent")) {
33 case "create": {
34 const events = form.get("which") === "some" ? form.getAll("event").map(String) : ["*"];
35 if (events.length === 0) return { error: "Choose at least one event, or send everything." };
36 const created = await webhooks.create(actor, owner, {
37 url: String(form.get("url") ?? ""),
38 events,
39 secret: String(form.get("secret") ?? "").trim() || undefined,
40 });
41 return created.ok ? { created: created.value } : { error: created.error.message };
42 }
43 case "toggle": {
44 const updated = await webhooks.update(actor, owner, id, { active: form.get("active") === "true" });
45 return updated.ok ? {} : { error: updated.error.message };
46 }
47 case "delete": {
48 const removed = await webhooks.delete(actor, owner, id);
49 return removed.ok ? {} : { error: removed.error.message };
50 }
51 case "ping": {
52 const sent = await webhooks.ping(actor, owner, id);
53 return sent.ok ? { sent: sent.value } : { error: sent.error.message };
54 }
55 case "redeliver": {
56 const sent = await webhooks.redeliver(actor, owner, String(form.get("delivery") ?? ""));
57 return sent.ok ? { sent: sent.value } : { error: sent.error.message };
58 }
59 default:
60 return { error: "Nothing to do." };
61 }
62}