g1t/packages/contracts/src/webhooks.ts

84 lines2,507 bytesCodeBlame
1import type { User, Viewer } from "./identity";
2import type { RepoPath } from "./repos";
3import type { Result } from "./result";
4
5/**
6 * Events, delivered to the addresses a repository or a workspace registers.
7 * Mirrors `crates/contracts/src/webhooks.rs`.
8 */
9
10/** Every event a webhook can be sent, in the order people are shown them. */
11export const EVENT_TYPES = [
12 "git.push",
13 "repo.created",
14 "repo.forked",
15 "issue.opened",
16 "issue.updated",
17 "issue.assigned",
18 "issue.closed",
19 "issue.reopened",
20 "comment.created",
21 "pull.opened",
22 "pull.ready",
23 "pull.updated",
24 "pull.merge_requested",
25 "pull.merged",
26 "pull.closed",
27 "checks.completed",
28 "review.completed",
29 "workflow.completed",
30 "queue.changed",
31 "session.appended",
32] as const;
33
34export type Hook = {
35 id: string;
36 scope: "repo" | "workspace";
37 workspace: string;
38 /** For a repository's webhook: `owner/name`. */
39 repo: string | null;
40 url: string;
41 /** Event types, or `["*"]` for all. */
42 events: string[];
43 active: boolean;
44 secretHint: string;
45 createdBy: string;
46 createdAt: string;
47 lastStatus: "delivered" | "pending" | "failed" | null;
48 lastDeliveredAt: string | null;
49};
50
51export type HookDelivery = {
52 id: string;
53 hookId: string;
54 eventId: string;
55 event: string;
56 status: "pending" | "delivered" | "failed";
57 attempts: number;
58 responseStatus: number | null;
59 responseBody: string | null;
60 error: string | null;
61 durationMs: number | null;
62 /** The JSON that was sent. */
63 payload: string;
64 createdAt: string;
65 deliveredAt: string | null;
66 nextAttemptAt: string | null;
67};
68
69/** A repository's webhooks, or with `repo` left out, the workspace's own. */
70export type HookOwner = { workspace: string; repo?: RepoPath };
71
72export interface WebhooksApi {
73 list(viewer: Viewer, owner: HookOwner): Promise<Result<Hook[]>>;
74 create(
75 actor: User,
76 owner: HookOwner,
77 input: { url: string; events?: string[]; secret?: string },
78 ): Promise<Result<{ hook: Hook; secret: string | null }>>;
79 update(actor: User, owner: HookOwner, id: string, input: { url?: string; events?: string[]; active?: boolean }): Promise<Result<Hook>>;
80 delete(actor: User, owner: HookOwner, id: string): Promise<Result<boolean>>;
81 ping(actor: User, owner: HookOwner, id: string): Promise<Result<HookDelivery>>;
82 deliveries(viewer: Viewer, owner: HookOwner, id: string): Promise<Result<HookDelivery[]>>;
83 redeliver(actor: User, owner: HookOwner, deliveryId: string): Promise<Result<HookDelivery>>;
84}