ezthrottle 1.1.1 → 1.4.0

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/client.d.ts CHANGED
@@ -54,5 +54,113 @@ export declare class EZThrottle {
54
54
  queueRequest({ url, webhookUrl, method, headers, body, metadata, retryAt }: QueueRequestParams): Promise<any>;
55
55
  request({ url, method, headers, body }: RequestParams): Promise<any>;
56
56
  queueAndWait({ url, webhookUrl, method, headers, body, metadata, retryAt, timeout, pollInterval, }: QueueAndWaitParams): Promise<any>;
57
+ /**
58
+ * Create or update webhook HMAC secrets for signature verification.
59
+ *
60
+ * @param primarySecret - Primary webhook secret (min 16 characters)
61
+ * @param secondarySecret - Optional secondary secret for rotation (min 16 characters)
62
+ * @returns Response with status and message
63
+ * @throws {Error} If secret creation fails
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Create primary secret
68
+ * await client.createWebhookSecret('your_secure_secret_here_min_16_chars');
69
+ *
70
+ * // Create with rotation support (primary + secondary)
71
+ * await client.createWebhookSecret(
72
+ * 'new_secret_after_rotation',
73
+ * 'old_secret_before_rotation'
74
+ * );
75
+ * ```
76
+ */
77
+ createWebhookSecret(primarySecret: string, secondarySecret?: string): Promise<any>;
78
+ /**
79
+ * Get webhook secrets (masked for security).
80
+ *
81
+ * @returns Object with masked secrets
82
+ * @throws {Error} If secrets not configured (404) or request fails
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const secrets = await client.getWebhookSecret();
87
+ * console.log(secrets);
88
+ * // {
89
+ * // customer_id: 'cust_XXX',
90
+ * // primary_secret: 'your****ars',
91
+ * // secondary_secret: 'opti****ars',
92
+ * // has_secondary: true
93
+ * // }
94
+ * ```
95
+ */
96
+ getWebhookSecret(): Promise<any>;
97
+ /**
98
+ * Delete webhook secrets.
99
+ *
100
+ * @returns Response with status and message
101
+ * @throws {Error} If deletion fails
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const result = await client.deleteWebhookSecret();
106
+ * console.log(result); // { status: 'ok', message: 'Webhook secrets deleted' }
107
+ * ```
108
+ */
109
+ deleteWebhookSecret(): Promise<any>;
110
+ /**
111
+ * Rotate webhook secret safely by promoting secondary to primary.
112
+ *
113
+ * @param newSecret - New webhook secret to set as primary
114
+ * @returns Response with status and message
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * // Step 1: Rotate (keeps old secret as backup)
119
+ * await client.rotateWebhookSecret('new_secret_min_16_chars');
120
+ *
121
+ * // Step 2: After verifying webhooks work with new secret
122
+ * // Remove old secret by setting only new one
123
+ * await client.createWebhookSecret('new_secret_min_16_chars');
124
+ * ```
125
+ */
126
+ /**
127
+ * Try to forward request to EZThrottle, fall back to callback if EZThrottle is unreachable.
128
+ *
129
+ * This makes EZThrottle a reliability LAYER, not a single point of failure.
130
+ * If EZThrottle is down, you just lose the extra reliability features and
131
+ * fall back to your existing solution.
132
+ *
133
+ * @param fallback - Callback function to execute if EZThrottle is unreachable
134
+ * @param options - Job options (same as submitJob)
135
+ * @returns Either EZThrottle job response or the fallback function's return value
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * // If EZThrottle is down, fall back to direct HTTP call
140
+ * const result = await client.forwardOrFallback(
141
+ * async () => {
142
+ * const response = await fetch('https://api.stripe.com/charges', {
143
+ * method: 'POST',
144
+ * headers: { 'Authorization': 'Bearer sk_live_...' },
145
+ * body: JSON.stringify({ amount: 1000 })
146
+ * });
147
+ * return response.json();
148
+ * },
149
+ * {
150
+ * url: 'https://api.stripe.com/charges',
151
+ * method: 'POST',
152
+ * headers: { 'Authorization': 'Bearer sk_live_...' },
153
+ * body: JSON.stringify({ amount: 1000 }),
154
+ * webhooks: [{ url: 'https://your-app.com/webhook' }]
155
+ * }
156
+ * );
157
+ * ```
158
+ *
159
+ * Note: The fallback is ONLY called when EZThrottle itself is unreachable
160
+ * (connection errors, timeouts). It is NOT called for rate limiting or
161
+ * other EZThrottle errors - those indicate EZThrottle is working.
162
+ */
163
+ forwardOrFallback<T>(fallback: () => Promise<T>, options: SubmitJobParams): Promise<any | T>;
164
+ rotateWebhookSecret(newSecret: string): Promise<any>;
57
165
  }
