-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebhook-router.ts
More file actions
56 lines (51 loc) · 1.77 KB
/
Copy pathwebhook-router.ts
File metadata and controls
56 lines (51 loc) · 1.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* Wire the inbound webhook router behind a single HTTP handler.
*
* The router takes care of signature verification, parsing, and
* idempotency dedup. The product's `deliver()` callback runs async and
* sees a normalized envelope.
*/
import {
WebhookRouter,
stripeWebhookProvider,
docusealWebhookProvider,
slackWebhookProvider,
} from '@tangle-network/agent-integrations/webhooks'
const idempotency = (() => {
const seen = new Set<string>()
return {
seen: (id: string) => seen.has(id),
remember: (id: string) => {
seen.add(id)
},
}
})()
const router = new WebhookRouter({
providers: [stripeWebhookProvider, docusealWebhookProvider, slackWebhookProvider],
idempotency,
resolveSecret: async (providerId) => {
// In production: pull from a secret manager keyed by the requesting
// tenant. Headers (e.g., a Stripe Account-Id) are available to scope
// the lookup when multiple tenants share a provider.
if (providerId === 'stripe') return process.env.STRIPE_WEBHOOK_SECRET ?? null
if (providerId === 'docuseal') return process.env.DOCUSEAL_WEBHOOK_SECRET ?? null
if (providerId === 'slack') return process.env.SLACK_SIGNING_SECRET ?? null
return null
},
deliver: async (event) => {
console.log(`[webhook] ${event.eventType} (${event.providerEventId ?? 'no-id'})`)
// Branch on eventType and enqueue domain-specific work here.
},
})
// In an HTTP handler:
// const rawBody = await req.text()
// const result = await router.handle({
// providerId: req.params.provider,
// rawBody,
// headers: Object.fromEntries(req.headers.entries()),
// })
// return new Response(JSON.stringify(result.body), {
// status: result.status,
// headers: { 'content-type': 'application/json' },
// })
void router