@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.
- package/CHANGELOG.md +5484 -0
- package/README.md +428 -0
- package/THIRD-PARTY-NOTICES.md +1511 -276
- package/dist/catalog.js +1 -2
- package/dist/checkoutStore.js +164 -0
- package/dist/closeStore.js +124 -0
- package/dist/custodyInventory.js +154 -0
- package/dist/customerStore.js +258 -0
- package/dist/dunning.js +1 -2
- package/dist/economy.d.ts +30 -0
- package/dist/economy.js +265 -0
- package/dist/entitlement.js +1 -2
- package/dist/eventDelivery.js +71 -0
- package/dist/flushClaim.js +1 -2
- package/dist/index.d.ts +669 -65
- package/dist/index.js +230 -173
- package/dist/invoiceHistory.js +90 -0
- package/dist/invoiceHistoryJournal.js +475 -0
- package/dist/invoiceHistoryProgress.js +234 -0
- package/dist/invoiceHistoryWork.js +362 -0
- package/dist/invoiceSnapshot.js +65 -0
- package/dist/invoiceStore.js +132 -0
- package/dist/metering.js +1 -2
- package/dist/plans.js +1 -2
- package/dist/providerIdentity.js +23 -0
- package/dist/providers.js +271 -67
- package/dist/provision.js +1 -2
- package/dist/rpc.js +1 -2
- package/dist/service.js +892 -392
- package/dist/stores.js +125 -291
- package/dist/stripeClient.js +1 -2
- package/dist/stripeIdentity.js +55 -0
- package/dist/stripeInvoiceHistory.js +66 -0
- package/dist/stripeInvoiceSnapshot.js +85 -0
- package/dist/stripeProvider.js +305 -179
- package/dist/stripeRest.js +1 -2
- package/dist/stripeVerifiedEvent.js +28 -0
- package/dist/table.js +70 -48
- package/dist/types.d.ts +298 -27
- package/dist/types.js +1 -2
- package/dist/usageEvents.js +64 -0
- package/dist/web/index.js +1 -2
- package/dist/webhook.js +32 -40
- package/package.json +18 -8
package/dist/index.js
CHANGED
|
@@ -1,32 +1,43 @@
|
|
|
1
1
|
import { BillingError as e, BillingService as t, DEFAULT_PLAN as n, EntitlementExceeded as r, SubscriptionLocked as i } from "./types.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
import { makeBillingEventDelivery as a } from "./eventDelivery.js";
|
|
3
|
+
import { BILLING_CUSTODY_INVENTORY_TABLES as o, inspectBillingCustody as s } from "./custodyInventory.js";
|
|
4
|
+
import { BILLING_CUSTOMER_ACCOUNTS_TABLE as c, BILLING_CUSTOMER_CUSTODY_TABLE as l, billingCustomerAccountsTable as u, billingCustomerCustodyTable as ee } from "./customerStore.js";
|
|
5
|
+
import { buildEnforceInterceptor as te, evaluateEntitlement as d, requireEntitled as f, requireEntitlement as ne } from "./entitlement.js";
|
|
6
|
+
import { BILLING_INVOICE_HISTORY_PAGES_TABLE as p, BILLING_INVOICE_HISTORY_REFERENCES_TABLE as m, BILLING_INVOICE_HISTORY_WALKS_TABLE as h, billingInvoiceHistoryPagesTable as g, billingInvoiceHistoryReferencesTable as _, billingInvoiceHistoryWalksTable as v, dataStoreInvoiceHistoryJournal as y } from "./invoiceHistoryJournal.js";
|
|
7
|
+
import { BILLING_INVOICE_OBSERVATIONS_TABLE as re, billingInvoiceObservationsTable as ie, billingRetainedInvoiceObservationsTable as ae } from "./invoiceStore.js";
|
|
8
|
+
import { BILLING_INVOICE_HISTORY_WORK_TABLE as oe, billingInvoiceHistoryWorkTable as se, dataStoreInvoiceHistoryWorkStore as b } from "./invoiceHistoryWork.js";
|
|
9
|
+
import { BILLING_INVOICE_HISTORY_DISPATCH_TABLE as ce, BILLING_INVOICE_HISTORY_SCAN_ACCOUNTS_TABLE as x, billingInvoiceHistoryDispatchTable as S, billingInvoiceHistoryScanAccountsTable as C, dataStoreInvoiceHistoryProgressStore as w } from "./invoiceHistoryProgress.js";
|
|
10
|
+
import { BILLING_USAGE_EVENTS_TABLE as T, billingUsageEventsTable as E } from "./usageEvents.js";
|
|
11
|
+
import { BILLING_CHECKOUT_OPERATIONS_TABLE as D, billingCheckoutOperationsTable as O, dataStoreCheckoutOperationStore as k, memoryCheckoutOperationStore as A } from "./checkoutStore.js";
|
|
12
|
+
import { BILLING_CLOSE_OPERATIONS_TABLE as j, billingCloseOperationsTable as M, dataStoreBillingCloseStore as N, memoryBillingCloseStore as P } from "./closeStore.js";
|
|
13
|
+
import { BILLING_DUNNING_NOTICES_TABLE as le, DEFAULT_DUNNING_STEPS as F, DEFAULT_GRACE_HOURS as I, DEFAULT_LOCKOUT as L, DUNNING_LOCK_STEP_ID as R, billingDunningNoticesTable as z, dataStoreDunningNoticeStore as B, defaultDunningEmail as ue, dueSteps as de, dunningMailNotifier as fe, episodeKeyOf as pe, evaluateBillingEntitlement as me, graceEndOf as he, memoryDunningNoticeStore as ge, resolveDunningConfig as V } from "./dunning.js";
|
|
14
|
+
import { BILLING_CUSTOMERS_TABLE as _e, BILLING_INVOICES_TABLE as ve, BILLING_SUBSCRIPTIONS_TABLE as H, BILLING_USAGE_TABLE as U, billingCustomersTable as ye, billingInvoicesTable as be, billingSubscriptionsTable as xe, billingTables as W, billingUsageTable as Se } from "./table.js";
|
|
15
|
+
import { dataStoreStores as G, isStaleStatusEvent as Ce, memoryStores as we, selectCurrentSubscription as Te } from "./stores.js";
|
|
16
|
+
import { billingServiceLayer as K, buildBillingService as Ee, periodKey as De } from "./service.js";
|
|
17
|
+
import { buildMeteringChangeTap as Oe, buildMeteringInterceptor as ke, hasCdcMeters as Ae, runAutopilotFlush as je, validateMeteringConfig as Me } from "./metering.js";
|
|
18
|
+
import { buildPlanRegistry as Ne, emptyPlanRegistry as Pe } from "./plans.js";
|
|
19
|
+
import { BILLING_FLUSH_CLAIMS_TABLE as Fe, billingFlushClaimsTable as Ie, claimFlushWindow as Le, flushWindowKey as Re } from "./flushClaim.js";
|
|
20
|
+
import { STRIPE_API_VERSION as ze, STRIPE_DASHBOARD_REMINDERS as Be, diffMeter as Ve, diffPortal as He, diffPrice as Ue, diffProduct as We, diffTaxSettings as Ge, diffWebhook as Ke, portalParams as qe, sellingReadiness as Je } from "./catalog.js";
|
|
21
|
+
import { StripeRestError as Ye, formEncode as Xe, redactStripeKeys as Ze, stripeRest as Qe } from "./stripeRest.js";
|
|
22
|
+
import { STRIPE_WEBHOOK_EVENTS as $e, normalizeStripeEvent as et, stripeProvider as tt } from "./stripeProvider.js";
|
|
23
|
+
import { assertBillingProductionReady as nt, billingEgressOf as rt, isProductionBoot as it, mockProvider as at, resolveProvider as ot } from "./providers.js";
|
|
24
|
+
import { BILLING_WEBHOOK_ID as st, BILLING_WEBHOOK_PATH as q, billingWebhookDescriptor as ct, mountBillingWebhook as lt } from "./webhook.js";
|
|
25
|
+
import { billingRpcClientImports as ut, cancelSubscriptionDescriptor as dt, changePlanDescriptor as ft, changeSeatsDescriptor as pt, entitlementStatusDescriptor as mt, invoicesDescriptor as ht, portalUrlDescriptor as gt, previewChangeDescriptor as _t, reportUsageDescriptor as vt, resumeSubscriptionDescriptor as yt, startCheckoutDescriptor as J, subscriptionDescriptor as bt, syncDescriptor as xt } from "./rpc.js";
|
|
26
|
+
import { envOutRefusal as St, mergeEnvFile as Ct, openFindings as wt, parseProvisionArgs as Tt, provisionStripeCatalog as Et, resolveProvisionKey as Dt, runStripeProvision as Ot } from "./provision.js";
|
|
27
|
+
import { Effect as Y } from "effect";
|
|
28
|
+
import { pluginEnv as kt } from "@voltro/env";
|
|
29
|
+
import { composeRpcInterceptors as At, definePlugin as jt, pluginInstanceName as Mt, recheckGuardsEffect as Nt } from "@voltro/protocol";
|
|
30
|
+
import { and as Pt, eq as Ft, registerRetention as X, retentionTtlMsFromEnv as Z } from "@voltro/database";
|
|
31
|
+
import { replicaId as It } from "@voltro/protocol/identity";
|
|
32
|
+
import { dataStoreIdempotencyStore as Lt } from "@voltro/runtime";
|
|
33
|
+
// src/index.ts
|
|
34
|
+
var Q = (e) => e === null ? null : {
|
|
24
35
|
plan: e.plan,
|
|
25
36
|
status: e.status,
|
|
26
37
|
quantity: e.quantity,
|
|
27
38
|
currentPeriodEnd: e.currentPeriodEnd ? e.currentPeriodEnd.toISOString() : null,
|
|
28
39
|
cancelAt: e.cancelAt ? e.cancelAt.toISOString() : null
|
|
29
|
-
},
|
|
40
|
+
}, Rt = kt([{
|
|
30
41
|
name: "STRIPE_SECRET_KEY",
|
|
31
42
|
required: !1,
|
|
32
43
|
secret: !0,
|
|
@@ -36,41 +47,42 @@ var $ = (e) => e === null ? null : {
|
|
|
36
47
|
required: !1,
|
|
37
48
|
secret: !0,
|
|
38
49
|
description: "Stripe webhook signing secret (whsec_…) for verifying webhook payloads."
|
|
39
|
-
}]), $
|
|
40
|
-
let n = process.env, o =
|
|
50
|
+
}]), $ = "@voltro/plugin-billing", zt = (t = {}) => {
|
|
51
|
+
let n = process.env, o = Ne(t.plans ?? {}), s = ot({
|
|
41
52
|
...t.provider === void 0 ? {} : { provider: t.provider },
|
|
42
53
|
...t.apiKey === void 0 ? {} : { apiKey: t.apiKey },
|
|
43
54
|
planForPriceId: o.planForPriceId,
|
|
44
55
|
env: n
|
|
45
|
-
}),
|
|
46
|
-
|
|
56
|
+
}), u = t.webhookSecret ?? Rt.read("STRIPE_WEBHOOK_SECRET") ?? null;
|
|
57
|
+
nt({
|
|
47
58
|
env: n,
|
|
48
59
|
providerOption: t.provider,
|
|
49
60
|
resolvedName: s.name,
|
|
50
|
-
webhookSecret:
|
|
61
|
+
webhookSecret: u,
|
|
51
62
|
redirectOrigins: t.redirectOrigins
|
|
52
63
|
});
|
|
53
|
-
let
|
|
54
|
-
|
|
64
|
+
let ee = V(t.dunning, n);
|
|
65
|
+
X({
|
|
55
66
|
source: "plugin",
|
|
56
|
-
table:
|
|
67
|
+
table: U,
|
|
57
68
|
timeColumn: "updatedAt",
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
where: Pt(Ft("used", 0), Ft("reportedToProvider", 0)),
|
|
70
|
+
ttlMs: Z(process.env.VOLTRO_BILLING_USAGE_TTL_HOURS, 9600),
|
|
71
|
+
label: "unused billing usage counters"
|
|
72
|
+
}), X({
|
|
61
73
|
source: "plugin",
|
|
62
|
-
table:
|
|
74
|
+
table: Fe,
|
|
63
75
|
timeColumn: "claimedAt",
|
|
64
|
-
ttlMs:
|
|
76
|
+
ttlMs: Z(process.env.VOLTRO_BILLING_FLUSH_CLAIM_TTL_HOURS, 1),
|
|
65
77
|
label: "billing flush claims"
|
|
66
|
-
}),
|
|
78
|
+
}), X({
|
|
67
79
|
source: "plugin",
|
|
68
|
-
table:
|
|
80
|
+
table: le,
|
|
69
81
|
timeColumn: "sentAt",
|
|
70
|
-
ttlMs:
|
|
82
|
+
ttlMs: Z(process.env.VOLTRO_BILLING_DUNNING_TTL_HOURS, 9600),
|
|
71
83
|
label: "billing dunning notices"
|
|
72
84
|
});
|
|
73
|
-
let { service:
|
|
85
|
+
let { service: d, holder: f } = Ee({
|
|
74
86
|
provider: s,
|
|
75
87
|
plans: o,
|
|
76
88
|
...t.attempts === void 0 ? {} : { attempts: t.attempts },
|
|
@@ -80,21 +92,37 @@ var $ = (e) => e === null ? null : {
|
|
|
80
92
|
...t.isTenantClosed === void 0 ? {} : { isTenantClosed: t.isTenantClosed },
|
|
81
93
|
...t.onEvent === void 0 ? {} : { onEvent: t.onEvent },
|
|
82
94
|
...t.resolveEntitlementLimit === void 0 ? {} : { resolveEntitlementLimit: t.resolveEntitlementLimit },
|
|
83
|
-
dunning:
|
|
84
|
-
}),
|
|
95
|
+
dunning: ee
|
|
96
|
+
}), ne = K(d), p, m = {
|
|
97
|
+
scope: Mt({
|
|
98
|
+
base: $,
|
|
99
|
+
alias: t.alias,
|
|
100
|
+
instance: t.name
|
|
101
|
+
}),
|
|
102
|
+
store: () => {
|
|
103
|
+
if (p === void 0) throw Error("Billing delivery requires the bound native store.");
|
|
104
|
+
return p;
|
|
105
|
+
}
|
|
106
|
+
}, h = a({
|
|
107
|
+
provider: s,
|
|
108
|
+
service: d,
|
|
109
|
+
receipts: m,
|
|
110
|
+
...t.onEvent === void 0 ? {} : { onEvent: t.onEvent }
|
|
111
|
+
}), g = lt({
|
|
85
112
|
provider: s,
|
|
86
|
-
service:
|
|
87
|
-
|
|
113
|
+
service: d,
|
|
114
|
+
receipts: m,
|
|
115
|
+
webhookSecret: u,
|
|
88
116
|
...t.onEvent === void 0 ? {} : { onEvent: t.onEvent },
|
|
89
117
|
onLateDelivery: () => {
|
|
90
|
-
|
|
118
|
+
R();
|
|
91
119
|
}
|
|
92
|
-
}),
|
|
120
|
+
}), _ = {
|
|
93
121
|
method: "POST",
|
|
94
|
-
path:
|
|
122
|
+
path: q,
|
|
95
123
|
originGuard: "exempt",
|
|
96
124
|
handle: async (e) => {
|
|
97
|
-
let t = await
|
|
125
|
+
let t = await g({
|
|
98
126
|
method: e.method,
|
|
99
127
|
path: e.path,
|
|
100
128
|
headers: e.headers,
|
|
@@ -107,46 +135,59 @@ var $ = (e) => e === null ? null : {
|
|
|
107
135
|
...t.headers === void 0 ? {} : { headers: { ...t.headers } }
|
|
108
136
|
};
|
|
109
137
|
}
|
|
110
|
-
},
|
|
138
|
+
}, v = (t) => ({
|
|
111
139
|
...t,
|
|
112
140
|
execute: (n, r) => {
|
|
113
141
|
let i = r.request.subject;
|
|
114
|
-
return i.type === "anonymous" || typeof i.tenantId != "string" || i.tenantId === "" ?
|
|
142
|
+
return i.type === "anonymous" || typeof i.tenantId != "string" || i.tenantId === "" ? Y.fail(new e({
|
|
115
143
|
source: "billing",
|
|
116
144
|
message: "billing routes answer only a signed-in caller that belongs to a tenant",
|
|
117
145
|
transient: !1
|
|
118
146
|
})) : t.execute(n, r);
|
|
119
147
|
}
|
|
120
|
-
}),
|
|
148
|
+
}), y = (e, t, n, r) => e.pipe(Y.flatMap((e) => Nt(r.request.subject, t.guards, n).pipe(Y.flatMap((t) => t === null ? Y.succeed(e) : Y.fail(t))))), ie = [
|
|
121
149
|
{
|
|
122
|
-
...
|
|
123
|
-
execute: (
|
|
124
|
-
let
|
|
125
|
-
return
|
|
126
|
-
tenantId:
|
|
127
|
-
plan:
|
|
128
|
-
successUrl:
|
|
129
|
-
cancelUrl:
|
|
130
|
-
...
|
|
131
|
-
|
|
150
|
+
...J,
|
|
151
|
+
execute: (t, n) => {
|
|
152
|
+
let r = t;
|
|
153
|
+
return y(d.startCheckout({
|
|
154
|
+
tenantId: n.request.subject.tenantId ?? "",
|
|
155
|
+
plan: r.plan,
|
|
156
|
+
successUrl: r.successUrl,
|
|
157
|
+
cancelUrl: r.cancelUrl,
|
|
158
|
+
...r.quantity === void 0 ? {} : { quantity: r.quantity },
|
|
159
|
+
authorize: () => Nt(n.request.subject, J.guards, t).pipe(Y.flatMap((t) => t === null ? Y.void : Y.fail(new e({
|
|
160
|
+
source: "billing",
|
|
161
|
+
message: "Current checkout authority could not be confirmed.",
|
|
162
|
+
transient: !1
|
|
163
|
+
}))))
|
|
164
|
+
}), J, t, n);
|
|
132
165
|
}
|
|
133
166
|
},
|
|
134
167
|
{
|
|
135
|
-
...
|
|
168
|
+
...gt,
|
|
136
169
|
execute: (e, t) => {
|
|
137
170
|
let n = e;
|
|
138
|
-
return
|
|
171
|
+
return y(d.portalUrl(t.request.subject.tenantId ?? "", n.returnUrl), gt, e, t);
|
|
139
172
|
}
|
|
140
173
|
},
|
|
141
174
|
{
|
|
142
|
-
...
|
|
143
|
-
source:
|
|
144
|
-
|
|
175
|
+
...bt,
|
|
176
|
+
source: [
|
|
177
|
+
H,
|
|
178
|
+
c,
|
|
179
|
+
l
|
|
180
|
+
],
|
|
181
|
+
execute: (e, t) => d.subscription(t.request.subject.tenantId ?? "").pipe(Y.map((e) => ({ subscription: Q(e) })))
|
|
145
182
|
},
|
|
146
183
|
{
|
|
147
|
-
...
|
|
148
|
-
source:
|
|
149
|
-
|
|
184
|
+
...mt,
|
|
185
|
+
source: [
|
|
186
|
+
H,
|
|
187
|
+
c,
|
|
188
|
+
l
|
|
189
|
+
],
|
|
190
|
+
execute: (e, t) => d.entitlementStatus(t.request.subject.tenantId ?? "").pipe(Y.map((e) => ({
|
|
150
191
|
plan: e.plan,
|
|
151
192
|
billedPlan: e.billedPlan,
|
|
152
193
|
status: e.status,
|
|
@@ -158,13 +199,13 @@ var $ = (e) => e === null ? null : {
|
|
|
158
199
|
})))
|
|
159
200
|
},
|
|
160
201
|
{
|
|
161
|
-
...
|
|
202
|
+
..._t,
|
|
162
203
|
execute: (e, t) => {
|
|
163
204
|
let n = e;
|
|
164
|
-
return
|
|
205
|
+
return d.previewChange(t.request.subject.tenantId ?? "", {
|
|
165
206
|
...n.plan === void 0 ? {} : { plan: n.plan },
|
|
166
207
|
...n.quantity === void 0 ? {} : { quantity: n.quantity }
|
|
167
|
-
}).pipe(
|
|
208
|
+
}).pipe(Y.map((e) => ({
|
|
168
209
|
plan: e.plan,
|
|
169
210
|
quantity: e.quantity,
|
|
170
211
|
prorationMinor: e.prorationMinor,
|
|
@@ -173,25 +214,29 @@ var $ = (e) => e === null ? null : {
|
|
|
173
214
|
}
|
|
174
215
|
},
|
|
175
216
|
{
|
|
176
|
-
...
|
|
177
|
-
source: [
|
|
178
|
-
|
|
217
|
+
...ht,
|
|
218
|
+
source: [
|
|
219
|
+
re,
|
|
220
|
+
l,
|
|
221
|
+
c
|
|
222
|
+
],
|
|
223
|
+
execute: (e, t) => d.invoices(t.request.subject.tenantId ?? "").pipe(Y.map((e) => ({ invoices: e.map((e) => ({
|
|
179
224
|
...e,
|
|
180
225
|
createdAt: e.createdAt?.toISOString() ?? null
|
|
181
226
|
})) })))
|
|
182
227
|
},
|
|
183
228
|
{
|
|
184
|
-
...
|
|
229
|
+
...vt,
|
|
185
230
|
execute: (e, t) => {
|
|
186
231
|
let n = e;
|
|
187
|
-
return
|
|
232
|
+
return d.reportUsage(t.request.subject.tenantId ?? "", n.key, n.quantity).pipe(Y.map(() => ({ ok: !0 })));
|
|
188
233
|
}
|
|
189
234
|
},
|
|
190
235
|
{
|
|
191
|
-
...
|
|
236
|
+
...ft,
|
|
192
237
|
execute: (e, t) => {
|
|
193
238
|
let n = e;
|
|
194
|
-
return
|
|
239
|
+
return d.changePlan(t.request.subject.tenantId ?? "", n.plan).pipe(Y.map((e) => ({
|
|
195
240
|
plan: e.plan,
|
|
196
241
|
quantity: e.quantity,
|
|
197
242
|
prorationMinor: e.prorationMinor,
|
|
@@ -200,10 +245,10 @@ var $ = (e) => e === null ? null : {
|
|
|
200
245
|
}
|
|
201
246
|
},
|
|
202
247
|
{
|
|
203
|
-
...
|
|
248
|
+
...pt,
|
|
204
249
|
execute: (e, t) => {
|
|
205
250
|
let n = e;
|
|
206
|
-
return
|
|
251
|
+
return d.changeSeats(t.request.subject.tenantId ?? "", n.quantity).pipe(Y.map((e) => ({
|
|
207
252
|
plan: e.plan,
|
|
208
253
|
quantity: e.quantity,
|
|
209
254
|
prorationMinor: e.prorationMinor,
|
|
@@ -212,34 +257,34 @@ var $ = (e) => e === null ? null : {
|
|
|
212
257
|
}
|
|
213
258
|
},
|
|
214
259
|
{
|
|
215
|
-
...
|
|
216
|
-
execute: (e, t) =>
|
|
260
|
+
...dt,
|
|
261
|
+
execute: (e, t) => d.cancelSubscription(t.request.subject.tenantId ?? "").pipe(Y.map((e) => ({ subscription: Q(e) })))
|
|
217
262
|
},
|
|
218
263
|
{
|
|
219
|
-
...
|
|
220
|
-
execute: (e, t) =>
|
|
264
|
+
...xt,
|
|
265
|
+
execute: (e, t) => d.syncTenant(t.request.subject.tenantId ?? "").pipe(Y.map((e) => ({ subscription: e === null ? null : Q(e) })))
|
|
221
266
|
},
|
|
222
267
|
{
|
|
223
|
-
...
|
|
224
|
-
execute: (e, t) =>
|
|
268
|
+
...yt,
|
|
269
|
+
execute: (e, t) => d.resumeSubscription(t.request.subject.tenantId ?? "").pipe(Y.map((e) => ({ subscription: Q(e) })))
|
|
225
270
|
}
|
|
226
|
-
].map(
|
|
271
|
+
].map(v), ae = (e, t) => ({
|
|
227
272
|
kind: "json",
|
|
228
273
|
status: e,
|
|
229
274
|
data: { error: t }
|
|
230
|
-
}),
|
|
275
|
+
}), oe = [{
|
|
231
276
|
method: "GET",
|
|
232
277
|
path: "/stats",
|
|
233
278
|
scope: "declaration",
|
|
234
279
|
description: "Billing config: provider, declared plans, enforced tags",
|
|
235
|
-
handler: () =>
|
|
280
|
+
handler: () => Y.succeed({
|
|
236
281
|
kind: "json",
|
|
237
282
|
data: {
|
|
238
283
|
provider: s.name,
|
|
239
284
|
supportsMeteredUsage: s.supportsMeteredUsage,
|
|
240
285
|
plans: o.planIds(),
|
|
241
286
|
enforce: t.enforce ? Object.keys(t.enforce) : [],
|
|
242
|
-
webhookPath:
|
|
287
|
+
webhookPath: q
|
|
243
288
|
}
|
|
244
289
|
})
|
|
245
290
|
}, {
|
|
@@ -247,11 +292,11 @@ var $ = (e) => e === null ? null : {
|
|
|
247
292
|
path: "/usage",
|
|
248
293
|
scope: "process",
|
|
249
294
|
description: "Pending (un-flushed) metered usage counters",
|
|
250
|
-
handler: () =>
|
|
295
|
+
handler: () => f.stores.usage.pending().pipe(Y.map((e) => ({
|
|
251
296
|
kind: "json",
|
|
252
297
|
data: { usage: e }
|
|
253
|
-
})),
|
|
254
|
-
}],
|
|
298
|
+
})), Y.catch((e) => Y.succeed(ae(500, `${e.source} failed`))))
|
|
299
|
+
}], se = [
|
|
255
300
|
{
|
|
256
301
|
schema: e,
|
|
257
302
|
import: {
|
|
@@ -273,126 +318,138 @@ var $ = (e) => e === null ? null : {
|
|
|
273
318
|
name: "SubscriptionLocked"
|
|
274
319
|
}
|
|
275
320
|
}
|
|
276
|
-
],
|
|
277
|
-
|
|
278
|
-
let
|
|
279
|
-
claimChange: () =>
|
|
321
|
+
], b = t.enforce, ce = b !== void 0 && Object.keys(b).length > 0 ? te(b, d) : void 0, x = t.metering;
|
|
322
|
+
x !== void 0 && Me(x);
|
|
323
|
+
let S = x !== void 0 && Object.keys(x).length > 0 ? ke(d, x) : void 0, C = x !== void 0 && Ae(x), w = { claim: void 0 }, T = x === void 0 ? void 0 : Oe(d, x, {
|
|
324
|
+
claimChange: () => w.claim,
|
|
280
325
|
onUngated: () => {
|
|
281
|
-
|
|
326
|
+
Y.runSync(Y.logWarning("metering: CDC meters are accruing PER PROCESS — with N replicas a tenant is billed N times. The framework did not hand this plugin a change claimer (expected on the memory store; on a SQL store this is a bug worth reporting).").pipe(Y.annotateLogs({ scope: "voltro:billing" })));
|
|
282
327
|
}
|
|
283
|
-
}),
|
|
328
|
+
}), E = At([S, ce].filter((e) => e !== void 0)), D, O, k = !1, A = !1, j, M, N = null, P = !1, F, I = {
|
|
284
329
|
info: (e, t) => {
|
|
285
330
|
console.info(e, t ?? {});
|
|
286
331
|
},
|
|
287
332
|
error: (e, t) => {
|
|
288
333
|
console.error(e, t ?? {});
|
|
289
334
|
}
|
|
290
|
-
},
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
335
|
+
}, L = (e) => {
|
|
336
|
+
k && M === void 0 && (M = setTimeout(() => {
|
|
337
|
+
M = void 0, R();
|
|
338
|
+
}, e), M.unref?.());
|
|
339
|
+
}, R = () => {
|
|
340
|
+
let e = s.listUndeliveredEvents;
|
|
341
|
+
if (!k || D === void 0 || e === void 0) return Promise.resolve();
|
|
342
|
+
if (j !== void 0) return j;
|
|
343
|
+
let t = F === void 0 ? 0 : 6e4 - (performance.now() - F);
|
|
344
|
+
return t > 0 ? (L(t), Promise.resolve()) : (j = Promise.resolve().then(async () => {
|
|
345
|
+
let t = !1, n = 0, r = 0, i = 0, a = /* @__PURE__ */ new Set();
|
|
294
346
|
try {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
347
|
+
for (let o = 0; o < 10 && k; o++) {
|
|
348
|
+
let o = N;
|
|
349
|
+
if (o !== null) {
|
|
350
|
+
if (a.has(o)) throw Error("The provider event cursor repeated.");
|
|
351
|
+
a.add(o);
|
|
352
|
+
}
|
|
353
|
+
let s = await Y.runPromise(e({
|
|
354
|
+
cursor: o,
|
|
355
|
+
limit: 100
|
|
356
|
+
}));
|
|
357
|
+
if (!Array.isArray(s.events) || s.events.length > 100 || s.nextCursor !== null && (typeof s.nextCursor != "string" || !s.nextCursor || s.nextCursor !== s.events.at(-1)?.id || s.nextCursor === o)) throw Error("The provider event page did not supply a bounded advancing cursor.");
|
|
358
|
+
for (let e of s.events) {
|
|
359
|
+
if (!k) return;
|
|
360
|
+
try {
|
|
361
|
+
await Y.runPromise(h(e)) === "processed" ? n++ : r++;
|
|
362
|
+
} catch {
|
|
363
|
+
i++, P = !0, I.error("billing catch-up: delivery remains retryable", { eventId: e.id });
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
if (N = s.nextCursor, N === null) {
|
|
367
|
+
t = P, P = !1;
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
t = !0;
|
|
371
|
+
}
|
|
372
|
+
I.info("billing catch-up", {
|
|
373
|
+
processed: n,
|
|
374
|
+
replayed: r,
|
|
375
|
+
failed: i,
|
|
376
|
+
continuation: N !== null
|
|
315
377
|
});
|
|
316
|
-
} catch
|
|
317
|
-
|
|
378
|
+
} catch {
|
|
379
|
+
t = !0, I.error("billing catch-up failed; the current page will be retried");
|
|
318
380
|
} finally {
|
|
319
|
-
|
|
381
|
+
F = performance.now(), j = void 0, t && L(6e4);
|
|
320
382
|
}
|
|
321
|
-
}
|
|
322
|
-
},
|
|
323
|
-
e !== void 0 && (
|
|
324
|
-
},
|
|
383
|
+
}), j);
|
|
384
|
+
}, z = (e) => {
|
|
385
|
+
e !== void 0 && (I = e), !A && k && D !== void 0 && (A = !0, R());
|
|
386
|
+
}, B = [
|
|
325
387
|
"store:write",
|
|
326
388
|
"inspect:read",
|
|
327
389
|
"inspect:write",
|
|
328
390
|
"network:outbound:*",
|
|
329
|
-
...
|
|
391
|
+
...E === void 0 ? [] : [
|
|
330
392
|
"rpc:intercept:mutation",
|
|
331
393
|
"rpc:intercept:action",
|
|
332
394
|
"rpc:intercept:workflow"
|
|
333
395
|
],
|
|
334
|
-
...
|
|
335
|
-
...
|
|
396
|
+
...S === void 0 ? [] : ["rpc:intercept:query"],
|
|
397
|
+
...C ? ["store:changes:read"] : []
|
|
336
398
|
];
|
|
337
|
-
return
|
|
338
|
-
name:
|
|
339
|
-
base:
|
|
399
|
+
return jt({
|
|
400
|
+
name: Mt({
|
|
401
|
+
base: $,
|
|
340
402
|
alias: t.alias,
|
|
341
403
|
instance: t.name
|
|
342
404
|
}),
|
|
343
|
-
baseName:
|
|
405
|
+
baseName: $,
|
|
344
406
|
description: "Billing — subscriptions, plans, entitlements + usage metering over a pluggable BillingProvider (Stripe + mock). Ships the BillingService, the requireEntitlement() in-handler guard + the enforce-map interceptor, the /billing/webhook receiver (riding @voltro/plugin-webhooks for signature + idempotency), and the _voltro_billing_* tables. Money is integer minor units.",
|
|
345
|
-
permissions:
|
|
346
|
-
declaredEnv:
|
|
347
|
-
egress:
|
|
348
|
-
services:
|
|
407
|
+
permissions: B,
|
|
408
|
+
declaredEnv: Rt.declared,
|
|
409
|
+
egress: rt(s),
|
|
410
|
+
services: ne,
|
|
349
411
|
routes: ie,
|
|
350
|
-
rpcClientDescriptors:
|
|
351
|
-
httpRoutes: [
|
|
352
|
-
inspectEndpoints:
|
|
353
|
-
extendSchema: { tables: [
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
...P === void 0 ? {} : {
|
|
360
|
-
interceptMutation: P,
|
|
361
|
-
interceptAction: P,
|
|
362
|
-
interceptWorkflow: P
|
|
412
|
+
rpcClientDescriptors: ut,
|
|
413
|
+
httpRoutes: [_],
|
|
414
|
+
inspectEndpoints: oe,
|
|
415
|
+
extendSchema: { tables: [...W(), Ie] },
|
|
416
|
+
errorSchemas: se,
|
|
417
|
+
...E === void 0 ? {} : {
|
|
418
|
+
interceptMutation: E,
|
|
419
|
+
interceptAction: E,
|
|
420
|
+
interceptWorkflow: E
|
|
363
421
|
},
|
|
364
|
-
...
|
|
365
|
-
...
|
|
422
|
+
...S === void 0 ? {} : { interceptQuery: S },
|
|
423
|
+
...C ? { onChangeEvent: T } : {},
|
|
366
424
|
bindDataStore: (e, t) => {
|
|
367
|
-
|
|
425
|
+
f.stores = G(e), D = e, p = Lt(e), z(), w.claim = t?.claimChange;
|
|
368
426
|
},
|
|
369
|
-
onActivate: (e) =>
|
|
427
|
+
onActivate: (e) => Y.sync(() => {
|
|
370
428
|
e.logger.info("billing active", {
|
|
371
429
|
provider: s.name,
|
|
372
430
|
plans: o.planIds().length,
|
|
373
|
-
enforce:
|
|
374
|
-
metering:
|
|
375
|
-
webhook:
|
|
431
|
+
enforce: b ? Object.keys(b).length : 0,
|
|
432
|
+
metering: x ? Object.keys(x).length : 0,
|
|
433
|
+
webhook: q,
|
|
376
434
|
redirectOrigins: t.redirectOrigins?.length ?? "any"
|
|
377
435
|
}), s.name === "stripe" && t.redirectOrigins === void 0 && e.logger.warn("billing: no redirectOrigins — checkout and portal accept any return URL; set billingPlugin({ redirectOrigins })", {});
|
|
378
|
-
let n = t.flushIntervalMs ?? 6e4, r =
|
|
436
|
+
let n = t.flushIntervalMs ?? 6e4, r = x, i = r !== void 0 && Object.keys(r).length > 0;
|
|
379
437
|
if (n > 0) {
|
|
380
|
-
let e =
|
|
381
|
-
|
|
382
|
-
let t =
|
|
438
|
+
let e = It();
|
|
439
|
+
O = setInterval(() => {
|
|
440
|
+
let t = D;
|
|
383
441
|
if (t === void 0) return;
|
|
384
442
|
let a = Date.now();
|
|
385
443
|
(async () => {
|
|
386
|
-
await
|
|
444
|
+
await Le(t, Re(a, n), e, a) && await Y.runPromise((i ? je(d, t, r) : d.flushUsage()).pipe(Y.catch(() => Y.void)));
|
|
387
445
|
})();
|
|
388
|
-
}, n),
|
|
446
|
+
}, n), O.unref?.();
|
|
389
447
|
}
|
|
390
|
-
|
|
448
|
+
k = !0, z(e.logger);
|
|
391
449
|
}),
|
|
392
|
-
onDeactivate: () =>
|
|
393
|
-
|
|
450
|
+
onDeactivate: () => Y.promise(async () => {
|
|
451
|
+
k = !1, A = !1, M !== void 0 && (clearTimeout(M), M = void 0), O !== void 0 && (clearInterval(O), O = void 0), await j;
|
|
394
452
|
})
|
|
395
453
|
});
|
|
396
454
|
};
|
|
397
|
-
|
|
398
|
-
export { l as BILLING_CUSTOMERS_TABLE, ee as BILLING_DUNNING_NOTICES_TABLE, F as BILLING_FLUSH_CLAIMS_TABLE, u as BILLING_INVOICES_TABLE, d as BILLING_SUBSCRIPTIONS_TABLE, f as BILLING_USAGE_TABLE, Ce as BILLING_WEBHOOK_ID, Y as BILLING_WEBHOOK_PATH, e as BillingError, t as BillingService, te as DEFAULT_DUNNING_STEPS, ne as DEFAULT_GRACE_HOURS, re as DEFAULT_LOCKOUT, n as DEFAULT_PLAN, v as DUNNING_LOCK_STEP_ID, r as EntitlementExceeded, z as STRIPE_API_VERSION, B as STRIPE_DASHBOARD_REMINDERS, he as STRIPE_WEBHOOK_EVENTS, de as StripeRestError, i as SubscriptionLocked, ve as assertBillingProductionReady, p as billingCustomersTable, y as billingDunningNoticesTable, ye as billingEgressOf, I as billingFlushClaimsTable, m as billingInvoicesTable, et as billingPlugin, A as billingServiceLayer, h as billingSubscriptionsTable, g as billingTables, _ as billingUsageTable, we as billingWebhookDescriptor, j as buildBillingService, a as buildEnforceInterceptor, N as buildPlanRegistry, L as claimFlushWindow, ie as dataStoreDunningNoticeStore, ae as dataStoreStores, b as defaultDunningEmail, V as diffMeter, H as diffPortal, U as diffPrice, W as diffProduct, G as diffTaxSettings, K as diffWebhook, x as dueSteps, S as dunningMailNotifier, P as emptyPlanRegistry, ze as envOutRefusal, C as episodeKeyOf, w as evaluateBillingEntitlement, o as evaluateEntitlement, R as flushWindowKey, fe as formEncode, T as graceEndOf, be as isProductionBoot, O as isStaleStatusEvent, E as memoryDunningNoticeStore, k as memoryStores, Be as mergeEnvFile, xe as mockProvider, Te as mountBillingWebhook, ge as normalizeStripeEvent, Ve as openFindings, He as parseProvisionArgs, M as periodKey, q as portalParams, Ue as provisionStripeCatalog, pe as redactStripeKeys, s as requireEntitled, c as requireEntitlement, D as resolveDunningConfig, Se as resolveProvider, We as resolveProvisionKey, Ge as runStripeProvision, J as sellingReadiness, _e as stripeProvider, me as stripeRest };
|
|
455
|
+
export { D as BILLING_CHECKOUT_OPERATIONS_TABLE, j as BILLING_CLOSE_OPERATIONS_TABLE, o as BILLING_CUSTODY_INVENTORY_TABLES, _e as BILLING_CUSTOMERS_TABLE, c as BILLING_CUSTOMER_ACCOUNTS_TABLE, l as BILLING_CUSTOMER_CUSTODY_TABLE, le as BILLING_DUNNING_NOTICES_TABLE, Fe as BILLING_FLUSH_CLAIMS_TABLE, ve as BILLING_INVOICES_TABLE, ce as BILLING_INVOICE_HISTORY_DISPATCH_TABLE, p as BILLING_INVOICE_HISTORY_PAGES_TABLE, m as BILLING_INVOICE_HISTORY_REFERENCES_TABLE, x as BILLING_INVOICE_HISTORY_SCAN_ACCOUNTS_TABLE, h as BILLING_INVOICE_HISTORY_WALKS_TABLE, oe as BILLING_INVOICE_HISTORY_WORK_TABLE, re as BILLING_INVOICE_OBSERVATIONS_TABLE, H as BILLING_SUBSCRIPTIONS_TABLE, T as BILLING_USAGE_EVENTS_TABLE, U as BILLING_USAGE_TABLE, st as BILLING_WEBHOOK_ID, q as BILLING_WEBHOOK_PATH, e as BillingError, t as BillingService, F as DEFAULT_DUNNING_STEPS, I as DEFAULT_GRACE_HOURS, L as DEFAULT_LOCKOUT, n as DEFAULT_PLAN, R as DUNNING_LOCK_STEP_ID, r as EntitlementExceeded, ze as STRIPE_API_VERSION, Be as STRIPE_DASHBOARD_REMINDERS, $e as STRIPE_WEBHOOK_EVENTS, Ye as StripeRestError, i as SubscriptionLocked, nt as assertBillingProductionReady, O as billingCheckoutOperationsTable, M as billingCloseOperationsTable, u as billingCustomerAccountsTable, ee as billingCustomerCustodyTable, ye as billingCustomersTable, z as billingDunningNoticesTable, rt as billingEgressOf, Ie as billingFlushClaimsTable, S as billingInvoiceHistoryDispatchTable, g as billingInvoiceHistoryPagesTable, _ as billingInvoiceHistoryReferencesTable, C as billingInvoiceHistoryScanAccountsTable, v as billingInvoiceHistoryWalksTable, se as billingInvoiceHistoryWorkTable, ie as billingInvoiceObservationsTable, be as billingInvoicesTable, zt as billingPlugin, ae as billingRetainedInvoiceObservationsTable, K as billingServiceLayer, xe as billingSubscriptionsTable, W as billingTables, E as billingUsageEventsTable, Se as billingUsageTable, ct as billingWebhookDescriptor, Ee as buildBillingService, te as buildEnforceInterceptor, Ne as buildPlanRegistry, Le as claimFlushWindow, N as dataStoreBillingCloseStore, k as dataStoreCheckoutOperationStore, B as dataStoreDunningNoticeStore, y as dataStoreInvoiceHistoryJournal, w as dataStoreInvoiceHistoryProgressStore, b as dataStoreInvoiceHistoryWorkStore, G as dataStoreStores, ue as defaultDunningEmail, Ve as diffMeter, He as diffPortal, Ue as diffPrice, We as diffProduct, Ge as diffTaxSettings, Ke as diffWebhook, de as dueSteps, fe as dunningMailNotifier, Pe as emptyPlanRegistry, St as envOutRefusal, pe as episodeKeyOf, me as evaluateBillingEntitlement, d as evaluateEntitlement, Re as flushWindowKey, Xe as formEncode, he as graceEndOf, s as inspectBillingCustody, it as isProductionBoot, Ce as isStaleStatusEvent, P as memoryBillingCloseStore, A as memoryCheckoutOperationStore, ge as memoryDunningNoticeStore, we as memoryStores, Ct as mergeEnvFile, at as mockProvider, lt as mountBillingWebhook, et as normalizeStripeEvent, wt as openFindings, Tt as parseProvisionArgs, De as periodKey, qe as portalParams, Et as provisionStripeCatalog, Ze as redactStripeKeys, f as requireEntitled, ne as requireEntitlement, V as resolveDunningConfig, ot as resolveProvider, Dt as resolveProvisionKey, Ot as runStripeProvision, Te as selectCurrentSubscription, Je as sellingReadiness, tt as stripeProvider, Qe as stripeRest };
|