58
166
  export {};
package/dist/client.js CHANGED
@@ -173,5 +173,256 @@ class EZThrottle {
173
173
  checkResult();
174
174
  });
175
175
  }
176
+ // ============================================================================
177
+ // WEBHOOK SECRETS MANAGEMENT
178
+ // ============================================================================
179
+ /**
180
+ * Create or update webhook HMAC secrets for signature verification.
181
+ *
182
+ * @param primarySecret - Primary webhook secret (min 16 characters)
183
+ * @param secondarySecret - Optional secondary secret for rotation (min 16 characters)
184
+ * @returns Response with status and message
185
+ * @throws {Error} If secret creation fails
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * // Create primary secret
190
+ * await client.createWebhookSecret('your_secure_secret_here_min_16_chars');
191
+ *
192
+ * // Create with rotation support (primary + secondary)
193
+ * await client.createWebhookSecret(
194
+ * 'new_secret_after_rotation',
195
+ * 'old_secret_before_rotation'
196
+ * );
197
+ * ```
198
+ */
199
+ async createWebhookSecret(primarySecret, secondarySecret) {
200
+ if (primarySecret.length < 16) {
201
+ throw new Error('primarySecret must be at least 16 characters');
202
+ }
203
+ if (secondarySecret && secondarySecret.length < 16) {
204
+ throw new Error('secondarySecret must be at least 16 characters');
205
+ }
206
+ const payload = { primary_secret: primarySecret };
207
+ if (secondarySecret) {
208
+ payload.secondary_secret = secondarySecret;
209
+ }
210
+ const proxyPayload = {
211
+ scope: 'customer',
212
+ metric_name: '',
213
+ target_url: `${this.ezthrottleUrl}/api/v1/webhook-secrets`,
214
+ method: 'POST',
215
+ headers: { 'Content-Type': 'application/json' },
216
+ body: JSON.stringify(payload),
217
+ };
218
+ const response = await (0, node_fetch_1.default)(`${this.tracktagsUrl}/api/v1/proxy`, {
219
+ method: 'POST',
220
+ headers: {
221
+ 'Authorization': `Bearer ${this.apiKey}`,
222
+ 'Content-Type': 'application/json',
223
+ },
224
+ body: JSON.stringify(proxyPayload),
225
+ });
226
+ if (response.status !== 200) {
227
+ const text = await response.text();
228
+ throw new errors_1.EZThrottleError(`Failed to create webhook secret: ${text}`);
229
+ }
230
+ const proxyResponse = await response.json();
231
+ if (proxyResponse.status !== 'allowed') {
232
+ throw new errors_1.EZThrottleError(`Request denied: ${proxyResponse.error || 'Unknown error'}`);
233
+ }
234
+ const forwarded = proxyResponse.forwarded_response || {};
235
+ return JSON.parse(forwarded.body || '{}');
236
+ }
237
+ /**
238
+ * Get webhook secrets (masked for security).
239
+ *
240
+ * @returns Object with masked secrets
241
+ * @throws {Error} If secrets not configured (404) or request fails
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * const secrets = await client.getWebhookSecret();
246
+ * console.log(secrets);
247
+ * // {
248
+ * // customer_id: 'cust_XXX',
249
+ * // primary_secret: 'your****ars',
250
+ * // secondary_secret: 'opti****ars',
251
+ * // has_secondary: true
252
+ * // }
253
+ * ```
254
+ */
255
+ async getWebhookSecret() {
256
+ const proxyPayload = {
257
+ scope: 'customer',
258
+ metric_name: '',
259
+ target_url: `${this.ezthrottleUrl}/api/v1/webhook-secrets`,
260
+ method: 'GET',
261
+ headers: {},
262
+ body: '',
263
+ };
264
+ const response = await (0, node_fetch_1.default)(`${this.tracktagsUrl}/api/v1/proxy`, {
265
+ method: 'POST',
266
+ headers: {
267
+ 'Authorization': `Bearer ${this.apiKey}`,
268
+ 'Content-Type': 'application/json',
269
+ },
270
+ body: JSON.stringify(proxyPayload),
271
+ });
272
+ if (response.status !== 200) {
273
+ const text = await response.text();
274
+ throw new errors_1.EZThrottleError(`Failed to get webhook secret: ${text}`);
275
+ }
276
+ const proxyResponse = await response.json();
277
+ if (proxyResponse.status !== 'allowed') {
278
+ throw new errors_1.EZThrottleError(`Request denied: ${proxyResponse.error || 'Unknown error'}`);
279
+ }
280
+ const forwarded = proxyResponse.forwarded_response || {};
281
+ const statusCode = forwarded.status_code || 0;
282
+ if (statusCode === 404) {
283
+ throw new errors_1.EZThrottleError('No webhook secrets configured. Call createWebhookSecret() first.');
284
+ }
285
+ if (statusCode < 200 || statusCode >= 300) {
286
+ throw new errors_1.EZThrottleError(`Failed to get webhook secrets: ${forwarded.body}`);
287
+ }
288
+ return JSON.parse(forwarded.body || '{}');
289
+ }
290
+ /**
291
+ * Delete webhook secrets.
292
+ *
293
+ * @returns Response with status and message
294
+ * @throws {Error} If deletion fails
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const result = await client.deleteWebhookSecret();
299
+ * console.log(result); // { status: 'ok', message: 'Webhook secrets deleted' }
300
+ * ```
301
+ */
302
+ async deleteWebhookSecret() {
303
+ const proxyPayload = {
304
+ scope: 'customer',
305
+ metric_name: '',
306
+ target_url: `${this.ezthrottleUrl}/api/v1/webhook-secrets`,
307
+ method: 'DELETE',
308
+ headers: {},
309
+ body: '',
310
+ };
311
+ const response = await (0, node_fetch_1.default)(`${this.tracktagsUrl}/api/v1/proxy`, {
312
+ method: 'POST',
313
+ headers: {
314
+ 'Authorization': `Bearer ${this.apiKey}`,
315
+ 'Content-Type': 'application/json',
316
+ },
317
+ body: JSON.stringify(proxyPayload),
318
+ });
319
+ if (response.status !== 200) {
320
+ const text = await response.text();
321
+ throw new errors_1.EZThrottleError(`Failed to delete webhook secret: ${text}`);
322
+ }
323
+ const proxyResponse = await response.json();
324
+ if (proxyResponse.status !== 'allowed') {
325
+ throw new errors_1.EZThrottleError(`Request denied: ${proxyResponse.error || 'Unknown error'}`);
326
+ }
327
+ const forwarded = proxyResponse.forwarded_response || {};
328
+ return JSON.parse(forwarded.body || '{}');
329
+ }
330
+ /**
331
+ * Rotate webhook secret safely by promoting secondary to primary.
332
+ *
333
+ * @param newSecret - New webhook secret to set as primary
334
+ * @returns Response with status and message
335
+ *
336
+ * @example
337
+ * ```typescript
338
+ * // Step 1: Rotate (keeps old secret as backup)
339
+ * await client.rotateWebhookSecret('new_secret_min_16_chars');
340
+ *
341
+ * // Step 2: After verifying webhooks work with new secret
342
+ * // Remove old secret by setting only new one
343
+ * await client.createWebhookSecret('new_secret_min_16_chars');
344
+ * ```
345
+ */
346
+ /**
347
+ * Try to forward request to EZThrottle, fall back to callback if EZThrottle is unreachable.
348
+ *
349
+ * This makes EZThrottle a reliability LAYER, not a single point of failure.
350
+ * If EZThrottle is down, you just lose the extra reliability features and
351
+ * fall back to your existing solution.
352
+ *
353
+ * @param fallback - Callback function to execute if EZThrottle is unreachable
354
+ * @param options - Job options (same as submitJob)
355
+ * @returns Either EZThrottle job response or the fallback function's return value
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * // If EZThrottle is down, fall back to direct HTTP call
360
+ * const result = await client.forwardOrFallback(
361
+ * async () => {
362
+ * const response = await fetch('https://api.stripe.com/charges', {
363
+ * method: 'POST',
364
+ * headers: { 'Authorization': 'Bearer sk_live_...' },
365
+ * body: JSON.stringify({ amount: 1000 })
366
+ * });
367
+ * return response.json();
368
+ * },
369
+ * {
370
+ * url: 'https://api.stripe.com/charges',
371
+ * method: 'POST',
372
+ * headers: { 'Authorization': 'Bearer sk_live_...' },
373
+ * body: JSON.stringify({ amount: 1000 }),
374
+ * webhooks: [{ url: 'https://your-app.com/webhook' }]
375
+ * }
376
+ * );
377
+ * ```
378
+ *
379
+ * Note: The fallback is ONLY called when EZThrottle itself is unreachable
380
+ * (connection errors, timeouts). It is NOT called for rate limiting or
381
+ * other EZThrottle errors - those indicate EZThrottle is working.
382
+ */
383
+ async forwardOrFallback(fallback, options) {
384
+ try {
385
+ return await this.submitJob(options);
386
+ }
387
+ catch (error) {
388
+ // Check if it's a network/connection error
389
+ if (error.code === 'ECONNREFUSED' ||
390
+ error.code === 'ENOTFOUND' ||
391
+ error.code === 'ETIMEDOUT' ||
392
+ error.code === 'ECONNRESET' ||
393
+ error.name === 'AbortError' ||
394
+ error.type === 'system') {
395
+ // EZThrottle is unreachable - use fallback
396
+ return fallback();
397
+ }
398
+ // Re-throw other errors (rate limiting, validation, etc.)
399
+ throw error;
400
+ }
401
+ }
402
+ async rotateWebhookSecret(newSecret) {
403
+ if (newSecret.length < 16) {
404
+ throw new Error('newSecret must be at least 16 characters');
405
+ }
406
+ try {
407
+ // Get current secret to use as secondary
408
+ const current = await this.getWebhookSecret();
409
+ const oldPrimary = current.primary_secret || '';
410
+ // If we have a masked secret, we can't use it as secondary
411
+ // In this case, just set the new secret without secondary
412
+ if (oldPrimary.includes('****')) {
413
+ return this.createWebhookSecret(newSecret);
414
+ }
415
+ // Set new as primary, old as secondary
416
+ return this.createWebhookSecret(newSecret, oldPrimary);
417
+ }
418
+ catch (error) {
419
+ if (error instanceof errors_1.EZThrottleError &&
420
+ error.message.includes('No webhook secrets configured')) {
421
+ // No existing secret, just create new one
422
+ return this.createWebhookSecret(newSecret);
423
+ }
424
+ throw error;
425
+ }
426
+ }
176
427
  }
