@hookflo/tern 2.2.10 โ†’ 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/test.js CHANGED
@@ -65,9 +65,35 @@ function createWorkOSSignature(body, secret, timestamp) {
65
65
  hmac.update(signedPayload);
66
66
  return `t=${timestamp},v1=${hmac.digest('hex')}`;
67
67
  }
68
+ function createSentrySignature(body, secret) {
69
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
70
+ hmac.update(JSON.stringify(JSON.parse(body)));
71
+ return hmac.digest('hex');
72
+ }
73
+ function createSentryIssueAlertSignature(issueAlertObject, secret) {
74
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
75
+ hmac.update(JSON.stringify(issueAlertObject));
76
+ return hmac.digest('hex');
77
+ }
78
+ function createGrafanaSignature(body, secret, timestamp) {
79
+ const payload = timestamp ? `${timestamp}.${body}` : body;
80
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
81
+ hmac.update(payload);
82
+ return hmac.digest('hex');
83
+ }
84
+ function createDopplerSignature(body, secret) {
85
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
86
+ hmac.update(body);
87
+ return `sha256=${hmac.digest('hex')}`;
88
+ }
89
+ function createSanitySignature(body, secret, timestamp) {
90
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
91
+ hmac.update(`${timestamp}.${body}`);
92
+ return `t=${timestamp},v1=${hmac.digest('hex')}`;
93
+ }
68
94
  function createFalPayloadToSign(body, requestId, userId, timestamp) {
69
95
  const bodyHash = (0, crypto_1.createHash)('sha256').update(body).digest('hex');
70
- return `${requestId}.${userId}.${timestamp}.${bodyHash}`;
96
+ return `${requestId}\n${userId}\n${timestamp}\n${bodyHash}`;
71
97
  }
72
98
  async function runTests() {
73
99
  console.log('๐Ÿงช Running Webhook Verification Tests...\n');
@@ -81,7 +107,8 @@ async function runTests() {
81
107
  'content-type': 'application/json',
82
108
  });
83
109
  const stripeResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(stripeRequest, 'stripe', testSecret);
84
- console.log(' โœ… Stripe:', stripeResult.isValid ? 'PASSED' : 'FAILED');
110
+ const stripePassed = stripeResult.isValid && Boolean(stripeResult.eventId?.startsWith('stripe:'));
111
+ console.log(' โœ… Stripe:', stripePassed ? 'PASSED' : 'FAILED');
85
112
  if (!stripeResult.isValid) {
86
113
  console.log(' โŒ Error:', stripeResult.error);
87
114
  }
