@nimbusnexus/webhooks-sdk 0.3.0 → 0.5.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 +20 -2
- package/dist/index.cjs +50 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -27
- package/dist/index.d.ts +44 -27
- package/dist/index.js +47 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -105,8 +105,12 @@ interface OutboxRecord {
|
|
|
105
105
|
id: string;
|
|
106
106
|
eventType: string;
|
|
107
107
|
payload: Record<string, unknown>;
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
/**
|
|
109
|
+
* The id of the project the event is published into (`prj_…`), or `null` for the workspace's default
|
|
110
|
+
* project. `null` means the `project_id` field is OMITTED from the publish body — the id is opaque
|
|
111
|
+
* and per-workspace, so only the server can resolve the default.
|
|
112
|
+
*/
|
|
113
|
+
projectId: string | null;
|
|
110
114
|
source: string | null;
|
|
111
115
|
/** Epoch ms the record was first enqueued; `listPending` orders by this, oldest first. */
|
|
112
116
|
createdAt: number;
|
|
@@ -186,12 +190,12 @@ declare class SqliteStore implements Store {
|
|
|
186
190
|
}
|
|
187
191
|
|
|
188
192
|
/** The published event, as returned by `POST /v1/events` (webhookd's `EventOut`). */
|
|
189
|
-
interface
|
|
193
|
+
interface WebhooksEvent {
|
|
190
194
|
id: string;
|
|
191
195
|
eventUid: string;
|
|
192
196
|
eventType: string;
|
|
193
|
-
|
|
194
|
-
|
|
197
|
+
/** The id of the project the event was published into (always resolved server-side). */
|
|
198
|
+
projectId: string;
|
|
195
199
|
deliveriesCreated: number;
|
|
196
200
|
source: string | null;
|
|
197
201
|
}
|
|
@@ -208,8 +212,8 @@ interface Subscription {
|
|
|
208
212
|
interface Endpoint {
|
|
209
213
|
id: string;
|
|
210
214
|
url: string;
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
/** The id of the project the endpoint belongs to. */
|
|
216
|
+
project_id: string;
|
|
213
217
|
status: string;
|
|
214
218
|
subscriptions: Subscription[];
|
|
215
219
|
/** The signing secret — returned ONCE, on create + rotate-secret only. */
|
|
@@ -253,20 +257,20 @@ interface Page<T> {
|
|
|
253
257
|
}
|
|
254
258
|
interface ClientOptions {
|
|
255
259
|
baseUrl: string;
|
|
256
|
-
/** A per-
|
|
260
|
+
/** A per-workspace API key (`whsk_…`) or a service token. */
|
|
257
261
|
apiKey: string;
|
|
258
262
|
timeoutMs?: number;
|
|
259
263
|
maxRetries?: number;
|
|
260
264
|
/** Inject a `fetch` implementation (defaults to the global `fetch`); used for tests. */
|
|
261
265
|
fetchImpl?: typeof fetch;
|
|
262
266
|
/**
|
|
263
|
-
* Durable outbox store. When set, {@link
|
|
264
|
-
* (and the background drainer) become available. Omit to use only the live {@link
|
|
267
|
+
* Durable outbox store. When set, {@link WebhooksClient.enqueue} / {@link WebhooksClient.drain}
|
|
268
|
+
* (and the background drainer) become available. Omit to use only the live {@link WebhooksClient.publish}.
|
|
265
269
|
*/
|
|
266
270
|
store?: Store;
|
|
267
271
|
/** Max delivery attempts before a record is parked dead (default 10). */
|
|
268
272
|
maxAttempts?: number;
|
|
269
|
-
/** How many records a single {@link
|
|
273
|
+
/** How many records a single {@link WebhooksClient.drain} pulls from the store (default 100). */
|
|
270
274
|
drainBatchLimit?: number;
|
|
271
275
|
/** Invoked once when `drain` parks a record dead (retry budget exhausted). */
|
|
272
276
|
onDead?: (record: OutboxRecord) => void;
|
|
@@ -274,8 +278,11 @@ interface ClientOptions {
|
|
|
274
278
|
onDrainError?: (error: unknown) => void;
|
|
275
279
|
}
|
|
276
280
|
interface EnqueueOptions {
|
|
277
|
-
|
|
278
|
-
|
|
281
|
+
/**
|
|
282
|
+
* The id of the project to publish into (`prj_…`). Omit (or pass an empty string) to target the
|
|
283
|
+
* workspace's default project — the server resolves it, there is no client-side sentinel.
|
|
284
|
+
*/
|
|
285
|
+
projectId?: string;
|
|
279
286
|
source?: string;
|
|
280
287
|
/** The Idempotency-Key / record id. Defaults to a generated UUID v4. Re-enqueuing the same key is a no-op overwrite. */
|
|
281
288
|
idempotencyKey?: string;
|
|
@@ -295,16 +302,22 @@ interface DrainResult {
|
|
|
295
302
|
remaining: number;
|
|
296
303
|
}
|
|
297
304
|
interface PublishOptions {
|
|
298
|
-
|
|
299
|
-
|
|
305
|
+
/**
|
|
306
|
+
* The id of the project to publish into (`prj_…`). Omit (or pass an empty string) to target the
|
|
307
|
+
* workspace's default project — the server resolves it, there is no client-side sentinel.
|
|
308
|
+
*/
|
|
309
|
+
projectId?: string;
|
|
300
310
|
source?: string;
|
|
301
311
|
/** Makes the publish safe to retry — a replay returns the original event without re-fanning-out. */
|
|
302
312
|
idempotencyKey?: string;
|
|
303
313
|
}
|
|
304
314
|
interface CreateEndpointOptions {
|
|
305
|
-
|
|
315
|
+
/**
|
|
316
|
+
* The id of the project to create the endpoint in (`prj_…`). Omit (or pass an empty string) for
|
|
317
|
+
* the workspace's default project.
|
|
318
|
+
*/
|
|
319
|
+
projectId?: string;
|
|
306
320
|
subscriptions?: Subscription[];
|
|
307
|
-
application?: string;
|
|
308
321
|
secret?: string;
|
|
309
322
|
maxAttempts?: number;
|
|
310
323
|
retrySchedule?: number[];
|
|
@@ -313,7 +326,11 @@ interface CreateEndpointOptions {
|
|
|
313
326
|
deliveryTimeoutMs?: number;
|
|
314
327
|
}
|
|
315
328
|
interface ListEndpointsOptions {
|
|
316
|
-
|
|
329
|
+
/**
|
|
330
|
+
* The id of the project to list endpoints for (`prj_…`). Omit (or pass an empty string) for the
|
|
331
|
+
* workspace's default project.
|
|
332
|
+
*/
|
|
333
|
+
projectId?: string;
|
|
317
334
|
offset?: number;
|
|
318
335
|
limit?: number;
|
|
319
336
|
}
|
|
@@ -345,7 +362,7 @@ interface ListDeliveriesOptions {
|
|
|
345
362
|
offset?: number;
|
|
346
363
|
limit?: number;
|
|
347
364
|
}
|
|
348
|
-
declare class
|
|
365
|
+
declare class WebhooksClient {
|
|
349
366
|
private readonly baseUrl;
|
|
350
367
|
private readonly apiKey;
|
|
351
368
|
private readonly timeoutMs;
|
|
@@ -359,7 +376,7 @@ declare class WebhookdClient {
|
|
|
359
376
|
private drainTimer?;
|
|
360
377
|
private draining;
|
|
361
378
|
constructor(opts: ClientOptions);
|
|
362
|
-
publish(eventType: string, payload: Record<string, unknown>, opts?: PublishOptions): Promise<
|
|
379
|
+
publish(eventType: string, payload: Record<string, unknown>, opts?: PublishOptions): Promise<WebhooksEvent>;
|
|
363
380
|
/**
|
|
364
381
|
* Durably buffer an event and return IMMEDIATELY — NO network call. Builds an {@link OutboxRecord}
|
|
365
382
|
* (id = `opts.idempotencyKey` or a fresh UUID v4), saves it to the configured store, and returns the
|
|
@@ -388,7 +405,7 @@ declare class WebhookdClient {
|
|
|
388
405
|
private requireStore;
|
|
389
406
|
/** Create an endpoint. The response includes the signing `secret` exactly once — persist it. */
|
|
390
407
|
createEndpoint(url: string, opts?: CreateEndpointOptions): Promise<Endpoint>;
|
|
391
|
-
/** List endpoints for
|
|
408
|
+
/** List endpoints for a project. Omit `projectId` for the workspace's default project. */
|
|
392
409
|
listEndpoints(opts?: ListEndpointsOptions): Promise<Page<Endpoint>>;
|
|
393
410
|
/** Fetch a single endpoint by id. */
|
|
394
411
|
getEndpoint(id: string): Promise<Endpoint>;
|
|
@@ -416,13 +433,13 @@ declare class WebhookdClient {
|
|
|
416
433
|
/**
|
|
417
434
|
* The single request path used by every method: builds the URL (+ query), attaches auth, and runs
|
|
418
435
|
* the shared retry loop (connection errors + 429 honoring Retry-After + 5xx, capped exponential
|
|
419
|
-
* backoff), raising a typed {@link
|
|
436
|
+
* backoff), raising a typed {@link WebhooksApiError} on other 4xx/5xx. The caller reads the body.
|
|
420
437
|
*/
|
|
421
438
|
private request;
|
|
422
439
|
}
|
|
423
440
|
|
|
424
441
|
/** Base class for all webhookd SDK errors (network failures, etc.). */
|
|
425
|
-
declare class
|
|
442
|
+
declare class WebhooksError extends Error {
|
|
426
443
|
constructor(message: string);
|
|
427
444
|
}
|
|
428
445
|
/**
|
|
@@ -430,7 +447,7 @@ declare class WebhookdError extends Error {
|
|
|
430
447
|
* `code` (e.g. `"rate_limited"`, `"not_found"`, `"validation_error"`) and a human `message`,
|
|
431
448
|
* plus the HTTP `statusCode`.
|
|
432
449
|
*/
|
|
433
|
-
declare class
|
|
450
|
+
declare class WebhooksApiError extends WebhooksError {
|
|
434
451
|
readonly statusCode: number;
|
|
435
452
|
readonly code: string;
|
|
436
453
|
constructor(statusCode: number, code: string, message: string);
|
|
@@ -440,9 +457,9 @@ declare class WebhookdApiError extends WebhookdError {
|
|
|
440
457
|
* @nimbusnexus/webhooks-sdk — the official TypeScript client for NimbusNexus Webhooks.
|
|
441
458
|
*
|
|
442
459
|
* - `verify` — verify an incoming webhook's HMAC signature (for subscribers).
|
|
443
|
-
* - `
|
|
460
|
+
* - `WebhooksClient` — publish events to webhookd (for producers).
|
|
444
461
|
*/
|
|
445
462
|
|
|
446
|
-
declare const VERSION = "0.
|
|
463
|
+
declare const VERSION = "0.5.0";
|
|
447
464
|
|
|
448
|
-
export { type ApiKey, type ClientOptions, type CreateApiKeyOptions, type CreateEndpointOptions, DEAD_NEXT_ATTEMPT_MS, DEFAULT_TOLERANCE_SECONDS, type Delivery, type DrainOptions, type DrainResult, type Endpoint, type EndpointPatch, type EnqueueOptions, FileStore, type ListDeliveriesOptions, type ListEndpointsOptions, MemoryStore, type OutboxRecord, type Page, PostgresStore, type PostgresStoreOptions, type PublishOptions, RedisStore, type RedisStoreOptions, SqliteStore, type Store, type Subscription, VERSION, type VerifyOptions,
|
|
465
|
+
export { type ApiKey, type ClientOptions, type CreateApiKeyOptions, type CreateEndpointOptions, DEAD_NEXT_ATTEMPT_MS, DEFAULT_TOLERANCE_SECONDS, type Delivery, type DrainOptions, type DrainResult, type Endpoint, type EndpointPatch, type EnqueueOptions, FileStore, type ListDeliveriesOptions, type ListEndpointsOptions, MemoryStore, type OutboxRecord, type Page, PostgresStore, type PostgresStoreOptions, type PublishOptions, RedisStore, type RedisStoreOptions, SqliteStore, type Store, type Subscription, VERSION, type VerifyOptions, WebhooksApiError, WebhooksClient, WebhooksError, type WebhooksEvent, isDead, sign, verify };
|
package/dist/index.js
CHANGED
|
@@ -41,18 +41,18 @@ function verify(secret, rawBody, signature, opts = {}) {
|
|
|
41
41
|
import { randomUUID } from "crypto";
|
|
42
42
|
|
|
43
43
|
// src/errors.ts
|
|
44
|
-
var
|
|
44
|
+
var WebhooksError = class extends Error {
|
|
45
45
|
constructor(message) {
|
|
46
46
|
super(message);
|
|
47
|
-
this.name = "
|
|
47
|
+
this.name = "WebhooksError";
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
|
-
var
|
|
50
|
+
var WebhooksApiError = class extends WebhooksError {
|
|
51
51
|
statusCode;
|
|
52
52
|
code;
|
|
53
53
|
constructor(statusCode, code, message) {
|
|
54
54
|
super(`[${statusCode} ${code}] ${message}`);
|
|
55
|
-
this.name = "
|
|
55
|
+
this.name = "WebhooksApiError";
|
|
56
56
|
this.statusCode = statusCode;
|
|
57
57
|
this.code = code;
|
|
58
58
|
}
|
|
@@ -159,8 +159,7 @@ function rowToRecord(row) {
|
|
|
159
159
|
id: row.id,
|
|
160
160
|
eventType: row.event_type,
|
|
161
161
|
payload: row.payload,
|
|
162
|
-
|
|
163
|
-
application: row.application,
|
|
162
|
+
projectId: row.project_id,
|
|
164
163
|
source: row.source,
|
|
165
164
|
createdAt: Number(row.created_at),
|
|
166
165
|
attempts: row.attempts,
|
|
@@ -197,8 +196,7 @@ var PostgresStore = class {
|
|
|
197
196
|
id TEXT PRIMARY KEY,
|
|
198
197
|
event_type TEXT NOT NULL,
|
|
199
198
|
payload JSONB NOT NULL,
|
|
200
|
-
|
|
201
|
-
application TEXT NOT NULL,
|
|
199
|
+
project_id TEXT,
|
|
202
200
|
source TEXT,
|
|
203
201
|
sent BOOLEAN NOT NULL DEFAULT FALSE,
|
|
204
202
|
attempts INTEGER NOT NULL,
|
|
@@ -215,13 +213,12 @@ var PostgresStore = class {
|
|
|
215
213
|
const pool = await this.ensure();
|
|
216
214
|
await pool.query(
|
|
217
215
|
`INSERT INTO ${this.table}
|
|
218
|
-
(id, event_type, payload,
|
|
219
|
-
VALUES ($1, $2, $3, $4, $5, $6,
|
|
216
|
+
(id, event_type, payload, project_id, source, sent, attempts, last_error, next_attempt_at, created_at)
|
|
217
|
+
VALUES ($1, $2, $3, $4, $5, FALSE, $6, $7, $8, $9)
|
|
220
218
|
ON CONFLICT (id) DO UPDATE SET
|
|
221
219
|
event_type = EXCLUDED.event_type,
|
|
222
220
|
payload = EXCLUDED.payload,
|
|
223
|
-
|
|
224
|
-
application = EXCLUDED.application,
|
|
221
|
+
project_id = EXCLUDED.project_id,
|
|
225
222
|
source = EXCLUDED.source,
|
|
226
223
|
sent = EXCLUDED.sent,
|
|
227
224
|
attempts = EXCLUDED.attempts,
|
|
@@ -232,8 +229,7 @@ var PostgresStore = class {
|
|
|
232
229
|
record.id,
|
|
233
230
|
record.eventType,
|
|
234
231
|
JSON.stringify(record.payload),
|
|
235
|
-
record.
|
|
236
|
-
record.application,
|
|
232
|
+
record.projectId,
|
|
237
233
|
record.source,
|
|
238
234
|
record.attempts,
|
|
239
235
|
record.lastError,
|
|
@@ -389,8 +385,7 @@ function rowToRecord2(row) {
|
|
|
389
385
|
id: row.id,
|
|
390
386
|
eventType: row.event_type,
|
|
391
387
|
payload: JSON.parse(row.payload),
|
|
392
|
-
|
|
393
|
-
application: row.application,
|
|
388
|
+
projectId: row.project_id,
|
|
394
389
|
source: row.source,
|
|
395
390
|
createdAt: row.created_at,
|
|
396
391
|
attempts: row.attempts,
|
|
@@ -417,12 +412,14 @@ var SqliteStore = class {
|
|
|
417
412
|
}
|
|
418
413
|
this.db = new DatabaseSync(path);
|
|
419
414
|
this.db.exec(
|
|
415
|
+
// `project_id` is NULLABLE: NULL = the workspace's default project (the publish body simply
|
|
416
|
+
// omits the field). Renamed from the legacy `project` slug column — this store has no
|
|
417
|
+
// schema-versioning mechanism, so a table created by an older SDK build is not upgraded.
|
|
420
418
|
`CREATE TABLE IF NOT EXISTS webhookd_outbox (
|
|
421
419
|
id TEXT PRIMARY KEY,
|
|
422
420
|
event_type TEXT NOT NULL,
|
|
423
421
|
payload TEXT NOT NULL,
|
|
424
|
-
|
|
425
|
-
application TEXT NOT NULL,
|
|
422
|
+
project_id TEXT,
|
|
426
423
|
source TEXT,
|
|
427
424
|
created_at INTEGER NOT NULL,
|
|
428
425
|
attempts INTEGER NOT NULL,
|
|
@@ -434,13 +431,12 @@ var SqliteStore = class {
|
|
|
434
431
|
save(record) {
|
|
435
432
|
this.db.prepare(
|
|
436
433
|
`INSERT INTO webhookd_outbox
|
|
437
|
-
(id, event_type, payload,
|
|
438
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?,
|
|
434
|
+
(id, event_type, payload, project_id, source, created_at, attempts, last_error, next_attempt_at)
|
|
435
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
439
436
|
ON CONFLICT(id) DO UPDATE SET
|
|
440
437
|
event_type = excluded.event_type,
|
|
441
438
|
payload = excluded.payload,
|
|
442
|
-
|
|
443
|
-
application = excluded.application,
|
|
439
|
+
project_id = excluded.project_id,
|
|
444
440
|
source = excluded.source,
|
|
445
441
|
created_at = excluded.created_at,
|
|
446
442
|
attempts = excluded.attempts,
|
|
@@ -450,8 +446,7 @@ var SqliteStore = class {
|
|
|
450
446
|
record.id,
|
|
451
447
|
record.eventType,
|
|
452
448
|
JSON.stringify(record.payload),
|
|
453
|
-
record.
|
|
454
|
-
record.application,
|
|
449
|
+
record.projectId,
|
|
455
450
|
record.source,
|
|
456
451
|
record.createdAt,
|
|
457
452
|
record.attempts,
|
|
@@ -496,7 +491,7 @@ var SqliteStore = class {
|
|
|
496
491
|
|
|
497
492
|
// src/client.ts
|
|
498
493
|
var RETRY_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
499
|
-
var
|
|
494
|
+
var WebhooksClient = class {
|
|
500
495
|
baseUrl;
|
|
501
496
|
apiKey;
|
|
502
497
|
timeoutMs;
|
|
@@ -524,10 +519,10 @@ var WebhookdClient = class {
|
|
|
524
519
|
async publish(eventType, payload, opts = {}) {
|
|
525
520
|
const body = {
|
|
526
521
|
event_type: eventType,
|
|
527
|
-
payload
|
|
528
|
-
environment: opts.environment ?? "prod",
|
|
529
|
-
application: opts.application ?? "default"
|
|
522
|
+
payload
|
|
530
523
|
};
|
|
524
|
+
const projectId = normalizeProjectId(opts.projectId);
|
|
525
|
+
if (projectId !== null) body.project_id = projectId;
|
|
531
526
|
if (opts.source !== void 0) body.source = opts.source;
|
|
532
527
|
const headers = {};
|
|
533
528
|
if (opts.idempotencyKey !== void 0) headers["Idempotency-Key"] = opts.idempotencyKey;
|
|
@@ -537,8 +532,7 @@ var WebhookdClient = class {
|
|
|
537
532
|
id: String(data.id),
|
|
538
533
|
eventUid: String(data.event_uid),
|
|
539
534
|
eventType: String(data.event_type),
|
|
540
|
-
|
|
541
|
-
environment: String(data.environment ?? "prod"),
|
|
535
|
+
projectId: String(data.project_id),
|
|
542
536
|
deliveriesCreated: Number(data.deliveries_created ?? 0),
|
|
543
537
|
source: data.source ?? null
|
|
544
538
|
};
|
|
@@ -556,8 +550,8 @@ var WebhookdClient = class {
|
|
|
556
550
|
id: opts.idempotencyKey ?? randomUUID(),
|
|
557
551
|
eventType,
|
|
558
552
|
payload,
|
|
559
|
-
|
|
560
|
-
|
|
553
|
+
// null = the workspace's default project (the field is omitted from the publish body on drain).
|
|
554
|
+
projectId: normalizeProjectId(opts.projectId),
|
|
561
555
|
source: opts.source ?? null,
|
|
562
556
|
createdAt: now,
|
|
563
557
|
attempts: 0,
|
|
@@ -584,10 +578,9 @@ var WebhookdClient = class {
|
|
|
584
578
|
for (const record of rows) {
|
|
585
579
|
const body = {
|
|
586
580
|
event_type: record.eventType,
|
|
587
|
-
payload: record.payload
|
|
588
|
-
environment: record.environment,
|
|
589
|
-
application: record.application
|
|
581
|
+
payload: record.payload
|
|
590
582
|
};
|
|
583
|
+
if (record.projectId !== null) body.project_id = record.projectId;
|
|
591
584
|
if (record.source !== null) body.source = record.source;
|
|
592
585
|
try {
|
|
593
586
|
await this.request("POST", "/v1/events", {
|
|
@@ -647,18 +640,16 @@ var WebhookdClient = class {
|
|
|
647
640
|
}
|
|
648
641
|
requireStore() {
|
|
649
642
|
if (!this.store) {
|
|
650
|
-
throw new
|
|
643
|
+
throw new WebhooksError("no outbox store configured \u2014 pass `store` in ClientOptions");
|
|
651
644
|
}
|
|
652
645
|
return this.store;
|
|
653
646
|
}
|
|
654
647
|
// ── Endpoints ──────────────────────────────────────────────────────────────
|
|
655
648
|
/** Create an endpoint. The response includes the signing `secret` exactly once — persist it. */
|
|
656
649
|
async createEndpoint(url, opts = {}) {
|
|
657
|
-
const body = {
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
application: opts.application ?? "default"
|
|
661
|
-
};
|
|
650
|
+
const body = { url };
|
|
651
|
+
const projectId = normalizeProjectId(opts.projectId);
|
|
652
|
+
if (projectId !== null) body.project_id = projectId;
|
|
662
653
|
if (opts.subscriptions !== void 0) body.subscriptions = opts.subscriptions;
|
|
663
654
|
if (opts.secret !== void 0) body.secret = opts.secret;
|
|
664
655
|
if (opts.maxAttempts !== void 0) body.max_attempts = opts.maxAttempts;
|
|
@@ -668,9 +659,11 @@ var WebhookdClient = class {
|
|
|
668
659
|
if (opts.deliveryTimeoutMs !== void 0) body.delivery_timeout_ms = opts.deliveryTimeoutMs;
|
|
669
660
|
return this.requestJson("POST", "/v1/endpoints", { body });
|
|
670
661
|
}
|
|
671
|
-
/** List endpoints for
|
|
662
|
+
/** List endpoints for a project. Omit `projectId` for the workspace's default project. */
|
|
672
663
|
async listEndpoints(opts = {}) {
|
|
673
|
-
const query = {
|
|
664
|
+
const query = {};
|
|
665
|
+
const projectId = normalizeProjectId(opts.projectId);
|
|
666
|
+
if (projectId !== null) query.project_id = projectId;
|
|
674
667
|
if (opts.offset !== void 0) query.offset = opts.offset;
|
|
675
668
|
if (opts.limit !== void 0) query.limit = opts.limit;
|
|
676
669
|
return this.requestJson("GET", "/v1/endpoints", { query });
|
|
@@ -744,7 +737,7 @@ var WebhookdClient = class {
|
|
|
744
737
|
/**
|
|
745
738
|
* The single request path used by every method: builds the URL (+ query), attaches auth, and runs
|
|
746
739
|
* the shared retry loop (connection errors + 429 honoring Retry-After + 5xx, capped exponential
|
|
747
|
-
* backoff), raising a typed {@link
|
|
740
|
+
* backoff), raising a typed {@link WebhooksApiError} on other 4xx/5xx. The caller reads the body.
|
|
748
741
|
*/
|
|
749
742
|
async request(method, path, opts = {}) {
|
|
750
743
|
let url = `${this.baseUrl}${path}`;
|
|
@@ -781,7 +774,7 @@ var WebhookdClient = class {
|
|
|
781
774
|
await sleep(backoffMs(attempt));
|
|
782
775
|
continue;
|
|
783
776
|
}
|
|
784
|
-
throw new
|
|
777
|
+
throw new WebhooksError(`request failed: ${String(err)}`);
|
|
785
778
|
}
|
|
786
779
|
if (RETRY_STATUSES.has(resp.status) && attempt < this.maxRetries) {
|
|
787
780
|
await sleep(retryAfterMs(resp) ?? backoffMs(attempt));
|
|
@@ -790,9 +783,12 @@ var WebhookdClient = class {
|
|
|
790
783
|
if (resp.status >= 400) throw await apiError(resp);
|
|
791
784
|
return resp;
|
|
792
785
|
}
|
|
793
|
-
throw new
|
|
786
|
+
throw new WebhooksError(`request failed after retries: ${String(lastErr)}`);
|
|
794
787
|
}
|
|
795
788
|
};
|
|
789
|
+
function normalizeProjectId(projectId) {
|
|
790
|
+
return projectId === void 0 || projectId === null || projectId === "" ? null : projectId;
|
|
791
|
+
}
|
|
796
792
|
function backoffMs(attempt) {
|
|
797
793
|
return Math.min(2e3, 200 * 2 ** attempt);
|
|
798
794
|
}
|
|
@@ -811,14 +807,14 @@ async function apiError(resp) {
|
|
|
811
807
|
message = data.error?.message ?? message;
|
|
812
808
|
} catch {
|
|
813
809
|
}
|
|
814
|
-
return new
|
|
810
|
+
return new WebhooksApiError(resp.status, code, message);
|
|
815
811
|
}
|
|
816
812
|
function sleep(ms) {
|
|
817
813
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
818
814
|
}
|
|
819
815
|
|
|
820
816
|
// src/index.ts
|
|
821
|
-
var VERSION = "0.
|
|
817
|
+
var VERSION = "0.5.0";
|
|
822
818
|
export {
|
|
823
819
|
DEAD_NEXT_ATTEMPT_MS,
|
|
824
820
|
DEFAULT_TOLERANCE_SECONDS,
|
|
@@ -828,9 +824,9 @@ export {
|
|
|
828
824
|
RedisStore,
|
|
829
825
|
SqliteStore,
|
|
830
826
|
VERSION,
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
827
|
+
WebhooksApiError,
|
|
828
|
+
WebhooksClient,
|
|
829
|
+
WebhooksError,
|
|
834
830
|
isDead,
|
|
835
831
|
sign,
|
|
836
832
|
verify
|