177
428
  exports.EZThrottle = EZThrottle;
@@ -0,0 +1,75 @@
1
+ import { EZThrottle } from './client';
2
+ import { StepType } from './stepType';
3
+ import { WebhookConfig } from './types';
4
+ /**
5
+ * ForwardRequest - Represents a request that should be forwarded to EZThrottle
6
+ *
7
+ * Use this with executeWithForwarding() to integrate EZThrottle into legacy code
8
+ * without rewriting error handling.
9
+ */
10
+ export interface ForwardRequest {
11
+ url: string;
12
+ method?: string;
13
+ headers?: Record<string, string>;
14
+ body?: string;
15
+ idempotentKey?: string;
16
+ metadata?: Record<string, any>;
17
+ webhooks?: WebhookConfig[];
18
+ regions?: string[];
19
+ fallbackOnError?: number[];
20
+ stepType?: StepType;
21
+ }
22
+ /**
23
+ * executeWithForwarding - Higher-order function that wraps legacy code to auto-forward errors
24
+ *
25
+ * This is the Node.js equivalent of Python's @auto_forward decorator.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Legacy function that may throw ForwardRequest on errors
30
+ * async function processPayment(orderId: string): Promise<any> {
31
+ * try {
32
+ * const response = await fetch('https://api.stripe.com/charges', {...});
33
+ * if (response.status === 429) {
34
+ * // Return ForwardRequest to trigger auto-forwarding
35
+ * return {
36
+ * forward: {
37
+ * url: 'https://api.stripe.com/charges',
38
+ * method: 'POST',
39
+ * idempotentKey: `order_${orderId}`,
40
+ * webhooks: [{url: 'https://app.com/webhook', hasQuorumVote: true}]
41
+ * }
42
+ * };
43
+ * }
44
+ * return await response.json();
45
+ * } catch (error) {
46
+ * // Network error - forward to EZThrottle
47
+ * return {
48
+ * forward: {
49
+ * url: 'https://api.stripe.com/charges',
50
+ * method: 'POST',
51
+ * idempotentKey: `order_${orderId}`
52
+ * }
53
+ * };
54
+ * }
55
+ * }
56
+ *
57
+ * // Wrap with auto-forwarding
58
+ * const result = await executeWithForwarding(client, () => processPayment('order_123'));
59
+ * ```
60
+ */
61
+ export declare function executeWithForwarding<T>(client: EZThrottle, fn: () => Promise<T | {
62
+ forward: ForwardRequest;
63
+ }>): Promise<T | any>;
64
+ /**
65
+ * withAutoForward - Decorator-style wrapper for async functions
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const processPaymentWithForwarding = withAutoForward(client, processPayment);
70
+ * const result = await processPaymentWithForwarding('order_123');
71
+ * ```
72
+ */
73
+ export declare function withAutoForward<TArgs extends any[], TReturn>(client: EZThrottle, fn: (...args: TArgs) => Promise<TReturn | {
74
+ forward: ForwardRequest;
75
+ }>): (...args: TArgs) => Promise<TReturn | any>;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeWithForwarding = executeWithForwarding;
4
+ exports.withAutoForward = withAutoForward;
5
+ const step_1 = require("./step");
6
+ const stepType_1 = require("./stepType");
7
+ /**
8
+ * executeWithForwarding - Higher-order function that wraps legacy code to auto-forward errors
9
+ *
10
+ * This is the Node.js equivalent of Python's @auto_forward decorator.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Legacy function that may throw ForwardRequest on errors
15
+ * async function processPayment(orderId: string): Promise<any> {
16
+ * try {
17
+ * const response = await fetch('https://api.stripe.com/charges', {...});
18
+ * if (response.status === 429) {
19
+ * // Return ForwardRequest to trigger auto-forwarding
20
+ * return {
21
+ * forward: {
22
+ * url: 'https://api.stripe.com/charges',
23
+ * method: 'POST',
24
+ * idempotentKey: `order_${orderId}`,
25
+ * webhooks: [{url: 'https://app.com/webhook', hasQuorumVote: true}]
26
+ * }
27
+ * };
28
+ * }
29
+ * return await response.json();
30
+ * } catch (error) {
31
+ * // Network error - forward to EZThrottle
32
+ * return {
33
+ * forward: {
34
+ * url: 'https://api.stripe.com/charges',
35
+ * method: 'POST',
36
+ * idempotentKey: `order_${orderId}`
37
+ * }
38
+ * };
39
+ * }
40
+ * }
41
+ *
42
+ * // Wrap with auto-forwarding
43
+ * const result = await executeWithForwarding(client, () => processPayment('order_123'));
44
+ * ```
45
+ */
46
+ async function executeWithForwarding(client, fn) {
47
+ const result = await fn();
48
+ // Check if result contains a ForwardRequest
49
+ if (result && typeof result === 'object' && 'forward' in result) {
50
+ const forwardReq = result.forward;
51
+ // Auto-forward to EZThrottle
52
+ const step = new step_1.Step(client)
53
+ .url(forwardReq.url)
54
+ .method(forwardReq.method || 'GET');
55
+ if (forwardReq.headers) {
56
+ step.headers(forwardReq.headers);
57
+ }
58
+ if (forwardReq.body) {
59
+ step.body(forwardReq.body);
60
+ }
61
+ if (forwardReq.idempotentKey) {
62
+ step.idempotentKey(forwardReq.idempotentKey);
63
+ }
64
+ if (forwardReq.metadata) {
65
+ step.metadata(forwardReq.metadata);
66
+ }
67
+ if (forwardReq.webhooks) {
68
+ step.webhooks(forwardReq.webhooks);
69
+ }
70
+ if (forwardReq.regions) {
71
+ step.regions(forwardReq.regions);
72
+ }
73
+ // Set step type (default to FRUGAL if not specified)
74
+ if (forwardReq.stepType) {
75
+ step.type(forwardReq.stepType);
76
+ }
77
+ else {
78
+ step.type(stepType_1.StepType.FRUGAL);
79
+ }
80
+ // Set fallback on error codes if specified
81
+ if (forwardReq.fallbackOnError && forwardReq.fallbackOnError.length > 0) {
82
+ step.fallbackOnError(forwardReq.fallbackOnError);
83
+ }
84
+ return await step.execute();
85
+ }
86
+ return result;
87
+ }
88
+ /**
89
+ * withAutoForward - Decorator-style wrapper for async functions
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * const processPaymentWithForwarding = withAutoForward(client, processPayment);
94
+ * const result = await processPaymentWithForwarding('order_123');
95
+ * ```
96
+ */
97
+ function withAutoForward(client, fn) {
98
+ return async (...args) => {
99
+ return executeWithForwarding(client, () => fn(...args));
100
+ };
101
+ }
package/dist/index.d.ts CHANGED
@@ -4,5 +4,8 @@ export { Step } from './step';
4
4
  export { StepType } from './stepType';
