@voltro/plugin-billing 0.86.0 → 0.88.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +5484 -0
  2. package/README.md +428 -0
  3. package/THIRD-PARTY-NOTICES.md +1511 -276
  4. package/dist/catalog.js +1 -2
  5. package/dist/checkoutStore.js +164 -0
  6. package/dist/closeStore.js +124 -0
  7. package/dist/custodyInventory.js +154 -0
  8. package/dist/customerStore.js +258 -0
  9. package/dist/dunning.js +1 -2
  10. package/dist/economy.d.ts +30 -0
  11. package/dist/economy.js +265 -0
  12. package/dist/entitlement.js +1 -2
  13. package/dist/eventDelivery.js +71 -0
  14. package/dist/flushClaim.js +1 -2
  15. package/dist/index.d.ts +669 -65
  16. package/dist/index.js +230 -173
  17. package/dist/invoiceHistory.js +90 -0
  18. package/dist/invoiceHistoryJournal.js +475 -0
  19. package/dist/invoiceHistoryProgress.js +234 -0
  20. package/dist/invoiceHistoryWork.js +362 -0
  21. package/dist/invoiceSnapshot.js +65 -0
  22. package/dist/invoiceStore.js +132 -0
  23. package/dist/metering.js +1 -2
  24. package/dist/plans.js +1 -2
  25. package/dist/providerIdentity.js +23 -0
  26. package/dist/providers.js +271 -67
  27. package/dist/provision.js +1 -2
  28. package/dist/rpc.js +1 -2
  29. package/dist/service.js +892 -392
  30. package/dist/stores.js +125 -291
  31. package/dist/stripeClient.js +1 -2
  32. package/dist/stripeIdentity.js +55 -0
  33. package/dist/stripeInvoiceHistory.js +66 -0
  34. package/dist/stripeInvoiceSnapshot.js +85 -0
  35. package/dist/stripeProvider.js +305 -179
  36. package/dist/stripeRest.js +1 -2
  37. package/dist/stripeVerifiedEvent.js +28 -0
  38. package/dist/table.js +70 -48
  39. package/dist/types.d.ts +298 -27
  40. package/dist/types.js +1 -2
  41. package/dist/usageEvents.js +64 -0
  42. package/dist/web/index.js +1 -2
  43. package/dist/webhook.js +32 -40
  44. package/package.json +18 -8
