1import {
2 Body,
3 Controller,
4 Delete,
5 Get,
6 HttpCode,
7 Inject,
8 Param,
9 Patch,
10 Post,
11 Query,
12 Req
13} from "@nestjs/common";
14import type { Request } from "express";
15import { z } from "zod";
16import { WebhooksService } from "./webhooks.service.js";
17import { ZodValidate } from "../../common/pipes/zod-validation.pipe.js";
18import { requireUser } from "../../common/types.js";
19
20
38
39const createSchema = z.object({
40 url: z.string().url().max(2048),
41 events: z.array(z.string().min(1)).min(1).max(32).optional(),
42 secret: z.string().min(16).max(256).optional(),
43 active: z.boolean().optional()
44});
45type CreateInput = z.infer<typeof createSchema>;
46
47const updateSchema = z.object({
48 url: z.string().url().max(2048).optional(),
49 events: z.array(z.string().min(1)).min(1).max(32).optional(),
50 active: z.boolean().optional(),
51
52 rotateSecret: z.boolean().optional()
53});
54type UpdateInput = z.infer<typeof updateSchema>;
55
56
57const resubmitSchema = z
58 .object({
59 deliveryId: z.string().min(1).optional(),
60 all_dead: z.boolean().optional(),
61 window: z.object({ since: z.string().optional(), until: z.string().optional() }).optional()
62 })
63 .refine((v) => v.deliveryId || v.all_dead !== undefined || v.window, {
64 message: "Provide deliveryId, all_dead, or window"
65 });
66type ResubmitInput = z.infer<typeof resubmitSchema>;
67
68@Controller("workspaces/:workspaceId/webhooks")
69export class WebhooksController {
70 constructor(@Inject(WebhooksService) private readonly service: WebhooksService) {}
71
72 @Post()
73 create(@Param("workspaceId") wid: string, @Body(ZodValidate(createSchema)) body: CreateInput, @Req() req: Request) {
74 return this.service.create(wid, requireUser(req), body, req);
75 }
76
77 @Get()
78 list(
79 @Param("workspaceId") wid: string,
80 @Query() q: { cursor?: string; limit?: string },
81 @Req() req: Request
82 ) {
83 return this.service.list(wid, requireUser(req), q);
84 }
85
86 @Get(":webhookId")
87 get(@Param("workspaceId") wid: string, @Param("webhookId") webhookId: string, @Req() req: Request) {
88 return this.service.get(wid, webhookId, requireUser(req));
89 }
90
91 @Patch(":webhookId")
92 async update(
93 @Param("workspaceId") wid: string,
94 @Param("webhookId") webhookId: string,
95 @Body(ZodValidate(updateSchema)) body: UpdateInput,
96 @Req() req: Request
97 ) {
98
99 if (body.rotateSecret) {
100 return this.service.rotateSecret(wid, webhookId, requireUser(req), req);
101 }
102 const { rotateSecret: _ignored, ...patch } = body;
103 return this.service.update(wid, webhookId, requireUser(req), patch, req);
104 }
105
106 @Post(":webhookId/rotate-secret")
107 rotateSecret(@Param("workspaceId") wid: string, @Param("webhookId") webhookId: string, @Req() req: Request) {
108 return this.service.rotateSecret(wid, webhookId, requireUser(req), req);
109 }
110
111 @HttpCode(200)
112 @Post(":webhookId/test")
113 test(@Param("workspaceId") wid: string, @Param("webhookId") webhookId: string, @Req() req: Request) {
114 return this.service.test(wid, webhookId, requireUser(req), req);
115 }
116
117 @HttpCode(200)
118 @Post(":webhookId/resubmit")
119 resubmit(
120 @Param("workspaceId") wid: string,
121 @Param("webhookId") webhookId: string,
122 @Body(ZodValidate(resubmitSchema)) body: ResubmitInput,
123 @Req() req: Request
124 ) {
125 return this.service.resubmit(wid, webhookId, requireUser(req), body, req);
126 }
127
128 @Delete(":webhookId")
129 async remove(@Param("workspaceId") wid: string, @Param("webhookId") webhookId: string, @Req() req: Request) {
130 await this.service.remove(wid, webhookId, requireUser(req), req);
131 return;
132 }
133
134 @Get(":webhookId/deliveries")
135 deliveries(
136 @Param("workspaceId") wid: string,
137 @Param("webhookId") webhookId: string,
138 @Query()
139 q: { cursor?: string; limit?: string; status?: string; event?: string; since?: string; until?: string },
140 @Req() req: Request
141 ) {
142 return this.service.deliveries(wid, webhookId, requireUser(req), q);
143 }
144
145 @Get(":webhookId/deliveries/:deliveryId")
146 delivery(
147 @Param("workspaceId") wid: string,
148 @Param("webhookId") webhookId: string,
149 @Param("deliveryId") deliveryId: string,
150 @Req() req: Request
151 ) {
152 return this.service.delivery(wid, webhookId, deliveryId, requireUser(req));
153 }
154
155 @HttpCode(200)
156 @Post(":webhookId/deliveries/:deliveryId/retry")
157 retryDelivery(
158 @Param("workspaceId") wid: string,
159 @Param("webhookId") webhookId: string,
160 @Param("deliveryId") deliveryId: string,
161 @Req() req: Request
162 ) {
163 return this.service.retryDelivery(wid, webhookId, deliveryId, requireUser(req), req);
164 }
165}
166