5
5
  export { IdempotentStrategy } from './idempotentStrategy';
6
6
  export * from './types';
7
+ export { executeWithForwarding, withAutoForward } from './forward';
8
+ export type { ForwardRequest } from './forward';
9
+ export { verifyWebhookSignature, verifyWebhookSignatureStrict, tryVerifyWithSecrets, WebhookVerificationError, VerificationResult } from './webhookUtils';
7
10
  import { EZThrottle } from './client';
8
11
  export default EZThrottle;
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.IdempotentStrategy = exports.StepType = exports.Step = exports.RateLimitError = exports.TimeoutError = exports.EZThrottleError = exports.EZThrottle = void 0;
17
+ exports.WebhookVerificationError = exports.tryVerifyWithSecrets = exports.verifyWebhookSignatureStrict = exports.verifyWebhookSignature = exports.withAutoForward = exports.executeWithForwarding = exports.IdempotentStrategy = exports.StepType = exports.Step = exports.RateLimitError = exports.TimeoutError = exports.EZThrottleError = exports.EZThrottle = void 0;
18
18
  var client_1 = require("./client");
19
19
  Object.defineProperty(exports, "EZThrottle", { enumerable: true, get: function () { return client_1.EZThrottle; } });
20
20
  var errors_1 = require("./errors");
