@webhooks-cc/sdk 1.2.0 → 1.3.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.
@@ -26,11 +26,16 @@ var TimeoutError = class extends WebhooksCCError {
26
26
  }
27
27
  };
28
28
  var RateLimitError = class extends WebhooksCCError {
29
- constructor(retryAfter) {
30
- const message = retryAfter ? `Rate limited, retry after ${retryAfter}s` : "Rate limited";
29
+ constructor(retryAfter, meta) {
30
+ const message = retryAfter !== void 0 ? `Rate limited, retry after ${retryAfter}s` : "Rate limited";
31
31
  super(429, message);
32
32
  this.name = "RateLimitError";
33
33
  this.retryAfter = retryAfter;
34
+ if (meta) {
35
+ this.limit = meta.limit;
36
+ this.remaining = meta.remaining;
37
+ this.reset = meta.reset;
38
+ }
34
39
  }
35
40
  };
36
41
 
@@ -18,6 +18,10 @@ interface Endpoint {
18
18
  name?: string;
19
19
  /** Full URL where webhooks should be sent (undefined if server is misconfigured) */
20
20
  url?: string;
21
+ /** URL to POST a JSON summary to after each captured request (e.g. Slack/Discord webhook) */
22
+ notificationUrl?: string;
23
+ /** Ordered conditional response rules (first match wins, then falls back to default mock) */
24
+ responseRules?: ResponseRule[];
21
25
  /** Whether the endpoint auto-expires and may be cleaned up automatically */
22
26
  isEphemeral?: boolean;
23
27
  /** Unix timestamp (ms) when the endpoint expires, if ephemeral */
@@ -29,6 +33,34 @@ interface Endpoint {
29
33
  /** Team this endpoint was shared from (present when shared with you) */
30
34
  fromTeam?: TeamShare;
31
35
  }
36
+ /** A single condition within a response rule. */
37
+ interface ResponseRuleCondition {
38
+ /** Field to match: method, path, header, body_contains, body_path, query */
39
+ field: "method" | "path" | "header" | "body_contains" | "body_path" | "query";
40
+ /** Comparison operator */
41
+ op: "eq" | "contains" | "starts_with" | "matches" | "exists";
42
+ /** Value to compare against (not required for "exists") */
43
+ value?: string;
44
+ /** Header name or query param name (required for header/query conditions) */
45
+ name?: string;
46
+ /** JSON dot-notation path (required for body_path conditions) */
47
+ path?: string;
48
+ }
49
+ /** A conditional response rule: when conditions match, return this response. */
50
+ interface ResponseRule {
51
+ /** Stable identifier for UI drag-reorder */
52
+ id?: string;
53
+ /** Human-readable rule name */
54
+ name?: string;
55
+ /** Whether this rule is active (default: true) */
56
+ enabled?: boolean;
57
+ /** How to combine conditions: "and" (all match) or "or" (any match). Default: "and" */
58
+ logic?: "and" | "or";
59
+ /** Conditions to evaluate against the incoming request */
60
+ conditions: ResponseRuleCondition[];
61
+ /** Response to return when conditions match */
62
+ response: MockResponse;
63
+ }
32
64
  /** Mock response returned by the receiver instead of the default 200 OK. */
33
65
  interface MockResponse {
34
66
  /** HTTP status code (100-599) */
@@ -57,6 +89,8 @@ interface Request {
57
89
  headers: Record<string, string>;
58
90
  /** Request body, if present */
59
91
  body?: string;
92
+ /** Base64-encoded raw bytes, present only for non-UTF-8 payloads */
93
+ bodyRaw?: string;
60
94
  /** URL query parameters */
61
95
  queryParams: Record<string, string>;
62
96
  /** Content-Type header value, if present */
@@ -121,6 +155,10 @@ interface CreateEndpointOptions {
121
155
  expiresIn?: number | string;
122
156
  /** Optional mock response to configure at creation time */
123
157
  mockResponse?: MockResponse;
158
+ /** URL to POST a JSON summary to after each captured request */
159
+ notificationUrl?: string;
160
+ /** Ordered conditional response rules */
161
+ responseRules?: ResponseRule[];
124
162
  }
125
163
  /**
126
164
  * Options for updating an existing endpoint.
@@ -130,6 +168,10 @@ interface UpdateEndpointOptions {
130
168
  name?: string;
131
169
  /** Mock response config, or null to clear */
132
170
  mockResponse?: MockResponse | null;
171
+ /** Notification webhook URL, or null to clear */
172
+ notificationUrl?: string | null;
173
+ /** Ordered conditional response rules, or null to clear */
174
+ responseRules?: ResponseRule[] | null;
133
175
  }
134
176
  /**
135
177
  * Options for sending a test webhook to an endpoint.
@@ -488,11 +530,26 @@ declare class NotFoundError extends WebhooksCCError {
488
530
  declare class TimeoutError extends WebhooksCCError {
489
531
  constructor(timeoutMs: number);
490
532
  }
533
+ /** Rate limit metadata from X-RateLimit-* response headers. */
534
+ interface RateLimitMeta {
535
+ /** Maximum number of requests allowed in the current window. */
536
+ limit: number;
537
+ /** Number of requests remaining in the current window. */
538
+ remaining: number;
539
+ /** Unix epoch timestamp (seconds) when the rate limit window resets. */
540
+ reset: number;
541
+ }
491
542
  /** Thrown when the API returns 429 Too Many Requests. */
492
543
  declare class RateLimitError extends WebhooksCCError {
493
544
  /** Seconds until the rate limit resets, if provided by the server. */
494
545
  readonly retryAfter?: number;
495
- constructor(retryAfter?: number);
546
+ /** Maximum number of requests allowed in the current window. */
547
+ readonly limit?: number;
548
+ /** Number of requests remaining in the current window. */
549
+ readonly remaining?: number;
550
+ /** Unix epoch timestamp (seconds) when the rate limit window resets. */
551
+ readonly reset?: number;
552
+ constructor(retryAfter?: number, meta?: RateLimitMeta);
496
553
  }
497
554
 
498
555
  interface FlowClient {
@@ -711,4 +768,4 @@ type ComparableRequest = Pick<Request, "method" | "path" | "headers" | "body"> &
711
768
  */
712
769
  declare function diffRequests(left: ComparableRequest | SearchResult, right: ComparableRequest | SearchResult, options?: DiffRequestsOptions): DiffResult;
713
770
 
714
- export { type WebhookFlowResult as $, ApiError as A, type BodyDiff as B, type ClearRequestsOptions as C, type DiffRequestsOptions as D, type Endpoint as E, type FormBodyValue as F, type TextBodyDiff as G, type HarExport as H, TimeoutError as I, type JsonBodyDiff as J, type UpdateEndpointOptions as K, type ListPaginatedRequestsOptions as L, type MockResponse as M, NotFoundError as N, type OperationDescription as O, type ParsedBody as P, type UsageInfo as Q, type Request as R, type SearchResult as S, type TeamShare as T, UnauthorizedError as U, type VerifySignatureOptions as V, type ValueDifference as W, type VerifyProvider as X, type WaitForAllOptions as Y, type WaitForOptions as Z, WebhookFlowBuilder as _, type ParsedFormBody as a, type WebhookFlowVerifyOptions as a0, WebhooksCC as a1, WebhooksCCError as a2, diffRequests as a3, type SignatureVerificationResult as b, type ClientHooks as c, type ClientOptions as d, type CreateEndpointOptions as e, type CurlExport as f, type DiffResult as g, type ErrorHookInfo as h, type ExportRequestsOptions as i, type HeaderDiff as j, type ListRequestsOptions as k, type PaginatedResult as l, RateLimitError as m, type RequestDifferences as n, type RequestHookInfo as o, type RequestsExport as p, type ResponseHookInfo as q, type RetryOptions as r, type SDKDescription as s, type SearchFilters as t, type SendOptions as u, type SendTemplateOptions as v, type SendToOptions as w, type SubscribeOptions as x, type TemplateProvider as y, type TemplateProviderInfo as z };
771
+ export { type WaitForAllOptions as $, ApiError as A, type BodyDiff as B, type ClearRequestsOptions as C, type DiffRequestsOptions as D, type Endpoint as E, type FormBodyValue as F, type SubscribeOptions as G, type HarExport as H, type TemplateProvider as I, type JsonBodyDiff as J, type TemplateProviderInfo as K, type ListPaginatedRequestsOptions as L, type MockResponse as M, NotFoundError as N, type OperationDescription as O, type ParsedBody as P, type TextBodyDiff as Q, type Request as R, type SendTemplateOptions as S, type TeamShare as T, TimeoutError as U, type VerifySignatureOptions as V, UnauthorizedError as W, type UpdateEndpointOptions as X, type UsageInfo as Y, type ValueDifference as Z, type VerifyProvider as _, type ParsedFormBody as a, type WaitForOptions as a0, WebhookFlowBuilder as a1, type WebhookFlowResult as a2, type WebhookFlowVerifyOptions as a3, WebhooksCC as a4, WebhooksCCError as a5, diffRequests as a6, type SendOptions as b, type ResponseRule as c, type SearchResult as d, type SignatureVerificationResult as e, type ClientHooks as f, type ClientOptions as g, type CreateEndpointOptions as h, type CurlExport as i, type DiffResult as j, type ErrorHookInfo as k, type ExportRequestsOptions as l, type HeaderDiff as m, type ListRequestsOptions as n, type PaginatedResult as o, RateLimitError as p, type RateLimitMeta as q, type RequestDifferences as r, type RequestHookInfo as s, type RequestsExport as t, type ResponseHookInfo as u, type ResponseRuleCondition as v, type RetryOptions as w, type SDKDescription as x, type SearchFilters as y, type SendToOptions as z };
@@ -18,6 +18,10 @@ interface Endpoint {
18
18
  name?: string;
19
19
  /** Full URL where webhooks should be sent (undefined if server is misconfigured) */
20
20
  url?: string;
21
+ /** URL to POST a JSON summary to after each captured request (e.g. Slack/Discord webhook) */
22
+ notificationUrl?: string;
23
+ /** Ordered conditional response rules (first match wins, then falls back to default mock) */
24
+ responseRules?: ResponseRule[];
21
25
  /** Whether the endpoint auto-expires and may be cleaned up automatically */
22
26
  isEphemeral?: boolean;
23
27
  /** Unix timestamp (ms) when the endpoint expires, if ephemeral */
@@ -29,6 +33,34 @@ interface Endpoint {
29
33
  /** Team this endpoint was shared from (present when shared with you) */
30
34
  fromTeam?: TeamShare;
31
35
  }
36
+ /** A single condition within a response rule. */
37
+ interface ResponseRuleCondition {
38
+ /** Field to match: method, path, header, body_contains, body_path, query */
39
+ field: "method" | "path" | "header" | "body_contains" | "body_path" | "query";
40
+ /** Comparison operator */
41
+ op: "eq" | "contains" | "starts_with" | "matches" | "exists";
42
+ /** Value to compare against (not required for "exists") */
43
+ value?: string;
44
+ /** Header name or query param name (required for header/query conditions) */
45
+ name?: string;
46
+ /** JSON dot-notation path (required for body_path conditions) */
47
+ path?: string;
48
+ }
49
+ /** A conditional response rule: when conditions match, return this response. */
50
+ interface ResponseRule {
51
+ /** Stable identifier for UI drag-reorder */
52
+ id?: string;
53
+ /** Human-readable rule name */
54
+ name?: string;
55
+ /** Whether this rule is active (default: true) */
56
+ enabled?: boolean;
57
+ /** How to combine conditions: "and" (all match) or "or" (any match). Default: "and" */
58
+ logic?: "and" | "or";
59
+ /** Conditions to evaluate against the incoming request */
60
+ conditions: ResponseRuleCondition[];
61
+ /** Response to return when conditions match */
62
+ response: MockResponse;
63
+ }
32
64
  /** Mock response returned by the receiver instead of the default 200 OK. */
33
65
  interface MockResponse {
34
66
  /** HTTP status code (100-599) */
@@ -57,6 +89,8 @@ interface Request {
57
89
  headers: Record<string, string>;
58
90
  /** Request body, if present */
59
91
  body?: string;
92
+ /** Base64-encoded raw bytes, present only for non-UTF-8 payloads */
93
+ bodyRaw?: string;
60
94
  /** URL query parameters */
61
95
  queryParams: Record<string, string>;
62
96
  /** Content-Type header value, if present */
@@ -121,6 +155,10 @@ interface CreateEndpointOptions {
121
155
  expiresIn?: number | string;
122
156
  /** Optional mock response to configure at creation time */
123
157
  mockResponse?: MockResponse;
158
+ /** URL to POST a JSON summary to after each captured request */
159
+ notificationUrl?: string;
160
+ /** Ordered conditional response rules */
161
+ responseRules?: ResponseRule[];
124
162
  }
125
163
  /**
126
164
  * Options for updating an existing endpoint.
@@ -130,6 +168,10 @@ interface UpdateEndpointOptions {
130
168
  name?: string;
131
169
  /** Mock response config, or null to clear */
132
170
  mockResponse?: MockResponse | null;
171
+ /** Notification webhook URL, or null to clear */
172
+ notificationUrl?: string | null;
173
+ /** Ordered conditional response rules, or null to clear */
174
+ responseRules?: ResponseRule[] | null;
133
175
  }
134
176
  /**
135
177
  * Options for sending a test webhook to an endpoint.
@@ -488,11 +530,26 @@ declare class NotFoundError extends WebhooksCCError {
488
530
  declare class TimeoutError extends WebhooksCCError {
489
531
  constructor(timeoutMs: number);
490
532
  }
533
+ /** Rate limit metadata from X-RateLimit-* response headers. */
534
+ interface RateLimitMeta {
535
+ /** Maximum number of requests allowed in the current window. */
536
+ limit: number;
537
+ /** Number of requests remaining in the current window. */
538
+ remaining: number;
539
+ /** Unix epoch timestamp (seconds) when the rate limit window resets. */
540
+ reset: number;
541
+ }
491
542
  /** Thrown when the API returns 429 Too Many Requests. */
492
543
  declare class RateLimitError extends WebhooksCCError {
493
544
  /** Seconds until the rate limit resets, if provided by the server. */
494
545
  readonly retryAfter?: number;
495
- constructor(retryAfter?: number);
546
+ /** Maximum number of requests allowed in the current window. */
547
+ readonly limit?: number;
548
+ /** Number of requests remaining in the current window. */
549
+ readonly remaining?: number;
550
+ /** Unix epoch timestamp (seconds) when the rate limit window resets. */
551
+ readonly reset?: number;
552
+ constructor(retryAfter?: number, meta?: RateLimitMeta);
496
553
  }
497
554
 
498
555
  interface FlowClient {
@@ -711,4 +768,4 @@ type ComparableRequest = Pick<Request, "method" | "path" | "headers" | "body"> &
711
768
  */
712
769
  declare function diffRequests(left: ComparableRequest | SearchResult, right: ComparableRequest | SearchResult, options?: DiffRequestsOptions): DiffResult;
713
770
 
714
- export { type WebhookFlowResult as $, ApiError as A, type BodyDiff as B, type ClearRequestsOptions as C, type DiffRequestsOptions as D, type Endpoint as E, type FormBodyValue as F, type TextBodyDiff as G, type HarExport as H, TimeoutError as I, type JsonBodyDiff as J, type UpdateEndpointOptions as K, type ListPaginatedRequestsOptions as L, type MockResponse as M, NotFoundError as N, type OperationDescription as O, type ParsedBody as P, type UsageInfo as Q, type Request as R, type SearchResult as S, type TeamShare as T, UnauthorizedError as U, type VerifySignatureOptions as V, type ValueDifference as W, type VerifyProvider as X, type WaitForAllOptions as Y, type WaitForOptions as Z, WebhookFlowBuilder as _, type ParsedFormBody as a, type WebhookFlowVerifyOptions as a0, WebhooksCC as a1, WebhooksCCError as a2, diffRequests as a3, type SignatureVerificationResult as b, type ClientHooks as c, type ClientOptions as d, type CreateEndpointOptions as e, type CurlExport as f, type DiffResult as g, type ErrorHookInfo as h, type ExportRequestsOptions as i, type HeaderDiff as j, type ListRequestsOptions as k, type PaginatedResult as l, RateLimitError as m, type RequestDifferences as n, type RequestHookInfo as o, type RequestsExport as p, type ResponseHookInfo as q, type RetryOptions as r, type SDKDescription as s, type SearchFilters as t, type SendOptions as u, type SendTemplateOptions as v, type SendToOptions as w, type SubscribeOptions as x, type TemplateProvider as y, type TemplateProviderInfo as z };
771
+ export { type WaitForAllOptions as $, ApiError as A, type BodyDiff as B, type ClearRequestsOptions as C, type DiffRequestsOptions as D, type Endpoint as E, type FormBodyValue as F, type SubscribeOptions as G, type HarExport as H, type TemplateProvider as I, type JsonBodyDiff as J, type TemplateProviderInfo as K, type ListPaginatedRequestsOptions as L, type MockResponse as M, NotFoundError as N, type OperationDescription as O, type ParsedBody as P, type TextBodyDiff as Q, type Request as R, type SendTemplateOptions as S, type TeamShare as T, TimeoutError as U, type VerifySignatureOptions as V, UnauthorizedError as W, type UpdateEndpointOptions as X, type UsageInfo as Y, type ValueDifference as Z, type VerifyProvider as _, type ParsedFormBody as a, type WaitForOptions as a0, WebhookFlowBuilder as a1, type WebhookFlowResult as a2, type WebhookFlowVerifyOptions as a3, WebhooksCC as a4, WebhooksCCError as a5, diffRequests as a6, type SendOptions as b, type ResponseRule as c, type SearchResult as d, type SignatureVerificationResult as e, type ClientHooks as f, type ClientOptions as g, type CreateEndpointOptions as h, type CurlExport as i, type DiffResult as j, type ErrorHookInfo as k, type ExportRequestsOptions as l, type HeaderDiff as m, type ListRequestsOptions as n, type PaginatedResult as o, RateLimitError as p, type RateLimitMeta as q, type RequestDifferences as r, type RequestHookInfo as s, type RequestsExport as t, type ResponseHookInfo as u, type ResponseRuleCondition as v, type RetryOptions as w, type SDKDescription as x, type SearchFilters as y, type SendToOptions as z };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Request, P as ParsedBody, a as ParsedFormBody, S as SearchResult, V as VerifySignatureOptions, b as SignatureVerificationResult } from './diff-DbTsOT_n.mjs';
2
- export { A as ApiError, B as BodyDiff, C as ClearRequestsOptions, c as ClientHooks, d as ClientOptions, e as CreateEndpointOptions, f as CurlExport, D as DiffRequestsOptions, g as DiffResult, E as Endpoint, h as ErrorHookInfo, i as ExportRequestsOptions, F as FormBodyValue, H as HarExport, j as HeaderDiff, J as JsonBodyDiff, L as ListPaginatedRequestsOptions, k as ListRequestsOptions, M as MockResponse, N as NotFoundError, O as OperationDescription, l as PaginatedResult, m as RateLimitError, n as RequestDifferences, o as RequestHookInfo, p as RequestsExport, q as ResponseHookInfo, r as RetryOptions, s as SDKDescription, t as SearchFilters, u as SendOptions, v as SendTemplateOptions, w as SendToOptions, x as SubscribeOptions, T as TeamShare, y as TemplateProvider, z as TemplateProviderInfo, G as TextBodyDiff, I as TimeoutError, U as UnauthorizedError, K as UpdateEndpointOptions, Q as UsageInfo, W as ValueDifference, X as VerifyProvider, Y as WaitForAllOptions, Z as WaitForOptions, _ as WebhookFlowBuilder, $ as WebhookFlowResult, a0 as WebhookFlowVerifyOptions, a1 as WebhooksCC, a2 as WebhooksCCError, a3 as diffRequests } from './diff-DbTsOT_n.mjs';
1
+ import { R as Request, P as ParsedBody, a as ParsedFormBody, S as SendTemplateOptions, b as SendOptions, M as MockResponse, c as ResponseRule, d as SearchResult, V as VerifySignatureOptions, e as SignatureVerificationResult } from './diff-CRMlHQPX.mjs';
2
+ export { A as ApiError, B as BodyDiff, C as ClearRequestsOptions, f as ClientHooks, g as ClientOptions, h as CreateEndpointOptions, i as CurlExport, D as DiffRequestsOptions, j as DiffResult, E as Endpoint, k as ErrorHookInfo, l as ExportRequestsOptions, F as FormBodyValue, H as HarExport, m as HeaderDiff, J as JsonBodyDiff, L as ListPaginatedRequestsOptions, n as ListRequestsOptions, N as NotFoundError, O as OperationDescription, o as PaginatedResult, p as RateLimitError, q as RateLimitMeta, r as RequestDifferences, s as RequestHookInfo, t as RequestsExport, u as ResponseHookInfo, v as ResponseRuleCondition, w as RetryOptions, x as SDKDescription, y as SearchFilters, z as SendToOptions, G as SubscribeOptions, T as TeamShare, I as TemplateProvider, K as TemplateProviderInfo, Q as TextBodyDiff, U as TimeoutError, W as UnauthorizedError, X as UpdateEndpointOptions, Y as UsageInfo, Z as ValueDifference, _ as VerifyProvider, $ as WaitForAllOptions, a0 as WaitForOptions, a1 as WebhookFlowBuilder, a2 as WebhookFlowResult, a3 as WebhookFlowVerifyOptions, a4 as WebhooksCC, a5 as WebhooksCCError, a6 as diffRequests } from './diff-CRMlHQPX.mjs';
3
3
 
4
4
  /**
5
5
  * Safely parse a JSON request body.
@@ -140,6 +140,8 @@ interface SSEFrame {
140
140
  */
141
141
  declare function parseSSE(stream: ReadableStream<Uint8Array>): AsyncGenerator<SSEFrame, void, undefined>;
142
142
 
143
+ declare const TEMPLATE_PROVIDERS: readonly ["stripe", "github", "shopify", "twilio", "slack", "paddle", "linear", "sendgrid", "clerk", "discord", "vercel", "gitlab", "standard-webhooks"];
144
+ declare const VERIFY_PROVIDERS: readonly ["stripe", "github", "shopify", "twilio", "slack", "paddle", "linear", "clerk", "discord", "vercel", "gitlab", "standard-webhooks"];
143
145
  declare const TEMPLATE_METADATA: Readonly<{
144
146
  stripe: Readonly<{
145
147
  provider: "stripe";
@@ -241,6 +243,24 @@ declare const TEMPLATE_METADATA: Readonly<{
241
243
  signatureAlgorithm: "hmac-sha256";
242
244
  }>;
243
245
  }>;
246
+ /**
247
+ * Build method/headers/body for a provider template webhook.
248
+ */
249
+ declare function buildTemplateSendOptions(endpointUrl: string, options: SendTemplateOptions): Promise<SendOptions>;
250
+
251
+ declare const MOCK_RESPONSE_STATUS_MIN = 100;
252
+ declare const MOCK_RESPONSE_STATUS_MAX = 599;
253
+ declare const MOCK_RESPONSE_DELAY_MIN = 0;
254
+ declare const MOCK_RESPONSE_DELAY_MAX = 30000;
255
+ declare const MAX_RESPONSE_RULES = 50;
256
+ declare const MAX_CONDITIONS_PER_RULE = 10;
257
+ declare const MAX_CONDITION_VALUE_LEN = 4096;
258
+ declare const MAX_CONDITION_NAME_LEN = 256;
259
+ declare const MAX_CONDITION_PATH_LEN = 256;
260
+ declare const MAX_RULE_NAME_LEN = 200;
261
+ declare const MAX_GLOB_PATTERN_LEN = 500;
262
+ declare function validateMockResponse(mockResponse: MockResponse, fieldName?: string): void;
263
+ declare function validateResponseRules(rules: ResponseRule[]): void;
244
264
 
245
265
  type VerifyableRequest = Pick<Request, "body" | "headers"> | Pick<SearchResult, "body" | "headers">;
246
266
  /**
@@ -299,4 +319,4 @@ declare function verifyStandardWebhookSignature(body: string | undefined, header
299
319
  */
300
320
  declare function verifySignature(request: VerifyableRequest, options: VerifySignatureOptions): Promise<SignatureVerificationResult>;
301
321
 
302
- export { ParsedBody, ParsedFormBody, Request, type SSEFrame, SearchResult, SignatureVerificationResult, TEMPLATE_METADATA, VerifySignatureOptions, extractJsonField, isClerkWebhook, isDiscordWebhook, isGitHubWebhook, isGitLabWebhook, isLinearWebhook, isPaddleWebhook, isSendGridWebhook, isShopifyWebhook, isSlackWebhook, isStandardWebhook, isStripeWebhook, isTwilioWebhook, isVercelWebhook, matchAll, matchAny, matchBodyPath, matchBodySubset, matchContentType, matchHeader, matchJsonField, matchMethod, matchPath, matchQueryParam, parseBody, parseDuration, parseFormBody, parseJsonBody, parseSSE, verifyClerkSignature, verifyDiscordSignature, verifyGitHubSignature, verifyGitLabSignature, verifyLinearSignature, verifyPaddleSignature, verifyShopifySignature, verifySignature, verifySlackSignature, verifyStandardWebhookSignature, verifyStripeSignature, verifyTwilioSignature, verifyVercelSignature };
322
+ export { MAX_CONDITIONS_PER_RULE, MAX_CONDITION_NAME_LEN, MAX_CONDITION_PATH_LEN, MAX_CONDITION_VALUE_LEN, MAX_GLOB_PATTERN_LEN, MAX_RESPONSE_RULES, MAX_RULE_NAME_LEN, MOCK_RESPONSE_DELAY_MAX, MOCK_RESPONSE_DELAY_MIN, MOCK_RESPONSE_STATUS_MAX, MOCK_RESPONSE_STATUS_MIN, MockResponse, ParsedBody, ParsedFormBody, Request, ResponseRule, type SSEFrame, SearchResult, SendOptions, SendTemplateOptions, SignatureVerificationResult, TEMPLATE_METADATA, TEMPLATE_PROVIDERS, VERIFY_PROVIDERS, VerifySignatureOptions, buildTemplateSendOptions, extractJsonField, isClerkWebhook, isDiscordWebhook, isGitHubWebhook, isGitLabWebhook, isLinearWebhook, isPaddleWebhook, isSendGridWebhook, isShopifyWebhook, isSlackWebhook, isStandardWebhook, isStripeWebhook, isTwilioWebhook, isVercelWebhook, matchAll, matchAny, matchBodyPath, matchBodySubset, matchContentType, matchHeader, matchJsonField, matchMethod, matchPath, matchQueryParam, parseBody, parseDuration, parseFormBody, parseJsonBody, parseSSE, validateMockResponse, validateResponseRules, verifyClerkSignature, verifyDiscordSignature, verifyGitHubSignature, verifyGitLabSignature, verifyLinearSignature, verifyPaddleSignature, verifyShopifySignature, verifySignature, verifySlackSignature, verifyStandardWebhookSignature, verifyStripeSignature, verifyTwilioSignature, verifyVercelSignature };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Request, P as ParsedBody, a as ParsedFormBody, S as SearchResult, V as VerifySignatureOptions, b as SignatureVerificationResult } from './diff-DbTsOT_n.js';
2
- export { A as ApiError, B as BodyDiff, C as ClearRequestsOptions, c as ClientHooks, d as ClientOptions, e as CreateEndpointOptions, f as CurlExport, D as DiffRequestsOptions, g as DiffResult, E as Endpoint, h as ErrorHookInfo, i as ExportRequestsOptions, F as FormBodyValue, H as HarExport, j as HeaderDiff, J as JsonBodyDiff, L as ListPaginatedRequestsOptions, k as ListRequestsOptions, M as MockResponse, N as NotFoundError, O as OperationDescription, l as PaginatedResult, m as RateLimitError, n as RequestDifferences, o as RequestHookInfo, p as RequestsExport, q as ResponseHookInfo, r as RetryOptions, s as SDKDescription, t as SearchFilters, u as SendOptions, v as SendTemplateOptions, w as SendToOptions, x as SubscribeOptions, T as TeamShare, y as TemplateProvider, z as TemplateProviderInfo, G as TextBodyDiff, I as TimeoutError, U as UnauthorizedError, K as UpdateEndpointOptions, Q as UsageInfo, W as ValueDifference, X as VerifyProvider, Y as WaitForAllOptions, Z as WaitForOptions, _ as WebhookFlowBuilder, $ as WebhookFlowResult, a0 as WebhookFlowVerifyOptions, a1 as WebhooksCC, a2 as WebhooksCCError, a3 as diffRequests } from './diff-DbTsOT_n.js';
1
+ import { R as Request, P as ParsedBody, a as ParsedFormBody, S as SendTemplateOptions, b as SendOptions, M as MockResponse, c as ResponseRule, d as SearchResult, V as VerifySignatureOptions, e as SignatureVerificationResult } from './diff-CRMlHQPX.js';
2
+ export { A as ApiError, B as BodyDiff, C as ClearRequestsOptions, f as ClientHooks, g as ClientOptions, h as CreateEndpointOptions, i as CurlExport, D as DiffRequestsOptions, j as DiffResult, E as Endpoint, k as ErrorHookInfo, l as ExportRequestsOptions, F as FormBodyValue, H as HarExport, m as HeaderDiff, J as JsonBodyDiff, L as ListPaginatedRequestsOptions, n as ListRequestsOptions, N as NotFoundError, O as OperationDescription, o as PaginatedResult, p as RateLimitError, q as RateLimitMeta, r as RequestDifferences, s as RequestHookInfo, t as RequestsExport, u as ResponseHookInfo, v as ResponseRuleCondition, w as RetryOptions, x as SDKDescription, y as SearchFilters, z as SendToOptions, G as SubscribeOptions, T as TeamShare, I as TemplateProvider, K as TemplateProviderInfo, Q as TextBodyDiff, U as TimeoutError, W as UnauthorizedError, X as UpdateEndpointOptions, Y as UsageInfo, Z as ValueDifference, _ as VerifyProvider, $ as WaitForAllOptions, a0 as WaitForOptions, a1 as WebhookFlowBuilder, a2 as WebhookFlowResult, a3 as WebhookFlowVerifyOptions, a4 as WebhooksCC, a5 as WebhooksCCError, a6 as diffRequests } from './diff-CRMlHQPX.js';
3
3
 
4
4
  /**
5
5
  * Safely parse a JSON request body.
@@ -140,6 +140,8 @@ interface SSEFrame {
140
140
  */
141
141
  declare function parseSSE(stream: ReadableStream<Uint8Array>): AsyncGenerator<SSEFrame, void, undefined>;
142
142
 
143
+ declare const TEMPLATE_PROVIDERS: readonly ["stripe", "github", "shopify", "twilio", "slack", "paddle", "linear", "sendgrid", "clerk", "discord", "vercel", "gitlab", "standard-webhooks"];
144
+ declare const VERIFY_PROVIDERS: readonly ["stripe", "github", "shopify", "twilio", "slack", "paddle", "linear", "clerk", "discord", "vercel", "gitlab", "standard-webhooks"];
143
145
  declare const TEMPLATE_METADATA: Readonly<{
144
146
  stripe: Readonly<{
145
147
  provider: "stripe";
@@ -241,6 +243,24 @@ declare const TEMPLATE_METADATA: Readonly<{
241
243
  signatureAlgorithm: "hmac-sha256";
242
244
  }>;
243
245
  }>;
246
+ /**
247
+ * Build method/headers/body for a provider template webhook.
248
+ */
249
+ declare function buildTemplateSendOptions(endpointUrl: string, options: SendTemplateOptions): Promise<SendOptions>;
250
+
251
+ declare const MOCK_RESPONSE_STATUS_MIN = 100;
252
+ declare const MOCK_RESPONSE_STATUS_MAX = 599;
253
+ declare const MOCK_RESPONSE_DELAY_MIN = 0;
254
+ declare const MOCK_RESPONSE_DELAY_MAX = 30000;
255
+ declare const MAX_RESPONSE_RULES = 50;
256
+ declare const MAX_CONDITIONS_PER_RULE = 10;
257
+ declare const MAX_CONDITION_VALUE_LEN = 4096;
258
+ declare const MAX_CONDITION_NAME_LEN = 256;
259
+ declare const MAX_CONDITION_PATH_LEN = 256;
260
+ declare const MAX_RULE_NAME_LEN = 200;
261
+ declare const MAX_GLOB_PATTERN_LEN = 500;
262
+ declare function validateMockResponse(mockResponse: MockResponse, fieldName?: string): void;
263
+ declare function validateResponseRules(rules: ResponseRule[]): void;
244
264
 
245
265
  type VerifyableRequest = Pick<Request, "body" | "headers"> | Pick<SearchResult, "body" | "headers">;
246
266
  /**
@@ -299,4 +319,4 @@ declare function verifyStandardWebhookSignature(body: string | undefined, header
299
319
  */
300
320
  declare function verifySignature(request: VerifyableRequest, options: VerifySignatureOptions): Promise<SignatureVerificationResult>;
301
321
 
302
- export { ParsedBody, ParsedFormBody, Request, type SSEFrame, SearchResult, SignatureVerificationResult, TEMPLATE_METADATA, VerifySignatureOptions, extractJsonField, isClerkWebhook, isDiscordWebhook, isGitHubWebhook, isGitLabWebhook, isLinearWebhook, isPaddleWebhook, isSendGridWebhook, isShopifyWebhook, isSlackWebhook, isStandardWebhook, isStripeWebhook, isTwilioWebhook, isVercelWebhook, matchAll, matchAny, matchBodyPath, matchBodySubset, matchContentType, matchHeader, matchJsonField, matchMethod, matchPath, matchQueryParam, parseBody, parseDuration, parseFormBody, parseJsonBody, parseSSE, verifyClerkSignature, verifyDiscordSignature, verifyGitHubSignature, verifyGitLabSignature, verifyLinearSignature, verifyPaddleSignature, verifyShopifySignature, verifySignature, verifySlackSignature, verifyStandardWebhookSignature, verifyStripeSignature, verifyTwilioSignature, verifyVercelSignature };
322
+ export { MAX_CONDITIONS_PER_RULE, MAX_CONDITION_NAME_LEN, MAX_CONDITION_PATH_LEN, MAX_CONDITION_VALUE_LEN, MAX_GLOB_PATTERN_LEN, MAX_RESPONSE_RULES, MAX_RULE_NAME_LEN, MOCK_RESPONSE_DELAY_MAX, MOCK_RESPONSE_DELAY_MIN, MOCK_RESPONSE_STATUS_MAX, MOCK_RESPONSE_STATUS_MIN, MockResponse, ParsedBody, ParsedFormBody, Request, ResponseRule, type SSEFrame, SearchResult, SendOptions, SendTemplateOptions, SignatureVerificationResult, TEMPLATE_METADATA, TEMPLATE_PROVIDERS, VERIFY_PROVIDERS, VerifySignatureOptions, buildTemplateSendOptions, extractJsonField, isClerkWebhook, isDiscordWebhook, isGitHubWebhook, isGitLabWebhook, isLinearWebhook, isPaddleWebhook, isSendGridWebhook, isShopifyWebhook, isSlackWebhook, isStandardWebhook, isStripeWebhook, isTwilioWebhook, isVercelWebhook, matchAll, matchAny, matchBodyPath, matchBodySubset, matchContentType, matchHeader, matchJsonField, matchMethod, matchPath, matchQueryParam, parseBody, parseDuration, parseFormBody, parseJsonBody, parseSSE, validateMockResponse, validateResponseRules, verifyClerkSignature, verifyDiscordSignature, verifyGitHubSignature, verifyGitLabSignature, verifyLinearSignature, verifyPaddleSignature, verifyShopifySignature, verifySignature, verifySlackSignature, verifyStandardWebhookSignature, verifyStripeSignature, verifyTwilioSignature, verifyVercelSignature };
package/dist/index.js CHANGED
@@ -21,14 +21,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  ApiError: () => ApiError,
24
+ MAX_CONDITIONS_PER_RULE: () => MAX_CONDITIONS_PER_RULE,
25
+ MAX_CONDITION_NAME_LEN: () => MAX_CONDITION_NAME_LEN,
26
+ MAX_CONDITION_PATH_LEN: () => MAX_CONDITION_PATH_LEN,
27
+ MAX_CONDITION_VALUE_LEN: () => MAX_CONDITION_VALUE_LEN,
28
+ MAX_GLOB_PATTERN_LEN: () => MAX_GLOB_PATTERN_LEN,
29
+ MAX_RESPONSE_RULES: () => MAX_RESPONSE_RULES,
30
+ MAX_RULE_NAME_LEN: () => MAX_RULE_NAME_LEN,
31
+ MOCK_RESPONSE_DELAY_MAX: () => MOCK_RESPONSE_DELAY_MAX,
32
+ MOCK_RESPONSE_DELAY_MIN: () => MOCK_RESPONSE_DELAY_MIN,
33
+ MOCK_RESPONSE_STATUS_MAX: () => MOCK_RESPONSE_STATUS_MAX,
34
+ MOCK_RESPONSE_STATUS_MIN: () => MOCK_RESPONSE_STATUS_MIN,
24
35
  NotFoundError: () => NotFoundError,
25
36
  RateLimitError: () => RateLimitError,
26
37
  TEMPLATE_METADATA: () => TEMPLATE_METADATA,
38
+ TEMPLATE_PROVIDERS: () => TEMPLATE_PROVIDERS,
27
39
  TimeoutError: () => TimeoutError,
28
40
  UnauthorizedError: () => UnauthorizedError,
41
+ VERIFY_PROVIDERS: () => VERIFY_PROVIDERS,
29
42
  WebhookFlowBuilder: () => WebhookFlowBuilder,
30
43
  WebhooksCC: () => WebhooksCC,
31
44
  WebhooksCCError: () => WebhooksCCError,
45
+ buildTemplateSendOptions: () => buildTemplateSendOptions,
32
46
  diffRequests: () => diffRequests,
33
47
  extractJsonField: () => extractJsonField,
34
48
  isClerkWebhook: () => isClerkWebhook,
@@ -59,6 +73,8 @@ __export(src_exports, {
59
73
  parseFormBody: () => parseFormBody,
60
74
  parseJsonBody: () => parseJsonBody,
61
75
  parseSSE: () => parseSSE,
76
+ validateMockResponse: () => validateMockResponse,
77
+ validateResponseRules: () => validateResponseRules,
62
78
  verifyClerkSignature: () => verifyClerkSignature,
63
79
  verifyDiscordSignature: () => verifyDiscordSignature,
64
80
  verifyGitHubSignature: () => verifyGitHubSignature,
@@ -103,11 +119,16 @@ var TimeoutError = class extends WebhooksCCError {
103
119
  }
104
120
  };
105
121
  var RateLimitError = class extends WebhooksCCError {
106
- constructor(retryAfter) {
107
- const message = retryAfter ? `Rate limited, retry after ${retryAfter}s` : "Rate limited";
122
+ constructor(retryAfter, meta) {
123
+ const message = retryAfter !== void 0 ? `Rate limited, retry after ${retryAfter}s` : "Rate limited";
108
124
  super(429, message);
109
125
  this.name = "RateLimitError";
110
126
  this.retryAfter = retryAfter;
127
+ if (meta) {
128
+ this.limit = meta.limit;
129
+ this.remaining = meta.remaining;
130
+ this.reset = meta.reset;
131
+ }
111
132
  }
112
133
  };
113
134
 
@@ -268,6 +289,20 @@ var TEMPLATE_PROVIDERS = [
268
289
  "gitlab",
269
290
  "standard-webhooks"
270
291
  ];
292
+ var VERIFY_PROVIDERS = [
293
+ "stripe",
294
+ "github",
295
+ "shopify",
296
+ "twilio",
297
+ "slack",
298
+ "paddle",
299
+ "linear",
300
+ "clerk",
301
+ "discord",
302
+ "vercel",
303
+ "gitlab",
304
+ "standard-webhooks"
305
+ ];
271
306
  var TEMPLATE_METADATA = Object.freeze({
272
307
  stripe: Object.freeze({
273
308
  provider: "stripe",
@@ -2181,6 +2216,122 @@ var WebhookFlowBuilder = class {
2181
2216
  }
2182
2217
  };
2183
2218
 
2219
+ // src/validation.ts
2220
+ var MOCK_RESPONSE_STATUS_MIN = 100;
2221
+ var MOCK_RESPONSE_STATUS_MAX = 599;
2222
+ var MOCK_RESPONSE_DELAY_MIN = 0;
2223
+ var MOCK_RESPONSE_DELAY_MAX = 3e4;
2224
+ var MAX_RESPONSE_RULES = 50;
2225
+ var MAX_CONDITIONS_PER_RULE = 10;
2226
+ var VALID_CONDITION_FIELDS = /* @__PURE__ */ new Set([
2227
+ "method",
2228
+ "path",
2229
+ "header",
2230
+ "body_contains",
2231
+ "body_path",
2232
+ "query"
2233
+ ]);
2234
+ var VALID_CONDITION_OPS = /* @__PURE__ */ new Set(["eq", "contains", "starts_with", "matches", "exists"]);
2235
+ var VALID_OPS_BY_FIELD = {
2236
+ method: /* @__PURE__ */ new Set(["eq"]),
2237
+ path: /* @__PURE__ */ new Set(["eq", "contains", "starts_with", "matches"]),
2238
+ header: /* @__PURE__ */ new Set(["exists", "eq", "contains"]),
2239
+ body_contains: /* @__PURE__ */ new Set(["contains"]),
2240
+ body_path: /* @__PURE__ */ new Set(["exists", "eq", "contains"]),
2241
+ query: /* @__PURE__ */ new Set(["exists", "eq"])
2242
+ };
2243
+ var MAX_CONDITION_VALUE_LEN = 4096;
2244
+ var MAX_CONDITION_NAME_LEN = 256;
2245
+ var MAX_CONDITION_PATH_LEN = 256;
2246
+ var MAX_RULE_NAME_LEN = 200;
2247
+ var MAX_GLOB_PATTERN_LEN = 500;
2248
+ function validateMockResponse(mockResponse, fieldName = "mock response") {
2249
+ const { status, body, headers, delay } = mockResponse;
2250
+ if (!Number.isInteger(status) || status < MOCK_RESPONSE_STATUS_MIN || status > MOCK_RESPONSE_STATUS_MAX) {
2251
+ throw new Error(
2252
+ `Invalid ${fieldName} status: ${status}. Must be an integer ${MOCK_RESPONSE_STATUS_MIN}-${MOCK_RESPONSE_STATUS_MAX}.`
2253
+ );
2254
+ }
2255
+ if (body !== void 0 && typeof body !== "string") {
2256
+ throw new Error(`Invalid ${fieldName} body: must be a string.`);
2257
+ }
2258
+ if (headers !== void 0) {
2259
+ if (typeof headers !== "object" || headers === null || Array.isArray(headers)) {
2260
+ throw new Error(`Invalid ${fieldName} headers: must be a Record<string, string>.`);
2261
+ }
2262
+ for (const val of Object.values(headers)) {
2263
+ if (typeof val !== "string") {
2264
+ throw new Error(`Invalid ${fieldName} headers: all values must be strings.`);
2265
+ }
2266
+ }
2267
+ }
2268
+ if (delay !== void 0 && (!Number.isInteger(delay) || delay < MOCK_RESPONSE_DELAY_MIN || delay > MOCK_RESPONSE_DELAY_MAX)) {
2269
+ throw new Error(
2270
+ `Invalid ${fieldName} delay: ${delay}. Must be an integer ${MOCK_RESPONSE_DELAY_MIN}-${MOCK_RESPONSE_DELAY_MAX}.`
2271
+ );
2272
+ }
2273
+ }
2274
+ function validateResponseRules(rules) {
2275
+ if (!Array.isArray(rules)) {
2276
+ throw new Error("responseRules must be an array");
2277
+ }
2278
+ if (rules.length > MAX_RESPONSE_RULES) {
2279
+ throw new Error(`responseRules: max ${MAX_RESPONSE_RULES} rules allowed`);
2280
+ }
2281
+ for (let i = 0; i < rules.length; i++) {
2282
+ const rule = rules[i];
2283
+ const prefix = `responseRules[${i}]`;
2284
+ if (rule.name !== void 0 && (typeof rule.name !== "string" || rule.name.length > MAX_RULE_NAME_LEN)) {
2285
+ throw new Error(`${prefix}: name must be a string (max ${MAX_RULE_NAME_LEN} chars)`);
2286
+ }
2287
+ if (!Array.isArray(rule.conditions) || rule.conditions.length === 0) {
2288
+ throw new Error(`${prefix}: conditions must be a non-empty array`);
2289
+ }
2290
+ if (rule.conditions.length > MAX_CONDITIONS_PER_RULE) {
2291
+ throw new Error(`${prefix}: max ${MAX_CONDITIONS_PER_RULE} conditions per rule`);
2292
+ }
2293
+ if (rule.logic !== void 0 && rule.logic !== "and" && rule.logic !== "or") {
2294
+ throw new Error(`${prefix}: logic must be "and" or "or"`);
2295
+ }
2296
+ for (let j = 0; j < rule.conditions.length; j++) {
2297
+ const c = rule.conditions[j];
2298
+ const cp = `${prefix}.conditions[${j}]`;
2299
+ if (!VALID_CONDITION_FIELDS.has(c.field)) {
2300
+ throw new Error(`${cp}: invalid field "${c.field}"`);
2301
+ }
2302
+ if (!VALID_CONDITION_OPS.has(c.op)) {
2303
+ throw new Error(`${cp}: invalid op "${c.op}"`);
2304
+ }
2305
+ const fieldOps = VALID_OPS_BY_FIELD[c.field];
2306
+ if (fieldOps && !fieldOps.has(c.op)) {
2307
+ throw new Error(`${cp}: op "${c.op}" is not valid for field "${c.field}"`);
2308
+ }
2309
+ if (c.value !== void 0 && typeof c.value === "string" && c.value.length > MAX_CONDITION_VALUE_LEN) {
2310
+ throw new Error(`${cp}: value too long (max ${MAX_CONDITION_VALUE_LEN} chars)`);
2311
+ }
2312
+ if (c.name !== void 0 && typeof c.name === "string" && c.name.length > MAX_CONDITION_NAME_LEN) {
2313
+ throw new Error(`${cp}: name too long (max ${MAX_CONDITION_NAME_LEN} chars)`);
2314
+ }
2315
+ if (c.path !== void 0 && typeof c.path === "string" && c.path.length > MAX_CONDITION_PATH_LEN) {
2316
+ throw new Error(`${cp}: path too long (max ${MAX_CONDITION_PATH_LEN} chars)`);
2317
+ }
2318
+ if ((c.field === "header" || c.field === "query") && (!c.name || c.name.length === 0)) {
2319
+ throw new Error(`${cp}: name is required for ${c.field} conditions`);
2320
+ }
2321
+ if (c.field === "body_path" && (!c.path || c.path.length === 0)) {
2322
+ throw new Error(`${cp}: path is required for body_path conditions`);
2323
+ }
2324
+ if (c.op !== "exists" && (c.value === void 0 || c.value === null)) {
2325
+ throw new Error(`${cp}: value is required when op is "${c.op}"`);
2326
+ }
2327
+ if (c.op === "matches" && c.value && c.value.length > MAX_GLOB_PATTERN_LEN) {
2328
+ throw new Error(`${cp}: matches pattern too long (max ${MAX_GLOB_PATTERN_LEN} chars)`);
2329
+ }
2330
+ }
2331
+ validateMockResponse(rule.response, `${prefix}.response`);
2332
+ }
2333
+ }
2334
+
2184
2335
  // src/client.ts
2185
2336
  var DEFAULT_BASE_URL = "https://webhooks.cc";
2186
2337
  var DEFAULT_WEBHOOK_URL = "https://go.webhooks.cc";
@@ -2188,7 +2339,7 @@ var DEFAULT_TIMEOUT = 3e4;
2188
2339
  var DEFAULT_RETRY_ATTEMPTS = 1;
2189
2340
  var DEFAULT_RETRY_BACKOFF_MS = 1e3;
2190
2341
  var DEFAULT_RETRY_STATUSES = [429, 500, 502, 503, 504];
2191
- var SDK_VERSION = "0.6.0";
2342
+ var SDK_VERSION = true ? "1.3.0" : "0.0.0-dev";
2192
2343
  var WAIT_FOR_LOOKBACK_MS = 5 * 60 * 1e3;
2193
2344
  var DEFAULT_EXPORT_PAGE_SIZE = 100;
2194
2345
  var PROVIDER_PARAM_DESCRIPTION = TEMPLATE_PROVIDERS.map((provider) => `"${provider}"`).join("|");
@@ -2238,7 +2389,19 @@ function mapStatusToError(status, message, response) {
2238
2389
  const parsed = parseInt(retryAfterHeader, 10);
2239
2390
  retryAfter = Number.isNaN(parsed) ? void 0 : parsed;
2240
2391
  }
2241
- return new RateLimitError(retryAfter);
2392
+ const limitHeader = response.headers.get("x-ratelimit-limit");
2393
+ const remainingHeader = response.headers.get("x-ratelimit-remaining");
2394
+ const resetHeader = response.headers.get("x-ratelimit-reset");
2395
+ let meta;
2396
+ if (limitHeader !== null && remainingHeader !== null && resetHeader !== null) {
2397
+ const limit = parseInt(limitHeader, 10);
2398
+ const remaining = parseInt(remainingHeader, 10);
2399
+ const reset = parseInt(resetHeader, 10);
2400
+ if (!Number.isNaN(limit) && !Number.isNaN(remaining) && !Number.isNaN(reset) && limit >= 0 && remaining >= 0 && reset >= 0) {
2401
+ meta = { limit, remaining, reset };
2402
+ }
2403
+ }
2404
+ return new RateLimitError(retryAfter, meta);
2242
2405
  }
2243
2406
  default:
2244
2407
  return new WebhooksCCError(status, message);
@@ -2435,15 +2598,6 @@ async function collectMatchingRequests(fetchRequests, options) {
2435
2598
  }
2436
2599
  throw new TimeoutError(timeout);
2437
2600
  }
2438
- function validateMockResponse(mockResponse, fieldName) {
2439
- const { status, delay } = mockResponse;
2440
- if (!Number.isInteger(status) || status < 100 || status > 599) {
2441
- throw new Error(`Invalid ${fieldName} status: ${status}. Must be an integer 100-599.`);
2442
- }
2443
- if (delay !== void 0 && (!Number.isInteger(delay) || delay < 0 || delay > 3e4)) {
2444
- throw new Error(`Invalid ${fieldName} delay: ${delay}. Must be an integer 0-30000.`);
2445
- }
2446
- }
2447
2601
  var WebhooksCC = class {
2448
2602
  constructor(options) {
2449
2603
  this.endpoints = {
@@ -2451,6 +2605,9 @@ var WebhooksCC = class {
2451
2605
  if (options.mockResponse) {
2452
2606
  validateMockResponse(options.mockResponse, "mock response");
2453
2607
  }
2608
+ if (options.responseRules) {
2609
+ validateResponseRules(options.responseRules);
2610
+ }
2454
2611
  const body = {};
2455
2612
  if (options.name !== void 0) {
2456
2613
  body.name = options.name;
@@ -2458,6 +2615,12 @@ var WebhooksCC = class {
2458
2615
  if (options.mockResponse !== void 0) {
2459
2616
  body.mockResponse = options.mockResponse;
2460
2617
  }
2618
+ if (options.notificationUrl !== void 0) {
2619
+ body.notificationUrl = options.notificationUrl;
2620
+ }
2621
+ if (options.responseRules !== void 0) {
2622
+ body.responseRules = options.responseRules;
2623
+ }
2461
2624
  const isEphemeral = options.ephemeral === true || options.expiresIn !== void 0;
2462
2625
  if (isEphemeral) {
2463
2626
  body.isEphemeral = true;
@@ -2484,9 +2647,12 @@ var WebhooksCC = class {
2484
2647
  },
2485
2648
  update: async (slug, options) => {
2486
2649
  validatePathSegment(slug, "slug");
2487
- if (options.mockResponse && options.mockResponse !== null) {
2650
+ if (options.mockResponse != null) {
2488
2651
  validateMockResponse(options.mockResponse, "mock response");
2489
2652
  }
2653
+ if (options.responseRules != null) {
2654
+ validateResponseRules(options.responseRules);
2655
+ }
2490
2656
  return this.request("PATCH", `/endpoints/${slug}`, options);
2491
2657
  },
2492
2658
  delete: async (slug) => {
@@ -2796,7 +2962,18 @@ var WebhooksCC = class {
2796
2962
  }
2797
2963
  }
2798
2964
  const upperMethod = captured.method.toUpperCase();
2799
- const body = upperMethod === "GET" || upperMethod === "HEAD" ? void 0 : captured.body ?? void 0;
2965
+ let body;
2966
+ if (upperMethod === "GET" || upperMethod === "HEAD") {
2967
+ body = void 0;
2968
+ } else if (captured.bodyRaw) {
2969
+ try {
2970
+ body = Uint8Array.from(atob(captured.bodyRaw), (c) => c.charCodeAt(0));
2971
+ } catch {
2972
+ body = captured.body ?? void 0;
2973
+ }
2974
+ } else {
2975
+ body = captured.body ?? void 0;
2976
+ }
2800
2977
  return fetch(targetUrl, {
2801
2978
  method: captured.method,
2802
2979
  headers,
@@ -3082,7 +3259,9 @@ var WebhooksCC = class {
3082
3259
  name: "string?",
3083
3260
  ephemeral: "boolean?",
3084
3261
  expiresIn: "number|string?",
3085
- mockResponse: "object?"
3262
+ mockResponse: "object?",
3263
+ responseRules: "ResponseRule[]? \u2014 ordered conditional rules (first match wins, max 50). Each rule has conditions (field/op/value) and a response.",
3264
+ notificationUrl: "string?"
3086
3265
  }
3087
3266
  },
3088
3267
  list: {
@@ -3095,7 +3274,13 @@ var WebhooksCC = class {
3095
3274
  },
3096
3275
  update: {
3097
3276
  description: "Update endpoint settings",
3098
- params: { slug: "string", name: "string?", mockResponse: "object?" }
3277
+ params: {
3278
+ slug: "string",
3279
+ name: "string?",
3280
+ mockResponse: "object? \u2014 default response when no rule matches",
3281
+ responseRules: "ResponseRule[]|null? \u2014 conditional rules (first match wins), or null to clear",
3282
+ notificationUrl: "string?"
3283
+ }
3099
3284
  },
3100
3285
  delete: {
3101
3286
  description: "Delete endpoint and its requests",
@@ -3684,14 +3869,28 @@ function diffRequests(left, right, options = {}) {
3684
3869
  // Annotate the CommonJS export names for ESM import in node:
3685
3870
  0 && (module.exports = {
3686
3871
  ApiError,
3872
+ MAX_CONDITIONS_PER_RULE,
3873
+ MAX_CONDITION_NAME_LEN,
3874
+ MAX_CONDITION_PATH_LEN,
3875
+ MAX_CONDITION_VALUE_LEN,
3876
+ MAX_GLOB_PATTERN_LEN,
3877
+ MAX_RESPONSE_RULES,
3878
+ MAX_RULE_NAME_LEN,
3879
+ MOCK_RESPONSE_DELAY_MAX,
3880
+ MOCK_RESPONSE_DELAY_MIN,
3881
+ MOCK_RESPONSE_STATUS_MAX,
3882
+ MOCK_RESPONSE_STATUS_MIN,
3687
3883
  NotFoundError,
3688
3884
  RateLimitError,
3689
3885
  TEMPLATE_METADATA,
3886
+ TEMPLATE_PROVIDERS,
3690
3887
  TimeoutError,
3691
3888
  UnauthorizedError,
3889
+ VERIFY_PROVIDERS,
3692
3890
  WebhookFlowBuilder,
3693
3891
  WebhooksCC,
3694
3892
  WebhooksCCError,
3893
+ buildTemplateSendOptions,
3695
3894
  diffRequests,
3696
3895
  extractJsonField,
3697
3896
  isClerkWebhook,
@@ -3722,6 +3921,8 @@ function diffRequests(left, right, options = {}) {
3722
3921
  parseFormBody,
3723
3922
  parseJsonBody,
3724
3923
  parseSSE,
3924
+ validateMockResponse,
3925
+ validateResponseRules,
3725
3926
  verifyClerkSignature,
3726
3927
  verifyDiscordSignature,
3727
3928
  verifyGitHubSignature,
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  WebhooksCCError,
7
7
  diffRequests,
8
8
  parseDuration
9
- } from "./chunk-7IMPSHQY.mjs";
9
+ } from "./chunk-NSGVJJSF.mjs";
10
10
 
11
11
  // src/sse.ts
12
12
  async function* parseSSE(stream) {
@@ -127,6 +127,20 @@ var TEMPLATE_PROVIDERS = [
127
127
  "gitlab",
128
128
  "standard-webhooks"
129
129
  ];
130
+ var VERIFY_PROVIDERS = [
131
+ "stripe",
132
+ "github",
133
+ "shopify",
134
+ "twilio",
135
+ "slack",
136
+ "paddle",
137
+ "linear",
138
+ "clerk",
139
+ "discord",
140
+ "vercel",
141
+ "gitlab",
142
+ "standard-webhooks"
143
+ ];
130
144
  var TEMPLATE_METADATA = Object.freeze({
131
145
  stripe: Object.freeze({
132
146
  provider: "stripe",
@@ -2040,6 +2054,122 @@ var WebhookFlowBuilder = class {
2040
2054
  }
2041
2055
  };
2042
2056
 
2057
+ // src/validation.ts
2058
+ var MOCK_RESPONSE_STATUS_MIN = 100;
2059
+ var MOCK_RESPONSE_STATUS_MAX = 599;
2060
+ var MOCK_RESPONSE_DELAY_MIN = 0;
2061
+ var MOCK_RESPONSE_DELAY_MAX = 3e4;
2062
+ var MAX_RESPONSE_RULES = 50;
2063
+ var MAX_CONDITIONS_PER_RULE = 10;
2064
+ var VALID_CONDITION_FIELDS = /* @__PURE__ */ new Set([
2065
+ "method",
2066
+ "path",
2067
+ "header",
2068
+ "body_contains",
2069
+ "body_path",
2070
+ "query"
2071
+ ]);
2072
+ var VALID_CONDITION_OPS = /* @__PURE__ */ new Set(["eq", "contains", "starts_with", "matches", "exists"]);
2073
+ var VALID_OPS_BY_FIELD = {
2074
+ method: /* @__PURE__ */ new Set(["eq"]),
2075
+ path: /* @__PURE__ */ new Set(["eq", "contains", "starts_with", "matches"]),
2076
+ header: /* @__PURE__ */ new Set(["exists", "eq", "contains"]),
2077
+ body_contains: /* @__PURE__ */ new Set(["contains"]),
2078
+ body_path: /* @__PURE__ */ new Set(["exists", "eq", "contains"]),
2079
+ query: /* @__PURE__ */ new Set(["exists", "eq"])
2080
+ };
2081
+ var MAX_CONDITION_VALUE_LEN = 4096;
2082
+ var MAX_CONDITION_NAME_LEN = 256;
2083
+ var MAX_CONDITION_PATH_LEN = 256;
2084
+ var MAX_RULE_NAME_LEN = 200;
2085
+ var MAX_GLOB_PATTERN_LEN = 500;
2086
+ function validateMockResponse(mockResponse, fieldName = "mock response") {
2087
+ const { status, body, headers, delay } = mockResponse;
2088
+ if (!Number.isInteger(status) || status < MOCK_RESPONSE_STATUS_MIN || status > MOCK_RESPONSE_STATUS_MAX) {
2089
+ throw new Error(
2090
+ `Invalid ${fieldName} status: ${status}. Must be an integer ${MOCK_RESPONSE_STATUS_MIN}-${MOCK_RESPONSE_STATUS_MAX}.`
2091
+ );
2092
+ }
2093
+ if (body !== void 0 && typeof body !== "string") {
2094
+ throw new Error(`Invalid ${fieldName} body: must be a string.`);
2095
+ }
2096
+ if (headers !== void 0) {
2097
+ if (typeof headers !== "object" || headers === null || Array.isArray(headers)) {
2098
+ throw new Error(`Invalid ${fieldName} headers: must be a Record<string, string>.`);
2099
+ }
2100
+ for (const val of Object.values(headers)) {
2101
+ if (typeof val !== "string") {
2102
+ throw new Error(`Invalid ${fieldName} headers: all values must be strings.`);
2103
+ }
2104
+ }
2105
+ }
2106
+ if (delay !== void 0 && (!Number.isInteger(delay) || delay < MOCK_RESPONSE_DELAY_MIN || delay > MOCK_RESPONSE_DELAY_MAX)) {
2107
+ throw new Error(
2108
+ `Invalid ${fieldName} delay: ${delay}. Must be an integer ${MOCK_RESPONSE_DELAY_MIN}-${MOCK_RESPONSE_DELAY_MAX}.`
2109
+ );
2110
+ }
2111
+ }
2112
+ function validateResponseRules(rules) {
2113
+ if (!Array.isArray(rules)) {
2114
+ throw new Error("responseRules must be an array");
2115
+ }
2116
+ if (rules.length > MAX_RESPONSE_RULES) {
2117
+ throw new Error(`responseRules: max ${MAX_RESPONSE_RULES} rules allowed`);
2118
+ }
2119
+ for (let i = 0; i < rules.length; i++) {
2120
+ const rule = rules[i];
2121
+ const prefix = `responseRules[${i}]`;
2122
+ if (rule.name !== void 0 && (typeof rule.name !== "string" || rule.name.length > MAX_RULE_NAME_LEN)) {
2123
+ throw new Error(`${prefix}: name must be a string (max ${MAX_RULE_NAME_LEN} chars)`);
2124
+ }
2125
+ if (!Array.isArray(rule.conditions) || rule.conditions.length === 0) {
2126
+ throw new Error(`${prefix}: conditions must be a non-empty array`);
2127
+ }
2128
+ if (rule.conditions.length > MAX_CONDITIONS_PER_RULE) {
2129
+ throw new Error(`${prefix}: max ${MAX_CONDITIONS_PER_RULE} conditions per rule`);
2130
+ }
2131
+ if (rule.logic !== void 0 && rule.logic !== "and" && rule.logic !== "or") {
2132
+ throw new Error(`${prefix}: logic must be "and" or "or"`);
2133
+ }
2134
+ for (let j = 0; j < rule.conditions.length; j++) {
2135
+ const c = rule.conditions[j];
2136
+ const cp = `${prefix}.conditions[${j}]`;
2137
+ if (!VALID_CONDITION_FIELDS.has(c.field)) {
2138
+ throw new Error(`${cp}: invalid field "${c.field}"`);
2139
+ }
2140
+ if (!VALID_CONDITION_OPS.has(c.op)) {
2141
+ throw new Error(`${cp}: invalid op "${c.op}"`);
2142
+ }
2143
+ const fieldOps = VALID_OPS_BY_FIELD[c.field];
2144
+ if (fieldOps && !fieldOps.has(c.op)) {
2145
+ throw new Error(`${cp}: op "${c.op}" is not valid for field "${c.field}"`);
2146
+ }
2147
+ if (c.value !== void 0 && typeof c.value === "string" && c.value.length > MAX_CONDITION_VALUE_LEN) {
2148
+ throw new Error(`${cp}: value too long (max ${MAX_CONDITION_VALUE_LEN} chars)`);
2149
+ }
2150
+ if (c.name !== void 0 && typeof c.name === "string" && c.name.length > MAX_CONDITION_NAME_LEN) {
2151
+ throw new Error(`${cp}: name too long (max ${MAX_CONDITION_NAME_LEN} chars)`);
2152
+ }
2153
+ if (c.path !== void 0 && typeof c.path === "string" && c.path.length > MAX_CONDITION_PATH_LEN) {
2154
+ throw new Error(`${cp}: path too long (max ${MAX_CONDITION_PATH_LEN} chars)`);
2155
+ }
2156
+ if ((c.field === "header" || c.field === "query") && (!c.name || c.name.length === 0)) {
2157
+ throw new Error(`${cp}: name is required for ${c.field} conditions`);
2158
+ }
2159
+ if (c.field === "body_path" && (!c.path || c.path.length === 0)) {
2160
+ throw new Error(`${cp}: path is required for body_path conditions`);
2161
+ }
2162
+ if (c.op !== "exists" && (c.value === void 0 || c.value === null)) {
2163
+ throw new Error(`${cp}: value is required when op is "${c.op}"`);
2164
+ }
2165
+ if (c.op === "matches" && c.value && c.value.length > MAX_GLOB_PATTERN_LEN) {
2166
+ throw new Error(`${cp}: matches pattern too long (max ${MAX_GLOB_PATTERN_LEN} chars)`);
2167
+ }
2168
+ }
2169
+ validateMockResponse(rule.response, `${prefix}.response`);
2170
+ }
2171
+ }
2172
+
2043
2173
  // src/client.ts
2044
2174
  var DEFAULT_BASE_URL = "https://webhooks.cc";
2045
2175
  var DEFAULT_WEBHOOK_URL = "https://go.webhooks.cc";
@@ -2047,7 +2177,7 @@ var DEFAULT_TIMEOUT = 3e4;
2047
2177
  var DEFAULT_RETRY_ATTEMPTS = 1;
2048
2178
  var DEFAULT_RETRY_BACKOFF_MS = 1e3;
2049
2179
  var DEFAULT_RETRY_STATUSES = [429, 500, 502, 503, 504];
2050
- var SDK_VERSION = "0.6.0";
2180
+ var SDK_VERSION = true ? "1.3.0" : "0.0.0-dev";
2051
2181
  var WAIT_FOR_LOOKBACK_MS = 5 * 60 * 1e3;
2052
2182
  var DEFAULT_EXPORT_PAGE_SIZE = 100;
2053
2183
  var PROVIDER_PARAM_DESCRIPTION = TEMPLATE_PROVIDERS.map((provider) => `"${provider}"`).join("|");
@@ -2097,7 +2227,19 @@ function mapStatusToError(status, message, response) {
2097
2227
  const parsed = parseInt(retryAfterHeader, 10);
2098
2228
  retryAfter = Number.isNaN(parsed) ? void 0 : parsed;
2099
2229
  }
2100
- return new RateLimitError(retryAfter);
2230
+ const limitHeader = response.headers.get("x-ratelimit-limit");
2231
+ const remainingHeader = response.headers.get("x-ratelimit-remaining");
2232
+ const resetHeader = response.headers.get("x-ratelimit-reset");
2233
+ let meta;
2234
+ if (limitHeader !== null && remainingHeader !== null && resetHeader !== null) {
2235
+ const limit = parseInt(limitHeader, 10);
2236
+ const remaining = parseInt(remainingHeader, 10);
2237
+ const reset = parseInt(resetHeader, 10);
2238
+ if (!Number.isNaN(limit) && !Number.isNaN(remaining) && !Number.isNaN(reset) && limit >= 0 && remaining >= 0 && reset >= 0) {
2239
+ meta = { limit, remaining, reset };
2240
+ }
2241
+ }
2242
+ return new RateLimitError(retryAfter, meta);
2101
2243
  }
2102
2244
  default:
2103
2245
  return new WebhooksCCError(status, message);
@@ -2294,15 +2436,6 @@ async function collectMatchingRequests(fetchRequests, options) {
2294
2436
  }
2295
2437
  throw new TimeoutError(timeout);
2296
2438
  }
2297
- function validateMockResponse(mockResponse, fieldName) {
2298
- const { status, delay } = mockResponse;
2299
- if (!Number.isInteger(status) || status < 100 || status > 599) {
2300
- throw new Error(`Invalid ${fieldName} status: ${status}. Must be an integer 100-599.`);
2301
- }
2302
- if (delay !== void 0 && (!Number.isInteger(delay) || delay < 0 || delay > 3e4)) {
2303
- throw new Error(`Invalid ${fieldName} delay: ${delay}. Must be an integer 0-30000.`);
2304
- }
2305
- }
2306
2439
  var WebhooksCC = class {
2307
2440
  constructor(options) {
2308
2441
  this.endpoints = {
@@ -2310,6 +2443,9 @@ var WebhooksCC = class {
2310
2443
  if (options.mockResponse) {
2311
2444
  validateMockResponse(options.mockResponse, "mock response");
2312
2445
  }
2446
+ if (options.responseRules) {
2447
+ validateResponseRules(options.responseRules);
2448
+ }
2313
2449
  const body = {};
2314
2450
  if (options.name !== void 0) {
2315
2451
  body.name = options.name;
@@ -2317,6 +2453,12 @@ var WebhooksCC = class {
2317
2453
  if (options.mockResponse !== void 0) {
2318
2454
  body.mockResponse = options.mockResponse;
2319
2455
  }
2456
+ if (options.notificationUrl !== void 0) {
2457
+ body.notificationUrl = options.notificationUrl;
2458
+ }
2459
+ if (options.responseRules !== void 0) {
2460
+ body.responseRules = options.responseRules;
2461
+ }
2320
2462
  const isEphemeral = options.ephemeral === true || options.expiresIn !== void 0;
2321
2463
  if (isEphemeral) {
2322
2464
  body.isEphemeral = true;
@@ -2343,9 +2485,12 @@ var WebhooksCC = class {
2343
2485
  },
2344
2486
  update: async (slug, options) => {
2345
2487
  validatePathSegment(slug, "slug");
2346
- if (options.mockResponse && options.mockResponse !== null) {
2488
+ if (options.mockResponse != null) {
2347
2489
  validateMockResponse(options.mockResponse, "mock response");
2348
2490
  }
2491
+ if (options.responseRules != null) {
2492
+ validateResponseRules(options.responseRules);
2493
+ }
2349
2494
  return this.request("PATCH", `/endpoints/${slug}`, options);
2350
2495
  },
2351
2496
  delete: async (slug) => {
@@ -2655,7 +2800,18 @@ var WebhooksCC = class {
2655
2800
  }
2656
2801
  }
2657
2802
  const upperMethod = captured.method.toUpperCase();
2658
- const body = upperMethod === "GET" || upperMethod === "HEAD" ? void 0 : captured.body ?? void 0;
2803
+ let body;
2804
+ if (upperMethod === "GET" || upperMethod === "HEAD") {
2805
+ body = void 0;
2806
+ } else if (captured.bodyRaw) {
2807
+ try {
2808
+ body = Uint8Array.from(atob(captured.bodyRaw), (c) => c.charCodeAt(0));
2809
+ } catch {
2810
+ body = captured.body ?? void 0;
2811
+ }
2812
+ } else {
2813
+ body = captured.body ?? void 0;
2814
+ }
2659
2815
  return fetch(targetUrl, {
2660
2816
  method: captured.method,
2661
2817
  headers,
@@ -2941,7 +3097,9 @@ var WebhooksCC = class {
2941
3097
  name: "string?",
2942
3098
  ephemeral: "boolean?",
2943
3099
  expiresIn: "number|string?",
2944
- mockResponse: "object?"
3100
+ mockResponse: "object?",
3101
+ responseRules: "ResponseRule[]? \u2014 ordered conditional rules (first match wins, max 50). Each rule has conditions (field/op/value) and a response.",
3102
+ notificationUrl: "string?"
2945
3103
  }
2946
3104
  },
2947
3105
  list: {
@@ -2954,7 +3112,13 @@ var WebhooksCC = class {
2954
3112
  },
2955
3113
  update: {
2956
3114
  description: "Update endpoint settings",
2957
- params: { slug: "string", name: "string?", mockResponse: "object?" }
3115
+ params: {
3116
+ slug: "string",
3117
+ name: "string?",
3118
+ mockResponse: "object? \u2014 default response when no rule matches",
3119
+ responseRules: "ResponseRule[]|null? \u2014 conditional rules (first match wins), or null to clear",
3120
+ notificationUrl: "string?"
3121
+ }
2958
3122
  },
2959
3123
  delete: {
2960
3124
  description: "Delete endpoint and its requests",
@@ -3389,14 +3553,28 @@ function matchAny(first, ...rest) {
3389
3553
  }
3390
3554
  export {
3391
3555
  ApiError,
3556
+ MAX_CONDITIONS_PER_RULE,
3557
+ MAX_CONDITION_NAME_LEN,
3558
+ MAX_CONDITION_PATH_LEN,
3559
+ MAX_CONDITION_VALUE_LEN,
3560
+ MAX_GLOB_PATTERN_LEN,
3561
+ MAX_RESPONSE_RULES,
3562
+ MAX_RULE_NAME_LEN,
3563
+ MOCK_RESPONSE_DELAY_MAX,
3564
+ MOCK_RESPONSE_DELAY_MIN,
3565
+ MOCK_RESPONSE_STATUS_MAX,
3566
+ MOCK_RESPONSE_STATUS_MIN,
3392
3567
  NotFoundError,
3393
3568
  RateLimitError,
3394
3569
  TEMPLATE_METADATA,
3570
+ TEMPLATE_PROVIDERS,
3395
3571
  TimeoutError,
3396
3572
  UnauthorizedError,
3573
+ VERIFY_PROVIDERS,
3397
3574
  WebhookFlowBuilder,
3398
3575
  WebhooksCC,
3399
3576
  WebhooksCCError,
3577
+ buildTemplateSendOptions,
3400
3578
  diffRequests,
3401
3579
  extractJsonField,
3402
3580
  isClerkWebhook,
@@ -3427,6 +3605,8 @@ export {
3427
3605
  parseFormBody,
3428
3606
  parseJsonBody,
3429
3607
  parseSSE,
3608
+ validateMockResponse,
3609
+ validateResponseRules,
3430
3610
  verifyClerkSignature,
3431
3611
  verifyDiscordSignature,
3432
3612
  verifyGitHubSignature,
@@ -1,4 +1,4 @@
1
- import { g as DiffResult, e as CreateEndpointOptions, R as Request, a1 as WebhooksCC, E as Endpoint } from './diff-DbTsOT_n.mjs';
1
+ import { j as DiffResult, h as CreateEndpointOptions, R as Request, a4 as WebhooksCC, E as Endpoint } from './diff-CRMlHQPX.mjs';
2
2
 
3
3
  type TestingClient = Pick<WebhooksCC, "endpoints" | "requests">;
4
4
  interface AssertRequestExpectation {
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { g as DiffResult, e as CreateEndpointOptions, R as Request, a1 as WebhooksCC, E as Endpoint } from './diff-DbTsOT_n.js';
1
+ import { j as DiffResult, h as CreateEndpointOptions, R as Request, a4 as WebhooksCC, E as Endpoint } from './diff-CRMlHQPX.js';
2
2
 
3
3
  type TestingClient = Pick<WebhooksCC, "endpoints" | "requests">;
4
4
  interface AssertRequestExpectation {
package/dist/testing.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  TimeoutError,
4
4
  diffRequests,
5
5
  parseDuration
6
- } from "./chunk-7IMPSHQY.mjs";
6
+ } from "./chunk-NSGVJJSF.mjs";
7
7
 
8
8
  // src/testing.ts
9
9
  var MIN_CAPTURE_POLL_INTERVAL = 10;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webhooks-cc/sdk",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "TypeScript SDK for webhooks.cc — create endpoints, capture requests, assert in tests",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -37,9 +37,10 @@
37
37
  },
38
38
  "homepage": "https://webhooks.cc",
39
39
  "devDependencies": {
40
+ "@types/node": "^24.0.0",
40
41
  "tsup": "^8.5.1",
41
- "typescript": "^5.9.3",
42
- "vitest": "^4.1.1"
42
+ "typescript": "^6.0.2",
43
+ "vitest": "^4.1.2"
43
44
  },
44
45
  "scripts": {
45
46
  "build": "tsup --config tsup.config.ts",