@@ -181,7 +208,7 @@ async function runTests() {
181
208
  catch (error) {
182
209
  console.log(' โŒ Dodo Payments test failed:', error);
183
210
  }
184
- // Test 5: Token-based (Supabase)
211
+ // Test 5: Token-based authentication helper
185
212
  console.log('\n5. Testing Token-based Authentication...');
186
213
  try {
187
214
  const webhookId = 'test-webhook-id';
@@ -191,8 +218,10 @@ async function runTests() {
191
218
  'x-webhook-token': webhookToken,
192
219
  'content-type': 'application/json',
193
220
  });
194
- const tokenResult = await index_1.WebhookVerificationService.verifyTokenBased(tokenRequest, webhookId, webhookToken);
195
- console.log(' โœ… Token-based:', tokenResult.isValid ? 'PASSED' : 'FAILED');
221
+ const tokenResult = await index_1.WebhookVerificationService.verifyTokenAuth(tokenRequest.clone(), webhookId, webhookToken);
222
+ const tokenAliasResult = await index_1.WebhookVerificationService.verifyTokenBased(tokenRequest.clone(), webhookId, webhookToken);
223
+ const tokenPassed = tokenResult.isValid && tokenAliasResult.isValid;
224
+ console.log(' โœ… Token-based:', tokenPassed ? 'PASSED' : 'FAILED');
196
225
  if (!tokenResult.isValid) {
197
226
  console.log(' โŒ Error:', tokenResult.error);
198
227
  }
@@ -200,6 +229,88 @@ async function runTests() {
200
229
  catch (error) {
201
230
  console.log(' โŒ Token-based test failed:', error);
202
231
  }
232
+ // Test 5.5: Sentry webhook verification (standard + issue alert fallback)
233
+ console.log('\n5.5. Testing Sentry Webhook...');
234
+ try {
235
+ const timestamp = Math.floor(Date.now() / 1000);
236
+ const requestId = 'sentry-request-id-123';
237
+ const sentryBody = JSON.stringify({
238
+ action: 'triggered',
239
+ data: {
240
+ issue_alert: {
241
+ id: 'alert-1',
242
+ title: 'CPU high',
243
+ project: 'infra',
244
+ },
245
+ },
246
+ });
247
+ const sentryRequest = createMockRequest({
248
+ 'sentry-hook-signature': createSentrySignature(sentryBody, testSecret),
249
+ 'sentry-hook-timestamp': timestamp.toString(),
250
+ 'request-id': requestId,
251
+ 'content-type': 'application/json',
252
+ }, sentryBody);
253
+ const sentryResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(sentryRequest, 'sentry', testSecret);
254
+ const sentryIssueAlertRequest = createMockRequest({
255
+ 'sentry-hook-signature': createSentryIssueAlertSignature({ id: 'alert-1', title: 'CPU high', project: 'infra' }, testSecret),
256
+ 'sentry-hook-timestamp': timestamp.toString(),
257
+ 'request-id': `${requestId}-issue-alert`,
258
+ 'content-type': 'application/json',
259
+ }, sentryBody);
260
+ const sentryIssueAlertResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(sentryIssueAlertRequest, 'sentry', testSecret);
261
+ const sentryPassed = sentryResult.isValid && sentryIssueAlertResult.isValid && sentryResult.eventId?.startsWith('sentry:');
262
+ console.log(' โœ… Sentry:', sentryPassed ? 'PASSED' : 'FAILED');
263
+ }
264
+ catch (error) {
265
+ console.log(' โŒ Sentry test failed:', error);
266
+ }
267
+ // Test 5.6: Grafana webhook verification
268
+ console.log('\n5.6. Testing Grafana Webhook...');
269
+ try {
270
+ const timestamp = Math.floor(Date.now() / 1000);
271
+ const grafanaSignature = createGrafanaSignature(testBody, testSecret, timestamp);
272
+ const grafanaRequest = createMockRequest({
273
+ 'x-grafana-alerting-signature': grafanaSignature,
274
+ 'x-grafana-alerting-timestamp': timestamp.toString(),
275
+ 'content-type': 'application/json',
276
+ });
277
+ const grafanaResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(grafanaRequest, 'grafana', testSecret);
278
+ console.log(' โœ… Grafana:', grafanaResult.isValid ? 'PASSED' : 'FAILED');
279
+ }
280
+ catch (error) {
281
+ console.log(' โŒ Grafana test failed:', error);
282
+ }
283
+ // Test 5.7: Doppler webhook verification
284
+ console.log('\n5.7. Testing Doppler Webhook...');
285
+ try {
286
+ const dopplerRequest = createMockRequest({
287
+ 'x-doppler-signature': createDopplerSignature(testBody, testSecret),
288
+ 'content-type': 'application/json',
289
+ });
290
+ const dopplerResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(dopplerRequest, 'doppler', testSecret);
291
+ const dopplerPassed = dopplerResult.isValid && Boolean(dopplerResult.eventId?.startsWith('doppler:'));
292
+ console.log(' โœ… Doppler:', dopplerPassed ? 'PASSED' : 'FAILED');
293
+ }
294
+ catch (error) {
295
+ console.log(' โŒ Doppler test failed:', error);
296
+ }
297
+ // Test 5.8: Sanity webhook verification
298
+ console.log('\n5.8. Testing Sanity Webhook...');
299
+ try {
300
+ const timestamp = Math.floor(Date.now() / 1000);
301
+ const idempotencyKey = 'sanity-idem-123';
302
+ const sanityRequest = createMockRequest({
303
+ 'sanity-webhook-signature': createSanitySignature(testBody, testSecret, timestamp),
304
+ 'idempotency-key': idempotencyKey,
305
+ 'content-type': 'application/json',
306
+ });
307
+ const sanityResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(sanityRequest, 'sanity', testSecret);
308
+ const sanityPassed = sanityResult.isValid && sanityResult.eventId === `sanity:${idempotencyKey}`;
309
+ console.log(' โœ… Sanity:', sanityPassed ? 'PASSED' : 'FAILED');
310
+ }
311
+ catch (error) {
312
+ console.log(' โŒ Sanity test failed:', error);
313
+ }
203
314
  // Test 6: Invalid signatures
204
315
  console.log('\n6. Testing Invalid Signatures...');
205
316
  try {
@@ -388,24 +499,8 @@ async function runTests() {
388
499
  catch (error) {
389
500
  console.log(' โŒ Paddle test failed:', error);
390
501
  }
391
- // Test 16: Auth0
392
- console.log('\n16. Testing Auth0 webhook...');
393
- try {
394
- const hmac = (0, crypto_1.createHmac)('sha256', testSecret);
395
- hmac.update(testBody);
396
- const signature = hmac.digest('hex');
397
- const request = createMockRequest({
398
- 'x-auth0-signature': signature,
399
- 'content-type': 'application/json',
400
- });
401
- const result = await index_1.WebhookVerificationService.verifyWithPlatformConfig(request, 'auth0', testSecret);
402
- console.log(' โœ… Auth0:', result.isValid ? 'PASSED' : 'FAILED');
403
- }
404
- catch (error) {
405
- console.log(' โŒ Auth0 test failed:', error);
406
- }
407
- // Test 17: WorkOS
408
- console.log('\n17. Testing WorkOS webhook...');
502
+ // Test 16: WorkOS
503
+ console.log('\n16. Testing WorkOS webhook...');
409
504
  try {
410
505
  const timestamp = Math.floor(Date.now() / 1000);
411
506
  const signature = createWorkOSSignature(testBody, testSecret, timestamp);
@@ -420,7 +515,7 @@ async function runTests() {
420
515
  console.log(' โŒ WorkOS test failed:', error);
421
516
  }
422
517
  // Test 17.5: Shopify
423
- console.log('\n17.5. Testing Shopify webhook...');
518
+ console.log('\n17. Testing Shopify webhook...');
424
519
  try {
425
520
  const signature = createShopifySignature(testBody, testSecret);
426
521
  const request = createMockRequest({
@@ -501,11 +596,11 @@ async function runTests() {
501
596
  const timestamp = Math.floor(Date.now() / 1000).toString();
502
597
  const payloadToSign = createFalPayloadToSign(testBody, requestId, userId, timestamp);
503
598
  const payloadBytes = new Uint8Array(Buffer.from(payloadToSign));
504
- const signature = (0, crypto_1.sign)(null, payloadBytes, privateKey).toString('base64');
599
+ const signature = (0, crypto_1.sign)(null, payloadBytes, privateKey).toString('hex');
505
600
  const request = createMockRequest({
506
601
  'x-fal-webhook-signature': signature,
507
- 'x-fal-request-id': requestId,
508
- 'x-fal-user-id': userId,
602
+ 'x-fal-webhook-request-id': requestId,
603
+ 'x-fal-webhook-user-id': userId,
509
604
  'x-fal-webhook-timestamp': timestamp,
510
605
  'content-type': 'application/json',
511
606
  });
@@ -519,8 +614,8 @@ async function runTests() {
519
614
  payloadFormat: 'custom',
520
615
  customConfig: {
521
616
  publicKey: publicKey.export({ type: 'spki', format: 'pem' }).toString(),
522
- requestIdHeader: 'x-fal-request-id',
523
- userIdHeader: 'x-fal-user-id',
617
+ requestIdHeader: 'x-fal-webhook-request-id',
618
+ userIdHeader: 'x-fal-webhook-user-id',
524
619
  timestampHeader: 'x-fal-webhook-timestamp',
525
620
  },
526
621
  },
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type WebhookPlatform = 'custom' | 'clerk' | 'supabase' | 'github' | 'stripe' | 'shopify' | 'vercel' | 'polar' | 'dodopayments' | 'gitlab' | 'paddle' | 'razorpay' | 'lemonsqueezy' | 'auth0' | 'workos' | 'woocommerce' | 'replicateai' | 'falai' | 'unknown';
1
+ export type WebhookPlatform = 'custom' | 'clerk' | 'github' | 'stripe' | 'shopify' | 'vercel' | 'polar' | 'dodopayments' | 'gitlab' | 'paddle' | 'razorpay' | 'lemonsqueezy' | 'workos' | 'woocommerce' | 'replicateai' | 'falai' | 'sentry' | 'grafana' | 'doppler' | 'sanity' | 'unknown';
2
2
  export declare enum WebhookPlatformKeys {
3
3
  GitHub = "github",
4
4
  Stripe = "stripe",
@@ -7,16 +7,18 @@ export declare enum WebhookPlatformKeys {
7
7
  Shopify = "shopify",
8
8
  Vercel = "vercel",
9
9
  Polar = "polar",
10
- Supabase = "supabase",
11
10
  GitLab = "gitlab",
12
11
  Paddle = "paddle",
13
12
  Razorpay = "razorpay",
14
13
  LemonSqueezy = "lemonsqueezy",
15
- Auth0 = "auth0",
16
14
  WorkOS = "workos",
17
15
  WooCommerce = "woocommerce",
18
16
  ReplicateAI = "replicateai",
19
17
  FalAI = "falai",
18
+ Sentry = "sentry",
19
+ Grafana = "grafana",
20
+ Doppler = "doppler",
21
+ Sanity = "sanity",
20
22
  Custom = "custom",
21
23
  Unknown = "unknown"
22
24
  }
@@ -28,7 +30,8 @@ export interface SignatureConfig {
28
30
  prefix?: string;
29
31
  timestampHeader?: string;
30
32
  timestampFormat?: 'unix' | 'iso' | 'custom';
31
- payloadFormat?: 'raw' | 'timestamped' | 'custom';
33
+ payloadFormat?: 'raw' | 'timestamped' | 'json-stringified' | 'custom';
34
+ idHeader?: string;
32
35
  customConfig?: Record<string, any>;
33
36
  }
34
37
  export type WebhookErrorCode = 'MISSING_SIGNATURE' | 'INVALID_SIGNATURE' | 'TIMESTAMP_EXPIRED' | 'MISSING_TOKEN' | 'INVALID_TOKEN' | 'PLATFORM_NOT_SUPPORTED' | 'NORMALIZATION_ERROR' | 'VERIFICATION_ERROR';
@@ -101,6 +104,7 @@ export interface WebhookVerificationResult<TPayload = unknown> {
101
104
  errorCode?: WebhookErrorCode;
102
105
  platform: WebhookPlatform;
103
106
  payload?: TPayload;
107
+ eventId?: string;
104
108
  metadata?: {
105
109
  timestamp?: string;
106
110
  id?: string | null;
package/dist/types.js CHANGED
@@ -10,16 +10,18 @@ var WebhookPlatformKeys;
10
10
  WebhookPlatformKeys["Shopify"] = "shopify";
11
11
  WebhookPlatformKeys["Vercel"] = "vercel";
12
12
  WebhookPlatformKeys["Polar"] = "polar";
13
- WebhookPlatformKeys["Supabase"] = "supabase";
14
13
  WebhookPlatformKeys["GitLab"] = "gitlab";
15
14
  WebhookPlatformKeys["Paddle"] = "paddle";
16
15
  WebhookPlatformKeys["Razorpay"] = "razorpay";
17
16
  WebhookPlatformKeys["LemonSqueezy"] = "lemonsqueezy";
18
- WebhookPlatformKeys["Auth0"] = "auth0";
19
17
  WebhookPlatformKeys["WorkOS"] = "workos";
20
18
  WebhookPlatformKeys["WooCommerce"] = "woocommerce";
21
19
  WebhookPlatformKeys["ReplicateAI"] = "replicateai";
22
20
  WebhookPlatformKeys["FalAI"] = "falai";
21
+ WebhookPlatformKeys["Sentry"] = "sentry";
22
+ WebhookPlatformKeys["Grafana"] = "grafana";
23
+ WebhookPlatformKeys["Doppler"] = "doppler";
24
+ WebhookPlatformKeys["Sanity"] = "sanity";
23
25
  WebhookPlatformKeys["Custom"] = "custom";
24
26
  WebhookPlatformKeys["Unknown"] = "unknown";
25
27
  })(WebhookPlatformKeys || (exports.WebhookPlatformKeys = WebhookPlatformKeys = {}));
package/dist/utils.js CHANGED
@@ -131,9 +131,6 @@ function detectPlatformFromHeaders(headers) {
131
131
  if (headerMap.has('x-signature')) {
132
132
  return 'lemonsqueezy';
133
133
  }
134
- if (headerMap.has('x-auth0-signature')) {
135
- return 'auth0';
136
- }
137
134
  if (headerMap.has('x-wc-webhook-signature')) {
138
135
  return 'woocommerce';
139
136
  }
@@ -158,10 +155,6 @@ function detectPlatformFromHeaders(headers) {
158
155
  return 'polar';
159
156
  }
160
157
  }
161
- // Supabase
162
- if (headerMap.has('x-webhook-token')) {
163
- return 'supabase';
164
- }
165
158
  return null;
166
159
  }
167
160
  /**
@@ -17,6 +17,7 @@ export declare abstract class AlgorithmBasedVerifier extends WebhookVerifier {
17
17
  protected extractMetadata(request: Request): Record<string, any>;
18
18
  }
19
19
  export declare class GenericHMACVerifier extends AlgorithmBasedVerifier {
20
+ private resolveSentryPayloadCandidates;
20
21
  verify(request: Request): Promise<WebhookVerificationResult>;
21
22
  }
22
23
  export declare class Ed25519Verifier extends AlgorithmBasedVerifier {
@@ -93,6 +93,13 @@ class AlgorithmBasedVerifier extends base_1.WebhookVerifier {
93
93
  this.extractTimestamp(request);
94
94
  return timestamp ? `${timestamp}.${rawBody}` : rawBody;
95
95
  }
96
+ case "json-stringified":
97
+ try {
98
+ return JSON.stringify(JSON.parse(rawBody));
99
+ }
100
+ catch {
101
+ return rawBody;
102
+ }
96
103
  case "custom":
97
104
  return this.formatCustomPayload(rawBody, request);
98
105
  case "raw":
@@ -107,10 +114,18 @@ class AlgorithmBasedVerifier extends base_1.WebhookVerifier {
107
114
  const customFormat = this.config.customConfig.payloadFormat;
108
115
  if (customFormat.includes("{id}") && customFormat.includes("{timestamp}")) {
109
116
  const id = request.headers.get(this.config.customConfig.idHeader || "x-webhook-id");
110
- const timestamp = request.headers.get(this.config.timestampHeader || "x-webhook-timestamp");
117
+ const timestamp = request.headers.get(this.config.timestampHeader ||
118
+ this.config.customConfig?.timestampHeader ||
119
+ "x-webhook-timestamp");
120
+ // if either is missing payload will be malformed โ€” fail explicitly
121
+ if (!id || !timestamp) {
122
+ throw new Error(`Missing required headers for payload construction: ${!id ? this.config.customConfig.idHeader || "x-webhook-id" : ""} ${!timestamp
123
+ ? this.config.timestampHeader || "x-webhook-timestamp"
124
+ : ""}`.trim());
125
+ }
111
126
  return customFormat
112
- .replace("{id}", id || "")
113
- .replace("{timestamp}", timestamp || "")
127
+ .replace("{id}", id.trim() || "")
128
+ .replace("{timestamp}", timestamp.trim() || "")
114
129
  .replace("{body}", rawBody);
115
130
  }
116
131
  if (customFormat.includes("{timestamp}") &&
@@ -178,9 +193,16 @@ class AlgorithmBasedVerifier extends base_1.WebhookVerifier {
178
193
  metadata.id = request.headers.get(this.config.customConfig?.idHeader || "webhook-id");
179
194
  break;
180
195
  case "workos":
181
- metadata.id = request.headers.get(this.config.customConfig?.idHeader || "webhook-id");
196
+ case "sentry":
197
+ case "sanity":
198
+ metadata.id = request.headers.get(this.config.idHeader ||
199
+ this.config.customConfig?.idHeader ||
200
+ "webhook-id");
182
201
  break;
183
202
  default:
203
+ if (this.config.idHeader) {
204
+ metadata.id = request.headers.get(this.config.idHeader);
205
+ }
184
206
  break;
185
207
  }
186
208
  return metadata;
@@ -188,6 +210,33 @@ class AlgorithmBasedVerifier extends base_1.WebhookVerifier {
188
210
  }
189
211
  exports.AlgorithmBasedVerifier = AlgorithmBasedVerifier;
190
212
  class GenericHMACVerifier extends AlgorithmBasedVerifier {
213
+ resolveSentryPayloadCandidates(rawBody, request) {
214
+ const candidates = [
215
+ this.formatPayload(rawBody, request),
216
+ rawBody,
217
+ ];
218
+ if (this.config.payloadFormat === "json-stringified") {
219
+ try {
220
+ const parsed = JSON.parse(rawBody);
221
+ candidates.push(JSON.stringify(parsed));
222
+ const issueAlertPath = this.config.customConfig?.issueAlertPayloadPath;
223
+ if (issueAlertPath) {
224
+ const segments = `${issueAlertPath}`.split(".").filter(Boolean);
225
+ let current = parsed;
226
+ for (const segment of segments) {
227
+ current = current?.[segment];
228
+ }
229
+ if (current !== undefined) {
230
+ candidates.push(typeof current === "string" ? current : JSON.stringify(current));
231
+ }
232
+ }
233
+ }
234
+ catch {
235
+ // ignore malformed JSON payloads
236
+ }
237
+ }
238
+ return [...new Set(candidates.filter(Boolean))];
239
+ }
191
240
  async verify(request) {
192
241
  try {
193
242
  const signature = this.extractSignature(request);
@@ -215,17 +264,24 @@ class GenericHMACVerifier extends AlgorithmBasedVerifier {
215
264
  platform: this.platform,
216
265
  };
217
266
  }
218
- const payload = this.formatPayload(rawBody, request);
267
+ const payloadCandidates = this.platform === "sentry"
268
+ ? this.resolveSentryPayloadCandidates(rawBody, request)
269
+ : [this.formatPayload(rawBody, request)];
219
270
  let isValid = false;
220
271
  const algorithm = this.config.algorithm.replace("hmac-", "");
221
- if (this.config.customConfig?.encoding === "base64") {
222
- isValid = this.verifyHMACWithBase64(payload, signature, algorithm);
223
- }
224
- else if (this.config.headerFormat === "prefixed") {
225
- isValid = this.verifyHMACWithPrefix(payload, signature, algorithm);
226
- }
227
- else {
228
- isValid = this.verifyHMAC(payload, signature, algorithm);
272
+ for (const payload of payloadCandidates) {
273
+ if (this.config.customConfig?.encoding === "base64") {
274
+ isValid = this.verifyHMACWithBase64(payload, signature, algorithm);
275
+ }
276
+ else if (this.config.headerFormat === "prefixed") {
277
+ isValid = this.verifyHMACWithPrefix(payload, signature, algorithm);
278
+ }
279
+ else {
280
+ isValid = this.verifyHMAC(payload, signature, algorithm);
281
+ }
282
+ if (isValid) {
283
+ break;
284
+ }
229
285
  }
230
286
  if (!isValid) {
231
287
  return {
@@ -242,11 +298,18 @@ class GenericHMACVerifier extends AlgorithmBasedVerifier {
242
298
  catch (e) {
243
299
  parsedPayload = rawBody;
244
300
  }
301
+ const metadata = this.extractMetadata(request);
302
+ if (this.platform === "doppler" && !metadata.id) {
303
+ const timestamp = metadata.timestamp || Math.floor(Date.now() / 1000).toString();
304
+ metadata.id = (0, crypto_1.createHash)("sha256")
305
+ .update(`${timestamp}:${rawBody}`)
306
+ .digest("hex");
307
+ }
245
308
  return {
246
309
  isValid: true,
247
310
  platform: this.platform,
248
311
  payload: parsedPayload,
249
- metadata: this.extractMetadata(request),
312
+ metadata,
250
313
  };
251
314
  }
252
315
  catch (error) {
@@ -1,4 +1,4 @@
1
- import { WebhookVerificationResult } from "../types";
1
+ import { WebhookVerificationResult } from '../types';
2
2
  export declare abstract class WebhookVerifier {
3
3
  protected secret: string;
4
4
  protected toleranceInSeconds: number;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TokenBasedVerifier = void 0;
4
4
  exports.createCustomVerifier = createCustomVerifier;
5
5
  const base_1 = require("./base");
6
- // Token-based verifier for platforms like Supabase
6
+ // Token-based verifier for providers that use header token authentication
7
7
  class TokenBasedVerifier extends base_1.WebhookVerifier {
8
8
  constructor(secret, config, toleranceInSeconds = 300) {
9
9
  super(secret, toleranceInSeconds);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hookflo/tern",
3
- "version": "2.2.10",
3
+ "version": "3.0.1",
4
4
  "description": "A robust, scalable webhook verification framework supporting multiple platforms and signature algorithms",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",