pr_01m47d24b0e6n91zwymwxg0vpx/packages/contracts/src/webhooks.ts

83 lines2,483 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Webhooks: every event, to your own addresses, signed and retried1import 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 "queue.changed",
30 "session.appended",
31] as const;
32
33export type Hook = {
34 id: string;
35 scope: "repo" | "workspace";
36 workspace: string;
37 /** For a repository's webhook: `owner/name`. */
38 repo: string | null;
39 url: string;
40 /** Event types, or `["*"]` for all. */
41 events: string[];
42 active: boolean;
43 secretHint: string;
44 createdBy: string;
45 createdAt: string;
46 lastStatus: "delivered" | "pending" | "failed" | null;
47 lastDeliveredAt: string | null;
48};
49
50export type HookDelivery = {
51 id: string;
52 hookId: string;
53 eventId: string;
54 event: string;
55 status: "pending" | "delivered" | "failed";
56 attempts: number;
57 responseStatus: number | null;
58 responseBody: string | null;
59 error: string | null;
60 durationMs: number | null;
61 /** The JSON that was sent. */
62 payload: string;
63 createdAt: string;
64 deliveredAt: string | null;
65 nextAttemptAt: string | null;
66};
67
68/** A repository's webhooks, or with `repo` left out, the workspace's own. */
69export type HookOwner = { workspace: string; repo?: RepoPath };
70
71export interface WebhooksApi {
72 list(viewer: Viewer, owner: HookOwner): Promise<Result<Hook[]>>;
73 create(
74 actor: User,
75 owner: HookOwner,
76 input: { url: string; events?: string[]; secret?: string },
77 ): Promise<Result<{ hook: Hook; secret: string | null }>>;
78 update(actor: User, owner: HookOwner, id: string, input: { url?: string; events?: string[]; active?: boolean }): Promise<Result<Hook>>;
79 delete(actor: User, owner: HookOwner, id: string): Promise<Result<boolean>>;
80 ping(actor: User, owner: HookOwner, id: string): Promise<Result<HookDelivery>>;
81 deliveries(viewer: Viewer, owner: HookOwner, id: string): Promise<Result<HookDelivery[]>>;
82 redeliver(actor: User, owner: HookOwner, deliveryId: string): Promise<Result<HookDelivery>>;
83}