@@ -28,6 +28,14 @@ Object.defineProperty(exports, "StepType", { enumerable: true, get: function ()
28
28
  var idempotentStrategy_1 = require("./idempotentStrategy");
29
29
  Object.defineProperty(exports, "IdempotentStrategy", { enumerable: true, get: function () { return idempotentStrategy_1.IdempotentStrategy; } });
30
30
  __exportStar(require("./types"), exports);
31
+ var forward_1 = require("./forward");
32
+ Object.defineProperty(exports, "executeWithForwarding", { enumerable: true, get: function () { return forward_1.executeWithForwarding; } });
33
+ Object.defineProperty(exports, "withAutoForward", { enumerable: true, get: function () { return forward_1.withAutoForward; } });
34
+ var webhookUtils_1 = require("./webhookUtils");
35
+ Object.defineProperty(exports, "verifyWebhookSignature", { enumerable: true, get: function () { return webhookUtils_1.verifyWebhookSignature; } });
36
+ Object.defineProperty(exports, "verifyWebhookSignatureStrict", { enumerable: true, get: function () { return webhookUtils_1.verifyWebhookSignatureStrict; } });
37
+ Object.defineProperty(exports, "tryVerifyWithSecrets", { enumerable: true, get: function () { return webhookUtils_1.tryVerifyWithSecrets; } });
38
+ Object.defineProperty(exports, "WebhookVerificationError", { enumerable: true, get: function () { return webhookUtils_1.WebhookVerificationError; } });
31
39
  // Default export for CommonJS compatibility
32
40
  const client_2 = require("./client");
33
41
  exports.default = client_2.EZThrottle;