@@ -0,0 +1,90 @@
1
+ import { BillingError as e } from "./types.js";
2
+ import { captureProviderAccount as t, exactProviderIdentifier as n, sameProviderAccount as r } from "./providerIdentity.js";
3
+ // src/invoiceHistory.ts
4
+ var i = (e) => n(e) && e.length <= 191 && e.isWellFormed(), a = (e) => {
5
+ let n = t(e.account), a = e.providerCustomerId, o = e.limit ?? 100;
6
+ if (!i(n.providerAccountId) || !i(a) || !Number.isSafeInteger(o) || o < 1 || o > 100) throw u();
7
+ let s;
8
+ if (e.cursor !== void 0) {
9
+ let o = e.cursor, c = t(o);
10
+ if (!r(c, n) || o.providerCustomerId !== a || !i(o.afterInvoiceId)) throw u();
11
+ s = Object.freeze({
12
+ ...c,
13
+ providerCustomerId: a,
14
+ afterInvoiceId: o.afterInvoiceId
15
+ });
16
+ }
17
+ return Object.freeze({
18
+ account: n,
19
+ providerCustomerId: a,
20
+ ...s === void 0 ? {} : { cursor: s },
21
+ limit: o
22
+ });
23
+ }, o = (e, n) => {
24
+ let o = t(n.account);
25
+ if (!r(o, e.account) || n.providerCustomerId !== e.providerCustomerId || !Array.isArray(n.invoices) || n.invoices.length > e.limit || Object.keys(n.invoices).length !== n.invoices.length) throw u();
26
+ let s = /* @__PURE__ */ new Set(), d = n.invoices.map((t) => {
27
+ if (!i(t.providerInvoiceId) || t.providerCustomerId !== e.providerCustomerId || t.livemode !== o.livemode || t.providerInvoiceId === e.cursor?.afterInvoiceId || s.has(t.providerInvoiceId) || ![
28
+ "draft",
29
+ "open",
30
+ "paid",
31
+ "uncollectible",
32
+ "void"
33
+ ].includes(t.status) || !Number.isSafeInteger(t.amountMinor) || !/^[a-z]{3}$/.test(t.currency)) throw u();
34
+ return s.add(t.providerInvoiceId), Object.freeze({
35
+ providerInvoiceId: t.providerInvoiceId,
36
+ providerCustomerId: e.providerCustomerId,
37
+ livemode: o.livemode,
38
+ status: t.status,
39
+ amountMinor: t.amountMinor,
40
+ currency: t.currency,
41
+ createdAt: c(t.createdAt),
42
+ hostedUrl: l(t.hostedUrl),
43
+ pdfUrl: l(t.pdfUrl)
44
+ });
45
+ }), f = null;
46
+ if (n.nextCursor !== null) {
47
+ let t = a({
48
+ account: o,
49
+ providerCustomerId: e.providerCustomerId,
50
+ cursor: n.nextCursor,
51
+ limit: e.limit
52
+ }).cursor;
53
+ if (t === void 0 || d.length === 0 || t.afterInvoiceId !== d[d.length - 1]?.providerInvoiceId) throw u();
54
+ f = t;
55
+ }
56
+ return Object.freeze({
57
+ account: o,
58
+ providerCustomerId: e.providerCustomerId,
59
+ invoices: Object.freeze(d),
60
+ nextCursor: f,
61
+ observedAt: c(n.observedAt)
62
+ });
63
+ }, s = (e) => ({
64
+ providerInvoiceId: e.providerInvoiceId,
65
+ amountMinor: e.amountMinor,
66
+ currency: e.currency,
67
+ status: e.status,
68
+ createdAt: new Date(e.createdAt),
69
+ hostedUrl: e.hostedUrl,
70
+ pdfUrl: e.pdfUrl
71
+ }), c = (e) => {
72
+ if (!(e instanceof Date) || !Number.isFinite(e.getTime())) throw u();
73
+ return new Date(e);
74
+ }, l = (e) => {
75
+ if (e === null) return null;
76
+ if (typeof e != "string") throw u();
77
+ let t;
78
+ try {
79
+ t = new URL(e);
80
+ } catch {
81
+ throw u();
82
+ }
83
+ if (t.protocol !== "https:" || t.username || t.password) throw u();
84
+ return e;
85
+ }, u = (t = "The complete account/customer-bound invoice history page could not be confirmed.", n = !1) => new e({
86
+ source: "invoiceHistory",
87
+ message: t,
88
+ transient: n
89
+ });
90
+ export { a as captureInvoiceHistoryInput, o as captureInvoiceHistoryPage, u as historyError, s as invoiceHistoryPreview };
@@ -0,0 +1,475 @@
1
+ import { BillingError as e } from "./types.js";
2
+ import { captureProviderAccount as t, exactProviderIdentifier as n, sameProviderAccount as r } from "./providerIdentity.js";
3
+ import { dataStoreCustomerStore as i } from "./customerStore.js";
4
+ import { captureInvoiceHistoryInput as a, captureInvoiceHistoryPage as o, historyError as s } from "./invoiceHistory.js";
5
+ import { Effect as c } from "effect";
6
+ import { and as l, count as u, eq as d, gt as f, id as p, inSet as m, integer as h, lt as g, lte as _, neq as v, or as y, sum as b, table as x, text as S, timestamp as C } from "@voltro/database";
7
+ // src/invoiceHistoryJournal.ts
8
+ var w = "_voltro_billing_invoice_history_walks", T = "_voltro_billing_invoice_history_pages", E = "_voltro_billing_invoice_history_references", D = () => ({
9
+ tenantId: S().maxLength(191),
10
+ provider: S().maxLength(64),
11
+ providerAccountId: S().maxLength(191),
12
+ livemode: h(),
13
+ providerCustomerId: S().maxLength(191),
14
+ custodyId: S().maxLength(191)
15
+ }), O = x(w, {
16
+ id: p({ prefix: "bihwalk" }),
17
+ ...D(),
18
+ identityKey: S().maxLength(64),
19
+ revision: h(),
20
+ round: h(),
21
+ pageOrdinal: h(),
22
+ cursorAfter: S().maxLength(191).nullable(),
23
+ exhausted: h()
24
+ }).unique("byBillingInvoiceHistoryOwner", ["identityKey"]).index("byBillingInvoiceHistoryTenant", ["tenantId"]), k = x(T, {
25
+ id: p({ prefix: "bihpage" }),
26
+ ...D(),
27
+ walkId: S().maxLength(191),
28
+ round: h(),
29
+ pageOrdinal: h(),
30
+ pageKey: S().maxLength(64),
31
+ bodyDigest: S().maxLength(64),
32
+ cursorAfter: S().maxLength(191).nullable(),
33
+ nextCursorAfter: S().maxLength(191).nullable(),
34
+ referenceCount: h(),
35
+ observedAt: C()
36
+ }).unique("byBillingInvoiceHistoryPageKey", ["pageKey"]).unique("byBillingInvoiceHistoryPageOrder", ["walkId", "pageOrdinal"]).index("byBillingInvoiceHistoryPageTenant", ["tenantId"]), A = x(E, {
37
+ id: p({ prefix: "bihref" }),
38
+ ...D(),
39
+ walkId: S().maxLength(191),
40
+ round: h(),
41
+ pageId: S().maxLength(191),
42
+ pageOrdinal: h(),
43
+ position: h(),
44
+ referenceKey: S().maxLength(64),
45
+ providerInvoiceId: S().maxLength(191),
46
+ discoveryStatus: S().maxLength(32),
47
+ providerCreatedAt: C()
48
+ }).unique("byBillingInvoiceHistoryReference", ["referenceKey"]).unique("byBillingInvoiceHistoryReferenceOrder", [
49
+ "walkId",
50
+ "pageOrdinal",
51
+ "position"
52
+ ]).index("byBillingInvoiceHistoryReferenceTenant", ["tenantId"]), j = 2147483647, M = (e, t = 191) => {
53
+ if (!n(e) || e.length > t || !e.isWellFormed()) throw F();
54
+ return e;
55
+ }, N = (e, t = 0) => {
56
+ if (typeof e != "number" || !Number.isSafeInteger(e) || e < t || e > j) throw F();
57
+ return e;
58
+ }, P = (e) => {
59
+ let t = e instanceof Date ? new Date(e) : new Date(typeof e == "string" ? e : NaN);
60
+ if (!Number.isFinite(t.getTime())) throw F();
61
+ return t;
62
+ }, F = (e = "The durable invoice history journal requires reconciliation.", t = !1) => s(e, t), I = (t) => c.tryPromise({
63
+ try: t,
64
+ catch: (t) => t instanceof e ? t : F("The native invoice history transaction could not be confirmed.", !0)
65
+ }), L = async (e) => {
66
+ let t = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify(e)));
67
+ return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("");
68
+ }, R = (e) => {
69
+ let n = t(e.account);
70
+ return M(n.providerAccountId), Object.freeze({
71
+ tenantId: M(e.tenantId),
72
+ provider: M(e.provider, 64),
73
+ account: Object.freeze(n),
74
+ providerCustomerId: M(e.providerCustomerId),
75
+ custodyId: M(e.custodyId ?? e.id)
76
+ });
77
+ }, z = (e) => ({
78
+ tenantId: e.tenantId,
79
+ provider: e.provider,
80
+ providerAccountId: M(e.account.providerAccountId),
81
+ livemode: +!!e.account.livemode,
82
+ providerCustomerId: e.providerCustomerId,
83
+ custodyId: e.custodyId
84
+ }), B = (e) => {
85
+ if (e.livemode !== 0 && e.livemode !== 1) throw F();
86
+ return R({
87
+ tenantId: M(e.tenantId),
88
+ provider: M(e.provider, 64),
89
+ account: {
90
+ providerAccountId: M(e.providerAccountId),
91
+ livemode: e.livemode === 1
92
+ },
93
+ providerCustomerId: M(e.providerCustomerId),
94
+ custodyId: M(e.custodyId)
95
+ });
96
+ }, V = (e, t) => {
97
+ if (e.tenantId !== t.tenantId || e.provider !== t.provider || e.custodyId !== t.custodyId || e.providerCustomerId !== t.providerCustomerId || !r(e.account, t.account)) throw F();
98
+ }, H = (e) => {
99
+ let t = R(e);
100
+ if (typeof e.exhausted != "boolean" || e.exhausted && e.cursor !== null) throw F();
101
+ let n = e.cursor === null ? null : a({
102
+ account: t.account,
103
+ providerCustomerId: t.providerCustomerId,
104
+ cursor: e.cursor
105
+ }).cursor;
106
+ if (n === void 0 || e.revision !== e.pageOrdinal + e.round || e.pageOrdinal === 0 && (e.cursor !== null || e.exhausted)) throw F();
107
+ return Object.freeze({
108
+ ...t,
109
+ id: M(e.id),
110
+ revision: N(e.revision, 1),
111
+ round: N(e.round, 1),
112
+ pageOrdinal: N(e.pageOrdinal),
113
+ cursor: n,
114
+ exhausted: e.exhausted
115
+ });
116
+ }, U = (e) => {
117
+ let t = B(e), n = e.cursorAfter;
118
+ if (e.exhausted !== 0 && e.exhausted !== 1 || n !== null && typeof n != "string") throw F();
119
+ return H({
120
+ ...t,
121
+ id: M(e.id),
122
+ revision: N(e.revision, 1),
123
+ round: N(e.round, 1),
124
+ pageOrdinal: N(e.pageOrdinal),
125
+ exhausted: e.exhausted === 1,
126
+ cursor: n === null ? null : {
127
+ ...t.account,
128
+ providerCustomerId: t.providerCustomerId,
129
+ afterInvoiceId: M(n)
130
+ }
131
+ });
132
+ }, W = (e) => L([
133
+ "voltro.invoice-history-walk.v1",
134
+ e.provider,
135
+ e.account.providerAccountId,
136
+ e.account.livemode,
137
+ e.providerCustomerId
138
+ ]), G = (e, t, n, r = !1) => ({
139
+ table: e,
140
+ predicate: t,
141
+ order: [],
142
+ take: n,
143
+ skip: void 0,
144
+ projection: void 0,
145
+ ...r ? { lock: "update" } : {}
146
+ }), K = (e, t) => e.id === t.id && e.revision === t.revision && e.round === t.round && e.pageOrdinal === t.pageOrdinal && e.exhausted === t.exhausted && e.cursor?.afterInvoiceId === t.cursor?.afterInvoiceId, q = (e) => {
147
+ let t = async (e, t) => {
148
+ let n = await c.runPromise(i(e).getByProviderCustomerId(t.providerCustomerId, t));
149
+ if (n === null) throw F("Positive retained customer custody is required before invoice history admission.");
150
+ V(R(n), t);
151
+ }, n = (e) => l(d("provider", e.provider), d("providerAccountId", e.account.providerAccountId), d("livemode", +!!e.account.livemode), d("providerCustomerId", e.providerCustomerId)), r = async (e, t) => {
152
+ for (let r of [T, E]) {
153
+ let i = y(v("walkId", t.id), v("custodyId", t.custodyId), v("tenantId", t.tenantId), f("pageOrdinal", t.pageOrdinal), f("round", t.round), g("pageOrdinal", 1), g("round", 1)), a = y(v("provider", t.provider), v("providerAccountId", t.account.providerAccountId), v("livemode", +!!t.account.livemode), v("providerCustomerId", t.providerCustomerId)), o = y(l(n(t), i), l(d("walkId", t.id), y(i, a)));
154
+ if ((await e.query(G(r, o, 1))).length) throw F("Invoice history receipts do not belong to the retained walk checkpoint; explicit reconciliation is required.", !0);
155
+ }
156
+ }, s = (e) => {
157
+ if (typeof e == "bigint") {
158
+ if (e < 0n || e > BigInt(2 ** 53 - 1)) throw F();
159
+ return Number(e);
160
+ }
161
+ if (typeof e == "string" && /^(0|[1-9][0-9]{0,15})$/.test(e) && (e = Number(e)), typeof e != "number" || !Number.isSafeInteger(e) || e < 0) throw F();
162
+ return e;
163
+ }, p = async (e, t) => {
164
+ let n = await e.query({
165
+ ...G(T, d("walkId", t.id), 1),
166
+ take: void 0,
167
+ aggregations: [u("pageCount"), b("referenceCount", "referenceTotal")]
168
+ });
169
+ if (n.length !== 1 || !n[0] || s(n[0].pageCount) !== t.pageOrdinal) throw F("An admitted invoice history page is missing; completion cannot be inferred.", !0);
170
+ let r = n[0].referenceTotal === null && t.pageOrdinal === 0 ? 0 : s(n[0].referenceTotal);
171
+ if (r > t.pageOrdinal * 100) throw F();
172
+ let i = await e.query({
173
+ ...G(E, d("walkId", t.id), 1),
174
+ take: void 0,
175
+ aggregations: [u("referenceTotal")]
176
+ });
177
+ if (i.length !== 1 || !i[0] || s(i[0].referenceTotal) !== r) throw F("Admitted invoice references are missing; the history requires explicit reconciliation.", !0);
178
+ if (t.pageOrdinal > 0) {
179
+ let n = await e.query(G(T, l(d("walkId", t.id), d("pageOrdinal", t.pageOrdinal)), 2));
180
+ if (n.length !== 1 || !n[0]) throw F();
181
+ let r = N(n[0].round, 1), i = n[0].nextCursorAfter;
182
+ if (i !== null && typeof i != "string" || r > t.round || r === t.round && (i !== (t.cursor?.afterInvoiceId ?? null) || t.exhausted !== (i === null)) || r < t.round && (t.cursor !== null || t.exhausted)) throw F("The retained provider cursor does not match the admitted history head.");
183
+ }
184
+ }, h = async (e, t, n, i = !1) => {
185
+ let a = await e.query(G(w, d("identityKey", n), 2, i));
186
+ if (a.length > 1) throw F();
187
+ if (!a[0]) return null;
188
+ let o = U(a[0]);
189
+ if (V(o, t), a[0].identityKey !== n || await W(o) !== n) throw F();
190
+ return await r(e, o), await p(e, o), o;
191
+ }, x = async (e, t, n, r) => {
192
+ if (t.revision >= j) throw F("The invoice history revision is exhausted.");
193
+ if (await e.updateMany("_voltro_billing_invoice_history_walks", {
194
+ revision: n.revision,
195
+ round: n.round,
196
+ pageOrdinal: n.pageOrdinal,
197
+ cursorAfter: n.cursor?.afterInvoiceId ?? null,
198
+ exhausted: +!!n.exhausted
199
+ }, { where: l(d("id", t.id), d("identityKey", r), d("revision", t.revision), d("custodyId", t.custodyId)) }) !== 1) throw F("Invoice history changed during the native page transaction.", !0);
200
+ let i = await h(e, n, r, !0);
201
+ if (i === null || !K(i, n)) throw F("The invoice history checkpoint was not read back.", !0);
202
+ return i;
203
+ }, S = (e, t) => {
204
+ let n = B(e);
205
+ V(n, t);
206
+ let r = e.discoveryStatus;
207
+ if (r !== "draft" && r !== "open" && r !== "paid" && r !== "uncollectible" && r !== "void") throw F();
208
+ let i = {
209
+ ...n,
210
+ id: M(e.id),
211
+ walkId: M(e.walkId),
212
+ round: N(e.round, 1),
213
+ pageId: M(e.pageId),
214
+ pageOrdinal: N(e.pageOrdinal, 1),
215
+ position: N(e.position),
216
+ providerInvoiceId: M(e.providerInvoiceId),
217
+ discoveryStatus: r,
218
+ providerCreatedAt: P(e.providerCreatedAt)
219
+ };
220
+ if (i.walkId !== t.id || i.round > t.round || i.pageOrdinal > t.pageOrdinal || i.position > 99) throw F();
221
+ return i;
222
+ }, C = async (e, t, n) => {
223
+ let r = [...new Set(n.map((e) => M(e.pageId)))];
224
+ if (r.length === 0) return;
225
+ let i = await e.query(G(T, m("id", r), r.length + 1));
226
+ if (i.length !== r.length) throw F("A referenced invoice history page is missing.", !0);
227
+ let a = i.reduce((e, t) => {
228
+ let n = N(t.referenceCount);
229
+ if (n > 100) throw F();
230
+ return e + n;
231
+ }, 0), o = await e.query({
232
+ ...G(E, m("pageId", r), a + 1),
233
+ order: [{
234
+ column: "pageOrdinal",
235
+ direction: "asc"
236
+ }, {
237
+ column: "position",
238
+ direction: "asc"
239
+ }]
240
+ });
241
+ if (o.length !== a) throw F("A retained invoice page is incomplete.", !0);
242
+ let s = /* @__PURE__ */ new Map();
243
+ for (let e of i) {
244
+ V(B(e), t);
245
+ let n = M(e.id), r = N(e.round, 1), i = N(e.pageOrdinal, 1);
246
+ if (e.walkId !== t.id || r > t.round || i > t.pageOrdinal) throw F();
247
+ let a = e.cursorAfter, c = e.nextCursorAfter;
248
+ if (a !== null && typeof a != "string" || c !== null && typeof c != "string") throw F();
249
+ let l = await L([
250
+ "voltro.invoice-history-page.v1",
251
+ t.id,
252
+ r,
253
+ a
254
+ ]), u = o.filter((e) => e.pageId === n);
255
+ if (u.length !== e.referenceCount) throw F();
256
+ let d = await Promise.all(u.map(async (e, n) => {
257
+ let a = S(e, t);
258
+ if (a.round !== r || a.pageOrdinal !== i || a.position !== n || e.referenceKey !== await L([
259
+ "voltro.invoice-history-reference.v1",
260
+ t.id,
261
+ r,
262
+ a.providerInvoiceId
263
+ ])) throw F();
264
+ return [
265
+ a.providerInvoiceId,
266
+ a.discoveryStatus,
267
+ a.providerCreatedAt.toISOString()
268
+ ];
269
+ })), f = await L([
270
+ l,
271
+ c,
272
+ P(e.observedAt).toISOString(),
273
+ d
274
+ ]);
275
+ if (e.pageKey !== l || e.bodyDigest !== f) throw F("Retained invoice references differ from their admitted page.", !0);
276
+ s.set(n, u);
277
+ }
278
+ for (let e of n) {
279
+ let t = s.get(M(e.pageId));
280
+ if (t === void 0 || !t.some((t) => t.id === e.id && t.referenceKey === e.referenceKey)) throw F();
281
+ }
282
+ }, D = async (e, n, r) => {
283
+ if (r.length > 101 || new Set(r).size !== r.length) throw F();
284
+ await t(e, n);
285
+ let i = await h(e, n, await W(n), !0);
286
+ if (i === null) throw F("No retained owned invoice history walk exists.");
287
+ if (r.length === 0) return /* @__PURE__ */ new Map();
288
+ let a = await e.query(G(E, m("id", r), r.length + 1));
289
+ if (a.length > r.length) throw F();
290
+ await C(e, i, a);
291
+ let o = /* @__PURE__ */ new Map();
292
+ for (let e of a) {
293
+ let t = S(e, i);
294
+ if (!r.includes(t.id) || o.has(t.id)) throw F();
295
+ o.set(t.id, t);
296
+ }
297
+ return o;
298
+ };
299
+ return {
300
+ referencesByIds: (t, n) => I(async () => {
301
+ let r = R(t), i = n.map((e) => M(e));
302
+ return e(async (e) => {
303
+ let t = await D(e, r, i);
304
+ return i.map((e) => {
305
+ let n = t.get(e);
306
+ if (n === void 0) throw F("A selected invoice history reference is missing.");
307
+ return n;
308
+ });
309
+ });
310
+ }),
311
+ begin: (r) => I(async () => {
312
+ let i = R(r), a = await W(i);
313
+ return e(async (e) => {
314
+ await t(e, i);
315
+ let r = await h(e, i, a, !0);
316
+ if (r !== null) return r;
317
+ for (let t of [T, E]) if ((await e.query(G(t, n(i), 1))).length) throw F("Retained invoice history receipts require their original walk root; no replacement root is fabricated.");
318
+ await e.insertIgnore(w, {
319
+ id: "bihwalk_" + globalThis.crypto.randomUUID(),
320
+ ...z(i),
321
+ identityKey: a,
322
+ revision: 1,
323
+ round: 1,
324
+ pageOrdinal: 0,
325
+ cursorAfter: null,
326
+ exhausted: 0
327
+ }, { conflictColumns: ["identityKey"] });
328
+ let o = await h(e, i, a, !0);
329
+ if (o === null) throw F("The invoice history owner reservation was not read back.", !0);
330
+ return o;
331
+ });
332
+ }),
333
+ read: (n) => I(async () => {
334
+ let r = R(n), i = await W(r);
335
+ return e(async (e) => (await t(e, r), h(e, r, i)));
336
+ }),
337
+ commitPage: (n, r) => I(async () => {
338
+ let i = H(n), s = a({
339
+ account: i.account,
340
+ providerCustomerId: i.providerCustomerId,
341
+ ...i.cursor === null ? {} : { cursor: i.cursor }
342
+ }), c = o(s, r);
343
+ if (i.exhausted || i.revision >= j || i.pageOrdinal >= j) throw F();
344
+ let l = await W(i), u = i.cursor?.afterInvoiceId ?? null, f = await L([
345
+ "voltro.invoice-history-page.v1",
346
+ i.id,
347
+ i.round,
348
+ u
349
+ ]), p = await Promise.all(c.invoices.map((e) => L([
350
+ "voltro.invoice-history-reference.v1",
351
+ i.id,
352
+ i.round,
353
+ e.providerInvoiceId
354
+ ]))), g = await L([
355
+ f,
356
+ c.nextCursor?.afterInvoiceId ?? null,
357
+ c.observedAt.toISOString(),
358
+ c.invoices.map((e) => [
359
+ e.providerInvoiceId,
360
+ e.status,
361
+ e.createdAt.toISOString()
362
+ ])
363
+ ]);
364
+ return e(async (e) => {
365
+ await t(e, i);
366
+ let n = await h(e, i, l, !0);
367
+ if (n === null || !K(n, i)) return null;
368
+ if ((await e.query(G("_voltro_billing_invoice_history_pages", d("pageKey", f), 1))).length || p.length > 0 && (await e.query(G("_voltro_billing_invoice_history_references", m("referenceKey", p), 1))).length) throw F("The invoice history cursor or invoice repeated within this round; the page remains uncommitted.");
369
+ let r = "bihpage_" + globalThis.crypto.randomUUID(), a = n.pageOrdinal + 1;
370
+ await e.insert(T, {
371
+ id: r,
372
+ ...z(n),
373
+ walkId: n.id,
374
+ round: n.round,
375
+ pageOrdinal: a,
376
+ pageKey: f,
377
+ bodyDigest: g,
378
+ cursorAfter: u,
379
+ nextCursorAfter: c.nextCursor?.afterInvoiceId ?? null,
380
+ referenceCount: c.invoices.length,
381
+ observedAt: c.observedAt
382
+ }), await e.insertMany(E, c.invoices.map((e, t) => ({
383
+ id: "bihref_" + globalThis.crypto.randomUUID(),
384
+ ...z(n),
385
+ walkId: n.id,
386
+ round: n.round,
387
+ pageId: r,
388
+ pageOrdinal: a,
389
+ position: t,
390
+ referenceKey: p[t],
391
+ providerInvoiceId: e.providerInvoiceId,
392
+ discoveryStatus: e.status,
393
+ providerCreatedAt: e.createdAt
394
+ })));
395
+ let o = H({
396
+ ...n,
397
+ revision: n.revision + 1,
398
+ pageOrdinal: a,
399
+ cursor: c.nextCursor,
400
+ exhausted: c.nextCursor === null
401
+ }), s = await e.query(G(T, d("pageKey", f), 2));
402
+ if (s.length !== 1 || s[0]?.id !== r || s[0]?.bodyDigest !== g || s[0]?.referenceCount !== c.invoices.length || s[0]?.walkId !== n.id || s[0]?.round !== n.round || s[0]?.pageOrdinal !== a || s[0]?.cursorAfter !== u || s[0]?.nextCursorAfter !== (c.nextCursor?.afterInvoiceId ?? null) || P(s[0]?.observedAt).getTime() !== c.observedAt.getTime()) throw F("The admitted page receipt was not read back.", !0);
403
+ V(B(s[0]), n);
404
+ let _ = await e.query({
405
+ ...G(E, d("pageId", r), 101),
406
+ order: [{
407
+ column: "position",
408
+ direction: "asc"
409
+ }]
410
+ });
411
+ if (_.length !== c.invoices.length) throw F("Not every invoice reference was read back; the page transaction must roll back.", !0);
412
+ return _.forEach((e, t) => {
413
+ let i = S(e, o), s = c.invoices[t];
414
+ if (!s || i.round !== n.round || i.pageOrdinal !== a || i.pageId !== r || i.position !== t || e.referenceKey !== p[t] || i.providerInvoiceId !== s.providerInvoiceId || i.discoveryStatus !== s.status || i.providerCreatedAt.getTime() !== s.createdAt.getTime()) throw F("The persisted invoice reference differs from its admitted page.", !0);
415
+ }), x(e, n, o, l);
416
+ });
417
+ }),
418
+ restart: (n) => I(async () => {
419
+ let r = H(n), i = await W(r);
420
+ if (r.round >= j || r.revision >= j) throw F();
421
+ return e(async (e) => {
422
+ await t(e, r);
423
+ let n = await h(e, r, i, !0);
424
+ return n === null || !K(n, r) ? null : x(e, n, H({
425
+ ...n,
426
+ revision: n.revision + 1,
427
+ round: n.round + 1,
428
+ cursor: null,
429
+ exhausted: !1
430
+ }), i);
431
+ });
432
+ }),
433
+ reference: (t, n) => I(async () => {
434
+ let r = R(t), i = M(n);
435
+ return e(async (e) => (await D(e, r, [i])).get(i) ?? null);
436
+ }),
437
+ references: (n, r) => I(async () => {
438
+ let i = R(n), a = r?.limit ?? 100, o = r?.afterReferenceId === void 0 ? null : M(r.afterReferenceId);
439
+ if (!Number.isSafeInteger(a) || a < 1 || a > 100) throw F();
440
+ let s = await W(i);
441
+ return e(async (e) => {
442
+ await t(e, i);
443
+ let n = await h(e, i, s);
444
+ if (n === null) throw F("No owned invoice history walk exists.");
445
+ let r = [d("walkId", n.id), _("pageOrdinal", n.pageOrdinal)];
446
+ if (o !== null) {
447
+ let t = await e.query(G(E, d("id", o), 2));
448
+ if (t.length !== 1 || t[0]?.id !== o) throw F("The invoice reference cursor is not retained by this walk.");
449
+ await C(e, n, t);
450
+ let i = S(t[0], n);
451
+ r.push(y(f("pageOrdinal", i.pageOrdinal), l(d("pageOrdinal", i.pageOrdinal), f("position", i.position))));
452
+ }
453
+ let c = await e.query({
454
+ ...G(E, l(...r), a + 1),
455
+ order: [{
456
+ column: "pageOrdinal",
457
+ direction: "asc"
458
+ }, {
459
+ column: "position",
460
+ direction: "asc"
461
+ }]
462
+ });
463
+ await C(e, n, c);
464
+ let u = c.map((e) => S(e, n)), p = u.slice(0, a);
465
+ return {
466
+ references: p,
467
+ nextReferenceId: u.length > a ? p.at(-1).id : null,
468
+ watermarkPageOrdinal: n.pageOrdinal,
469
+ walkRevision: n.revision
470
+ };
471
+ });
472
+ })
473
+ };
474
+ }, J = (e) => q((t) => e.transactional(t)), Y = (e) => q((t) => t(e));
475
+ export { T as BILLING_INVOICE_HISTORY_PAGES_TABLE, E as BILLING_INVOICE_HISTORY_REFERENCES_TABLE, w as BILLING_INVOICE_HISTORY_WALKS_TABLE, k as billingInvoiceHistoryPagesTable, A as billingInvoiceHistoryReferencesTable, O as billingInvoiceHistoryWalksTable, J as dataStoreInvoiceHistoryJournal, Y as invoiceHistoryJournalInTransaction };