MCPcopy
hub / github.com/callumalpass/tasknotes / WebhookController

Class WebhookController

src/api/WebhookController.ts:45–542  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

43}
44
45export class WebhookController extends BaseController {
46 private webhooks: Map<string, WebhookConfig> = new Map();
47 private webhookDeliveryQueue: WebhookDelivery[] = [];
48
49 constructor(private plugin: TaskNotesPlugin) {
50 super();
51 this.loadWebhooks();
52 }
53
54 @Post("/api/webhooks")
55 async registerWebhook(req: HTTPRequestLike, res: HTTPResponseLike): Promise<void> {
56 try {
57 const body = await this.parseRequestBody(req);
58 const requestBody = isRecord(body) ? body : {};
59
60 if (typeof requestBody.url !== "string") {
61 this.sendResponse(
62 res,
63 400,
64 this.errorResponse("URL is required and must be a string")
65 );
66 return;
67 }
68
69 if (
70 !Array.isArray(requestBody.events) ||
71 requestBody.events.length === 0 ||
72 !requestBody.events.every(isWebhookEvent)
73 ) {
74 this.sendResponse(
75 res,
76 400,
77 this.errorResponse(
78 "Events array is required and must contain valid webhook events"
79 )
80 );
81 return;
82 }
83
84 // Generate webhook ID and secret if not provided
85 const id = optionalString(requestBody.id) ?? this.generateWebhookId();
86 const secret = optionalString(requestBody.secret) ?? this.generateWebhookSecret();
87
88 const webhook: WebhookConfig = {
89 id,
90 url: requestBody.url,
91 events: requestBody.events,
92 secret,
93 active: requestBody.active !== false,
94 createdAt: new Date().toISOString(),
95 failureCount: 0,
96 successCount: 0,
97 transformFile: optionalString(requestBody.transformFile),
98 corsHeaders: requestBody.corsHeaders !== false, // Default to true unless explicitly set to false
99 };
100
101 this.webhooks.set(id, webhook);
102 await this.saveWebhooks();

Callers

nothing calls this directly

Calls 3

PostFunction · 0.90
GetFunction · 0.90
DeleteFunction · 0.90

Tested by

no test coverage detected