@webhooks-cc/sdk 0.1.1 → 0.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.
- package/README.md +138 -45
- package/dist/index.d.mts +225 -13
- package/dist/index.d.ts +225 -13
- package/dist/index.js +631 -29
- package/dist/index.mjs +609 -28
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -49,6 +49,30 @@ interface CreateEndpointOptions {
|
|
|
49
49
|
/** Display name for the endpoint */
|
|
50
50
|
name?: string;
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Options for updating an existing endpoint.
|
|
54
|
+
*/
|
|
55
|
+
interface UpdateEndpointOptions {
|
|
56
|
+
/** New display name */
|
|
57
|
+
name?: string;
|
|
58
|
+
/** Mock response config, or null to clear */
|
|
59
|
+
mockResponse?: {
|
|
60
|
+
status: number;
|
|
61
|
+
body: string;
|
|
62
|
+
headers: Record<string, string>;
|
|
63
|
+
} | null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Options for sending a test webhook to an endpoint.
|
|
67
|
+
*/
|
|
68
|
+
interface SendOptions {
|
|
69
|
+
/** HTTP method (default: "POST") */
|
|
70
|
+
method?: string;
|
|
71
|
+
/** HTTP headers to include */
|
|
72
|
+
headers?: Record<string, string>;
|
|
73
|
+
/** Request body (will be JSON-serialized if not a string) */
|
|
74
|
+
body?: unknown;
|
|
75
|
+
}
|
|
52
76
|
/**
|
|
53
77
|
* Options for listing captured requests.
|
|
54
78
|
*/
|
|
@@ -62,13 +86,50 @@ interface ListRequestsOptions {
|
|
|
62
86
|
* Options for waitFor() polling behavior.
|
|
63
87
|
*/
|
|
64
88
|
interface WaitForOptions {
|
|
65
|
-
/** Maximum time to wait
|
|
66
|
-
timeout?: number;
|
|
67
|
-
/** Interval between polls
|
|
68
|
-
pollInterval?: number;
|
|
89
|
+
/** Maximum time to wait (ms or duration string like "30s", "5m") (default: 30000) */
|
|
90
|
+
timeout?: number | string;
|
|
91
|
+
/** Interval between polls (ms or duration string) (default: 500, min: 10, max: 60000) */
|
|
92
|
+
pollInterval?: number | string;
|
|
69
93
|
/** Filter function to match specific requests */
|
|
70
94
|
match?: (request: Request) => boolean;
|
|
71
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Options for subscribe() SSE streaming.
|
|
98
|
+
*/
|
|
99
|
+
interface SubscribeOptions {
|
|
100
|
+
/** AbortSignal to cancel the subscription */
|
|
101
|
+
signal?: AbortSignal;
|
|
102
|
+
/** Maximum time to stream (ms or duration string like "30m") */
|
|
103
|
+
timeout?: number | string;
|
|
104
|
+
}
|
|
105
|
+
/** Info passed to the onRequest hook before a request is sent. */
|
|
106
|
+
interface RequestHookInfo {
|
|
107
|
+
method: string;
|
|
108
|
+
url: string;
|
|
109
|
+
}
|
|
110
|
+
/** Info passed to the onResponse hook after a successful response. */
|
|
111
|
+
interface ResponseHookInfo {
|
|
112
|
+
method: string;
|
|
113
|
+
url: string;
|
|
114
|
+
status: number;
|
|
115
|
+
durationMs: number;
|
|
116
|
+
}
|
|
117
|
+
/** Info passed to the onError hook when a request fails. */
|
|
118
|
+
interface ErrorHookInfo {
|
|
119
|
+
method: string;
|
|
120
|
+
url: string;
|
|
121
|
+
error: Error;
|
|
122
|
+
durationMs: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Lifecycle hooks for observability and telemetry integration.
|
|
126
|
+
* All hooks are optional and are called synchronously (fire-and-forget).
|
|
127
|
+
*/
|
|
128
|
+
interface ClientHooks {
|
|
129
|
+
onRequest?: (info: RequestHookInfo) => void;
|
|
130
|
+
onResponse?: (info: ResponseHookInfo) => void;
|
|
131
|
+
onError?: (info: ErrorHookInfo) => void;
|
|
132
|
+
}
|
|
72
133
|
/**
|
|
73
134
|
* Configuration options for the WebhooksCC client.
|
|
74
135
|
*/
|
|
@@ -77,8 +138,50 @@ interface ClientOptions {
|
|
|
77
138
|
apiKey: string;
|
|
78
139
|
/** Base URL for the API (default: https://webhooks.cc) */
|
|
79
140
|
baseUrl?: string;
|
|
141
|
+
/** Base URL for sending webhooks (default: https://go.webhooks.cc) */
|
|
142
|
+
webhookUrl?: string;
|
|
80
143
|
/** Request timeout in milliseconds (default: 30000) */
|
|
81
144
|
timeout?: number;
|
|
145
|
+
/** Lifecycle hooks for observability */
|
|
146
|
+
hooks?: ClientHooks;
|
|
147
|
+
}
|
|
148
|
+
/** Description of a single SDK operation. */
|
|
149
|
+
interface OperationDescription {
|
|
150
|
+
description: string;
|
|
151
|
+
params: Record<string, string>;
|
|
152
|
+
}
|
|
153
|
+
/** Self-describing schema returned by client.describe(). */
|
|
154
|
+
interface SDKDescription {
|
|
155
|
+
version: string;
|
|
156
|
+
endpoints: Record<string, OperationDescription>;
|
|
157
|
+
requests: Record<string, OperationDescription>;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Base error class for all webhooks.cc SDK errors.
|
|
162
|
+
* Extends the standard Error with an HTTP status code.
|
|
163
|
+
*/
|
|
164
|
+
declare class WebhooksCCError extends Error {
|
|
165
|
+
readonly statusCode: number;
|
|
166
|
+
constructor(statusCode: number, message: string);
|
|
167
|
+
}
|
|
168
|
+
/** Thrown when the API key is invalid or missing (401). */
|
|
169
|
+
declare class UnauthorizedError extends WebhooksCCError {
|
|
170
|
+
constructor(message?: string);
|
|
171
|
+
}
|
|
172
|
+
/** Thrown when the requested resource does not exist (404). */
|
|
173
|
+
declare class NotFoundError extends WebhooksCCError {
|
|
174
|
+
constructor(message?: string);
|
|
175
|
+
}
|
|
176
|
+
/** Thrown when the request times out. */
|
|
177
|
+
declare class TimeoutError extends WebhooksCCError {
|
|
178
|
+
constructor(timeoutMs: number);
|
|
179
|
+
}
|
|
180
|
+
/** Thrown when the API returns 429 Too Many Requests. */
|
|
181
|
+
declare class RateLimitError extends WebhooksCCError {
|
|
182
|
+
/** Seconds until the rate limit resets, if provided by the server. */
|
|
183
|
+
readonly retryAfter?: number;
|
|
184
|
+
constructor(retryAfter?: number);
|
|
82
185
|
}
|
|
83
186
|
|
|
84
187
|
/**
|
|
@@ -86,23 +189,21 @@ interface ClientOptions {
|
|
|
86
189
|
*
|
|
87
190
|
* @example
|
|
88
191
|
* ```typescript
|
|
192
|
+
* import { WebhooksCC, matchMethod } from '@webhooks-cc/sdk';
|
|
193
|
+
*
|
|
89
194
|
* const client = new WebhooksCC({ apiKey: 'whcc_...' });
|
|
90
195
|
* const endpoint = await client.endpoints.create({ name: 'My Webhook' });
|
|
91
196
|
* const request = await client.requests.waitFor(endpoint.slug, {
|
|
92
|
-
* timeout:
|
|
93
|
-
* match: (
|
|
197
|
+
* timeout: '30s',
|
|
198
|
+
* match: matchMethod('POST'),
|
|
94
199
|
* });
|
|
95
200
|
* ```
|
|
96
201
|
*/
|
|
97
202
|
|
|
98
203
|
/**
|
|
99
|
-
*
|
|
100
|
-
* Allows callers to distinguish between different error types.
|
|
204
|
+
* @deprecated Use {@link WebhooksCCError} instead. Kept for backward compatibility.
|
|
101
205
|
*/
|
|
102
|
-
declare
|
|
103
|
-
readonly statusCode: number;
|
|
104
|
-
constructor(statusCode: number, message: string);
|
|
105
|
-
}
|
|
206
|
+
declare const ApiError: typeof WebhooksCCError;
|
|
106
207
|
/**
|
|
107
208
|
* Client for the webhooks.cc API.
|
|
108
209
|
*
|
|
@@ -113,14 +214,20 @@ declare class ApiError extends Error {
|
|
|
113
214
|
declare class WebhooksCC {
|
|
114
215
|
private readonly apiKey;
|
|
115
216
|
private readonly baseUrl;
|
|
217
|
+
private readonly webhookUrl;
|
|
116
218
|
private readonly timeout;
|
|
219
|
+
private readonly hooks;
|
|
117
220
|
constructor(options: ClientOptions);
|
|
118
221
|
private request;
|
|
222
|
+
/** Returns a static description of all SDK operations (no API call). */
|
|
223
|
+
describe(): SDKDescription;
|
|
119
224
|
endpoints: {
|
|
120
225
|
create: (options?: CreateEndpointOptions) => Promise<Endpoint>;
|
|
121
226
|
list: () => Promise<Endpoint[]>;
|
|
122
227
|
get: (slug: string) => Promise<Endpoint>;
|
|
228
|
+
update: (slug: string, options: UpdateEndpointOptions) => Promise<Endpoint>;
|
|
123
229
|
delete: (slug: string) => Promise<void>;
|
|
230
|
+
send: (slug: string, options?: SendOptions) => Promise<Response>;
|
|
124
231
|
};
|
|
125
232
|
requests: {
|
|
126
233
|
list: (endpointSlug: string, options?: ListRequestsOptions) => Promise<Request[]>;
|
|
@@ -138,7 +245,112 @@ declare class WebhooksCC {
|
|
|
138
245
|
* @throws Error if timeout expires or max iterations (10000) reached
|
|
139
246
|
*/
|
|
140
247
|
waitFor: (endpointSlug: string, options?: WaitForOptions) => Promise<Request>;
|
|
248
|
+
/**
|
|
249
|
+
* Replay a captured request to a target URL.
|
|
250
|
+
*
|
|
251
|
+
* Fetches the original request by ID and re-sends it to the specified URL
|
|
252
|
+
* with the original method, headers, and body. Hop-by-hop headers are stripped.
|
|
253
|
+
*/
|
|
254
|
+
replay: (requestId: string, targetUrl: string) => Promise<Response>;
|
|
255
|
+
/**
|
|
256
|
+
* Stream incoming requests via SSE as an async iterator.
|
|
257
|
+
*
|
|
258
|
+
* Connects to the SSE endpoint and yields Request objects as they arrive.
|
|
259
|
+
* The connection is closed when the iterator is broken, the signal is aborted,
|
|
260
|
+
* or the timeout expires.
|
|
261
|
+
*
|
|
262
|
+
* No automatic reconnection — if the connection drops, the iterator ends.
|
|
263
|
+
*/
|
|
264
|
+
subscribe: (slug: string, options?: SubscribeOptions) => AsyncIterable<Request>;
|
|
141
265
|
};
|
|
142
266
|
}
|
|
143
267
|
|
|
144
|
-
|
|
268
|
+
/**
|
|
269
|
+
* Safely parse a JSON request body.
|
|
270
|
+
* Returns undefined if the body is empty or not valid JSON.
|
|
271
|
+
*/
|
|
272
|
+
declare function parseJsonBody(request: Request): unknown | undefined;
|
|
273
|
+
/**
|
|
274
|
+
* Check if a request looks like a Stripe webhook.
|
|
275
|
+
* Matches on the `stripe-signature` header being present.
|
|
276
|
+
*/
|
|
277
|
+
declare function isStripeWebhook(request: Request): boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Check if a request looks like a GitHub webhook.
|
|
280
|
+
* Matches on the `x-github-event` header being present.
|
|
281
|
+
*/
|
|
282
|
+
declare function isGitHubWebhook(request: Request): boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Returns a match function that checks whether a JSON field in the
|
|
285
|
+
* request body equals the expected value.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* ```ts
|
|
289
|
+
* const req = await client.requests.waitFor(slug, {
|
|
290
|
+
* match: matchJsonField("type", "checkout.session.completed"),
|
|
291
|
+
* });
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
declare function matchJsonField(field: string, value: unknown): (request: Request) => boolean;
|
|
295
|
+
/** Check if a request looks like a Shopify webhook. */
|
|
296
|
+
declare function isShopifyWebhook(request: Request): boolean;
|
|
297
|
+
/** Check if a request looks like a Slack webhook. */
|
|
298
|
+
declare function isSlackWebhook(request: Request): boolean;
|
|
299
|
+
/** Check if a request looks like a Twilio webhook. */
|
|
300
|
+
declare function isTwilioWebhook(request: Request): boolean;
|
|
301
|
+
/** Check if a request looks like a Paddle webhook. */
|
|
302
|
+
declare function isPaddleWebhook(request: Request): boolean;
|
|
303
|
+
/** Check if a request looks like a Linear webhook. */
|
|
304
|
+
declare function isLinearWebhook(request: Request): boolean;
|
|
305
|
+
|
|
306
|
+
/** Match requests by HTTP method (case-insensitive). */
|
|
307
|
+
declare function matchMethod(method: string): (request: Request) => boolean;
|
|
308
|
+
/** Match requests that have a specific header, optionally with a specific value. Header names are matched case-insensitively; values are matched with exact (case-sensitive) equality. */
|
|
309
|
+
declare function matchHeader(name: string, value?: string): (request: Request) => boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Match requests by a dot-notation path into the JSON body.
|
|
312
|
+
* Supports array indexing with numeric path segments (e.g., `"items.0.id"`).
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* ```ts
|
|
316
|
+
* matchBodyPath("data.object.id", "obj_123")
|
|
317
|
+
* matchBodyPath("type", "checkout.session.completed")
|
|
318
|
+
* matchBodyPath("items.0.name", "Widget")
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
declare function matchBodyPath(path: string, value: unknown): (request: Request) => boolean;
|
|
322
|
+
/** Match when ALL matchers return true. Requires at least one matcher. */
|
|
323
|
+
declare function matchAll(first: (request: Request) => boolean, ...rest: Array<(request: Request) => boolean>): (request: Request) => boolean;
|
|
324
|
+
/** Match when ANY matcher returns true. Requires at least one matcher. */
|
|
325
|
+
declare function matchAny(first: (request: Request) => boolean, ...rest: Array<(request: Request) => boolean>): (request: Request) => boolean;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Parse a duration value into milliseconds.
|
|
329
|
+
*
|
|
330
|
+
* Accepts:
|
|
331
|
+
* - Numbers: passed through as-is (treated as milliseconds)
|
|
332
|
+
* - Numeric strings: `"500"` → 500
|
|
333
|
+
* - Duration strings: `"30s"` → 30000, `"5m"` → 300000, `"1.5s"` → 1500, `"500ms"` → 500
|
|
334
|
+
*
|
|
335
|
+
* @throws {Error} If the input string is not a valid duration format
|
|
336
|
+
*/
|
|
337
|
+
declare function parseDuration(input: number | string): number;
|
|
338
|
+
|
|
339
|
+
/** A parsed SSE frame with event type and data. */
|
|
340
|
+
interface SSEFrame {
|
|
341
|
+
event: string;
|
|
342
|
+
data: string;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Async generator that parses SSE frames from a ReadableStream.
|
|
346
|
+
*
|
|
347
|
+
* Handles:
|
|
348
|
+
* - Multi-line `data:` fields (joined with newlines)
|
|
349
|
+
* - `event:` type fields
|
|
350
|
+
* - Comment lines (`: ...`) — yielded with event "comment"
|
|
351
|
+
* - Empty data fields
|
|
352
|
+
* - Frames terminated by blank lines
|
|
353
|
+
*/
|
|
354
|
+
declare function parseSSE(stream: ReadableStream<Uint8Array>): AsyncGenerator<SSEFrame, void, undefined>;
|
|
355
|
+
|
|
356
|
+
export { ApiError, type ClientHooks, type ClientOptions, type CreateEndpointOptions, type Endpoint, type ErrorHookInfo, type ListRequestsOptions, NotFoundError, type OperationDescription, RateLimitError, type Request, type RequestHookInfo, type ResponseHookInfo, type SDKDescription, type SSEFrame, type SendOptions, type SubscribeOptions, TimeoutError, UnauthorizedError, type UpdateEndpointOptions, type WaitForOptions, WebhooksCC, WebhooksCCError, isGitHubWebhook, isLinearWebhook, isPaddleWebhook, isShopifyWebhook, isSlackWebhook, isStripeWebhook, isTwilioWebhook, matchAll, matchAny, matchBodyPath, matchHeader, matchJsonField, matchMethod, parseDuration, parseJsonBody, parseSSE };
|