@voltro/plugin-webhooks 0.23.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/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, u as l } from "./signing-BOUxHdAo.js";
2
- import { WebhookDeliveryNotFound as u, WebhookPayloadInvalid as d, WebhookPayloadUnrepresentable as f, WebhookPayloadVersionInvalid as p, WebhookSubscribeInvalid as m } from "./errors.js";
3
- import { _voltroWebhookDeliveriesTable as h, _voltroWebhookRateWindowsTable as g, _voltroWebhookTargetsTable as _, webhookTables as v } from "./mixin.js";
4
- import { randomBytes as y, randomUUID as b } from "node:crypto";
5
- import { Context as ee, Effect as x, Either as te, Schema as S } from "effect";
6
- import { and as C, eq as w } from "@voltro/database";
7
- import { assertPublicUrl as T } from "@voltro/integration-http";
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 E, DurableClock as D, Workflow as ie } from "@effect/workflow";
11
- //#region src/retry.ts
12
- var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
13
- let t = ae.exec(e);
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
- }), oe = () => ({
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")() {}, se = 32, N = 32, P = () => y(se).toString("hex"), F = (e) => {
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 m({
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 m({
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
- T(e.url);
100
+ w(e.url);
91
101
  } catch (e) {
92
- throw new m({
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 m({
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 m({
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 m({
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 m({
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 m({
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 m({
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: b(),
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
- }), ce = (e, t) => e === t ? "current" : e < t ? "behind" : "ahead", L = (e, t) => {
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(le(n, t), r)) return !1;
154
+ for (let [t, r] of Object.entries(e)) if (!de(ue(n, t), r)) return !1;
145
155
  return !0;
146
- }, le = (e, t) => {
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
- }, ue = (e, t) => {
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
- }, de = (e, t, n = {}) => {
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, o = typeof n == "string" ? n : n.id;
185
- if (a !== void 0) {
186
- let e = S.decodeUnknownEither(a.payload)(i, { errors: "all" });
187
- if (te.isLeft(e)) throw new d({
188
- event: o,
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 s = b(), c = (await e.store.query({
202
+ let c = y(), l = (await e.store.query({
193
203
  table: "_voltro_webhook_targets",
194
- predicate: w("event", o),
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)), l = [], u = JSON.stringify(i);
203
- for (let n of c) {
204
- let r = b();
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: o,
209
- eventId: s,
210
- payloadJson: u
211
- }), l.push({
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: o,
221
- eventId: s,
230
+ event: s,
231
+ eventId: c,
222
232
  attempt: 1,
223
233
  status: "pending",
224
- payload: u,
234
+ payload: f,
225
235
  scheduledAt: /* @__PURE__ */ new Date(),
226
236
  createdAt: /* @__PURE__ */ new Date(),
227
237
  updatedAt: /* @__PURE__ */ new Date()
228
- }), l.push({
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: s,
236
- deliveries: l
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: w("deliveryId", n),
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 u({ deliveryId: n });
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 ?? b(),
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(w("targetId", n), w("status", "pending")),
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 ?? b(),
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(w("targetId", t), w("status", "pending")) });
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 p({ version: n });
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 : w("event", t),
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
- }, fe = x.gen(function* () {
346
+ }, pe = b.gen(function* () {
337
347
  return yield* M;
338
- }), pe = (e) => {
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
- }, me = 1e4, R = class {
351
+ }, he = 1e4, R = class {
342
352
  capacity;
343
353
  cache = /* @__PURE__ */ new Map();
344
- constructor(e = me) {
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
- }), he = (e, t) => {
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 = S.decodeUnknownSync(e.payload)(f);
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
- }, ge = (e) => `/webhooks/${e}`, W = "_voltro_webhook_rate_windows", G = 6e4, _e = (e, t) => `${e}@${t}`, K = async (e, t, n) => (await e.query({
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(w("scope", t), w("bucket", n)),
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: _e(t.key, n),
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(w("id", i.id), w("count", i.count)) }) === 1) return !0;
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(w("id", i.id), w("count", i.count)) }) === 1) return;
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 f({
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(ve(n), "utf8")
637
+ bytes: Buffer.from(ye(n), "utf8")
628
638
  } : {
629
639
  contentType: "application/xml",
630
- bytes: Buffer.from(be(n), "utf8")
640
+ bytes: Buffer.from(xe(n), "utf8")
631
641
  };
632
- }, ve = (e) => {
633
- if (typeof e != "object" || !e || Array.isArray(e)) throw new f({
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 ${Ce(e)}`
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
- }, ye = /^[A-Za-z_][A-Za-z0-9_.-]*$/, be = (e) => `<?xml version="1.0" encoding="UTF-8"?>${$("webhook", e)}`, $ = (e, t) => {
655
- if (!ye.test(e)) throw new f({
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}>${xe(e, t)}</${e}>`;
660
- }, xe = (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("") : Se(String(t)), Se = (e) => e.replace(/[&<>"']/g, (e) => {
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 "&amp;";
663
673
  case "<": return "&lt;";
@@ -665,17 +675,17 @@ var ae = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, O = (e) => {
665
675
  case "\"": return "&quot;";
666
676
  default: return "&apos;";
667
677
  }
668
- }), Ce = (e) => e === null ? "null" : Array.isArray(e) ? "array" : typeof e, we = "_voltro_webhook_targets", Te = 32, Ee = async (e, t) => (await e.query({
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: w("id", t),
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, De = async (e, t, n, r, i = /* @__PURE__ */ new Date()) => {
676
- for (let a = 0; a < Te; 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 Ee(e, t);
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(w("id", t), w("consecutiveFailures", s)) }) === 1) return {
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(w("id", t), w("consecutiveFailures", s)) }) === 1) return {
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 ${Te} attempts`);
704
- }, Oe = S.Struct({
705
- status: S.Number,
706
- body: S.String,
707
- latencyMs: S.Number,
708
- retryAfterSec: S.Union(S.Number, S.Undefined),
709
- transportError: S.Union(S.String, S.Undefined),
710
- encodeError: S.Union(S.String, S.Undefined)
711
- }), ke = S.Struct({
712
- outcome: S.Literal("succeeded", "failed", "retry"),
713
- delayMs: S.Union(S.Number, S.Undefined),
714
- reason: S.Union(S.String, S.Undefined),
715
- autoDisabled: S.Union(S.Boolean, S.Undefined),
716
- consecutiveFailures: S.Union(S.Number, S.Undefined)
717
- }), Ae = S.Struct({
718
- acquired: S.Boolean,
719
- retryInMs: S.Number
720
- }), je = ie.make({
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: S.String,
724
- targetId: S.String,
725
- event: S.String,
726
- eventId: S.String,
727
- payloadJson: S.String,
728
- attemptEpoch: S.optionalWith(S.Number, { default: () => 0 })
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: S.Struct({
731
- finalStatus: S.Literal("succeeded", "failed", "deferred"),
732
- attempts: S.Number
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
- }), Me = (e, t = {}) => (n, r) => {
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 x.gen(function* () {
738
- let n = yield* E.make({
747
+ return b.gen(function* () {
748
+ let n = yield* T.make({
739
749
  name: "fetch-target",
740
- success: S.Union(S.Null, S.Struct({
741
- id: S.String,
742
- event: S.String,
743
- url: S.String,
744
- secret: S.String,
745
- signing: S.Any,
746
- retry: S.Any,
747
- headers: S.Union(S.Record({
748
- key: S.String,
749
- value: S.String
750
- }), S.Null),
751
- rateLimitPerMinute: S.Union(S.Number, S.Null),
752
- active: S.Boolean,
753
- format: S.Literal("json", "form", "xml"),
754
- tenantId: S.Union(S.String, S.Null)
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: x.tryPromise({
766
+ execute: b.tryPromise({
757
767
  try: async () => (await e.store.query({
758
768
  table: "_voltro_webhook_targets",
759
- predicate: w("id", a),
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(x.orDie)
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* E.make({
808
+ if (n.active !== !0) return yield* T.make({
799
809
  name: "record-paused-pending",
800
- success: S.Void,
801
- execute: x.tryPromise({
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(x.orDie)
814
+ }).pipe(b.orDie)
805
815
  }), {
806
816
  finalStatus: "deferred",
807
817
  attempts: 0
808
818
  };
809
- let d = (e) => typeof e == "string" ? JSON.parse(e) : e, p = d(n.retry), m = d(n.signing), h = n.headers === null ? null : d(n.headers), g = t.rateWindowMs ?? 6e4, _ = t.events?.find((e) => e.id === s)?.globalRateLimit, v = [...typeof n.rateLimitPerMinute == "number" && n.rateLimitPerMinute > 0 ? [{
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 d = `${i}:${t}`;
827
+ let f = `${i}:${t}`;
818
828
  if (v.length > 0) for (let n = 0;; n++) {
819
- let i = yield* E.make({
829
+ let i = yield* T.make({
820
830
  name: `rate-acquire-${t}-${n}`,
821
- success: Ae,
822
- execute: x.tryPromise({
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(x.orDie)
840
+ }).pipe(b.orDie)
831
841
  });
832
842
  if (i.acquired) break;
833
- yield* E.make({
843
+ yield* T.make({
834
844
  name: `record-rate-deferral-${t}-${n}`,
835
- success: S.Void,
836
- execute: x.tryPromise({
837
- try: () => r(d, t, {
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(x.orDie)
843
- }), yield* D.sleep({
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* E.make({
858
+ yield* T.make({
849
859
  name: `record-attempt-start-${t}`,
850
- success: S.Void,
851
- execute: x.tryPromise({
852
- try: () => r(d, t, {
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(x.orDie)
868
+ }).pipe(b.orDie)
859
869
  });
860
- let _ = yield* E.make({
870
+ let _ = yield* T.make({
861
871
  name: `sign-and-post-${t}`,
862
- success: Oe,
863
- execute: x.promise(async () => {
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 f) return {
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: d } = o(m, a, n.secret);
879
- process.env.NODE_ENV === "production" && T(n.url);
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]: d,
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), f = o.headers.get("retry-after");
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: f !== null && /^\d+$/.test(f) ? Number(f) : void 0,
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* E.make({
924
+ }), y = yield* T.make({
915
925
  name: `classify-and-record-${t}`,
916
- success: ke,
917
- execute: x.tryPromise({
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) => De(e.store, a, 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", d, {
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", d, {
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", d, {
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(x.orDie)
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* D.sleep({
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, we as TARGETS_TABLE, u as WebhookDeliveryNotFound, d as WebhookPayloadInvalid, f as WebhookPayloadUnrepresentable, p as WebhookPayloadVersionInvalid, m as WebhookSubscribeInvalid, M as WebhooksService, h as _voltroWebhookDeliveriesTable, g as _voltroWebhookRateWindowsTable, _ as _voltroWebhookTargetsTable, X as acquireRateSlots, Me as buildDeliverWebhookExecute, de as buildWebhooksService, ce as compareVersions, J as consumeRateSlot, ge as defaultIncomingPath, c as defaultOutgoingSignature, j as defaultRetryPolicy, s as defineIncomingWebhook, t as defineOutgoingEvent, r as defineWebhookProvider, je as deliverWebhookWorkflow, Z as encodePayload, oe as fastRetryPolicy, P as generateSecret, B as getIdempotencyCache, i as githubSignature, l as isWebhookDescriptor, L as matchesFilter, he as mountIncomingWebhook, A as nextRetry, O as parseDuration, H as parseTtl, De as recordDeliveryOutcome, Y as releaseRateSlot, I as resolveSubscribe, o as signPayload, n as slackSignature, e as stripeSignature, pe as useWebhooks, fe as useWebhooksEffect, F as validateSubscribe, a as verifySignature, v as webhookTables };
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 };