@voltro/plugin-webhooks 0.25.0 → 0.26.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/CHANGELOG.md +244 -0
- package/dist/index.d.ts +148 -1
- package/dist/index.js +307 -198
- package/dist/mixin.d.ts +48 -0
- package/dist/mixin.js +1 -0
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "./signing-DUG4JWwk.js";
|
|
2
2
|
import { WebhookDeliveryNotFound as l, WebhookPayloadInvalid as u, WebhookPayloadUnrepresentable as d, WebhookPayloadVersionInvalid as f, WebhookSubscribeInvalid as p } from "./errors.js";
|
|
3
|
-
import { _voltroWebhookDeliveriesTable as m, _voltroWebhookRateWindowsTable as h, _voltroWebhookTargetsTable as
|
|
4
|
-
import { randomBytes as
|
|
5
|
-
import { Context as
|
|
6
|
-
import { and as
|
|
7
|
-
import { assertPublicUrl as
|
|
8
|
-
import { publishServerError as
|
|
9
|
-
import { createLogger as
|
|
3
|
+
import { _voltroWebhookDeliveriesTable as m, _voltroWebhookRateWindowsTable as h, _voltroWebhookTargetsTable as ee, webhookTables as g } from "./mixin.js";
|
|
4
|
+
import { randomBytes as _, randomUUID as v } from "node:crypto";
|
|
5
|
+
import { Context as te, Effect as y, Either as ne, Schema as b } from "effect";
|
|
6
|
+
import { and as x, eq as S } from "@voltro/database";
|
|
7
|
+
import { assertPublicUrl as C } from "@voltro/integration-http";
|
|
8
|
+
import { publishServerError as re } from "@voltro/protocol";
|
|
9
|
+
import { createLogger as w } from "@voltro/logger";
|
|
10
10
|
import { Activity as T, DurableClock as E, Workflow as ie } from "@effect/workflow";
|
|
11
11
|
//#region src/eventAudience.ts
|
|
12
12
|
var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
@@ -82,7 +82,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
82
82
|
retryOn: k,
|
|
83
83
|
honourRetryAfter: !0,
|
|
84
84
|
jitter: "full"
|
|
85
|
-
}), M = class extends
|
|
85
|
+
}), M = class extends te.Tag("@voltro/webhooks/WebhooksService")() {}, ce = 32, N = 32, P = () => _(ce).toString("hex"), F = (e) => {
|
|
86
86
|
let t;
|
|
87
87
|
try {
|
|
88
88
|
t = new URL(e.url);
|
|
@@ -97,7 +97,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
97
97
|
reason: `url protocol must be http or https, got ${t.protocol}`
|
|
98
98
|
});
|
|
99
99
|
if (process.env.NODE_ENV === "production") try {
|
|
100
|
-
|
|
100
|
+
C(e.url);
|
|
101
101
|
} catch (e) {
|
|
102
102
|
throw new p({
|
|
103
103
|
field: "url",
|
|
@@ -131,13 +131,14 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
131
131
|
reason: `autoDisableAfter must be a positive integer, got ${e.autoDisableAfter}`
|
|
132
132
|
});
|
|
133
133
|
}, I = (e, t) => ({
|
|
134
|
-
id:
|
|
134
|
+
id: v(),
|
|
135
135
|
event: e.event,
|
|
136
136
|
url: e.url,
|
|
137
137
|
secret: e.secret ?? P(),
|
|
138
138
|
signing: e.signing ?? t?.defaultSigning ?? c(),
|
|
139
139
|
retry: e.retry ?? t?.defaultRetry ?? j(),
|
|
140
140
|
filter: e.filter ?? null,
|
|
141
|
+
scope: e.scope ?? null,
|
|
141
142
|
headers: e.headers ?? null,
|
|
142
143
|
rateLimitPerMinute: e.rateLimitPerMinute ?? null,
|
|
143
144
|
active: !0,
|
|
@@ -148,19 +149,40 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
148
149
|
autoDisableReason: null,
|
|
149
150
|
payloadVersion: e.payloadVersion ?? t?.version ?? 1,
|
|
150
151
|
description: e.description ?? null
|
|
151
|
-
}), le = (e
|
|
152
|
+
}), le = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : 0, L = (e) => e instanceof Date ? e.toISOString() : typeof e == "string" ? e : null, ue = (e) => {
|
|
153
|
+
if (typeof e != "string") return e;
|
|
154
|
+
try {
|
|
155
|
+
return JSON.parse(e);
|
|
156
|
+
} catch {
|
|
157
|
+
return e;
|
|
158
|
+
}
|
|
159
|
+
}, R = (e) => ({
|
|
160
|
+
id: String(e.id),
|
|
161
|
+
deliveryId: String(e.deliveryId),
|
|
162
|
+
targetId: String(e.targetId),
|
|
163
|
+
event: String(e.event),
|
|
164
|
+
eventId: e.eventId ?? null,
|
|
165
|
+
attempt: Number(e.attempt ?? 0),
|
|
166
|
+
status: e.status,
|
|
167
|
+
responseStatus: e.responseStatus ?? null,
|
|
168
|
+
errorMessage: e.errorMessage ?? null,
|
|
169
|
+
latencyMs: e.latencyMs ?? null,
|
|
170
|
+
scheduledAt: L(e.scheduledAt),
|
|
171
|
+
nextAttemptAt: L(e.nextAttemptAt),
|
|
172
|
+
createdAt: L(e.createdAt)
|
|
173
|
+
}), de = (e, t) => e === t ? "current" : e < t ? "behind" : "ahead", z = (e, t) => {
|
|
152
174
|
if (e === null) return !0;
|
|
153
175
|
let n = { payload: t };
|
|
154
|
-
for (let [t, r] of Object.entries(e)) if (!
|
|
176
|
+
for (let [t, r] of Object.entries(e)) if (!pe(fe(n, t), r)) return !1;
|
|
155
177
|
return !0;
|
|
156
|
-
},
|
|
178
|
+
}, fe = (e, t) => {
|
|
157
179
|
let n = t.split("."), r = e;
|
|
158
180
|
for (let e of n) {
|
|
159
181
|
if (typeof r != "object" || !r) return;
|
|
160
182
|
r = r[e];
|
|
161
183
|
}
|
|
162
184
|
return r;
|
|
163
|
-
},
|
|
185
|
+
}, pe = (e, t) => {
|
|
164
186
|
if (typeof t == "object" && t && !Array.isArray(t)) {
|
|
165
187
|
let n = t;
|
|
166
188
|
if ("eq" in n) return e === n.eq;
|
|
@@ -171,7 +193,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
171
193
|
if ("in" in n && Array.isArray(n.in)) return n.in.includes(e);
|
|
172
194
|
}
|
|
173
195
|
return e === t;
|
|
174
|
-
},
|
|
196
|
+
}, me = (e, t, n = {}) => {
|
|
175
197
|
let r = new Map((n.events ?? []).map((e) => [e.id, e]));
|
|
176
198
|
return {
|
|
177
199
|
subscribe: async (t) => {
|
|
@@ -193,15 +215,15 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
193
215
|
emit: async (n, i) => {
|
|
194
216
|
let a = typeof n == "object" && n.kind === "event" ? D(n) : void 0, o = typeof n == "string" ? r.get(n) : a ?? n, s = typeof n == "string" ? n : n.id ?? n.name;
|
|
195
217
|
if (o !== void 0) {
|
|
196
|
-
let e =
|
|
197
|
-
if (
|
|
218
|
+
let e = b.decodeUnknownEither(o.payload)(i, { errors: "all" });
|
|
219
|
+
if (ne.isLeft(e)) throw new u({
|
|
198
220
|
event: s,
|
|
199
221
|
issues: e.left.message
|
|
200
222
|
});
|
|
201
223
|
}
|
|
202
|
-
let c =
|
|
224
|
+
let c = v(), l = (await e.store.query({
|
|
203
225
|
table: "_voltro_webhook_targets",
|
|
204
|
-
predicate:
|
|
226
|
+
predicate: S("event", s),
|
|
205
227
|
order: [{
|
|
206
228
|
column: "createdAt",
|
|
207
229
|
direction: "asc"
|
|
@@ -209,9 +231,9 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
209
231
|
take: 1e3,
|
|
210
232
|
skip: void 0,
|
|
211
233
|
projection: void 0
|
|
212
|
-
})).filter((e) =>
|
|
234
|
+
})).filter((e) => z(e.filter, i)), d = [], f = JSON.stringify(i);
|
|
213
235
|
for (let n of l) {
|
|
214
|
-
let r =
|
|
236
|
+
let r = v();
|
|
215
237
|
n.active ? (await t({
|
|
216
238
|
deliveryId: r,
|
|
217
239
|
targetId: n.id,
|
|
@@ -249,7 +271,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
249
271
|
replay: async (n) => {
|
|
250
272
|
let r = (await e.store.query({
|
|
251
273
|
table: "_voltro_webhook_deliveries",
|
|
252
|
-
predicate:
|
|
274
|
+
predicate: S("deliveryId", n),
|
|
253
275
|
order: [{
|
|
254
276
|
column: "attempt",
|
|
255
277
|
direction: "asc"
|
|
@@ -263,7 +285,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
263
285
|
deliveryId: r.deliveryId,
|
|
264
286
|
targetId: r.targetId,
|
|
265
287
|
event: r.event,
|
|
266
|
-
eventId: r.eventId ??
|
|
288
|
+
eventId: r.eventId ?? v(),
|
|
267
289
|
payloadJson: typeof r.payload == "string" ? r.payload : JSON.stringify(r.payload),
|
|
268
290
|
attemptEpoch: Date.now()
|
|
269
291
|
});
|
|
@@ -284,7 +306,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
284
306
|
});
|
|
285
307
|
let r = await e.store.query({
|
|
286
308
|
table: "_voltro_webhook_deliveries",
|
|
287
|
-
predicate: S(
|
|
309
|
+
predicate: x(S("targetId", n), S("status", "pending")),
|
|
288
310
|
order: [{
|
|
289
311
|
column: "createdAt",
|
|
290
312
|
direction: "asc"
|
|
@@ -297,13 +319,13 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
297
319
|
deliveryId: e.deliveryId,
|
|
298
320
|
targetId: n,
|
|
299
321
|
event: e.event,
|
|
300
|
-
eventId: e.eventId ??
|
|
322
|
+
eventId: e.eventId ?? v(),
|
|
301
323
|
payloadJson: typeof e.payload == "string" ? e.payload : JSON.stringify(e.payload),
|
|
302
324
|
attemptEpoch: i
|
|
303
325
|
});
|
|
304
326
|
},
|
|
305
327
|
deleteTarget: async (t) => {
|
|
306
|
-
await e.store.delete("_voltro_webhook_targets", t), await e.store.deleteMany("_voltro_webhook_deliveries", { where: S(
|
|
328
|
+
await e.store.delete("_voltro_webhook_targets", t), await e.store.deleteMany("_voltro_webhook_deliveries", { where: x(S("targetId", t), S("status", "pending")) });
|
|
307
329
|
},
|
|
308
330
|
rotateSecret: async (t) => {
|
|
309
331
|
let n = P();
|
|
@@ -312,6 +334,89 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
312
334
|
updatedAt: /* @__PURE__ */ new Date()
|
|
313
335
|
}), { secret: n };
|
|
314
336
|
},
|
|
337
|
+
updateTarget: async (t, n) => {
|
|
338
|
+
if (n.url !== void 0 && F({
|
|
339
|
+
event: "x",
|
|
340
|
+
url: n.url
|
|
341
|
+
}), n.rateLimitPerMinute !== void 0 && n.rateLimitPerMinute !== null && (!Number.isInteger(n.rateLimitPerMinute) || n.rateLimitPerMinute < 1)) throw Error("updateTarget: rateLimitPerMinute must be a positive integer or null");
|
|
342
|
+
let r = { updatedAt: /* @__PURE__ */ new Date() };
|
|
343
|
+
for (let e of [
|
|
344
|
+
"url",
|
|
345
|
+
"description",
|
|
346
|
+
"filter",
|
|
347
|
+
"scope",
|
|
348
|
+
"headers",
|
|
349
|
+
"rateLimitPerMinute",
|
|
350
|
+
"autoDisableAfter",
|
|
351
|
+
"format"
|
|
352
|
+
]) n[e] !== void 0 && (r[e] = n[e]);
|
|
353
|
+
await e.store.update("_voltro_webhook_targets", t, r);
|
|
354
|
+
},
|
|
355
|
+
testTarget: async (n, r) => {
|
|
356
|
+
let i = (await e.store.query({
|
|
357
|
+
table: "_voltro_webhook_targets",
|
|
358
|
+
predicate: S("id", n),
|
|
359
|
+
order: void 0,
|
|
360
|
+
take: 1,
|
|
361
|
+
skip: void 0,
|
|
362
|
+
projection: void 0
|
|
363
|
+
}))[0];
|
|
364
|
+
if (i === void 0) throw Error(`testTarget: no target ${n}`);
|
|
365
|
+
let a = v(), o = JSON.stringify(r ?? {
|
|
366
|
+
test: !0,
|
|
367
|
+
targetId: n,
|
|
368
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
369
|
+
});
|
|
370
|
+
return i.active ? await t({
|
|
371
|
+
deliveryId: a,
|
|
372
|
+
targetId: i.id,
|
|
373
|
+
event: i.event,
|
|
374
|
+
eventId: v(),
|
|
375
|
+
payloadJson: o
|
|
376
|
+
}) : await e.store.insert("_voltro_webhook_deliveries", {
|
|
377
|
+
id: `${a}:1`,
|
|
378
|
+
deliveryId: a,
|
|
379
|
+
targetId: i.id,
|
|
380
|
+
tenantId: i.tenantId ?? null,
|
|
381
|
+
event: i.event,
|
|
382
|
+
eventId: null,
|
|
383
|
+
attempt: 1,
|
|
384
|
+
status: "pending",
|
|
385
|
+
payload: o,
|
|
386
|
+
scheduledAt: /* @__PURE__ */ new Date(),
|
|
387
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
388
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
389
|
+
}), { deliveryId: a };
|
|
390
|
+
},
|
|
391
|
+
listDeliveries: async (t) => {
|
|
392
|
+
let n = await e.store.query({
|
|
393
|
+
table: "_voltro_webhook_deliveries",
|
|
394
|
+
predicate: t?.targetId === void 0 ? void 0 : S("targetId", t.targetId),
|
|
395
|
+
order: [{
|
|
396
|
+
column: "createdAt",
|
|
397
|
+
direction: "desc"
|
|
398
|
+
}],
|
|
399
|
+
take: Math.min((t?.limit ?? 200) * (t?.status !== void 0 || t?.since !== void 0 ? 10 : 1), 5e3),
|
|
400
|
+
skip: void 0,
|
|
401
|
+
projection: void 0
|
|
402
|
+
}), r = t?.since?.getTime();
|
|
403
|
+
return n.filter((e) => t?.status === void 0 || e.status === t.status).filter((e) => r === void 0 || le(e.createdAt) >= r).slice(0, t?.limit ?? 200).map(R);
|
|
404
|
+
},
|
|
405
|
+
getDelivery: async (t) => {
|
|
406
|
+
let n = (await e.store.query({
|
|
407
|
+
table: "_voltro_webhook_deliveries",
|
|
408
|
+
predicate: S("id", t),
|
|
409
|
+
order: void 0,
|
|
410
|
+
take: 1,
|
|
411
|
+
skip: void 0,
|
|
412
|
+
projection: void 0
|
|
413
|
+
}))[0];
|
|
414
|
+
return n === void 0 ? null : {
|
|
415
|
+
...R(n),
|
|
416
|
+
payload: ue(n.payload),
|
|
417
|
+
responseBody: n.responseBody ?? null
|
|
418
|
+
};
|
|
419
|
+
},
|
|
315
420
|
updateTargetPayloadVersion: async (t, n) => {
|
|
316
421
|
if (n < 1 || !Number.isInteger(n)) throw new f({ version: n });
|
|
317
422
|
await e.store.update("_voltro_webhook_targets", t, {
|
|
@@ -319,39 +424,43 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
319
424
|
updatedAt: /* @__PURE__ */ new Date()
|
|
320
425
|
});
|
|
321
426
|
},
|
|
322
|
-
listTargets: async (t) =>
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
427
|
+
listTargets: async (t, n) => {
|
|
428
|
+
let r = await e.store.query({
|
|
429
|
+
table: "_voltro_webhook_targets",
|
|
430
|
+
predicate: t === void 0 ? void 0 : S("event", t),
|
|
431
|
+
order: [{
|
|
432
|
+
column: "createdAt",
|
|
433
|
+
direction: "desc"
|
|
434
|
+
}],
|
|
435
|
+
take: 500,
|
|
436
|
+
skip: void 0,
|
|
437
|
+
projection: void 0
|
|
438
|
+
});
|
|
439
|
+
return (n === void 0 ? r : r.filter((e) => e.scope !== null && Object.entries(n).every(([t, n]) => e.scope?.[t] === n))).map((e) => ({
|
|
440
|
+
id: e.id,
|
|
441
|
+
event: e.event,
|
|
442
|
+
url: e.url,
|
|
443
|
+
active: e.active,
|
|
444
|
+
rateLimitPerMinute: e.rateLimitPerMinute,
|
|
445
|
+
description: e.description,
|
|
446
|
+
payloadVersion: e.payloadVersion,
|
|
447
|
+
autoDisableAfter: e.autoDisableAfter,
|
|
448
|
+
consecutiveFailures: e.consecutiveFailures ?? 0,
|
|
449
|
+
autoDisabledAt: e.autoDisabledAt === null || e.autoDisabledAt === void 0 ? null : e.autoDisabledAt instanceof Date ? e.autoDisabledAt.toISOString() : String(e.autoDisabledAt),
|
|
450
|
+
autoDisableReason: e.autoDisableReason,
|
|
451
|
+
scope: e.scope
|
|
452
|
+
}));
|
|
453
|
+
}
|
|
345
454
|
};
|
|
346
|
-
},
|
|
455
|
+
}, he = y.gen(function* () {
|
|
347
456
|
return yield* M;
|
|
348
|
-
}),
|
|
457
|
+
}), ge = (e) => {
|
|
349
458
|
if (e.webhooks === void 0) throw Error("useWebhooks: `ctx.webhooks` is not set. Add @voltro/plugin-webhooks to your app.config.ts plugin list and declare at least one *.webhook.tsx file.");
|
|
350
459
|
return e.webhooks;
|
|
351
|
-
},
|
|
460
|
+
}, _e = 1e4, B = class {
|
|
352
461
|
capacity;
|
|
353
462
|
cache = /* @__PURE__ */ new Map();
|
|
354
|
-
constructor(e =
|
|
463
|
+
constructor(e = _e) {
|
|
355
464
|
this.capacity = e;
|
|
356
465
|
}
|
|
357
466
|
evictExpired() {
|
|
@@ -386,20 +495,20 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
386
495
|
clear() {
|
|
387
496
|
this.cache.clear();
|
|
388
497
|
}
|
|
389
|
-
},
|
|
498
|
+
}, V = null, H = () => (V === null && (V = new B()), V), U = {
|
|
390
499
|
"5m": 5 * 6e4,
|
|
391
500
|
"1h": 60 * 6e4,
|
|
392
501
|
"6h": 360 * 6e4,
|
|
393
502
|
"1d": 1440 * 6e4,
|
|
394
503
|
"7d": 10080 * 6e4,
|
|
395
504
|
"30d": 720 * 60 * 6e4
|
|
396
|
-
},
|
|
505
|
+
}, W = (e) => e === void 0 ? U["7d"] : U[e] ?? U["7d"], G = (e, t) => ({
|
|
397
506
|
status: e,
|
|
398
507
|
contentType: "application/json; charset=utf-8",
|
|
399
508
|
body: JSON.stringify(t)
|
|
400
|
-
}),
|
|
401
|
-
let n = e.provider, r = e.signature ?? n?.signature ?? null, i = e.idempotency ?? n?.idempotency ?? null, o = e.bodyType ?? n?.bodyType ?? "json", s = t.idempotencyCache ??
|
|
402
|
-
|
|
509
|
+
}), ve = (e, t) => {
|
|
510
|
+
let n = e.provider, r = e.signature ?? n?.signature ?? null, i = e.idempotency ?? n?.idempotency ?? null, o = e.bodyType ?? n?.bodyType ?? "json", s = t.idempotencyCache ?? H(), c = W(i?.ttl), l = t.log ?? ((e) => {
|
|
511
|
+
w({ scope: `webhook:${e.webhookId}` }).debug("incoming webhook", {
|
|
403
512
|
status: e.status,
|
|
404
513
|
signatureOk: e.signatureOk,
|
|
405
514
|
idempotency: e.idempotency,
|
|
@@ -410,7 +519,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
410
519
|
return async (n) => {
|
|
411
520
|
let u = Date.now();
|
|
412
521
|
if (n.method !== "POST") {
|
|
413
|
-
let t =
|
|
522
|
+
let t = G(405, {
|
|
414
523
|
error: "method not allowed",
|
|
415
524
|
expected: "POST"
|
|
416
525
|
});
|
|
@@ -431,7 +540,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
431
540
|
r._tag === "custom" && n.headers["x-slack-request-timestamp"] && (o = `${n.headers["x-slack-request-timestamp"]}|${t ?? ""}`);
|
|
432
541
|
let s = a(r, n.rawBody, i, o);
|
|
433
542
|
if (d = s.ok, !s.ok) {
|
|
434
|
-
let t =
|
|
543
|
+
let t = G(401, {
|
|
435
544
|
error: "invalid signature",
|
|
436
545
|
reason: s.reason
|
|
437
546
|
});
|
|
@@ -457,7 +566,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
457
566
|
f = r;
|
|
458
567
|
} else f = n.rawBody;
|
|
459
568
|
} catch (t) {
|
|
460
|
-
let n =
|
|
569
|
+
let n = G(400, {
|
|
461
570
|
error: "malformed body",
|
|
462
571
|
reason: t.message
|
|
463
572
|
});
|
|
@@ -472,9 +581,9 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
472
581
|
}
|
|
473
582
|
let p;
|
|
474
583
|
try {
|
|
475
|
-
p =
|
|
584
|
+
p = b.decodeUnknownSync(e.payload)(f);
|
|
476
585
|
} catch (t) {
|
|
477
|
-
let n =
|
|
586
|
+
let n = G(422, {
|
|
478
587
|
error: "schema validation failed",
|
|
479
588
|
reason: t.message
|
|
480
589
|
});
|
|
@@ -493,7 +602,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
493
602
|
if (m = typeof t == "string" ? n.headers[t.toLowerCase()] : t(n.headers, n.rawBody), m !== void 0 && m.length > 0) {
|
|
494
603
|
let t = s.claim(m, c);
|
|
495
604
|
if (h = t, t === "duplicate") {
|
|
496
|
-
let t =
|
|
605
|
+
let t = G(200, {
|
|
497
606
|
received: !0,
|
|
498
607
|
duplicate: !0
|
|
499
608
|
});
|
|
@@ -506,7 +615,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
506
615
|
}), t;
|
|
507
616
|
}
|
|
508
617
|
if (t === "inflight") {
|
|
509
|
-
let t =
|
|
618
|
+
let t = G(409, {
|
|
510
619
|
error: "request already in flight",
|
|
511
620
|
idempotencyKey: m
|
|
512
621
|
});
|
|
@@ -529,7 +638,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
529
638
|
idempotencyKey: m ?? "",
|
|
530
639
|
...r ? { workflows: r } : {}
|
|
531
640
|
}), m !== void 0 && s.commit(m);
|
|
532
|
-
let i =
|
|
641
|
+
let i = G(200, { received: !0 });
|
|
533
642
|
return l({
|
|
534
643
|
webhookId: e.id,
|
|
535
644
|
status: 200,
|
|
@@ -539,7 +648,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
539
648
|
}), i;
|
|
540
649
|
} catch (t) {
|
|
541
650
|
m !== void 0 && s.release(m);
|
|
542
|
-
let n =
|
|
651
|
+
let n = G(500, {
|
|
543
652
|
error: "handler threw",
|
|
544
653
|
reason: t.message
|
|
545
654
|
});
|
|
@@ -550,7 +659,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
550
659
|
idempotency: h,
|
|
551
660
|
durationMs: Date.now() - u,
|
|
552
661
|
errorMessage: t.message
|
|
553
|
-
}),
|
|
662
|
+
}), re({
|
|
554
663
|
error: t,
|
|
555
664
|
source: "webhook",
|
|
556
665
|
name: e.id,
|
|
@@ -558,20 +667,20 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
558
667
|
}), n;
|
|
559
668
|
}
|
|
560
669
|
};
|
|
561
|
-
},
|
|
670
|
+
}, ye = (e) => `/webhooks/${e}`, K = "_voltro_webhook_rate_windows", q = 6e4, be = (e, t) => `${e}@${t}`, J = async (e, t, n) => (await e.query({
|
|
562
671
|
table: "_voltro_webhook_rate_windows",
|
|
563
|
-
predicate: S(
|
|
672
|
+
predicate: x(S("scope", t), S("bucket", n)),
|
|
564
673
|
order: [],
|
|
565
674
|
take: 1,
|
|
566
675
|
skip: void 0,
|
|
567
676
|
projection: void 0
|
|
568
|
-
}))[0] ?? null,
|
|
569
|
-
for (let r = 0; r <
|
|
677
|
+
}))[0] ?? null, Y = 32, X = async (e, t, n) => {
|
|
678
|
+
for (let r = 0; r < Y; r++) {
|
|
570
679
|
r > 0 && await new Promise((e) => setTimeout(e, r));
|
|
571
|
-
let i = await
|
|
680
|
+
let i = await J(e, t.key, n);
|
|
572
681
|
if (i === null) {
|
|
573
|
-
await e.insertIgnore(
|
|
574
|
-
id:
|
|
682
|
+
await e.insertIgnore(K, {
|
|
683
|
+
id: be(t.key, n),
|
|
575
684
|
scope: t.key,
|
|
576
685
|
bucket: n,
|
|
577
686
|
count: 0,
|
|
@@ -584,31 +693,31 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
584
693
|
if (await e.updateMany("_voltro_webhook_rate_windows", {
|
|
585
694
|
count: i.count + 1,
|
|
586
695
|
updatedAt: /* @__PURE__ */ new Date()
|
|
587
|
-
}, { where: S(
|
|
696
|
+
}, { where: x(S("id", i.id), S("count", i.count)) }) === 1) return !0;
|
|
588
697
|
}
|
|
589
|
-
throw Error(`webhook rate window: contention on (${t.key}, ${n}) exceeded ${
|
|
590
|
-
},
|
|
591
|
-
for (let r = 0; r <
|
|
698
|
+
throw Error(`webhook rate window: contention on (${t.key}, ${n}) exceeded ${Y} attempts`);
|
|
699
|
+
}, Z = async (e, t, n) => {
|
|
700
|
+
for (let r = 0; r < Y; r++) {
|
|
592
701
|
r > 0 && await new Promise((e) => setTimeout(e, r));
|
|
593
|
-
let i = await
|
|
702
|
+
let i = await J(e, t, n);
|
|
594
703
|
if (i === null || i.count <= 0 || await e.updateMany("_voltro_webhook_rate_windows", {
|
|
595
704
|
count: i.count - 1,
|
|
596
705
|
updatedAt: /* @__PURE__ */ new Date()
|
|
597
|
-
}, { where: S(
|
|
706
|
+
}, { where: x(S("id", i.id), S("count", i.count)) }) === 1) return;
|
|
598
707
|
}
|
|
599
|
-
throw Error(`webhook rate window: release contention on (${t}) exceeded ${
|
|
600
|
-
},
|
|
708
|
+
throw Error(`webhook rate window: release contention on (${t}) exceeded ${Y} attempts`);
|
|
709
|
+
}, xe = async (e, t, n, r = q) => {
|
|
601
710
|
if (t.length === 0) return {
|
|
602
711
|
acquired: !0,
|
|
603
712
|
retryInMs: 0
|
|
604
713
|
};
|
|
605
714
|
let i = Math.floor(n / r), a = [];
|
|
606
715
|
for (let o of t) {
|
|
607
|
-
if (await
|
|
716
|
+
if (await X(e, o, i)) {
|
|
608
717
|
a.push(o);
|
|
609
718
|
continue;
|
|
610
719
|
}
|
|
611
|
-
for (let t of a) await
|
|
720
|
+
for (let t of a) await Z(e, t.key, i);
|
|
612
721
|
return {
|
|
613
722
|
acquired: !1,
|
|
614
723
|
retryInMs: (i + 1) * r - n
|
|
@@ -618,7 +727,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
618
727
|
acquired: !0,
|
|
619
728
|
retryInMs: 0
|
|
620
729
|
};
|
|
621
|
-
},
|
|
730
|
+
}, Se = (e, t) => {
|
|
622
731
|
if (e === "json") return {
|
|
623
732
|
contentType: "application/json",
|
|
624
733
|
bytes: Buffer.from(t, "utf8")
|
|
@@ -634,15 +743,15 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
634
743
|
}
|
|
635
744
|
return e === "form" ? {
|
|
636
745
|
contentType: "application/x-www-form-urlencoded",
|
|
637
|
-
bytes: Buffer.from(
|
|
746
|
+
bytes: Buffer.from(Ce(n), "utf8")
|
|
638
747
|
} : {
|
|
639
748
|
contentType: "application/xml",
|
|
640
|
-
bytes: Buffer.from(
|
|
749
|
+
bytes: Buffer.from(Te(n), "utf8")
|
|
641
750
|
};
|
|
642
|
-
},
|
|
751
|
+
}, Ce = (e) => {
|
|
643
752
|
if (typeof e != "object" || !e || Array.isArray(e)) throw new d({
|
|
644
753
|
format: "form",
|
|
645
|
-
reason: `form encoding requires a JSON object at the top level, got ${
|
|
754
|
+
reason: `form encoding requires a JSON object at the top level, got ${Oe(e)}`
|
|
646
755
|
});
|
|
647
756
|
let t = new URLSearchParams();
|
|
648
757
|
for (let [n, r] of Object.entries(e)) Q(t, n, r);
|
|
@@ -661,13 +770,13 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
661
770
|
return;
|
|
662
771
|
}
|
|
663
772
|
e.append(t, String(n));
|
|
664
|
-
},
|
|
665
|
-
if (!
|
|
773
|
+
}, we = /^[A-Za-z_][A-Za-z0-9_.-]*$/, Te = (e) => `<?xml version="1.0" encoding="UTF-8"?>${$("webhook", e)}`, $ = (e, t) => {
|
|
774
|
+
if (!we.test(e)) throw new d({
|
|
666
775
|
format: "xml",
|
|
667
776
|
reason: `object key ${JSON.stringify(e)} is not a valid XML element name`
|
|
668
777
|
});
|
|
669
|
-
return `<${e}>${
|
|
670
|
-
},
|
|
778
|
+
return `<${e}>${Ee(e, t)}</${e}>`;
|
|
779
|
+
}, Ee = (e, t) => t == null ? "" : Array.isArray(t) ? t.map((e) => $("item", e)).join("") : typeof t == "object" ? Object.entries(t).map(([e, t]) => $(e, t)).join("") : De(String(t)), De = (e) => e.replace(/[&<>"']/g, (e) => {
|
|
671
780
|
switch (e) {
|
|
672
781
|
case "&": return "&";
|
|
673
782
|
case "<": return "<";
|
|
@@ -675,17 +784,17 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
675
784
|
case "\"": return """;
|
|
676
785
|
default: return "'";
|
|
677
786
|
}
|
|
678
|
-
}),
|
|
787
|
+
}), Oe = (e) => e === null ? "null" : Array.isArray(e) ? "array" : typeof e, ke = "_voltro_webhook_targets", Ae = 32, je = async (e, t) => (await e.query({
|
|
679
788
|
table: "_voltro_webhook_targets",
|
|
680
|
-
predicate:
|
|
789
|
+
predicate: S("id", t),
|
|
681
790
|
order: [],
|
|
682
791
|
take: 1,
|
|
683
792
|
skip: void 0,
|
|
684
793
|
projection: void 0
|
|
685
|
-
}))[0] ?? null,
|
|
686
|
-
for (let a = 0; a <
|
|
794
|
+
}))[0] ?? null, Me = async (e, t, n, r, i = /* @__PURE__ */ new Date()) => {
|
|
795
|
+
for (let a = 0; a < Ae; a++) {
|
|
687
796
|
a > 0 && await new Promise((e) => setTimeout(e, a));
|
|
688
|
-
let o = await
|
|
797
|
+
let o = await je(e, t);
|
|
689
798
|
if (o === null) return {
|
|
690
799
|
consecutiveFailures: 0,
|
|
691
800
|
autoDisabled: !1
|
|
@@ -695,7 +804,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
695
804
|
if (s === 0 || await e.updateMany("_voltro_webhook_targets", {
|
|
696
805
|
consecutiveFailures: 0,
|
|
697
806
|
updatedAt: i
|
|
698
|
-
}, { where: S(
|
|
807
|
+
}, { where: x(S("id", t), S("consecutiveFailures", s)) }) === 1) return {
|
|
699
808
|
consecutiveFailures: 0,
|
|
700
809
|
autoDisabled: !1
|
|
701
810
|
};
|
|
@@ -705,68 +814,68 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
705
814
|
consecutiveFailures: c,
|
|
706
815
|
updatedAt: i
|
|
707
816
|
};
|
|
708
|
-
if (u && (d.active = !1, d.autoDisabledAt = i, d.autoDisableReason = r.slice(0, 500)), await e.updateMany("_voltro_webhook_targets", d, { where: S(
|
|
817
|
+
if (u && (d.active = !1, d.autoDisabledAt = i, d.autoDisableReason = r.slice(0, 500)), await e.updateMany("_voltro_webhook_targets", d, { where: x(S("id", t), S("consecutiveFailures", s)) }) === 1) return {
|
|
709
818
|
consecutiveFailures: c,
|
|
710
819
|
autoDisabled: u
|
|
711
820
|
};
|
|
712
821
|
}
|
|
713
|
-
throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${
|
|
714
|
-
},
|
|
715
|
-
status:
|
|
716
|
-
body:
|
|
717
|
-
latencyMs:
|
|
718
|
-
retryAfterSec:
|
|
719
|
-
transportError:
|
|
720
|
-
encodeError:
|
|
721
|
-
}),
|
|
722
|
-
outcome:
|
|
723
|
-
delayMs:
|
|
724
|
-
reason:
|
|
725
|
-
autoDisabled:
|
|
726
|
-
consecutiveFailures:
|
|
727
|
-
}),
|
|
728
|
-
acquired:
|
|
729
|
-
retryInMs:
|
|
730
|
-
}),
|
|
822
|
+
throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${Ae} attempts`);
|
|
823
|
+
}, Ne = b.Struct({
|
|
824
|
+
status: b.Number,
|
|
825
|
+
body: b.String,
|
|
826
|
+
latencyMs: b.Number,
|
|
827
|
+
retryAfterSec: b.Union(b.Number, b.Undefined),
|
|
828
|
+
transportError: b.Union(b.String, b.Undefined),
|
|
829
|
+
encodeError: b.Union(b.String, b.Undefined)
|
|
830
|
+
}), Pe = b.Struct({
|
|
831
|
+
outcome: b.Literal("succeeded", "failed", "retry"),
|
|
832
|
+
delayMs: b.Union(b.Number, b.Undefined),
|
|
833
|
+
reason: b.Union(b.String, b.Undefined),
|
|
834
|
+
autoDisabled: b.Union(b.Boolean, b.Undefined),
|
|
835
|
+
consecutiveFailures: b.Union(b.Number, b.Undefined)
|
|
836
|
+
}), Fe = b.Struct({
|
|
837
|
+
acquired: b.Boolean,
|
|
838
|
+
retryInMs: b.Number
|
|
839
|
+
}), Ie = ie.make({
|
|
731
840
|
name: "voltro.deliverWebhook",
|
|
732
841
|
payload: {
|
|
733
|
-
deliveryId:
|
|
734
|
-
targetId:
|
|
735
|
-
event:
|
|
736
|
-
eventId:
|
|
737
|
-
payloadJson:
|
|
738
|
-
attemptEpoch:
|
|
842
|
+
deliveryId: b.String,
|
|
843
|
+
targetId: b.String,
|
|
844
|
+
event: b.String,
|
|
845
|
+
eventId: b.String,
|
|
846
|
+
payloadJson: b.String,
|
|
847
|
+
attemptEpoch: b.optionalWith(b.Number, { default: () => 0 })
|
|
739
848
|
},
|
|
740
|
-
success:
|
|
741
|
-
finalStatus:
|
|
742
|
-
attempts:
|
|
849
|
+
success: b.Struct({
|
|
850
|
+
finalStatus: b.Literal("succeeded", "failed", "deferred"),
|
|
851
|
+
attempts: b.Number
|
|
743
852
|
}),
|
|
744
853
|
idempotencyKey: ({ deliveryId: e, attemptEpoch: t }) => `voltro.deliverWebhook:${e}:${t ?? 0}`
|
|
745
|
-
}),
|
|
746
|
-
let { deliveryId: i, targetId: a, event: s, eventId: c, payloadJson: l } = n, u =
|
|
747
|
-
return
|
|
854
|
+
}), Le = (e, t = {}) => (n, r) => {
|
|
855
|
+
let { deliveryId: i, targetId: a, event: s, eventId: c, payloadJson: l } = n, u = w({ scope: `webhook:${i}` });
|
|
856
|
+
return y.gen(function* () {
|
|
748
857
|
let n = yield* T.make({
|
|
749
858
|
name: "fetch-target",
|
|
750
|
-
success:
|
|
751
|
-
id:
|
|
752
|
-
event:
|
|
753
|
-
url:
|
|
754
|
-
secret:
|
|
755
|
-
signing:
|
|
756
|
-
retry:
|
|
757
|
-
headers:
|
|
758
|
-
key:
|
|
759
|
-
value:
|
|
760
|
-
}),
|
|
761
|
-
rateLimitPerMinute:
|
|
762
|
-
active:
|
|
763
|
-
format:
|
|
764
|
-
tenantId:
|
|
859
|
+
success: b.Union(b.Null, b.Struct({
|
|
860
|
+
id: b.String,
|
|
861
|
+
event: b.String,
|
|
862
|
+
url: b.String,
|
|
863
|
+
secret: b.String,
|
|
864
|
+
signing: b.Any,
|
|
865
|
+
retry: b.Any,
|
|
866
|
+
headers: b.Union(b.Record({
|
|
867
|
+
key: b.String,
|
|
868
|
+
value: b.String
|
|
869
|
+
}), b.Null),
|
|
870
|
+
rateLimitPerMinute: b.Union(b.Number, b.Null),
|
|
871
|
+
active: b.Boolean,
|
|
872
|
+
format: b.Literal("json", "form", "xml"),
|
|
873
|
+
tenantId: b.Union(b.String, b.Null)
|
|
765
874
|
})),
|
|
766
|
-
execute:
|
|
875
|
+
execute: y.tryPromise({
|
|
767
876
|
try: async () => (await e.store.query({
|
|
768
877
|
table: "_voltro_webhook_targets",
|
|
769
|
-
predicate:
|
|
878
|
+
predicate: S("id", a),
|
|
770
879
|
order: [{
|
|
771
880
|
column: "createdAt",
|
|
772
881
|
direction: "asc"
|
|
@@ -780,7 +889,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
780
889
|
event: s,
|
|
781
890
|
cause: String(e)
|
|
782
891
|
}), /* @__PURE__ */ Error(`fetch-target failed: ${e.message}`))
|
|
783
|
-
}).pipe(
|
|
892
|
+
}).pipe(y.orDie)
|
|
784
893
|
});
|
|
785
894
|
if (n === null) return {
|
|
786
895
|
finalStatus: "failed",
|
|
@@ -807,49 +916,49 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
807
916
|
};
|
|
808
917
|
if (n.active !== !0) return yield* T.make({
|
|
809
918
|
name: "record-paused-pending",
|
|
810
|
-
success:
|
|
811
|
-
execute:
|
|
919
|
+
success: b.Void,
|
|
920
|
+
execute: y.tryPromise({
|
|
812
921
|
try: () => r(`${i}:1`, 1, { status: "pending" }),
|
|
813
922
|
catch: (e) => /* @__PURE__ */ Error(`record-paused-pending failed: ${e.message}`)
|
|
814
|
-
}).pipe(
|
|
923
|
+
}).pipe(y.orDie)
|
|
815
924
|
}), {
|
|
816
925
|
finalStatus: "deferred",
|
|
817
926
|
attempts: 0
|
|
818
927
|
};
|
|
819
|
-
let f = (e) => typeof e == "string" ? JSON.parse(e) : e, p = f(n.retry), m = f(n.signing), h = n.headers === null ? null : f(n.headers),
|
|
928
|
+
let f = (e) => typeof e == "string" ? JSON.parse(e) : e, p = f(n.retry), m = f(n.signing), h = n.headers === null ? null : f(n.headers), ee = t.rateWindowMs ?? 6e4, g = t.events?.find((e) => e.id === s)?.globalRateLimit, _ = [...typeof n.rateLimitPerMinute == "number" && n.rateLimitPerMinute > 0 ? [{
|
|
820
929
|
key: `target:${n.id}`,
|
|
821
930
|
limit: n.rateLimitPerMinute
|
|
822
|
-
}] : [], ...
|
|
931
|
+
}] : [], ...g !== void 0 && g.perMinute > 0 ? [{
|
|
823
932
|
key: `event:${s}`,
|
|
824
|
-
limit:
|
|
933
|
+
limit: g.perMinute
|
|
825
934
|
}] : []];
|
|
826
935
|
for (let t = 1; t <= p.maxAttempts; t++) {
|
|
827
936
|
let f = `${i}:${t}`;
|
|
828
|
-
if (
|
|
937
|
+
if (_.length > 0) for (let n = 0;; n++) {
|
|
829
938
|
let i = yield* T.make({
|
|
830
939
|
name: `rate-acquire-${t}-${n}`,
|
|
831
|
-
success:
|
|
832
|
-
execute:
|
|
833
|
-
try: () =>
|
|
940
|
+
success: Fe,
|
|
941
|
+
execute: y.tryPromise({
|
|
942
|
+
try: () => xe(e.store, _, Date.now(), ee),
|
|
834
943
|
catch: (e) => (u.debug("rate-acquire raw error", {
|
|
835
944
|
targetId: a,
|
|
836
945
|
event: s,
|
|
837
946
|
attempt: t,
|
|
838
947
|
cause: String(e)
|
|
839
948
|
}), /* @__PURE__ */ Error(`rate-acquire failed: ${e.message}`))
|
|
840
|
-
}).pipe(
|
|
949
|
+
}).pipe(y.orDie)
|
|
841
950
|
});
|
|
842
951
|
if (i.acquired) break;
|
|
843
952
|
yield* T.make({
|
|
844
953
|
name: `record-rate-deferral-${t}-${n}`,
|
|
845
|
-
success:
|
|
846
|
-
execute:
|
|
954
|
+
success: b.Void,
|
|
955
|
+
execute: y.tryPromise({
|
|
847
956
|
try: () => r(f, t, {
|
|
848
957
|
status: "pending",
|
|
849
958
|
nextAttemptAt: new Date(Date.now() + i.retryInMs)
|
|
850
959
|
}),
|
|
851
960
|
catch: (e) => /* @__PURE__ */ Error(`record-rate-deferral failed: ${e.message}`)
|
|
852
|
-
}).pipe(
|
|
961
|
+
}).pipe(y.orDie)
|
|
853
962
|
}), yield* E.sleep({
|
|
854
963
|
name: `rate-window-sleep-${t}-${n}`,
|
|
855
964
|
duration: `${i.retryInMs} millis`
|
|
@@ -857,23 +966,23 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
857
966
|
}
|
|
858
967
|
yield* T.make({
|
|
859
968
|
name: `record-attempt-start-${t}`,
|
|
860
|
-
success:
|
|
861
|
-
execute:
|
|
969
|
+
success: b.Void,
|
|
970
|
+
execute: y.tryPromise({
|
|
862
971
|
try: () => r(f, t, {
|
|
863
972
|
status: "inFlight",
|
|
864
973
|
nextAttemptAt: null,
|
|
865
974
|
scheduledAt: /* @__PURE__ */ new Date()
|
|
866
975
|
}),
|
|
867
976
|
catch: (e) => /* @__PURE__ */ Error(`record-attempt-start failed: ${e.message}`)
|
|
868
|
-
}).pipe(
|
|
977
|
+
}).pipe(y.orDie)
|
|
869
978
|
});
|
|
870
|
-
let
|
|
979
|
+
let g = yield* T.make({
|
|
871
980
|
name: `sign-and-post-${t}`,
|
|
872
|
-
success:
|
|
873
|
-
execute:
|
|
981
|
+
success: Ne,
|
|
982
|
+
execute: y.promise(async () => {
|
|
874
983
|
let e = Date.now(), r;
|
|
875
984
|
try {
|
|
876
|
-
r =
|
|
985
|
+
r = Se(n.format, l);
|
|
877
986
|
} catch (t) {
|
|
878
987
|
if (t instanceof d) return {
|
|
879
988
|
status: 0,
|
|
@@ -886,7 +995,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
886
995
|
throw t;
|
|
887
996
|
}
|
|
888
997
|
let a = Buffer.from(r.bytes), { headerName: u, headerValue: f } = o(m, a, n.secret);
|
|
889
|
-
process.env.NODE_ENV === "production" &&
|
|
998
|
+
process.env.NODE_ENV === "production" && C(n.url);
|
|
890
999
|
try {
|
|
891
1000
|
let o = await fetch(n.url, {
|
|
892
1001
|
method: "POST",
|
|
@@ -921,18 +1030,18 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
921
1030
|
};
|
|
922
1031
|
}
|
|
923
1032
|
})
|
|
924
|
-
}),
|
|
1033
|
+
}), v = yield* T.make({
|
|
925
1034
|
name: `classify-and-record-${t}`,
|
|
926
|
-
success:
|
|
927
|
-
execute:
|
|
1035
|
+
success: Pe,
|
|
1036
|
+
execute: y.tryPromise({
|
|
928
1037
|
try: async () => {
|
|
929
|
-
let r =
|
|
1038
|
+
let r = g.status >= 200 && g.status < 300, i = g.transportError !== void 0, o = g.encodeError !== void 0, s = (t, n) => Me(e.store, a, t, n);
|
|
930
1039
|
if (r) {
|
|
931
1040
|
await e.store.update("_voltro_webhook_deliveries", f, {
|
|
932
1041
|
status: "succeeded",
|
|
933
|
-
responseStatus:
|
|
934
|
-
responseBody:
|
|
935
|
-
latencyMs:
|
|
1042
|
+
responseStatus: g.status,
|
|
1043
|
+
responseBody: g.body,
|
|
1044
|
+
latencyMs: g.latencyMs,
|
|
936
1045
|
updatedAt: /* @__PURE__ */ new Date()
|
|
937
1046
|
});
|
|
938
1047
|
let t = await s(!0, "");
|
|
@@ -945,17 +1054,17 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
945
1054
|
};
|
|
946
1055
|
}
|
|
947
1056
|
let c = o ? null : A(p, t, {
|
|
948
|
-
...i ? {} : { status:
|
|
949
|
-
...
|
|
1057
|
+
...i ? {} : { status: g.status },
|
|
1058
|
+
...g.retryAfterSec === void 0 ? {} : { retryAfterSeconds: g.retryAfterSec }
|
|
950
1059
|
});
|
|
951
1060
|
if (c === null) {
|
|
952
|
-
let t = o ? `encode (${n.format}): ${
|
|
1061
|
+
let t = o ? `encode (${n.format}): ${g.encodeError}` : i ? `transport: ${g.transportError}` : `http ${g.status}: ${g.body.slice(0, 200)}`;
|
|
953
1062
|
await e.store.update("_voltro_webhook_deliveries", f, {
|
|
954
1063
|
status: "failed",
|
|
955
|
-
responseStatus: i || o ? null :
|
|
956
|
-
responseBody: i || o ? null :
|
|
957
|
-
errorMessage: o ? t :
|
|
958
|
-
latencyMs:
|
|
1064
|
+
responseStatus: i || o ? null : g.status,
|
|
1065
|
+
responseBody: i || o ? null : g.body,
|
|
1066
|
+
errorMessage: o ? t : g.transportError ?? null,
|
|
1067
|
+
latencyMs: g.latencyMs,
|
|
959
1068
|
updatedAt: /* @__PURE__ */ new Date()
|
|
960
1069
|
});
|
|
961
1070
|
let r = await s(!1, t);
|
|
@@ -969,10 +1078,10 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
969
1078
|
}
|
|
970
1079
|
return await e.store.update("_voltro_webhook_deliveries", f, {
|
|
971
1080
|
status: "retryScheduled",
|
|
972
|
-
responseStatus: i ? null :
|
|
973
|
-
responseBody: i ? null :
|
|
974
|
-
errorMessage:
|
|
975
|
-
latencyMs:
|
|
1081
|
+
responseStatus: i ? null : g.status,
|
|
1082
|
+
responseBody: i ? null : g.body,
|
|
1083
|
+
errorMessage: g.transportError ?? null,
|
|
1084
|
+
latencyMs: g.latencyMs,
|
|
976
1085
|
nextAttemptAt: new Date(Date.now() + c.delayMs),
|
|
977
1086
|
updatedAt: /* @__PURE__ */ new Date()
|
|
978
1087
|
}), {
|
|
@@ -989,24 +1098,24 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
989
1098
|
attempt: t,
|
|
990
1099
|
cause: String(e)
|
|
991
1100
|
}), /* @__PURE__ */ Error(`classify-and-record failed: ${e.message}`))
|
|
992
|
-
}).pipe(
|
|
1101
|
+
}).pipe(y.orDie)
|
|
993
1102
|
});
|
|
994
|
-
if (
|
|
1103
|
+
if (v.autoDisabled === !0 && u.warn("target auto-disabled after consecutive failures", {
|
|
995
1104
|
targetId: a,
|
|
996
1105
|
event: s,
|
|
997
|
-
consecutiveFailures:
|
|
998
|
-
reason:
|
|
999
|
-
}),
|
|
1106
|
+
consecutiveFailures: v.consecutiveFailures ?? null,
|
|
1107
|
+
reason: v.reason ?? null
|
|
1108
|
+
}), v.outcome === "succeeded") return {
|
|
1000
1109
|
finalStatus: "succeeded",
|
|
1001
1110
|
attempts: t
|
|
1002
1111
|
};
|
|
1003
|
-
if (
|
|
1112
|
+
if (v.outcome === "failed") return {
|
|
1004
1113
|
finalStatus: "failed",
|
|
1005
1114
|
attempts: t
|
|
1006
1115
|
};
|
|
1007
|
-
|
|
1116
|
+
v.delayMs !== void 0 && (yield* E.sleep({
|
|
1008
1117
|
name: `retry-sleep-${t}`,
|
|
1009
|
-
duration: `${
|
|
1118
|
+
duration: `${v.delayMs} millis`
|
|
1010
1119
|
}));
|
|
1011
1120
|
}
|
|
1012
1121
|
return {
|
|
@@ -1016,4 +1125,4 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
1016
1125
|
});
|
|
1017
1126
|
};
|
|
1018
1127
|
//#endregion
|
|
1019
|
-
export {
|
|
1128
|
+
export { B as IdempotencyCache, q as RATE_WINDOW_MS, K as RATE_WINDOW_TABLE, ke as TARGETS_TABLE, l as WebhookDeliveryNotFound, u as WebhookPayloadInvalid, d as WebhookPayloadUnrepresentable, f as WebhookPayloadVersionInvalid, p as WebhookSubscribeInvalid, M as WebhooksService, m as _voltroWebhookDeliveriesTable, h as _voltroWebhookRateWindowsTable, ee as _voltroWebhookTargetsTable, xe as acquireRateSlots, D as asOutgoingEvent, Le as buildDeliverWebhookExecute, me as buildWebhooksService, de as compareVersions, X as consumeRateSlot, ye as defaultIncomingPath, c as defaultOutgoingSignature, j as defaultRetryPolicy, s as defineIncomingWebhook, t as defineWebhookProvider, Ie as deliverWebhookWorkflow, Se as encodePayload, se as fastRetryPolicy, P as generateSecret, H as getIdempotencyCache, i as githubSignature, ae as hasWebhookAudience, r as isWebhookDescriptor, z as matchesFilter, ve as mountIncomingWebhook, A as nextRetry, O as parseDuration, W as parseTtl, Me as recordDeliveryOutcome, Z as releaseRateSlot, I as resolveSubscribe, o as signPayload, n as slackSignature, e as stripeSignature, ge as useWebhooks, he as useWebhooksEffect, F as validateSubscribe, a as verifySignature, g as webhookTables };
|