@voltro/plugin-webhooks 0.24.0 → 0.25.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 +426 -0
- package/dist/errors.d.ts +1 -1
- package/dist/index.d.ts +48 -8
- package/dist/index.js +183 -173
- package/dist/providers/index.js +1 -1
- package/dist/{signing-BOUxHdAo.js → signing-DUG4JWwk.js} +29 -32
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
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
|
|
2
|
-
import { WebhookDeliveryNotFound as
|
|
3
|
-
import { _voltroWebhookDeliveriesTable as
|
|
4
|
-
import { randomBytes as
|
|
5
|
-
import { Context as ee, Effect as
|
|
6
|
-
import { and as
|
|
7
|
-
import { assertPublicUrl as
|
|
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
|
+
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 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
8
|
import { publishServerError as ne } from "@voltro/protocol";
|
|
9
9
|
import { createLogger as re } from "@voltro/logger";
|
|
10
|
-
import { Activity as
|
|
11
|
-
//#region src/
|
|
12
|
-
var ae =
|
|
13
|
-
let t =
|
|
10
|
+
import { Activity as T, DurableClock as E, Workflow as ie } from "@effect/workflow";
|
|
11
|
+
//#region src/eventAudience.ts
|
|
12
|
+
var ae = (e) => e.webhook !== void 0, D = (e) => {
|
|
13
|
+
let t = e.webhook;
|
|
14
|
+
if (t !== void 0) return {
|
|
15
|
+
_tag: "outgoingEvent",
|
|
16
|
+
id: e.name,
|
|
17
|
+
payload: e.payload,
|
|
18
|
+
...t.description === void 0 ? {} : { description: t.description },
|
|
19
|
+
...t.version === void 0 ? {} : { version: t.version },
|
|
20
|
+
...t.rateLimit === void 0 ? {} : { globalRateLimit: t.rateLimit }
|
|
21
|
+
};
|
|
22
|
+
}, oe = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
23
|
+
let t = oe.exec(e);
|
|
14
24
|
if (!t) throw Error(`invalid duration literal: ${e}`);
|
|
15
25
|
let n = Number(t[1]), r = t[2] ?? "s";
|
|
16
26
|
switch (r) {
|
|
@@ -64,7 +74,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
64
74
|
retryOn: k,
|
|
65
75
|
honourRetryAfter: !0,
|
|
66
76
|
jitter: "full"
|
|
67
|
-
}),
|
|
77
|
+
}), se = () => ({
|
|
68
78
|
strategy: "fixed",
|
|
69
79
|
maxAttempts: 120,
|
|
70
80
|
initialDelay: "30s",
|
|
@@ -72,56 +82,56 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
72
82
|
retryOn: k,
|
|
73
83
|
honourRetryAfter: !0,
|
|
74
84
|
jitter: "full"
|
|
75
|
-
}), M = class extends ee.Tag("@voltro/webhooks/WebhooksService")() {},
|
|
85
|
+
}), M = class extends ee.Tag("@voltro/webhooks/WebhooksService")() {}, ce = 32, N = 32, P = () => v(ce).toString("hex"), F = (e) => {
|
|
76
86
|
let t;
|
|
77
87
|
try {
|
|
78
88
|
t = new URL(e.url);
|
|
79
89
|
} catch (e) {
|
|
80
|
-
throw new
|
|
90
|
+
throw new p({
|
|
81
91
|
field: "url",
|
|
82
92
|
reason: `invalid subscriber url: ${e.message}`
|
|
83
93
|
});
|
|
84
94
|
}
|
|
85
|
-
if (t.protocol !== "http:" && t.protocol !== "https:") throw new
|
|
95
|
+
if (t.protocol !== "http:" && t.protocol !== "https:") throw new p({
|
|
86
96
|
field: "url",
|
|
87
97
|
reason: `url protocol must be http or https, got ${t.protocol}`
|
|
88
98
|
});
|
|
89
99
|
if (process.env.NODE_ENV === "production") try {
|
|
90
|
-
|
|
100
|
+
w(e.url);
|
|
91
101
|
} catch (e) {
|
|
92
|
-
throw new
|
|
102
|
+
throw new p({
|
|
93
103
|
field: "url",
|
|
94
104
|
reason: e.message
|
|
95
105
|
});
|
|
96
106
|
}
|
|
97
|
-
if (e.event.length === 0) throw new
|
|
107
|
+
if (e.event.length === 0) throw new p({
|
|
98
108
|
field: "event",
|
|
99
109
|
reason: "event id required"
|
|
100
110
|
});
|
|
101
|
-
if (e.secret !== void 0 && e.secret.length < N) throw new
|
|
111
|
+
if (e.secret !== void 0 && e.secret.length < N) throw new p({
|
|
102
112
|
field: "secret",
|
|
103
113
|
reason: `secret must be at least ${N} chars`
|
|
104
114
|
});
|
|
105
115
|
if (e.retry !== void 0) {
|
|
106
|
-
if (e.retry.maxAttempts < 1) throw new
|
|
116
|
+
if (e.retry.maxAttempts < 1) throw new p({
|
|
107
117
|
field: "retry",
|
|
108
118
|
reason: "retry.maxAttempts must be ≥ 1"
|
|
109
119
|
});
|
|
110
|
-
if (e.retry.maxAttempts > 1e3) throw new
|
|
120
|
+
if (e.retry.maxAttempts > 1e3) throw new p({
|
|
111
121
|
field: "retry",
|
|
112
122
|
reason: "retry.maxAttempts must be ≤ 1000"
|
|
113
123
|
});
|
|
114
124
|
}
|
|
115
|
-
if (e.rateLimitPerMinute !== void 0 && e.rateLimitPerMinute < 1) throw new
|
|
125
|
+
if (e.rateLimitPerMinute !== void 0 && e.rateLimitPerMinute < 1) throw new p({
|
|
116
126
|
field: "rateLimitPerMinute",
|
|
117
127
|
reason: "rateLimitPerMinute must be ≥ 1"
|
|
118
128
|
});
|
|
119
|
-
if (e.autoDisableAfter !== void 0 && (e.autoDisableAfter < 1 || !Number.isInteger(e.autoDisableAfter))) throw new
|
|
129
|
+
if (e.autoDisableAfter !== void 0 && (e.autoDisableAfter < 1 || !Number.isInteger(e.autoDisableAfter))) throw new p({
|
|
120
130
|
field: "autoDisableAfter",
|
|
121
131
|
reason: `autoDisableAfter must be a positive integer, got ${e.autoDisableAfter}`
|
|
122
132
|
});
|
|
123
133
|
}, I = (e, t) => ({
|
|
124
|
-
id:
|
|
134
|
+
id: y(),
|
|
125
135
|
event: e.event,
|
|
126
136
|
url: e.url,
|
|
127
137
|
secret: e.secret ?? P(),
|
|
@@ -138,19 +148,19 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
138
148
|
autoDisableReason: null,
|
|
139
149
|
payloadVersion: e.payloadVersion ?? t?.version ?? 1,
|
|
140
150
|
description: e.description ?? null
|
|
141
|
-
}),
|
|
151
|
+
}), le = (e, t) => e === t ? "current" : e < t ? "behind" : "ahead", L = (e, t) => {
|
|
142
152
|
if (e === null) return !0;
|
|
143
153
|
let n = { payload: t };
|
|
144
|
-
for (let [t, r] of Object.entries(e)) if (!ue(
|
|
154
|
+
for (let [t, r] of Object.entries(e)) if (!de(ue(n, t), r)) return !1;
|
|
145
155
|
return !0;
|
|
146
|
-
},
|
|
156
|
+
}, ue = (e, t) => {
|
|
147
157
|
let n = t.split("."), r = e;
|
|
148
158
|
for (let e of n) {
|
|
149
159
|
if (typeof r != "object" || !r) return;
|
|
150
160
|
r = r[e];
|
|
151
161
|
}
|
|
152
162
|
return r;
|
|
153
|
-
},
|
|
163
|
+
}, de = (e, t) => {
|
|
154
164
|
if (typeof t == "object" && t && !Array.isArray(t)) {
|
|
155
165
|
let n = t;
|
|
156
166
|
if ("eq" in n) return e === n.eq;
|
|
@@ -161,7 +171,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
161
171
|
if ("in" in n && Array.isArray(n.in)) return n.in.includes(e);
|
|
162
172
|
}
|
|
163
173
|
return e === t;
|
|
164
|
-
},
|
|
174
|
+
}, fe = (e, t, n = {}) => {
|
|
165
175
|
let r = new Map((n.events ?? []).map((e) => [e.id, e]));
|
|
166
176
|
return {
|
|
167
177
|
subscribe: async (t) => {
|
|
@@ -181,17 +191,17 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
181
191
|
};
|
|
182
192
|
},
|
|
183
193
|
emit: async (n, i) => {
|
|
184
|
-
let a = typeof n == "string" ? r.get(n) : n,
|
|
185
|
-
if (
|
|
186
|
-
let e =
|
|
187
|
-
if (te.isLeft(e)) throw new
|
|
188
|
-
event:
|
|
194
|
+
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
|
+
if (o !== void 0) {
|
|
196
|
+
let e = x.decodeUnknownEither(o.payload)(i, { errors: "all" });
|
|
197
|
+
if (te.isLeft(e)) throw new u({
|
|
198
|
+
event: s,
|
|
189
199
|
issues: e.left.message
|
|
190
200
|
});
|
|
191
201
|
}
|
|
192
|
-
let
|
|
202
|
+
let c = y(), l = (await e.store.query({
|
|
193
203
|
table: "_voltro_webhook_targets",
|
|
194
|
-
predicate:
|
|
204
|
+
predicate: C("event", s),
|
|
195
205
|
order: [{
|
|
196
206
|
column: "createdAt",
|
|
197
207
|
direction: "asc"
|
|
@@ -199,16 +209,16 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
199
209
|
take: 1e3,
|
|
200
210
|
skip: void 0,
|
|
201
211
|
projection: void 0
|
|
202
|
-
})).filter((e) => L(e.filter, i)),
|
|
203
|
-
for (let n of
|
|
204
|
-
let r =
|
|
212
|
+
})).filter((e) => L(e.filter, i)), d = [], f = JSON.stringify(i);
|
|
213
|
+
for (let n of l) {
|
|
214
|
+
let r = y();
|
|
205
215
|
n.active ? (await t({
|
|
206
216
|
deliveryId: r,
|
|
207
217
|
targetId: n.id,
|
|
208
|
-
event:
|
|
209
|
-
eventId:
|
|
210
|
-
payloadJson:
|
|
211
|
-
}),
|
|
218
|
+
event: s,
|
|
219
|
+
eventId: c,
|
|
220
|
+
payloadJson: f
|
|
221
|
+
}), d.push({
|
|
212
222
|
targetId: n.id,
|
|
213
223
|
deliveryId: r,
|
|
214
224
|
status: "dispatched"
|
|
@@ -217,29 +227,29 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
217
227
|
deliveryId: r,
|
|
218
228
|
targetId: n.id,
|
|
219
229
|
tenantId: n.tenantId ?? null,
|
|
220
|
-
event:
|
|
221
|
-
eventId:
|
|
230
|
+
event: s,
|
|
231
|
+
eventId: c,
|
|
222
232
|
attempt: 1,
|
|
223
233
|
status: "pending",
|
|
224
|
-
payload:
|
|
234
|
+
payload: f,
|
|
225
235
|
scheduledAt: /* @__PURE__ */ new Date(),
|
|
226
236
|
createdAt: /* @__PURE__ */ new Date(),
|
|
227
237
|
updatedAt: /* @__PURE__ */ new Date()
|
|
228
|
-
}),
|
|
238
|
+
}), d.push({
|
|
229
239
|
targetId: n.id,
|
|
230
240
|
deliveryId: r,
|
|
231
241
|
status: "queued"
|
|
232
242
|
}));
|
|
233
243
|
}
|
|
234
244
|
return {
|
|
235
|
-
eventId:
|
|
236
|
-
deliveries:
|
|
245
|
+
eventId: c,
|
|
246
|
+
deliveries: d
|
|
237
247
|
};
|
|
238
248
|
},
|
|
239
249
|
replay: async (n) => {
|
|
240
250
|
let r = (await e.store.query({
|
|
241
251
|
table: "_voltro_webhook_deliveries",
|
|
242
|
-
predicate:
|
|
252
|
+
predicate: C("deliveryId", n),
|
|
243
253
|
order: [{
|
|
244
254
|
column: "attempt",
|
|
245
255
|
direction: "asc"
|
|
@@ -248,12 +258,12 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
248
258
|
skip: void 0,
|
|
249
259
|
projection: void 0
|
|
250
260
|
}))[0];
|
|
251
|
-
if (r === void 0) throw new
|
|
261
|
+
if (r === void 0) throw new l({ deliveryId: n });
|
|
252
262
|
await t({
|
|
253
263
|
deliveryId: r.deliveryId,
|
|
254
264
|
targetId: r.targetId,
|
|
255
265
|
event: r.event,
|
|
256
|
-
eventId: r.eventId ??
|
|
266
|
+
eventId: r.eventId ?? y(),
|
|
257
267
|
payloadJson: typeof r.payload == "string" ? r.payload : JSON.stringify(r.payload),
|
|
258
268
|
attemptEpoch: Date.now()
|
|
259
269
|
});
|
|
@@ -274,7 +284,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
274
284
|
});
|
|
275
285
|
let r = await e.store.query({
|
|
276
286
|
table: "_voltro_webhook_deliveries",
|
|
277
|
-
predicate: C(
|
|
287
|
+
predicate: S(C("targetId", n), C("status", "pending")),
|
|
278
288
|
order: [{
|
|
279
289
|
column: "createdAt",
|
|
280
290
|
direction: "asc"
|
|
@@ -287,13 +297,13 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
287
297
|
deliveryId: e.deliveryId,
|
|
288
298
|
targetId: n,
|
|
289
299
|
event: e.event,
|
|
290
|
-
eventId: e.eventId ??
|
|
300
|
+
eventId: e.eventId ?? y(),
|
|
291
301
|
payloadJson: typeof e.payload == "string" ? e.payload : JSON.stringify(e.payload),
|
|
292
302
|
attemptEpoch: i
|
|
293
303
|
});
|
|
294
304
|
},
|
|
295
305
|
deleteTarget: async (t) => {
|
|
296
|
-
await e.store.delete("_voltro_webhook_targets", t), await e.store.deleteMany("_voltro_webhook_deliveries", { where: C(
|
|
306
|
+
await e.store.delete("_voltro_webhook_targets", t), await e.store.deleteMany("_voltro_webhook_deliveries", { where: S(C("targetId", t), C("status", "pending")) });
|
|
297
307
|
},
|
|
298
308
|
rotateSecret: async (t) => {
|
|
299
309
|
let n = P();
|
|
@@ -303,7 +313,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
303
313
|
}), { secret: n };
|
|
304
314
|
},
|
|
305
315
|
updateTargetPayloadVersion: async (t, n) => {
|
|
306
|
-
if (n < 1 || !Number.isInteger(n)) throw new
|
|
316
|
+
if (n < 1 || !Number.isInteger(n)) throw new f({ version: n });
|
|
307
317
|
await e.store.update("_voltro_webhook_targets", t, {
|
|
308
318
|
payloadVersion: n,
|
|
309
319
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -311,7 +321,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
311
321
|
},
|
|
312
322
|
listTargets: async (t) => (await e.store.query({
|
|
313
323
|
table: "_voltro_webhook_targets",
|
|
314
|
-
predicate: t === void 0 ? void 0 :
|
|
324
|
+
predicate: t === void 0 ? void 0 : C("event", t),
|
|
315
325
|
order: [{
|
|
316
326
|
column: "createdAt",
|
|
317
327
|
direction: "desc"
|
|
@@ -333,15 +343,15 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
333
343
|
autoDisableReason: e.autoDisableReason
|
|
334
344
|
}))
|
|
335
345
|
};
|
|
336
|
-
},
|
|
346
|
+
}, pe = b.gen(function* () {
|
|
337
347
|
return yield* M;
|
|
338
|
-
}),
|
|
348
|
+
}), me = (e) => {
|
|
339
349
|
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.");
|
|
340
350
|
return e.webhooks;
|
|
341
|
-
},
|
|
351
|
+
}, he = 1e4, R = class {
|
|
342
352
|
capacity;
|
|
343
353
|
cache = /* @__PURE__ */ new Map();
|
|
344
|
-
constructor(e =
|
|
354
|
+
constructor(e = he) {
|
|
345
355
|
this.capacity = e;
|
|
346
356
|
}
|
|
347
357
|
evictExpired() {
|
|
@@ -387,7 +397,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
387
397
|
status: e,
|
|
388
398
|
contentType: "application/json; charset=utf-8",
|
|
389
399
|
body: JSON.stringify(t)
|
|
390
|
-
}),
|
|
400
|
+
}), ge = (e, t) => {
|
|
391
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 ?? B(), c = H(i?.ttl), l = t.log ?? ((e) => {
|
|
392
402
|
re({ scope: `webhook:${e.webhookId}` }).debug("incoming webhook", {
|
|
393
403
|
status: e.status,
|
|
@@ -462,7 +472,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
462
472
|
}
|
|
463
473
|
let p;
|
|
464
474
|
try {
|
|
465
|
-
p =
|
|
475
|
+
p = x.decodeUnknownSync(e.payload)(f);
|
|
466
476
|
} catch (t) {
|
|
467
477
|
let n = U(422, {
|
|
468
478
|
error: "schema validation failed",
|
|
@@ -548,9 +558,9 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
548
558
|
}), n;
|
|
549
559
|
}
|
|
550
560
|
};
|
|
551
|
-
},
|
|
561
|
+
}, _e = (e) => `/webhooks/${e}`, W = "_voltro_webhook_rate_windows", G = 6e4, ve = (e, t) => `${e}@${t}`, K = async (e, t, n) => (await e.query({
|
|
552
562
|
table: "_voltro_webhook_rate_windows",
|
|
553
|
-
predicate: C(
|
|
563
|
+
predicate: S(C("scope", t), C("bucket", n)),
|
|
554
564
|
order: [],
|
|
555
565
|
take: 1,
|
|
556
566
|
skip: void 0,
|
|
@@ -561,7 +571,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
561
571
|
let i = await K(e, t.key, n);
|
|
562
572
|
if (i === null) {
|
|
563
573
|
await e.insertIgnore(W, {
|
|
564
|
-
id:
|
|
574
|
+
id: ve(t.key, n),
|
|
565
575
|
scope: t.key,
|
|
566
576
|
bucket: n,
|
|
567
577
|
count: 0,
|
|
@@ -574,7 +584,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
574
584
|
if (await e.updateMany("_voltro_webhook_rate_windows", {
|
|
575
585
|
count: i.count + 1,
|
|
576
586
|
updatedAt: /* @__PURE__ */ new Date()
|
|
577
|
-
}, { where: C(
|
|
587
|
+
}, { where: S(C("id", i.id), C("count", i.count)) }) === 1) return !0;
|
|
578
588
|
}
|
|
579
589
|
throw Error(`webhook rate window: contention on (${t.key}, ${n}) exceeded ${q} attempts`);
|
|
580
590
|
}, Y = async (e, t, n) => {
|
|
@@ -584,7 +594,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
584
594
|
if (i === null || i.count <= 0 || await e.updateMany("_voltro_webhook_rate_windows", {
|
|
585
595
|
count: i.count - 1,
|
|
586
596
|
updatedAt: /* @__PURE__ */ new Date()
|
|
587
|
-
}, { where: C(
|
|
597
|
+
}, { where: S(C("id", i.id), C("count", i.count)) }) === 1) return;
|
|
588
598
|
}
|
|
589
599
|
throw Error(`webhook rate window: release contention on (${t}) exceeded ${q} attempts`);
|
|
590
600
|
}, X = async (e, t, n, r = G) => {
|
|
@@ -617,22 +627,22 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
617
627
|
try {
|
|
618
628
|
n = JSON.parse(t);
|
|
619
629
|
} catch (t) {
|
|
620
|
-
throw new
|
|
630
|
+
throw new d({
|
|
621
631
|
format: e,
|
|
622
632
|
reason: `payload is not valid JSON: ${t.message}`
|
|
623
633
|
});
|
|
624
634
|
}
|
|
625
635
|
return e === "form" ? {
|
|
626
636
|
contentType: "application/x-www-form-urlencoded",
|
|
627
|
-
bytes: Buffer.from(
|
|
637
|
+
bytes: Buffer.from(ye(n), "utf8")
|
|
628
638
|
} : {
|
|
629
639
|
contentType: "application/xml",
|
|
630
|
-
bytes: Buffer.from(
|
|
640
|
+
bytes: Buffer.from(xe(n), "utf8")
|
|
631
641
|
};
|
|
632
|
-
},
|
|
633
|
-
if (typeof e != "object" || !e || Array.isArray(e)) throw new
|
|
642
|
+
}, ye = (e) => {
|
|
643
|
+
if (typeof e != "object" || !e || Array.isArray(e)) throw new d({
|
|
634
644
|
format: "form",
|
|
635
|
-
reason: `form encoding requires a JSON object at the top level, got ${
|
|
645
|
+
reason: `form encoding requires a JSON object at the top level, got ${we(e)}`
|
|
636
646
|
});
|
|
637
647
|
let t = new URLSearchParams();
|
|
638
648
|
for (let [n, r] of Object.entries(e)) Q(t, n, r);
|
|
@@ -651,13 +661,13 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
651
661
|
return;
|
|
652
662
|
}
|
|
653
663
|
e.append(t, String(n));
|
|
654
|
-
},
|
|
655
|
-
if (!
|
|
664
|
+
}, be = /^[A-Za-z_][A-Za-z0-9_.-]*$/, xe = (e) => `<?xml version="1.0" encoding="UTF-8"?>${$("webhook", e)}`, $ = (e, t) => {
|
|
665
|
+
if (!be.test(e)) throw new d({
|
|
656
666
|
format: "xml",
|
|
657
667
|
reason: `object key ${JSON.stringify(e)} is not a valid XML element name`
|
|
658
668
|
});
|
|
659
|
-
return `<${e}>${
|
|
660
|
-
},
|
|
669
|
+
return `<${e}>${Se(e, t)}</${e}>`;
|
|
670
|
+
}, Se = (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("") : Ce(String(t)), Ce = (e) => e.replace(/[&<>"']/g, (e) => {
|
|
661
671
|
switch (e) {
|
|
662
672
|
case "&": return "&";
|
|
663
673
|
case "<": return "<";
|
|
@@ -665,17 +675,17 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
665
675
|
case "\"": return """;
|
|
666
676
|
default: return "'";
|
|
667
677
|
}
|
|
668
|
-
}),
|
|
678
|
+
}), we = (e) => e === null ? "null" : Array.isArray(e) ? "array" : typeof e, Te = "_voltro_webhook_targets", Ee = 32, De = async (e, t) => (await e.query({
|
|
669
679
|
table: "_voltro_webhook_targets",
|
|
670
|
-
predicate:
|
|
680
|
+
predicate: C("id", t),
|
|
671
681
|
order: [],
|
|
672
682
|
take: 1,
|
|
673
683
|
skip: void 0,
|
|
674
684
|
projection: void 0
|
|
675
|
-
}))[0] ?? null,
|
|
676
|
-
for (let a = 0; a <
|
|
685
|
+
}))[0] ?? null, Oe = async (e, t, n, r, i = /* @__PURE__ */ new Date()) => {
|
|
686
|
+
for (let a = 0; a < Ee; a++) {
|
|
677
687
|
a > 0 && await new Promise((e) => setTimeout(e, a));
|
|
678
|
-
let o = await
|
|
688
|
+
let o = await De(e, t);
|
|
679
689
|
if (o === null) return {
|
|
680
690
|
consecutiveFailures: 0,
|
|
681
691
|
autoDisabled: !1
|
|
@@ -685,7 +695,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
685
695
|
if (s === 0 || await e.updateMany("_voltro_webhook_targets", {
|
|
686
696
|
consecutiveFailures: 0,
|
|
687
697
|
updatedAt: i
|
|
688
|
-
}, { where: C(
|
|
698
|
+
}, { where: S(C("id", t), C("consecutiveFailures", s)) }) === 1) return {
|
|
689
699
|
consecutiveFailures: 0,
|
|
690
700
|
autoDisabled: !1
|
|
691
701
|
};
|
|
@@ -695,68 +705,68 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
695
705
|
consecutiveFailures: c,
|
|
696
706
|
updatedAt: i
|
|
697
707
|
};
|
|
698
|
-
if (u && (d.active = !1, d.autoDisabledAt = i, d.autoDisableReason = r.slice(0, 500)), await e.updateMany("_voltro_webhook_targets", d, { where: C(
|
|
708
|
+
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 {
|
|
699
709
|
consecutiveFailures: c,
|
|
700
710
|
autoDisabled: u
|
|
701
711
|
};
|
|
702
712
|
}
|
|
703
|
-
throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${
|
|
704
|
-
},
|
|
705
|
-
status:
|
|
706
|
-
body:
|
|
707
|
-
latencyMs:
|
|
708
|
-
retryAfterSec:
|
|
709
|
-
transportError:
|
|
710
|
-
encodeError:
|
|
711
|
-
}),
|
|
712
|
-
outcome:
|
|
713
|
-
delayMs:
|
|
714
|
-
reason:
|
|
715
|
-
autoDisabled:
|
|
716
|
-
consecutiveFailures:
|
|
717
|
-
}),
|
|
718
|
-
acquired:
|
|
719
|
-
retryInMs:
|
|
720
|
-
}),
|
|
713
|
+
throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${Ee} attempts`);
|
|
714
|
+
}, ke = x.Struct({
|
|
715
|
+
status: x.Number,
|
|
716
|
+
body: x.String,
|
|
717
|
+
latencyMs: x.Number,
|
|
718
|
+
retryAfterSec: x.Union(x.Number, x.Undefined),
|
|
719
|
+
transportError: x.Union(x.String, x.Undefined),
|
|
720
|
+
encodeError: x.Union(x.String, x.Undefined)
|
|
721
|
+
}), Ae = x.Struct({
|
|
722
|
+
outcome: x.Literal("succeeded", "failed", "retry"),
|
|
723
|
+
delayMs: x.Union(x.Number, x.Undefined),
|
|
724
|
+
reason: x.Union(x.String, x.Undefined),
|
|
725
|
+
autoDisabled: x.Union(x.Boolean, x.Undefined),
|
|
726
|
+
consecutiveFailures: x.Union(x.Number, x.Undefined)
|
|
727
|
+
}), je = x.Struct({
|
|
728
|
+
acquired: x.Boolean,
|
|
729
|
+
retryInMs: x.Number
|
|
730
|
+
}), Me = ie.make({
|
|
721
731
|
name: "voltro.deliverWebhook",
|
|
722
732
|
payload: {
|
|
723
|
-
deliveryId:
|
|
724
|
-
targetId:
|
|
725
|
-
event:
|
|
726
|
-
eventId:
|
|
727
|
-
payloadJson:
|
|
728
|
-
attemptEpoch:
|
|
733
|
+
deliveryId: x.String,
|
|
734
|
+
targetId: x.String,
|
|
735
|
+
event: x.String,
|
|
736
|
+
eventId: x.String,
|
|
737
|
+
payloadJson: x.String,
|
|
738
|
+
attemptEpoch: x.optionalWith(x.Number, { default: () => 0 })
|
|
729
739
|
},
|
|
730
|
-
success:
|
|
731
|
-
finalStatus:
|
|
732
|
-
attempts:
|
|
740
|
+
success: x.Struct({
|
|
741
|
+
finalStatus: x.Literal("succeeded", "failed", "deferred"),
|
|
742
|
+
attempts: x.Number
|
|
733
743
|
}),
|
|
734
744
|
idempotencyKey: ({ deliveryId: e, attemptEpoch: t }) => `voltro.deliverWebhook:${e}:${t ?? 0}`
|
|
735
|
-
}),
|
|
745
|
+
}), Ne = (e, t = {}) => (n, r) => {
|
|
736
746
|
let { deliveryId: i, targetId: a, event: s, eventId: c, payloadJson: l } = n, u = re({ scope: `webhook:${i}` });
|
|
737
|
-
return
|
|
738
|
-
let n = yield*
|
|
747
|
+
return b.gen(function* () {
|
|
748
|
+
let n = yield* T.make({
|
|
739
749
|
name: "fetch-target",
|
|
740
|
-
success:
|
|
741
|
-
id:
|
|
742
|
-
event:
|
|
743
|
-
url:
|
|
744
|
-
secret:
|
|
745
|
-
signing:
|
|
746
|
-
retry:
|
|
747
|
-
headers:
|
|
748
|
-
key:
|
|
749
|
-
value:
|
|
750
|
-
}),
|
|
751
|
-
rateLimitPerMinute:
|
|
752
|
-
active:
|
|
753
|
-
format:
|
|
754
|
-
tenantId:
|
|
750
|
+
success: x.Union(x.Null, x.Struct({
|
|
751
|
+
id: x.String,
|
|
752
|
+
event: x.String,
|
|
753
|
+
url: x.String,
|
|
754
|
+
secret: x.String,
|
|
755
|
+
signing: x.Any,
|
|
756
|
+
retry: x.Any,
|
|
757
|
+
headers: x.Union(x.Record({
|
|
758
|
+
key: x.String,
|
|
759
|
+
value: x.String
|
|
760
|
+
}), x.Null),
|
|
761
|
+
rateLimitPerMinute: x.Union(x.Number, x.Null),
|
|
762
|
+
active: x.Boolean,
|
|
763
|
+
format: x.Literal("json", "form", "xml"),
|
|
764
|
+
tenantId: x.Union(x.String, x.Null)
|
|
755
765
|
})),
|
|
756
|
-
execute:
|
|
766
|
+
execute: b.tryPromise({
|
|
757
767
|
try: async () => (await e.store.query({
|
|
758
768
|
table: "_voltro_webhook_targets",
|
|
759
|
-
predicate:
|
|
769
|
+
predicate: C("id", a),
|
|
760
770
|
order: [{
|
|
761
771
|
column: "createdAt",
|
|
762
772
|
direction: "asc"
|
|
@@ -770,7 +780,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
770
780
|
event: s,
|
|
771
781
|
cause: String(e)
|
|
772
782
|
}), /* @__PURE__ */ Error(`fetch-target failed: ${e.message}`))
|
|
773
|
-
}).pipe(
|
|
783
|
+
}).pipe(b.orDie)
|
|
774
784
|
});
|
|
775
785
|
if (n === null) return {
|
|
776
786
|
finalStatus: "failed",
|
|
@@ -795,18 +805,18 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
795
805
|
...o
|
|
796
806
|
});
|
|
797
807
|
};
|
|
798
|
-
if (n.active !== !0) return yield*
|
|
808
|
+
if (n.active !== !0) return yield* T.make({
|
|
799
809
|
name: "record-paused-pending",
|
|
800
|
-
success:
|
|
801
|
-
execute:
|
|
810
|
+
success: x.Void,
|
|
811
|
+
execute: b.tryPromise({
|
|
802
812
|
try: () => r(`${i}:1`, 1, { status: "pending" }),
|
|
803
813
|
catch: (e) => /* @__PURE__ */ Error(`record-paused-pending failed: ${e.message}`)
|
|
804
|
-
}).pipe(
|
|
814
|
+
}).pipe(b.orDie)
|
|
805
815
|
}), {
|
|
806
816
|
finalStatus: "deferred",
|
|
807
817
|
attempts: 0
|
|
808
818
|
};
|
|
809
|
-
let
|
|
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), g = t.rateWindowMs ?? 6e4, _ = t.events?.find((e) => e.id === s)?.globalRateLimit, v = [...typeof n.rateLimitPerMinute == "number" && n.rateLimitPerMinute > 0 ? [{
|
|
810
820
|
key: `target:${n.id}`,
|
|
811
821
|
limit: n.rateLimitPerMinute
|
|
812
822
|
}] : [], ..._ !== void 0 && _.perMinute > 0 ? [{
|
|
@@ -814,12 +824,12 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
814
824
|
limit: _.perMinute
|
|
815
825
|
}] : []];
|
|
816
826
|
for (let t = 1; t <= p.maxAttempts; t++) {
|
|
817
|
-
let
|
|
827
|
+
let f = `${i}:${t}`;
|
|
818
828
|
if (v.length > 0) for (let n = 0;; n++) {
|
|
819
|
-
let i = yield*
|
|
829
|
+
let i = yield* T.make({
|
|
820
830
|
name: `rate-acquire-${t}-${n}`,
|
|
821
|
-
success:
|
|
822
|
-
execute:
|
|
831
|
+
success: je,
|
|
832
|
+
execute: b.tryPromise({
|
|
823
833
|
try: () => X(e.store, v, Date.now(), g),
|
|
824
834
|
catch: (e) => (u.debug("rate-acquire raw error", {
|
|
825
835
|
targetId: a,
|
|
@@ -827,45 +837,45 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
827
837
|
attempt: t,
|
|
828
838
|
cause: String(e)
|
|
829
839
|
}), /* @__PURE__ */ Error(`rate-acquire failed: ${e.message}`))
|
|
830
|
-
}).pipe(
|
|
840
|
+
}).pipe(b.orDie)
|
|
831
841
|
});
|
|
832
842
|
if (i.acquired) break;
|
|
833
|
-
yield*
|
|
843
|
+
yield* T.make({
|
|
834
844
|
name: `record-rate-deferral-${t}-${n}`,
|
|
835
|
-
success:
|
|
836
|
-
execute:
|
|
837
|
-
try: () => r(
|
|
845
|
+
success: x.Void,
|
|
846
|
+
execute: b.tryPromise({
|
|
847
|
+
try: () => r(f, t, {
|
|
838
848
|
status: "pending",
|
|
839
849
|
nextAttemptAt: new Date(Date.now() + i.retryInMs)
|
|
840
850
|
}),
|
|
841
851
|
catch: (e) => /* @__PURE__ */ Error(`record-rate-deferral failed: ${e.message}`)
|
|
842
|
-
}).pipe(
|
|
843
|
-
}), yield*
|
|
852
|
+
}).pipe(b.orDie)
|
|
853
|
+
}), yield* E.sleep({
|
|
844
854
|
name: `rate-window-sleep-${t}-${n}`,
|
|
845
855
|
duration: `${i.retryInMs} millis`
|
|
846
856
|
});
|
|
847
857
|
}
|
|
848
|
-
yield*
|
|
858
|
+
yield* T.make({
|
|
849
859
|
name: `record-attempt-start-${t}`,
|
|
850
|
-
success:
|
|
851
|
-
execute:
|
|
852
|
-
try: () => r(
|
|
860
|
+
success: x.Void,
|
|
861
|
+
execute: b.tryPromise({
|
|
862
|
+
try: () => r(f, t, {
|
|
853
863
|
status: "inFlight",
|
|
854
864
|
nextAttemptAt: null,
|
|
855
865
|
scheduledAt: /* @__PURE__ */ new Date()
|
|
856
866
|
}),
|
|
857
867
|
catch: (e) => /* @__PURE__ */ Error(`record-attempt-start failed: ${e.message}`)
|
|
858
|
-
}).pipe(
|
|
868
|
+
}).pipe(b.orDie)
|
|
859
869
|
});
|
|
860
|
-
let _ = yield*
|
|
870
|
+
let _ = yield* T.make({
|
|
861
871
|
name: `sign-and-post-${t}`,
|
|
862
|
-
success:
|
|
863
|
-
execute:
|
|
872
|
+
success: ke,
|
|
873
|
+
execute: b.promise(async () => {
|
|
864
874
|
let e = Date.now(), r;
|
|
865
875
|
try {
|
|
866
876
|
r = Z(n.format, l);
|
|
867
877
|
} catch (t) {
|
|
868
|
-
if (t instanceof
|
|
878
|
+
if (t instanceof d) return {
|
|
869
879
|
status: 0,
|
|
870
880
|
body: "",
|
|
871
881
|
latencyMs: Date.now() - e,
|
|
@@ -875,14 +885,14 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
875
885
|
};
|
|
876
886
|
throw t;
|
|
877
887
|
}
|
|
878
|
-
let a = Buffer.from(r.bytes), { headerName: u, headerValue:
|
|
879
|
-
process.env.NODE_ENV === "production" &&
|
|
888
|
+
let a = Buffer.from(r.bytes), { headerName: u, headerValue: f } = o(m, a, n.secret);
|
|
889
|
+
process.env.NODE_ENV === "production" && w(n.url);
|
|
880
890
|
try {
|
|
881
891
|
let o = await fetch(n.url, {
|
|
882
892
|
method: "POST",
|
|
883
893
|
headers: {
|
|
884
894
|
"content-type": r.contentType,
|
|
885
|
-
[u]:
|
|
895
|
+
[u]: f,
|
|
886
896
|
"x-voltro-event": s,
|
|
887
897
|
"x-voltro-event-id": c,
|
|
888
898
|
"x-voltro-delivery-id": i,
|
|
@@ -891,12 +901,12 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
891
901
|
...h ?? {}
|
|
892
902
|
},
|
|
893
903
|
body: a
|
|
894
|
-
}), l = (await o.text()).slice(0, 8192),
|
|
904
|
+
}), l = (await o.text()).slice(0, 8192), d = o.headers.get("retry-after");
|
|
895
905
|
return {
|
|
896
906
|
status: o.status,
|
|
897
907
|
body: l,
|
|
898
908
|
latencyMs: Date.now() - e,
|
|
899
|
-
retryAfterSec:
|
|
909
|
+
retryAfterSec: d !== null && /^\d+$/.test(d) ? Number(d) : void 0,
|
|
900
910
|
transportError: void 0,
|
|
901
911
|
encodeError: void 0
|
|
902
912
|
};
|
|
@@ -911,14 +921,14 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
911
921
|
};
|
|
912
922
|
}
|
|
913
923
|
})
|
|
914
|
-
}), y = yield*
|
|
924
|
+
}), y = yield* T.make({
|
|
915
925
|
name: `classify-and-record-${t}`,
|
|
916
|
-
success:
|
|
917
|
-
execute:
|
|
926
|
+
success: Ae,
|
|
927
|
+
execute: b.tryPromise({
|
|
918
928
|
try: async () => {
|
|
919
|
-
let r = _.status >= 200 && _.status < 300, i = _.transportError !== void 0, o = _.encodeError !== void 0, s = (t, n) =>
|
|
929
|
+
let r = _.status >= 200 && _.status < 300, i = _.transportError !== void 0, o = _.encodeError !== void 0, s = (t, n) => Oe(e.store, a, t, n);
|
|
920
930
|
if (r) {
|
|
921
|
-
await e.store.update("_voltro_webhook_deliveries",
|
|
931
|
+
await e.store.update("_voltro_webhook_deliveries", f, {
|
|
922
932
|
status: "succeeded",
|
|
923
933
|
responseStatus: _.status,
|
|
924
934
|
responseBody: _.body,
|
|
@@ -940,7 +950,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
940
950
|
});
|
|
941
951
|
if (c === null) {
|
|
942
952
|
let t = o ? `encode (${n.format}): ${_.encodeError}` : i ? `transport: ${_.transportError}` : `http ${_.status}: ${_.body.slice(0, 200)}`;
|
|
943
|
-
await e.store.update("_voltro_webhook_deliveries",
|
|
953
|
+
await e.store.update("_voltro_webhook_deliveries", f, {
|
|
944
954
|
status: "failed",
|
|
945
955
|
responseStatus: i || o ? null : _.status,
|
|
946
956
|
responseBody: i || o ? null : _.body,
|
|
@@ -957,7 +967,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
957
967
|
consecutiveFailures: r.consecutiveFailures
|
|
958
968
|
};
|
|
959
969
|
}
|
|
960
|
-
return await e.store.update("_voltro_webhook_deliveries",
|
|
970
|
+
return await e.store.update("_voltro_webhook_deliveries", f, {
|
|
961
971
|
status: "retryScheduled",
|
|
962
972
|
responseStatus: i ? null : _.status,
|
|
963
973
|
responseBody: i ? null : _.body,
|
|
@@ -979,7 +989,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
979
989
|
attempt: t,
|
|
980
990
|
cause: String(e)
|
|
981
991
|
}), /* @__PURE__ */ Error(`classify-and-record failed: ${e.message}`))
|
|
982
|
-
}).pipe(
|
|
992
|
+
}).pipe(b.orDie)
|
|
983
993
|
});
|
|
984
994
|
if (y.autoDisabled === !0 && u.warn("target auto-disabled after consecutive failures", {
|
|
985
995
|
targetId: a,
|
|
@@ -994,7 +1004,7 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
994
1004
|
finalStatus: "failed",
|
|
995
1005
|
attempts: t
|
|
996
1006
|
};
|
|
997
|
-
y.delayMs !== void 0 && (yield*
|
|
1007
|
+
y.delayMs !== void 0 && (yield* E.sleep({
|
|
998
1008
|
name: `retry-sleep-${t}`,
|
|
999
1009
|
duration: `${y.delayMs} millis`
|
|
1000
1010
|
}));
|
|
@@ -1006,4 +1016,4 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
|
|
|
1006
1016
|
});
|
|
1007
1017
|
};
|
|
1008
1018
|
//#endregion
|
|
1009
|
-
export { R as IdempotencyCache, G as RATE_WINDOW_MS, W as RATE_WINDOW_TABLE,
|
|
1019
|
+
export { R as IdempotencyCache, G as RATE_WINDOW_MS, W as RATE_WINDOW_TABLE, Te 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, g as _voltroWebhookTargetsTable, X as acquireRateSlots, D as asOutgoingEvent, Ne as buildDeliverWebhookExecute, fe as buildWebhooksService, le as compareVersions, J as consumeRateSlot, _e as defaultIncomingPath, c as defaultOutgoingSignature, j as defaultRetryPolicy, s as defineIncomingWebhook, t as defineWebhookProvider, Me as deliverWebhookWorkflow, Z as encodePayload, se as fastRetryPolicy, P as generateSecret, B as getIdempotencyCache, i as githubSignature, ae as hasWebhookAudience, r as isWebhookDescriptor, L as matchesFilter, ge as mountIncomingWebhook, A as nextRetry, O as parseDuration, H as parseTtl, Oe as recordDeliveryOutcome, Y as releaseRateSlot, I as resolveSubscribe, o as signPayload, n as slackSignature, e as stripeSignature, me as useWebhooks, pe as useWebhooksEffect, F as validateSubscribe, a as verifySignature, _ as webhookTables };
|