@voltro/plugin-webhooks 0.26.0 → 0.27.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 +297 -0
- package/dist/index.d.ts +68 -9
- package/dist/index.js +258 -223
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
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
|
|
10
|
-
import { Activity as
|
|
3
|
+
import { _voltroWebhookDeliveriesTable as m, _voltroWebhookRateWindowsTable as h, _voltroWebhookTargetsTable as g, webhookTables as _ } from "./mixin.js";
|
|
4
|
+
import { randomBytes as v, randomUUID as y } from "node:crypto";
|
|
5
|
+
import { Context as ee, Effect as b, Either as te, Schema as x } from "effect";
|
|
6
|
+
import { and as S, eq as C } from "@voltro/database";
|
|
7
|
+
import { assertPublicUrl as w } from "@voltro/integration-http";
|
|
8
|
+
import { publishServerError as ne } from "@voltro/protocol";
|
|
9
|
+
import { createLogger as T } from "@voltro/logger";
|
|
10
|
+
import { Activity as E, DurableClock as re, Workflow as ie } from "@effect/workflow";
|
|
11
11
|
//#region src/eventAudience.ts
|
|
12
12
|
var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
13
13
|
let t = e.webhook;
|
|
@@ -39,7 +39,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
39
39
|
502,
|
|
40
40
|
503,
|
|
41
41
|
504
|
|
42
|
-
],
|
|
42
|
+
], se = (e, t, n) => {
|
|
43
43
|
if (t >= e.maxAttempts || n?.status !== void 0 && !(e.retryOn ?? k).includes(n.status)) return null;
|
|
44
44
|
if (e.honourRetryAfter !== !1 && n?.retryAfterSeconds !== void 0) {
|
|
45
45
|
let t = n.retryAfterSeconds * 1e3, r = O(e.maxDelay), i = Math.min(t, r);
|
|
@@ -66,7 +66,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
66
66
|
delayMs: Math.max(1, Math.floor(o)),
|
|
67
67
|
baseDelayMs: a
|
|
68
68
|
};
|
|
69
|
-
},
|
|
69
|
+
}, A = () => ({
|
|
70
70
|
strategy: "exponential",
|
|
71
71
|
maxAttempts: 8,
|
|
72
72
|
initialDelay: "5s",
|
|
@@ -74,7 +74,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
74
74
|
retryOn: k,
|
|
75
75
|
honourRetryAfter: !0,
|
|
76
76
|
jitter: "full"
|
|
77
|
-
}),
|
|
77
|
+
}), ce = () => ({
|
|
78
78
|
strategy: "fixed",
|
|
79
79
|
maxAttempts: 120,
|
|
80
80
|
initialDelay: "30s",
|
|
@@ -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
|
-
}),
|
|
85
|
+
}), j = class extends ee.Tag("@voltro/webhooks/WebhooksService")() {}, le = 32, M = 32, N = () => v(le).toString("hex"), P = (e) => e.events ?? (e.event === void 0 ? [] : [e.event]), F = (e) => {
|
|
86
86
|
let t;
|
|
87
87
|
try {
|
|
88
88
|
t = new URL(e.url);
|
|
@@ -97,20 +97,33 @@ 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
|
+
w(e.url);
|
|
101
101
|
} catch (e) {
|
|
102
102
|
throw new p({
|
|
103
103
|
field: "url",
|
|
104
104
|
reason: e.message
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
|
-
|
|
107
|
+
let n = P(e);
|
|
108
|
+
if (n.length === 0) throw new p({
|
|
108
109
|
field: "event",
|
|
109
110
|
reason: "event id required"
|
|
110
111
|
});
|
|
111
|
-
if (e.
|
|
112
|
+
if (e.event !== void 0 && e.events !== void 0) throw new p({
|
|
113
|
+
field: "event",
|
|
114
|
+
reason: "pass `event` OR `events`, not both — the row set would be ambiguous"
|
|
115
|
+
});
|
|
116
|
+
if (n.some((e) => e.length === 0)) throw new p({
|
|
117
|
+
field: "events",
|
|
118
|
+
reason: "event id required"
|
|
119
|
+
});
|
|
120
|
+
if (new Set(n).size !== n.length) throw new p({
|
|
121
|
+
field: "events",
|
|
122
|
+
reason: "duplicate event — one row per event, so a repeat would deliver twice"
|
|
123
|
+
});
|
|
124
|
+
if (e.secret !== void 0 && e.secret.length < M) throw new p({
|
|
112
125
|
field: "secret",
|
|
113
|
-
reason: `secret must be at least ${
|
|
126
|
+
reason: `secret must be at least ${M} chars`
|
|
114
127
|
});
|
|
115
128
|
if (e.retry !== void 0) {
|
|
116
129
|
if (e.retry.maxAttempts < 1) throw new p({
|
|
@@ -130,13 +143,13 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
130
143
|
field: "autoDisableAfter",
|
|
131
144
|
reason: `autoDisableAfter must be a positive integer, got ${e.autoDisableAfter}`
|
|
132
145
|
});
|
|
133
|
-
}, I = (e, t) => ({
|
|
134
|
-
id:
|
|
135
|
-
event: e.event,
|
|
146
|
+
}, I = (e, t, n, r) => ({
|
|
147
|
+
id: y(),
|
|
148
|
+
event: n ?? e.event ?? "",
|
|
136
149
|
url: e.url,
|
|
137
|
-
secret: e.secret ??
|
|
150
|
+
secret: r ?? e.secret ?? N(),
|
|
138
151
|
signing: e.signing ?? t?.defaultSigning ?? c(),
|
|
139
|
-
retry: e.retry ?? t?.defaultRetry ??
|
|
152
|
+
retry: e.retry ?? t?.defaultRetry ?? A(),
|
|
140
153
|
filter: e.filter ?? null,
|
|
141
154
|
scope: e.scope ?? null,
|
|
142
155
|
headers: e.headers ?? null,
|
|
@@ -149,7 +162,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
149
162
|
autoDisableReason: null,
|
|
150
163
|
payloadVersion: e.payloadVersion ?? t?.version ?? 1,
|
|
151
164
|
description: e.description ?? null
|
|
152
|
-
}),
|
|
165
|
+
}), ue = (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, de = (e) => {
|
|
153
166
|
if (typeof e != "string") return e;
|
|
154
167
|
try {
|
|
155
168
|
return JSON.parse(e);
|
|
@@ -170,19 +183,19 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
170
183
|
scheduledAt: L(e.scheduledAt),
|
|
171
184
|
nextAttemptAt: L(e.nextAttemptAt),
|
|
172
185
|
createdAt: L(e.createdAt)
|
|
173
|
-
}),
|
|
186
|
+
}), fe = (e, t) => e === t ? "current" : e < t ? "behind" : "ahead", z = (e, t) => {
|
|
174
187
|
if (e === null) return !0;
|
|
175
188
|
let n = { payload: t };
|
|
176
|
-
for (let [t, r] of Object.entries(e)) if (!pe(
|
|
189
|
+
for (let [t, r] of Object.entries(e)) if (!me(pe(n, t), r)) return !1;
|
|
177
190
|
return !0;
|
|
178
|
-
},
|
|
191
|
+
}, pe = (e, t) => {
|
|
179
192
|
let n = t.split("."), r = e;
|
|
180
193
|
for (let e of n) {
|
|
181
194
|
if (typeof r != "object" || !r) return;
|
|
182
195
|
r = r[e];
|
|
183
196
|
}
|
|
184
197
|
return r;
|
|
185
|
-
},
|
|
198
|
+
}, me = (e, t) => {
|
|
186
199
|
if (typeof t == "object" && t && !Array.isArray(t)) {
|
|
187
200
|
let n = t;
|
|
188
201
|
if ("eq" in n) return e === n.eq;
|
|
@@ -193,37 +206,42 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
193
206
|
if ("in" in n && Array.isArray(n.in)) return n.in.includes(e);
|
|
194
207
|
}
|
|
195
208
|
return e === t;
|
|
196
|
-
},
|
|
197
|
-
let r = new Map((n.events ?? []).map((e) => [e.id, e]))
|
|
198
|
-
return {
|
|
209
|
+
}, he = (e, t, n = {}) => {
|
|
210
|
+
let r = new Map((n.events ?? []).map((e) => [e.id, e])), i = {
|
|
199
211
|
subscribe: async (t) => {
|
|
200
212
|
F(t);
|
|
201
|
-
let n = I(t, r.get(
|
|
202
|
-
|
|
203
|
-
...
|
|
213
|
+
let n = P(t), i = t.secret ?? N(), a = n.map((e) => I(t, r.get(e), e, i));
|
|
214
|
+
for (let t of a) await e.store.insert("_voltro_webhook_targets", {
|
|
215
|
+
...t,
|
|
204
216
|
createdAt: /* @__PURE__ */ new Date(),
|
|
205
217
|
updatedAt: /* @__PURE__ */ new Date()
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
218
|
+
});
|
|
219
|
+
let o = a[0];
|
|
220
|
+
return {
|
|
221
|
+
id: o.id,
|
|
222
|
+
event: o.event,
|
|
223
|
+
url: o.url,
|
|
224
|
+
secret: o.secret,
|
|
225
|
+
signing: o.signing,
|
|
226
|
+
retry: o.retry,
|
|
227
|
+
...a.length > 1 ? { targets: a.map((e) => ({
|
|
228
|
+
id: e.id,
|
|
229
|
+
event: e.event
|
|
230
|
+
})) } : {}
|
|
213
231
|
};
|
|
214
232
|
},
|
|
215
233
|
emit: async (n, i) => {
|
|
216
234
|
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;
|
|
217
235
|
if (o !== void 0) {
|
|
218
|
-
let e =
|
|
219
|
-
if (
|
|
236
|
+
let e = x.decodeUnknownEither(o.payload)(i, { errors: "all" });
|
|
237
|
+
if (te.isLeft(e)) throw new u({
|
|
220
238
|
event: s,
|
|
221
239
|
issues: e.left.message
|
|
222
240
|
});
|
|
223
241
|
}
|
|
224
|
-
let c =
|
|
242
|
+
let c = y(), l = (await e.store.query({
|
|
225
243
|
table: "_voltro_webhook_targets",
|
|
226
|
-
predicate:
|
|
244
|
+
predicate: C("event", s),
|
|
227
245
|
order: [{
|
|
228
246
|
column: "createdAt",
|
|
229
247
|
direction: "asc"
|
|
@@ -233,7 +251,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
233
251
|
projection: void 0
|
|
234
252
|
})).filter((e) => z(e.filter, i)), d = [], f = JSON.stringify(i);
|
|
235
253
|
for (let n of l) {
|
|
236
|
-
let r =
|
|
254
|
+
let r = y();
|
|
237
255
|
n.active ? (await t({
|
|
238
256
|
deliveryId: r,
|
|
239
257
|
targetId: n.id,
|
|
@@ -271,7 +289,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
271
289
|
replay: async (n) => {
|
|
272
290
|
let r = (await e.store.query({
|
|
273
291
|
table: "_voltro_webhook_deliveries",
|
|
274
|
-
predicate:
|
|
292
|
+
predicate: C("deliveryId", n),
|
|
275
293
|
order: [{
|
|
276
294
|
column: "attempt",
|
|
277
295
|
direction: "asc"
|
|
@@ -285,54 +303,70 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
285
303
|
deliveryId: r.deliveryId,
|
|
286
304
|
targetId: r.targetId,
|
|
287
305
|
event: r.event,
|
|
288
|
-
eventId: r.eventId ??
|
|
306
|
+
eventId: r.eventId ?? y(),
|
|
289
307
|
payloadJson: typeof r.payload == "string" ? r.payload : JSON.stringify(r.payload),
|
|
290
308
|
attemptEpoch: Date.now()
|
|
291
309
|
});
|
|
292
310
|
},
|
|
311
|
+
resolveTargets: async (t) => {
|
|
312
|
+
if (typeof t == "string") return [t];
|
|
313
|
+
let n = (await e.store.query({
|
|
314
|
+
table: "_voltro_webhook_targets",
|
|
315
|
+
predicate: void 0,
|
|
316
|
+
order: void 0,
|
|
317
|
+
take: 1e3,
|
|
318
|
+
skip: void 0,
|
|
319
|
+
projection: void 0
|
|
320
|
+
})).filter((e) => e.scope !== null && Object.entries(t.scope).every(([t, n]) => e.scope?.[t] === n)).map((e) => e.id);
|
|
321
|
+
if (n.length === 0) throw Error(`webhooks: no target matches scope ${JSON.stringify(t.scope)} — the operation would have silently done nothing`);
|
|
322
|
+
return n;
|
|
323
|
+
},
|
|
293
324
|
pauseTarget: async (t) => {
|
|
294
|
-
await e.store.update("_voltro_webhook_targets",
|
|
325
|
+
for (let n of await i.resolveTargets(t)) await e.store.update("_voltro_webhook_targets", n, {
|
|
295
326
|
active: !1,
|
|
296
327
|
updatedAt: /* @__PURE__ */ new Date()
|
|
297
328
|
});
|
|
298
329
|
},
|
|
299
330
|
resumeTarget: async (n) => {
|
|
300
|
-
await
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
331
|
+
for (let r of await i.resolveTargets(n)) {
|
|
332
|
+
await e.store.update("_voltro_webhook_targets", r, {
|
|
333
|
+
active: !0,
|
|
334
|
+
consecutiveFailures: 0,
|
|
335
|
+
autoDisabledAt: null,
|
|
336
|
+
autoDisableReason: null,
|
|
337
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
338
|
+
});
|
|
339
|
+
let n = await e.store.query({
|
|
340
|
+
table: "_voltro_webhook_deliveries",
|
|
341
|
+
predicate: S(C("targetId", r), C("status", "pending")),
|
|
342
|
+
order: [{
|
|
343
|
+
column: "createdAt",
|
|
344
|
+
direction: "asc"
|
|
345
|
+
}],
|
|
346
|
+
take: 1e4,
|
|
347
|
+
skip: void 0,
|
|
348
|
+
projection: void 0
|
|
349
|
+
}), i = Date.now();
|
|
350
|
+
for (let e of n) await t({
|
|
351
|
+
deliveryId: e.deliveryId,
|
|
352
|
+
targetId: r,
|
|
353
|
+
event: e.event,
|
|
354
|
+
eventId: e.eventId ?? y(),
|
|
355
|
+
payloadJson: typeof e.payload == "string" ? e.payload : JSON.stringify(e.payload),
|
|
356
|
+
attemptEpoch: i
|
|
357
|
+
});
|
|
358
|
+
}
|
|
326
359
|
},
|
|
327
360
|
deleteTarget: async (t) => {
|
|
328
|
-
await e.store.delete("_voltro_webhook_targets",
|
|
361
|
+
for (let n of await i.resolveTargets(t)) await e.store.delete("_voltro_webhook_targets", n), await e.store.deleteMany("_voltro_webhook_deliveries", { where: S(C("targetId", n), C("status", "pending")) });
|
|
329
362
|
},
|
|
330
363
|
rotateSecret: async (t) => {
|
|
331
|
-
let n =
|
|
332
|
-
|
|
364
|
+
let n = N();
|
|
365
|
+
for (let r of await i.resolveTargets(t)) await e.store.update("_voltro_webhook_targets", r, {
|
|
333
366
|
secret: n,
|
|
334
367
|
updatedAt: /* @__PURE__ */ new Date()
|
|
335
|
-
})
|
|
368
|
+
});
|
|
369
|
+
return { secret: n };
|
|
336
370
|
},
|
|
337
371
|
updateTarget: async (t, n) => {
|
|
338
372
|
if (n.url !== void 0 && F({
|
|
@@ -350,19 +384,19 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
350
384
|
"autoDisableAfter",
|
|
351
385
|
"format"
|
|
352
386
|
]) n[e] !== void 0 && (r[e] = n[e]);
|
|
353
|
-
await e.store.update("_voltro_webhook_targets",
|
|
387
|
+
for (let n of await i.resolveTargets(t)) await e.store.update("_voltro_webhook_targets", n, r);
|
|
354
388
|
},
|
|
355
389
|
testTarget: async (n, r) => {
|
|
356
390
|
let i = (await e.store.query({
|
|
357
391
|
table: "_voltro_webhook_targets",
|
|
358
|
-
predicate:
|
|
392
|
+
predicate: C("id", n),
|
|
359
393
|
order: void 0,
|
|
360
394
|
take: 1,
|
|
361
395
|
skip: void 0,
|
|
362
396
|
projection: void 0
|
|
363
397
|
}))[0];
|
|
364
398
|
if (i === void 0) throw Error(`testTarget: no target ${n}`);
|
|
365
|
-
let a =
|
|
399
|
+
let a = y(), o = JSON.stringify(r ?? {
|
|
366
400
|
test: !0,
|
|
367
401
|
targetId: n,
|
|
368
402
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -371,7 +405,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
371
405
|
deliveryId: a,
|
|
372
406
|
targetId: i.id,
|
|
373
407
|
event: i.event,
|
|
374
|
-
eventId:
|
|
408
|
+
eventId: y(),
|
|
375
409
|
payloadJson: o
|
|
376
410
|
}) : await e.store.insert("_voltro_webhook_deliveries", {
|
|
377
411
|
id: `${a}:1`,
|
|
@@ -389,9 +423,9 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
389
423
|
}), { deliveryId: a };
|
|
390
424
|
},
|
|
391
425
|
listDeliveries: async (t) => {
|
|
392
|
-
let n = await e.store.query({
|
|
426
|
+
let n = t?.scope === void 0 ? void 0 : new Set(await i.resolveTargets({ scope: t.scope })), r = await e.store.query({
|
|
393
427
|
table: "_voltro_webhook_deliveries",
|
|
394
|
-
predicate: t?.targetId === void 0 ? void 0 :
|
|
428
|
+
predicate: t?.targetId === void 0 ? void 0 : C("targetId", t.targetId),
|
|
395
429
|
order: [{
|
|
396
430
|
column: "createdAt",
|
|
397
431
|
direction: "desc"
|
|
@@ -399,13 +433,13 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
399
433
|
take: Math.min((t?.limit ?? 200) * (t?.status !== void 0 || t?.since !== void 0 ? 10 : 1), 5e3),
|
|
400
434
|
skip: void 0,
|
|
401
435
|
projection: void 0
|
|
402
|
-
}),
|
|
403
|
-
return n.filter((e) => t?.status === void 0 || e.status === t.status).filter((e) =>
|
|
436
|
+
}), a = t?.since?.getTime();
|
|
437
|
+
return r.filter((e) => n === void 0 || n.has(String(e.targetId))).filter((e) => t?.status === void 0 || e.status === t.status).filter((e) => a === void 0 || ue(e.createdAt) >= a).slice(0, t?.limit ?? 200).map(R);
|
|
404
438
|
},
|
|
405
439
|
getDelivery: async (t) => {
|
|
406
440
|
let n = (await e.store.query({
|
|
407
441
|
table: "_voltro_webhook_deliveries",
|
|
408
|
-
predicate:
|
|
442
|
+
predicate: C("id", t),
|
|
409
443
|
order: void 0,
|
|
410
444
|
take: 1,
|
|
411
445
|
skip: void 0,
|
|
@@ -413,7 +447,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
413
447
|
}))[0];
|
|
414
448
|
return n === void 0 ? null : {
|
|
415
449
|
...R(n),
|
|
416
|
-
payload:
|
|
450
|
+
payload: de(n.payload),
|
|
417
451
|
responseBody: n.responseBody ?? null
|
|
418
452
|
};
|
|
419
453
|
},
|
|
@@ -427,7 +461,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
427
461
|
listTargets: async (t, n) => {
|
|
428
462
|
let r = await e.store.query({
|
|
429
463
|
table: "_voltro_webhook_targets",
|
|
430
|
-
predicate: t === void 0 ? void 0 :
|
|
464
|
+
predicate: t === void 0 ? void 0 : C("event", t),
|
|
431
465
|
order: [{
|
|
432
466
|
column: "createdAt",
|
|
433
467
|
direction: "desc"
|
|
@@ -452,15 +486,16 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
452
486
|
}));
|
|
453
487
|
}
|
|
454
488
|
};
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
489
|
+
return i;
|
|
490
|
+
}, ge = b.gen(function* () {
|
|
491
|
+
return yield* j;
|
|
492
|
+
}), _e = (e) => {
|
|
458
493
|
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.");
|
|
459
494
|
return e.webhooks;
|
|
460
|
-
},
|
|
495
|
+
}, ve = 1e4, B = class {
|
|
461
496
|
capacity;
|
|
462
497
|
cache = /* @__PURE__ */ new Map();
|
|
463
|
-
constructor(e =
|
|
498
|
+
constructor(e = ve) {
|
|
464
499
|
this.capacity = e;
|
|
465
500
|
}
|
|
466
501
|
evictExpired() {
|
|
@@ -506,9 +541,9 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
506
541
|
status: e,
|
|
507
542
|
contentType: "application/json; charset=utf-8",
|
|
508
543
|
body: JSON.stringify(t)
|
|
509
|
-
}),
|
|
544
|
+
}), ye = (e, t) => {
|
|
510
545
|
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
|
-
|
|
546
|
+
T({ scope: `webhook:${e.webhookId}` }).debug("incoming webhook", {
|
|
512
547
|
status: e.status,
|
|
513
548
|
signatureOk: e.signatureOk,
|
|
514
549
|
idempotency: e.idempotency,
|
|
@@ -581,7 +616,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
581
616
|
}
|
|
582
617
|
let p;
|
|
583
618
|
try {
|
|
584
|
-
p =
|
|
619
|
+
p = x.decodeUnknownSync(e.payload)(f);
|
|
585
620
|
} catch (t) {
|
|
586
621
|
let n = G(422, {
|
|
587
622
|
error: "schema validation failed",
|
|
@@ -659,7 +694,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
659
694
|
idempotency: h,
|
|
660
695
|
durationMs: Date.now() - u,
|
|
661
696
|
errorMessage: t.message
|
|
662
|
-
}),
|
|
697
|
+
}), ne({
|
|
663
698
|
error: t,
|
|
664
699
|
source: "webhook",
|
|
665
700
|
name: e.id,
|
|
@@ -667,9 +702,9 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
667
702
|
}), n;
|
|
668
703
|
}
|
|
669
704
|
};
|
|
670
|
-
},
|
|
705
|
+
}, be = (e) => `/webhooks/${e}`, K = "_voltro_webhook_rate_windows", q = 6e4, xe = (e, t) => `${e}@${t}`, J = async (e, t, n) => (await e.query({
|
|
671
706
|
table: "_voltro_webhook_rate_windows",
|
|
672
|
-
predicate:
|
|
707
|
+
predicate: S(C("scope", t), C("bucket", n)),
|
|
673
708
|
order: [],
|
|
674
709
|
take: 1,
|
|
675
710
|
skip: void 0,
|
|
@@ -680,7 +715,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
680
715
|
let i = await J(e, t.key, n);
|
|
681
716
|
if (i === null) {
|
|
682
717
|
await e.insertIgnore(K, {
|
|
683
|
-
id:
|
|
718
|
+
id: xe(t.key, n),
|
|
684
719
|
scope: t.key,
|
|
685
720
|
bucket: n,
|
|
686
721
|
count: 0,
|
|
@@ -693,7 +728,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
693
728
|
if (await e.updateMany("_voltro_webhook_rate_windows", {
|
|
694
729
|
count: i.count + 1,
|
|
695
730
|
updatedAt: /* @__PURE__ */ new Date()
|
|
696
|
-
}, { where:
|
|
731
|
+
}, { where: S(C("id", i.id), C("count", i.count)) }) === 1) return !0;
|
|
697
732
|
}
|
|
698
733
|
throw Error(`webhook rate window: contention on (${t.key}, ${n}) exceeded ${Y} attempts`);
|
|
699
734
|
}, Z = async (e, t, n) => {
|
|
@@ -703,10 +738,10 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
703
738
|
if (i === null || i.count <= 0 || await e.updateMany("_voltro_webhook_rate_windows", {
|
|
704
739
|
count: i.count - 1,
|
|
705
740
|
updatedAt: /* @__PURE__ */ new Date()
|
|
706
|
-
}, { where:
|
|
741
|
+
}, { where: S(C("id", i.id), C("count", i.count)) }) === 1) return;
|
|
707
742
|
}
|
|
708
743
|
throw Error(`webhook rate window: release contention on (${t}) exceeded ${Y} attempts`);
|
|
709
|
-
},
|
|
744
|
+
}, Se = async (e, t, n, r = q) => {
|
|
710
745
|
if (t.length === 0) return {
|
|
711
746
|
acquired: !0,
|
|
712
747
|
retryInMs: 0
|
|
@@ -727,7 +762,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
727
762
|
acquired: !0,
|
|
728
763
|
retryInMs: 0
|
|
729
764
|
};
|
|
730
|
-
},
|
|
765
|
+
}, Ce = (e, t) => {
|
|
731
766
|
if (e === "json") return {
|
|
732
767
|
contentType: "application/json",
|
|
733
768
|
bytes: Buffer.from(t, "utf8")
|
|
@@ -743,15 +778,15 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
743
778
|
}
|
|
744
779
|
return e === "form" ? {
|
|
745
780
|
contentType: "application/x-www-form-urlencoded",
|
|
746
|
-
bytes: Buffer.from(
|
|
781
|
+
bytes: Buffer.from(we(n), "utf8")
|
|
747
782
|
} : {
|
|
748
783
|
contentType: "application/xml",
|
|
749
|
-
bytes: Buffer.from(
|
|
784
|
+
bytes: Buffer.from(Ee(n), "utf8")
|
|
750
785
|
};
|
|
751
|
-
},
|
|
786
|
+
}, we = (e) => {
|
|
752
787
|
if (typeof e != "object" || !e || Array.isArray(e)) throw new d({
|
|
753
788
|
format: "form",
|
|
754
|
-
reason: `form encoding requires a JSON object at the top level, got ${
|
|
789
|
+
reason: `form encoding requires a JSON object at the top level, got ${ke(e)}`
|
|
755
790
|
});
|
|
756
791
|
let t = new URLSearchParams();
|
|
757
792
|
for (let [n, r] of Object.entries(e)) Q(t, n, r);
|
|
@@ -770,13 +805,13 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
770
805
|
return;
|
|
771
806
|
}
|
|
772
807
|
e.append(t, String(n));
|
|
773
|
-
},
|
|
774
|
-
if (!
|
|
808
|
+
}, Te = /^[A-Za-z_][A-Za-z0-9_.-]*$/, Ee = (e) => `<?xml version="1.0" encoding="UTF-8"?>${$("webhook", e)}`, $ = (e, t) => {
|
|
809
|
+
if (!Te.test(e)) throw new d({
|
|
775
810
|
format: "xml",
|
|
776
811
|
reason: `object key ${JSON.stringify(e)} is not a valid XML element name`
|
|
777
812
|
});
|
|
778
|
-
return `<${e}>${
|
|
779
|
-
},
|
|
813
|
+
return `<${e}>${De(e, t)}</${e}>`;
|
|
814
|
+
}, De = (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("") : Oe(String(t)), Oe = (e) => e.replace(/[&<>"']/g, (e) => {
|
|
780
815
|
switch (e) {
|
|
781
816
|
case "&": return "&";
|
|
782
817
|
case "<": return "<";
|
|
@@ -784,17 +819,17 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
784
819
|
case "\"": return """;
|
|
785
820
|
default: return "'";
|
|
786
821
|
}
|
|
787
|
-
}),
|
|
822
|
+
}), ke = (e) => e === null ? "null" : Array.isArray(e) ? "array" : typeof e, Ae = "_voltro_webhook_targets", je = 32, Me = async (e, t) => (await e.query({
|
|
788
823
|
table: "_voltro_webhook_targets",
|
|
789
|
-
predicate:
|
|
824
|
+
predicate: C("id", t),
|
|
790
825
|
order: [],
|
|
791
826
|
take: 1,
|
|
792
827
|
skip: void 0,
|
|
793
828
|
projection: void 0
|
|
794
|
-
}))[0] ?? null,
|
|
795
|
-
for (let a = 0; a <
|
|
829
|
+
}))[0] ?? null, Ne = async (e, t, n, r, i = /* @__PURE__ */ new Date()) => {
|
|
830
|
+
for (let a = 0; a < je; a++) {
|
|
796
831
|
a > 0 && await new Promise((e) => setTimeout(e, a));
|
|
797
|
-
let o = await
|
|
832
|
+
let o = await Me(e, t);
|
|
798
833
|
if (o === null) return {
|
|
799
834
|
consecutiveFailures: 0,
|
|
800
835
|
autoDisabled: !1
|
|
@@ -804,7 +839,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
804
839
|
if (s === 0 || await e.updateMany("_voltro_webhook_targets", {
|
|
805
840
|
consecutiveFailures: 0,
|
|
806
841
|
updatedAt: i
|
|
807
|
-
}, { where:
|
|
842
|
+
}, { where: S(C("id", t), C("consecutiveFailures", s)) }) === 1) return {
|
|
808
843
|
consecutiveFailures: 0,
|
|
809
844
|
autoDisabled: !1
|
|
810
845
|
};
|
|
@@ -814,68 +849,68 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
814
849
|
consecutiveFailures: c,
|
|
815
850
|
updatedAt: i
|
|
816
851
|
};
|
|
817
|
-
if (u && (d.active = !1, d.autoDisabledAt = i, d.autoDisableReason = r.slice(0, 500)), await e.updateMany("_voltro_webhook_targets", d, { where:
|
|
852
|
+
if (u && (d.active = !1, d.autoDisabledAt = i, d.autoDisableReason = r.slice(0, 500)), await e.updateMany("_voltro_webhook_targets", d, { where: S(C("id", t), C("consecutiveFailures", s)) }) === 1) return {
|
|
818
853
|
consecutiveFailures: c,
|
|
819
854
|
autoDisabled: u
|
|
820
855
|
};
|
|
821
856
|
}
|
|
822
|
-
throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${
|
|
823
|
-
},
|
|
824
|
-
status:
|
|
825
|
-
body:
|
|
826
|
-
latencyMs:
|
|
827
|
-
retryAfterSec:
|
|
828
|
-
transportError:
|
|
829
|
-
encodeError:
|
|
830
|
-
}),
|
|
831
|
-
outcome:
|
|
832
|
-
delayMs:
|
|
833
|
-
reason:
|
|
834
|
-
autoDisabled:
|
|
835
|
-
consecutiveFailures:
|
|
836
|
-
}),
|
|
837
|
-
acquired:
|
|
838
|
-
retryInMs:
|
|
839
|
-
}),
|
|
857
|
+
throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${je} attempts`);
|
|
858
|
+
}, Pe = x.Struct({
|
|
859
|
+
status: x.Number,
|
|
860
|
+
body: x.String,
|
|
861
|
+
latencyMs: x.Number,
|
|
862
|
+
retryAfterSec: x.Union(x.Number, x.Undefined),
|
|
863
|
+
transportError: x.Union(x.String, x.Undefined),
|
|
864
|
+
encodeError: x.Union(x.String, x.Undefined)
|
|
865
|
+
}), Fe = x.Struct({
|
|
866
|
+
outcome: x.Literal("succeeded", "failed", "retry"),
|
|
867
|
+
delayMs: x.Union(x.Number, x.Undefined),
|
|
868
|
+
reason: x.Union(x.String, x.Undefined),
|
|
869
|
+
autoDisabled: x.Union(x.Boolean, x.Undefined),
|
|
870
|
+
consecutiveFailures: x.Union(x.Number, x.Undefined)
|
|
871
|
+
}), Ie = x.Struct({
|
|
872
|
+
acquired: x.Boolean,
|
|
873
|
+
retryInMs: x.Number
|
|
874
|
+
}), Le = ie.make({
|
|
840
875
|
name: "voltro.deliverWebhook",
|
|
841
876
|
payload: {
|
|
842
|
-
deliveryId:
|
|
843
|
-
targetId:
|
|
844
|
-
event:
|
|
845
|
-
eventId:
|
|
846
|
-
payloadJson:
|
|
847
|
-
attemptEpoch:
|
|
877
|
+
deliveryId: x.String,
|
|
878
|
+
targetId: x.String,
|
|
879
|
+
event: x.String,
|
|
880
|
+
eventId: x.String,
|
|
881
|
+
payloadJson: x.String,
|
|
882
|
+
attemptEpoch: x.optionalWith(x.Number, { default: () => 0 })
|
|
848
883
|
},
|
|
849
|
-
success:
|
|
850
|
-
finalStatus:
|
|
851
|
-
attempts:
|
|
884
|
+
success: x.Struct({
|
|
885
|
+
finalStatus: x.Literal("succeeded", "failed", "deferred"),
|
|
886
|
+
attempts: x.Number
|
|
852
887
|
}),
|
|
853
888
|
idempotencyKey: ({ deliveryId: e, attemptEpoch: t }) => `voltro.deliverWebhook:${e}:${t ?? 0}`
|
|
854
|
-
}),
|
|
855
|
-
let { deliveryId: i, targetId: a, event: s, eventId: c, payloadJson: l } = n, u =
|
|
856
|
-
return
|
|
857
|
-
let n = yield*
|
|
889
|
+
}), Re = (e, t = {}) => (n, r) => {
|
|
890
|
+
let { deliveryId: i, targetId: a, event: s, eventId: c, payloadJson: l } = n, u = T({ scope: `webhook:${i}` });
|
|
891
|
+
return b.gen(function* () {
|
|
892
|
+
let n = yield* E.make({
|
|
858
893
|
name: "fetch-target",
|
|
859
|
-
success:
|
|
860
|
-
id:
|
|
861
|
-
event:
|
|
862
|
-
url:
|
|
863
|
-
secret:
|
|
864
|
-
signing:
|
|
865
|
-
retry:
|
|
866
|
-
headers:
|
|
867
|
-
key:
|
|
868
|
-
value:
|
|
869
|
-
}),
|
|
870
|
-
rateLimitPerMinute:
|
|
871
|
-
active:
|
|
872
|
-
format:
|
|
873
|
-
tenantId:
|
|
894
|
+
success: x.Union(x.Null, x.Struct({
|
|
895
|
+
id: x.String,
|
|
896
|
+
event: x.String,
|
|
897
|
+
url: x.String,
|
|
898
|
+
secret: x.String,
|
|
899
|
+
signing: x.Any,
|
|
900
|
+
retry: x.Any,
|
|
901
|
+
headers: x.Union(x.Record({
|
|
902
|
+
key: x.String,
|
|
903
|
+
value: x.String
|
|
904
|
+
}), x.Null),
|
|
905
|
+
rateLimitPerMinute: x.Union(x.Number, x.Null),
|
|
906
|
+
active: x.Boolean,
|
|
907
|
+
format: x.Literal("json", "form", "xml"),
|
|
908
|
+
tenantId: x.Union(x.String, x.Null)
|
|
874
909
|
})),
|
|
875
|
-
execute:
|
|
910
|
+
execute: b.tryPromise({
|
|
876
911
|
try: async () => (await e.store.query({
|
|
877
912
|
table: "_voltro_webhook_targets",
|
|
878
|
-
predicate:
|
|
913
|
+
predicate: C("id", a),
|
|
879
914
|
order: [{
|
|
880
915
|
column: "createdAt",
|
|
881
916
|
direction: "asc"
|
|
@@ -889,7 +924,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
889
924
|
event: s,
|
|
890
925
|
cause: String(e)
|
|
891
926
|
}), /* @__PURE__ */ Error(`fetch-target failed: ${e.message}`))
|
|
892
|
-
}).pipe(
|
|
927
|
+
}).pipe(b.orDie)
|
|
893
928
|
});
|
|
894
929
|
if (n === null) return {
|
|
895
930
|
finalStatus: "failed",
|
|
@@ -914,75 +949,75 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
914
949
|
...o
|
|
915
950
|
});
|
|
916
951
|
};
|
|
917
|
-
if (n.active !== !0) return yield*
|
|
952
|
+
if (n.active !== !0) return yield* E.make({
|
|
918
953
|
name: "record-paused-pending",
|
|
919
|
-
success:
|
|
920
|
-
execute:
|
|
954
|
+
success: x.Void,
|
|
955
|
+
execute: b.tryPromise({
|
|
921
956
|
try: () => r(`${i}:1`, 1, { status: "pending" }),
|
|
922
957
|
catch: (e) => /* @__PURE__ */ Error(`record-paused-pending failed: ${e.message}`)
|
|
923
|
-
}).pipe(
|
|
958
|
+
}).pipe(b.orDie)
|
|
924
959
|
}), {
|
|
925
960
|
finalStatus: "deferred",
|
|
926
961
|
attempts: 0
|
|
927
962
|
};
|
|
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),
|
|
963
|
+
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), g = t.rateWindowMs ?? 6e4, _ = t.events?.find((e) => e.id === s)?.globalRateLimit, v = [...typeof n.rateLimitPerMinute == "number" && n.rateLimitPerMinute > 0 ? [{
|
|
929
964
|
key: `target:${n.id}`,
|
|
930
965
|
limit: n.rateLimitPerMinute
|
|
931
|
-
}] : [], ...
|
|
966
|
+
}] : [], ..._ !== void 0 && _.perMinute > 0 ? [{
|
|
932
967
|
key: `event:${s}`,
|
|
933
|
-
limit:
|
|
968
|
+
limit: _.perMinute
|
|
934
969
|
}] : []];
|
|
935
970
|
for (let t = 1; t <= p.maxAttempts; t++) {
|
|
936
971
|
let f = `${i}:${t}`;
|
|
937
|
-
if (
|
|
938
|
-
let i = yield*
|
|
972
|
+
if (v.length > 0) for (let n = 0;; n++) {
|
|
973
|
+
let i = yield* E.make({
|
|
939
974
|
name: `rate-acquire-${t}-${n}`,
|
|
940
|
-
success:
|
|
941
|
-
execute:
|
|
942
|
-
try: () =>
|
|
975
|
+
success: Ie,
|
|
976
|
+
execute: b.tryPromise({
|
|
977
|
+
try: () => Se(e.store, v, Date.now(), g),
|
|
943
978
|
catch: (e) => (u.debug("rate-acquire raw error", {
|
|
944
979
|
targetId: a,
|
|
945
980
|
event: s,
|
|
946
981
|
attempt: t,
|
|
947
982
|
cause: String(e)
|
|
948
983
|
}), /* @__PURE__ */ Error(`rate-acquire failed: ${e.message}`))
|
|
949
|
-
}).pipe(
|
|
984
|
+
}).pipe(b.orDie)
|
|
950
985
|
});
|
|
951
986
|
if (i.acquired) break;
|
|
952
|
-
yield*
|
|
987
|
+
yield* E.make({
|
|
953
988
|
name: `record-rate-deferral-${t}-${n}`,
|
|
954
|
-
success:
|
|
955
|
-
execute:
|
|
989
|
+
success: x.Void,
|
|
990
|
+
execute: b.tryPromise({
|
|
956
991
|
try: () => r(f, t, {
|
|
957
992
|
status: "pending",
|
|
958
993
|
nextAttemptAt: new Date(Date.now() + i.retryInMs)
|
|
959
994
|
}),
|
|
960
995
|
catch: (e) => /* @__PURE__ */ Error(`record-rate-deferral failed: ${e.message}`)
|
|
961
|
-
}).pipe(
|
|
962
|
-
}), yield*
|
|
996
|
+
}).pipe(b.orDie)
|
|
997
|
+
}), yield* re.sleep({
|
|
963
998
|
name: `rate-window-sleep-${t}-${n}`,
|
|
964
999
|
duration: `${i.retryInMs} millis`
|
|
965
1000
|
});
|
|
966
1001
|
}
|
|
967
|
-
yield*
|
|
1002
|
+
yield* E.make({
|
|
968
1003
|
name: `record-attempt-start-${t}`,
|
|
969
|
-
success:
|
|
970
|
-
execute:
|
|
1004
|
+
success: x.Void,
|
|
1005
|
+
execute: b.tryPromise({
|
|
971
1006
|
try: () => r(f, t, {
|
|
972
1007
|
status: "inFlight",
|
|
973
1008
|
nextAttemptAt: null,
|
|
974
1009
|
scheduledAt: /* @__PURE__ */ new Date()
|
|
975
1010
|
}),
|
|
976
1011
|
catch: (e) => /* @__PURE__ */ Error(`record-attempt-start failed: ${e.message}`)
|
|
977
|
-
}).pipe(
|
|
1012
|
+
}).pipe(b.orDie)
|
|
978
1013
|
});
|
|
979
|
-
let
|
|
1014
|
+
let _ = yield* E.make({
|
|
980
1015
|
name: `sign-and-post-${t}`,
|
|
981
|
-
success:
|
|
982
|
-
execute:
|
|
1016
|
+
success: Pe,
|
|
1017
|
+
execute: b.promise(async () => {
|
|
983
1018
|
let e = Date.now(), r;
|
|
984
1019
|
try {
|
|
985
|
-
r =
|
|
1020
|
+
r = Ce(n.format, l);
|
|
986
1021
|
} catch (t) {
|
|
987
1022
|
if (t instanceof d) return {
|
|
988
1023
|
status: 0,
|
|
@@ -995,7 +1030,7 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
995
1030
|
throw t;
|
|
996
1031
|
}
|
|
997
1032
|
let a = Buffer.from(r.bytes), { headerName: u, headerValue: f } = o(m, a, n.secret);
|
|
998
|
-
process.env.NODE_ENV === "production" &&
|
|
1033
|
+
process.env.NODE_ENV === "production" && w(n.url);
|
|
999
1034
|
try {
|
|
1000
1035
|
let o = await fetch(n.url, {
|
|
1001
1036
|
method: "POST",
|
|
@@ -1030,18 +1065,18 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
1030
1065
|
};
|
|
1031
1066
|
}
|
|
1032
1067
|
})
|
|
1033
|
-
}),
|
|
1068
|
+
}), y = yield* E.make({
|
|
1034
1069
|
name: `classify-and-record-${t}`,
|
|
1035
|
-
success:
|
|
1036
|
-
execute:
|
|
1070
|
+
success: Fe,
|
|
1071
|
+
execute: b.tryPromise({
|
|
1037
1072
|
try: async () => {
|
|
1038
|
-
let r =
|
|
1073
|
+
let r = _.status >= 200 && _.status < 300, i = _.transportError !== void 0, o = _.encodeError !== void 0, s = (t, n) => Ne(e.store, a, t, n);
|
|
1039
1074
|
if (r) {
|
|
1040
1075
|
await e.store.update("_voltro_webhook_deliveries", f, {
|
|
1041
1076
|
status: "succeeded",
|
|
1042
|
-
responseStatus:
|
|
1043
|
-
responseBody:
|
|
1044
|
-
latencyMs:
|
|
1077
|
+
responseStatus: _.status,
|
|
1078
|
+
responseBody: _.body,
|
|
1079
|
+
latencyMs: _.latencyMs,
|
|
1045
1080
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1046
1081
|
});
|
|
1047
1082
|
let t = await s(!0, "");
|
|
@@ -1053,18 +1088,18 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
1053
1088
|
consecutiveFailures: t.consecutiveFailures
|
|
1054
1089
|
};
|
|
1055
1090
|
}
|
|
1056
|
-
let c = o ? null :
|
|
1057
|
-
...i ? {} : { status:
|
|
1058
|
-
...
|
|
1091
|
+
let c = o ? null : se(p, t, {
|
|
1092
|
+
...i ? {} : { status: _.status },
|
|
1093
|
+
..._.retryAfterSec === void 0 ? {} : { retryAfterSeconds: _.retryAfterSec }
|
|
1059
1094
|
});
|
|
1060
1095
|
if (c === null) {
|
|
1061
|
-
let t = o ? `encode (${n.format}): ${
|
|
1096
|
+
let t = o ? `encode (${n.format}): ${_.encodeError}` : i ? `transport: ${_.transportError}` : `http ${_.status}: ${_.body.slice(0, 200)}`;
|
|
1062
1097
|
await e.store.update("_voltro_webhook_deliveries", f, {
|
|
1063
1098
|
status: "failed",
|
|
1064
|
-
responseStatus: i || o ? null :
|
|
1065
|
-
responseBody: i || o ? null :
|
|
1066
|
-
errorMessage: o ? t :
|
|
1067
|
-
latencyMs:
|
|
1099
|
+
responseStatus: i || o ? null : _.status,
|
|
1100
|
+
responseBody: i || o ? null : _.body,
|
|
1101
|
+
errorMessage: o ? t : _.transportError ?? null,
|
|
1102
|
+
latencyMs: _.latencyMs,
|
|
1068
1103
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1069
1104
|
});
|
|
1070
1105
|
let r = await s(!1, t);
|
|
@@ -1078,10 +1113,10 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
1078
1113
|
}
|
|
1079
1114
|
return await e.store.update("_voltro_webhook_deliveries", f, {
|
|
1080
1115
|
status: "retryScheduled",
|
|
1081
|
-
responseStatus: i ? null :
|
|
1082
|
-
responseBody: i ? null :
|
|
1083
|
-
errorMessage:
|
|
1084
|
-
latencyMs:
|
|
1116
|
+
responseStatus: i ? null : _.status,
|
|
1117
|
+
responseBody: i ? null : _.body,
|
|
1118
|
+
errorMessage: _.transportError ?? null,
|
|
1119
|
+
latencyMs: _.latencyMs,
|
|
1085
1120
|
nextAttemptAt: new Date(Date.now() + c.delayMs),
|
|
1086
1121
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1087
1122
|
}), {
|
|
@@ -1098,24 +1133,24 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
1098
1133
|
attempt: t,
|
|
1099
1134
|
cause: String(e)
|
|
1100
1135
|
}), /* @__PURE__ */ Error(`classify-and-record failed: ${e.message}`))
|
|
1101
|
-
}).pipe(
|
|
1136
|
+
}).pipe(b.orDie)
|
|
1102
1137
|
});
|
|
1103
|
-
if (
|
|
1138
|
+
if (y.autoDisabled === !0 && u.warn("target auto-disabled after consecutive failures", {
|
|
1104
1139
|
targetId: a,
|
|
1105
1140
|
event: s,
|
|
1106
|
-
consecutiveFailures:
|
|
1107
|
-
reason:
|
|
1108
|
-
}),
|
|
1141
|
+
consecutiveFailures: y.consecutiveFailures ?? null,
|
|
1142
|
+
reason: y.reason ?? null
|
|
1143
|
+
}), y.outcome === "succeeded") return {
|
|
1109
1144
|
finalStatus: "succeeded",
|
|
1110
1145
|
attempts: t
|
|
1111
1146
|
};
|
|
1112
|
-
if (
|
|
1147
|
+
if (y.outcome === "failed") return {
|
|
1113
1148
|
finalStatus: "failed",
|
|
1114
1149
|
attempts: t
|
|
1115
1150
|
};
|
|
1116
|
-
|
|
1151
|
+
y.delayMs !== void 0 && (yield* re.sleep({
|
|
1117
1152
|
name: `retry-sleep-${t}`,
|
|
1118
|
-
duration: `${
|
|
1153
|
+
duration: `${y.delayMs} millis`
|
|
1119
1154
|
}));
|
|
1120
1155
|
}
|
|
1121
1156
|
return {
|
|
@@ -1125,4 +1160,4 @@ var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
|
1125
1160
|
});
|
|
1126
1161
|
};
|
|
1127
1162
|
//#endregion
|
|
1128
|
-
export { B as IdempotencyCache, q as RATE_WINDOW_MS, K as RATE_WINDOW_TABLE,
|
|
1163
|
+
export { B as IdempotencyCache, q as RATE_WINDOW_MS, K as RATE_WINDOW_TABLE, Ae as TARGETS_TABLE, l as WebhookDeliveryNotFound, u as WebhookPayloadInvalid, d as WebhookPayloadUnrepresentable, f as WebhookPayloadVersionInvalid, p as WebhookSubscribeInvalid, j as WebhooksService, m as _voltroWebhookDeliveriesTable, h as _voltroWebhookRateWindowsTable, g as _voltroWebhookTargetsTable, Se as acquireRateSlots, D as asOutgoingEvent, Re as buildDeliverWebhookExecute, he as buildWebhooksService, fe as compareVersions, X as consumeRateSlot, be as defaultIncomingPath, c as defaultOutgoingSignature, A as defaultRetryPolicy, s as defineIncomingWebhook, t as defineWebhookProvider, Le as deliverWebhookWorkflow, Ce as encodePayload, P as eventsOf, ce as fastRetryPolicy, N as generateSecret, H as getIdempotencyCache, i as githubSignature, ae as hasWebhookAudience, r as isWebhookDescriptor, z as matchesFilter, ye as mountIncomingWebhook, se as nextRetry, O as parseDuration, W as parseTtl, Ne as recordDeliveryOutcome, Z as releaseRateSlot, I as resolveSubscribe, o as signPayload, n as slackSignature, e as stripeSignature, _e as useWebhooks, ge as useWebhooksEffect, F as validateSubscribe, a as verifySignature, _ as webhookTables };
|