@voltro/plugin-billing 0.5.0 → 0.6.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 +48 -1
- package/README.md +1 -1
- package/THIRD-PARTY-NOTICES.md +28 -1
- package/dist/index.d.ts +149 -184
- package/dist/index.js +601 -581
- package/dist/rpc.d.ts +30 -0
- package/dist/rpc.js +42 -4
- package/dist/types.d.ts +95 -40
- package/package.json +8 -7
package/dist/index.js
CHANGED
|
@@ -1,222 +1,165 @@
|
|
|
1
1
|
import { BillingError as e, BillingService as t, DEFAULT_PLAN as n, EntitlementExceeded as r } from "./types.js";
|
|
2
|
-
import { billingRpcClientImports as i, changePlanDescriptor as a, changeSeatsDescriptor as o,
|
|
3
|
-
import { Effect as
|
|
4
|
-
import { pluginEnv as
|
|
5
|
-
import { composeRpcInterceptors as
|
|
6
|
-
import { and as
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
2
|
+
import { billingRpcClientImports as i, changePlanDescriptor as a, changeSeatsDescriptor as o, invoicesDescriptor as s, portalUrlDescriptor as c, previewChangeDescriptor as l, reportUsageDescriptor as u, startCheckoutDescriptor as ee, subscriptionDescriptor as d } from "./rpc.js";
|
|
3
|
+
import { Effect as f, Layer as p, Schedule as m, Schema as h } from "effect";
|
|
4
|
+
import { pluginEnv as g } from "@voltro/env";
|
|
5
|
+
import { composeRpcInterceptors as te, definePlugin as ne } from "@voltro/protocol";
|
|
6
|
+
import { and as _, eq as v, gte as re, id as y, integer as b, registerRetention as x, retentionTtlMsFromEnv as ie, table as S, text as C, timestamp as w } from "@voltro/database";
|
|
7
|
+
import T from "stripe";
|
|
8
|
+
import { defineIncomingWebhook as E, mountIncomingWebhook as D } from "@voltro/plugin-webhooks";
|
|
9
|
+
import { stripeProvider as O } from "@voltro/plugin-webhooks/providers";
|
|
10
|
+
import { createLogger as k } from "@voltro/logger";
|
|
10
11
|
//#region src/entitlement.ts
|
|
11
|
-
var
|
|
12
|
+
var A = (e, t, n, r) => ({
|
|
12
13
|
allowed: !Number.isFinite(t) || r <= 0 || n + r <= t,
|
|
13
14
|
entitlement: e,
|
|
14
15
|
limit: t,
|
|
15
16
|
used: n,
|
|
16
17
|
cost: r
|
|
17
|
-
}),
|
|
18
|
-
let a =
|
|
19
|
-
if (a === null) return i <= 0 ? void 0 : yield*
|
|
18
|
+
}), j = (e) => e.tenantId, M = (e, n, i) => f.gen(function* () {
|
|
19
|
+
let a = j(e.request.subject);
|
|
20
|
+
if (a === null) return i <= 0 ? void 0 : yield* f.fail(new r({
|
|
20
21
|
entitlement: n,
|
|
21
22
|
limit: 0,
|
|
22
23
|
used: 0,
|
|
23
24
|
cost: i
|
|
24
25
|
}));
|
|
25
26
|
yield* (yield* t).consumeEntitlement(a, n, i);
|
|
26
|
-
}),
|
|
27
|
+
}), N = (e, t) => (n, i) => {
|
|
27
28
|
let a = e[i.tag];
|
|
28
29
|
if (a === void 0) return n;
|
|
29
30
|
let o = a.cost ?? 1, s = i.subject.tenantId;
|
|
30
|
-
return s === null ? o <= 0 ? n :
|
|
31
|
+
return s === null ? o <= 0 ? n : f.fail(new r({
|
|
31
32
|
entitlement: a.entitlement,
|
|
32
33
|
limit: 0,
|
|
33
34
|
used: 0,
|
|
34
35
|
cost: o
|
|
35
|
-
})) :
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
let n = t.attempt + 1, r = P(t.startedAt, n, e.schedule);
|
|
74
|
-
return r === null ? (yield* e.dunning.advance(t.providerSubscriptionId, t.attempt, n, t.nextRetryAt)) ? (yield* e.dunning.close(t.providerSubscriptionId), yield* e.subscriptions.setStatus(t.providerSubscriptionId, "canceled"), "canceled") : null : (yield* e.dunning.advance(t.providerSubscriptionId, t.attempt, n, r)) ? "retried" : null;
|
|
75
|
-
}), de = (e, t) => d.gen(function* () {
|
|
76
|
-
let n = yield* e.dunning.due(t), r = 0, i = 0;
|
|
77
|
-
for (let t of n) {
|
|
78
|
-
let n = yield* ue(e, t);
|
|
79
|
-
n === "retried" ? r++ : n === "canceled" && i++;
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
retried: r,
|
|
83
|
-
canceled: i
|
|
84
|
-
};
|
|
85
|
-
}), F = "_voltro_billing_customers", I = "_voltro_billing_subscriptions", L = "_voltro_billing_invoices", R = "_voltro_billing_usage", z = "_voltro_billing_dunning", fe = C(F, {
|
|
86
|
-
id: v({ prefix: "bcust" }),
|
|
87
|
-
tenantId: w(),
|
|
88
|
-
provider: w(),
|
|
89
|
-
providerCustomerId: w(),
|
|
90
|
-
createdAt: T(),
|
|
91
|
-
updatedAt: T()
|
|
92
|
-
}).index("byBillingCustomerTenant", ["tenantId"]).index("byBillingProviderCustomer", ["providerCustomerId"]), pe = C(I, {
|
|
93
|
-
id: v({ prefix: "bsub" }),
|
|
94
|
-
tenantId: w(),
|
|
95
|
-
provider: w(),
|
|
96
|
-
providerSubscriptionId: w(),
|
|
97
|
-
plan: w(),
|
|
98
|
-
status: w(),
|
|
99
|
-
quantity: y().default(1),
|
|
100
|
-
currentPeriodStart: T().nullable(),
|
|
101
|
-
currentPeriodEnd: T().nullable(),
|
|
102
|
-
cancelAt: T().nullable(),
|
|
103
|
-
createdAt: T(),
|
|
104
|
-
updatedAt: T()
|
|
105
|
-
}).index("byBillingSubscriptionTenant", ["tenantId"]).index("byBillingProviderSubscription", ["providerSubscriptionId"]), me = C(L, {
|
|
106
|
-
id: v({ prefix: "binv" }),
|
|
107
|
-
tenantId: w(),
|
|
108
|
-
provider: w(),
|
|
109
|
-
providerInvoiceId: w(),
|
|
110
|
-
amountMinor: y(),
|
|
111
|
-
currency: w(),
|
|
112
|
-
status: w(),
|
|
113
|
-
createdAt: T()
|
|
114
|
-
}).index("byBillingInvoiceTenant", ["tenantId"]).index("byBillingProviderInvoice", ["providerInvoiceId"]), he = C(R, {
|
|
115
|
-
id: v({ prefix: "buse" }),
|
|
116
|
-
tenantId: w().maxLength(191),
|
|
117
|
-
entitlementKey: w().maxLength(191),
|
|
118
|
-
period: w().maxLength(16),
|
|
119
|
-
used: y().default(0),
|
|
120
|
-
reportedToProvider: y().default(0),
|
|
121
|
-
updatedAt: T()
|
|
36
|
+
})) : f.flatMap(t.consumeEntitlement(s, a.entitlement, o), () => n);
|
|
37
|
+
}, P = "_voltro_billing_customers", F = "_voltro_billing_subscriptions", I = "_voltro_billing_invoices", L = "_voltro_billing_usage", ae = S(P, {
|
|
38
|
+
id: y({ prefix: "bcust" }),
|
|
39
|
+
tenantId: C(),
|
|
40
|
+
provider: C(),
|
|
41
|
+
providerCustomerId: C(),
|
|
42
|
+
createdAt: w(),
|
|
43
|
+
updatedAt: w()
|
|
44
|
+
}).index("byBillingCustomerTenant", ["tenantId"]).index("byBillingProviderCustomer", ["providerCustomerId"]), oe = S(F, {
|
|
45
|
+
id: y({ prefix: "bsub" }),
|
|
46
|
+
tenantId: C(),
|
|
47
|
+
provider: C(),
|
|
48
|
+
providerSubscriptionId: C(),
|
|
49
|
+
plan: C(),
|
|
50
|
+
status: C(),
|
|
51
|
+
quantity: b().default(1),
|
|
52
|
+
currentPeriodStart: w().nullable(),
|
|
53
|
+
currentPeriodEnd: w().nullable(),
|
|
54
|
+
cancelAt: w().nullable(),
|
|
55
|
+
createdAt: w(),
|
|
56
|
+
updatedAt: w()
|
|
57
|
+
}).index("byBillingSubscriptionTenant", ["tenantId"]).index("byBillingProviderSubscription", ["providerSubscriptionId"]), se = S(I, {
|
|
58
|
+
id: y({ prefix: "binv" }),
|
|
59
|
+
tenantId: C(),
|
|
60
|
+
provider: C(),
|
|
61
|
+
providerInvoiceId: C(),
|
|
62
|
+
amountMinor: b(),
|
|
63
|
+
currency: C(),
|
|
64
|
+
status: C(),
|
|
65
|
+
createdAt: w()
|
|
66
|
+
}).index("byBillingInvoiceTenant", ["tenantId"]).index("byBillingProviderInvoice", ["providerInvoiceId"]), ce = S(L, {
|
|
67
|
+
id: y({ prefix: "buse" }),
|
|
68
|
+
tenantId: C().maxLength(191),
|
|
69
|
+
entitlementKey: C().maxLength(191),
|
|
70
|
+
period: C().maxLength(16),
|
|
71
|
+
used: b().default(0),
|
|
72
|
+
reportedToProvider: b().default(0),
|
|
73
|
+
updatedAt: w()
|
|
122
74
|
}).unique("byBillingUsageWindow", [
|
|
123
75
|
"tenantId",
|
|
124
76
|
"entitlementKey",
|
|
125
77
|
"period"
|
|
126
|
-
]),
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
startedAt: T(),
|
|
133
|
-
updatedAt: T()
|
|
134
|
-
}).unique("byBillingDunningSubscription", ["providerSubscriptionId"]).index("byBillingDunningTenant", ["tenantId"]), _e = () => [
|
|
135
|
-
fe,
|
|
136
|
-
pe,
|
|
137
|
-
me,
|
|
138
|
-
he,
|
|
139
|
-
ge
|
|
140
|
-
], B = (e) => `${e}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`, V = (t, n) => d.tryPromise({
|
|
78
|
+
]), le = () => [
|
|
79
|
+
ae,
|
|
80
|
+
oe,
|
|
81
|
+
se,
|
|
82
|
+
ce
|
|
83
|
+
], R = (e) => `${e}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`, z = (t, n) => f.tryPromise({
|
|
141
84
|
try: t,
|
|
142
85
|
catch: (t) => new e({
|
|
143
86
|
source: n,
|
|
144
87
|
message: String(t?.message ?? t),
|
|
145
88
|
transient: !0
|
|
146
89
|
})
|
|
147
|
-
}),
|
|
90
|
+
}), B = (e) => ({
|
|
148
91
|
table: e.table,
|
|
149
92
|
predicate: e.predicate,
|
|
150
93
|
order: e.order ?? [],
|
|
151
94
|
take: e.take,
|
|
152
95
|
skip: void 0,
|
|
153
96
|
projection: void 0
|
|
154
|
-
}),
|
|
97
|
+
}), ue = () => {
|
|
155
98
|
let e = /* @__PURE__ */ new Map();
|
|
156
99
|
return {
|
|
157
|
-
upsert: (t) =>
|
|
100
|
+
upsert: (t) => f.sync(() => {
|
|
158
101
|
e.set(t.tenantId, t);
|
|
159
102
|
}),
|
|
160
|
-
getByTenant: (t) =>
|
|
103
|
+
getByTenant: (t) => f.sync(() => e.get(t) ?? null)
|
|
161
104
|
};
|
|
162
|
-
},
|
|
105
|
+
}, de = (e) => ({
|
|
163
106
|
tenantId: String(e.tenantId),
|
|
164
107
|
provider: String(e.provider),
|
|
165
108
|
providerCustomerId: String(e.providerCustomerId)
|
|
166
|
-
}),
|
|
167
|
-
upsert: (t) =>
|
|
168
|
-
let n = await e.query(
|
|
169
|
-
table:
|
|
170
|
-
predicate:
|
|
109
|
+
}), fe = (e) => ({
|
|
110
|
+
upsert: (t) => z(async () => {
|
|
111
|
+
let n = await e.query(B({
|
|
112
|
+
table: P,
|
|
113
|
+
predicate: v("tenantId", t.tenantId),
|
|
171
114
|
take: 1
|
|
172
115
|
})), r = /* @__PURE__ */ new Date();
|
|
173
|
-
n[0] ? await e.update(
|
|
116
|
+
n[0] ? await e.update(P, String(n[0].id), {
|
|
174
117
|
provider: t.provider,
|
|
175
118
|
providerCustomerId: t.providerCustomerId,
|
|
176
119
|
updatedAt: r
|
|
177
|
-
}) : await e.insert(
|
|
178
|
-
id:
|
|
120
|
+
}) : await e.insert(P, {
|
|
121
|
+
id: R("bcust"),
|
|
179
122
|
...t,
|
|
180
123
|
createdAt: r,
|
|
181
124
|
updatedAt: r
|
|
182
125
|
});
|
|
183
126
|
}, "customerStore"),
|
|
184
|
-
getByTenant: (t) =>
|
|
185
|
-
let n = await e.query(
|
|
186
|
-
table:
|
|
187
|
-
predicate:
|
|
127
|
+
getByTenant: (t) => z(async () => {
|
|
128
|
+
let n = await e.query(B({
|
|
129
|
+
table: P,
|
|
130
|
+
predicate: v("tenantId", t),
|
|
188
131
|
take: 1
|
|
189
132
|
}));
|
|
190
|
-
return n[0] ?
|
|
133
|
+
return n[0] ? de(n[0]) : null;
|
|
191
134
|
}, "customerStore")
|
|
192
|
-
}),
|
|
135
|
+
}), pe = () => {
|
|
193
136
|
let e = /* @__PURE__ */ new Map();
|
|
194
137
|
return {
|
|
195
|
-
upsert: (t) =>
|
|
138
|
+
upsert: (t) => f.sync(() => {
|
|
196
139
|
e.set(t.tenantId, t);
|
|
197
140
|
}),
|
|
198
|
-
getByTenant: (t) =>
|
|
199
|
-
markCanceled: (t) =>
|
|
141
|
+
getByTenant: (t) => f.sync(() => e.get(t) ?? null),
|
|
142
|
+
markCanceled: (t) => f.sync(() => {
|
|
200
143
|
for (let [n, r] of e) r.providerSubscriptionId === t && e.set(n, {
|
|
201
144
|
...r,
|
|
202
145
|
status: "canceled"
|
|
203
146
|
});
|
|
204
147
|
}),
|
|
205
|
-
patchByTenant: (t, n) =>
|
|
148
|
+
patchByTenant: (t, n) => f.sync(() => {
|
|
206
149
|
let r = e.get(t);
|
|
207
150
|
r && e.set(t, {
|
|
208
151
|
...r,
|
|
209
152
|
...n
|
|
210
153
|
});
|
|
211
154
|
}),
|
|
212
|
-
setStatus: (t, n) =>
|
|
155
|
+
setStatus: (t, n) => f.sync(() => {
|
|
213
156
|
for (let [r, i] of e) i.providerSubscriptionId === t && e.set(r, {
|
|
214
157
|
...i,
|
|
215
158
|
status: n
|
|
216
159
|
});
|
|
217
160
|
})
|
|
218
161
|
};
|
|
219
|
-
},
|
|
162
|
+
}, me = (e) => ({
|
|
220
163
|
tenantId: String(e.tenantId),
|
|
221
164
|
provider: String(e.provider),
|
|
222
165
|
providerSubscriptionId: String(e.providerSubscriptionId),
|
|
@@ -226,14 +169,14 @@ var k = (e, t, n, r) => ({
|
|
|
226
169
|
currentPeriodStart: e.currentPeriodStart == null ? null : new Date(e.currentPeriodStart),
|
|
227
170
|
currentPeriodEnd: e.currentPeriodEnd == null ? null : new Date(e.currentPeriodEnd),
|
|
228
171
|
cancelAt: e.cancelAt == null ? null : new Date(e.cancelAt)
|
|
229
|
-
}),
|
|
172
|
+
}), V = async (e, t) => (await e.query(B({
|
|
230
173
|
table: "_voltro_billing_subscriptions",
|
|
231
|
-
predicate:
|
|
174
|
+
predicate: v("providerSubscriptionId", t),
|
|
232
175
|
take: 1
|
|
233
|
-
})))[0] ?? null,
|
|
234
|
-
upsert: (t) =>
|
|
235
|
-
let n = await
|
|
236
|
-
n ? await e.update(
|
|
176
|
+
})))[0] ?? null, he = (e) => ({
|
|
177
|
+
upsert: (t) => z(async () => {
|
|
178
|
+
let n = await V(e, t.providerSubscriptionId), r = /* @__PURE__ */ new Date();
|
|
179
|
+
n ? await e.update(F, String(n.id), {
|
|
237
180
|
tenantId: t.tenantId,
|
|
238
181
|
provider: t.provider,
|
|
239
182
|
plan: t.plan,
|
|
@@ -243,8 +186,8 @@ var k = (e, t, n, r) => ({
|
|
|
243
186
|
currentPeriodEnd: t.currentPeriodEnd,
|
|
244
187
|
cancelAt: t.cancelAt,
|
|
245
188
|
updatedAt: r
|
|
246
|
-
}) : await e.insert(
|
|
247
|
-
id:
|
|
189
|
+
}) : await e.insert(F, {
|
|
190
|
+
id: R("bsub"),
|
|
248
191
|
tenantId: t.tenantId,
|
|
249
192
|
provider: t.provider,
|
|
250
193
|
providerSubscriptionId: t.providerSubscriptionId,
|
|
@@ -258,95 +201,95 @@ var k = (e, t, n, r) => ({
|
|
|
258
201
|
updatedAt: r
|
|
259
202
|
});
|
|
260
203
|
}, "subscriptionStore"),
|
|
261
|
-
getByTenant: (t) =>
|
|
262
|
-
let n = await e.query(
|
|
263
|
-
table:
|
|
264
|
-
predicate:
|
|
204
|
+
getByTenant: (t) => z(async () => {
|
|
205
|
+
let n = await e.query(B({
|
|
206
|
+
table: F,
|
|
207
|
+
predicate: v("tenantId", t),
|
|
265
208
|
order: [{
|
|
266
209
|
column: "updatedAt",
|
|
267
210
|
direction: "desc"
|
|
268
211
|
}],
|
|
269
212
|
take: 1
|
|
270
213
|
}));
|
|
271
|
-
return n[0] ?
|
|
214
|
+
return n[0] ? me(n[0]) : null;
|
|
272
215
|
}, "subscriptionStore"),
|
|
273
|
-
markCanceled: (t) =>
|
|
274
|
-
let n = await
|
|
275
|
-
n && await e.update(
|
|
216
|
+
markCanceled: (t) => z(async () => {
|
|
217
|
+
let n = await V(e, t);
|
|
218
|
+
n && await e.update(F, String(n.id), {
|
|
276
219
|
status: "canceled",
|
|
277
220
|
updatedAt: /* @__PURE__ */ new Date()
|
|
278
221
|
});
|
|
279
222
|
}, "subscriptionStore"),
|
|
280
|
-
patchByTenant: (t, n) =>
|
|
281
|
-
let r = (await e.query(
|
|
282
|
-
table:
|
|
283
|
-
predicate:
|
|
223
|
+
patchByTenant: (t, n) => z(async () => {
|
|
224
|
+
let r = (await e.query(B({
|
|
225
|
+
table: F,
|
|
226
|
+
predicate: v("tenantId", t),
|
|
284
227
|
order: [{
|
|
285
228
|
column: "updatedAt",
|
|
286
229
|
direction: "desc"
|
|
287
230
|
}],
|
|
288
231
|
take: 1
|
|
289
232
|
})))[0];
|
|
290
|
-
r && await e.update(
|
|
233
|
+
r && await e.update(F, String(r.id), {
|
|
291
234
|
...n.plan === void 0 ? {} : { plan: n.plan },
|
|
292
235
|
...n.quantity === void 0 ? {} : { quantity: n.quantity },
|
|
293
236
|
...n.status === void 0 ? {} : { status: n.status },
|
|
294
237
|
updatedAt: /* @__PURE__ */ new Date()
|
|
295
238
|
});
|
|
296
239
|
}, "subscriptionStore"),
|
|
297
|
-
setStatus: (t, n) =>
|
|
298
|
-
let r = await
|
|
299
|
-
r && await e.update(
|
|
240
|
+
setStatus: (t, n) => z(async () => {
|
|
241
|
+
let r = await V(e, t);
|
|
242
|
+
r && await e.update(F, String(r.id), {
|
|
300
243
|
status: n,
|
|
301
244
|
updatedAt: /* @__PURE__ */ new Date()
|
|
302
245
|
});
|
|
303
246
|
}, "subscriptionStore")
|
|
304
|
-
}),
|
|
247
|
+
}), ge = () => {
|
|
305
248
|
let e = /* @__PURE__ */ new Map();
|
|
306
249
|
return {
|
|
307
|
-
upsert: (t) =>
|
|
250
|
+
upsert: (t) => f.sync(() => {
|
|
308
251
|
e.set(t.providerInvoiceId, t);
|
|
309
252
|
}),
|
|
310
|
-
listByTenant: (t) =>
|
|
253
|
+
listByTenant: (t) => f.sync(() => [...e.values()].filter((e) => e.tenantId === t))
|
|
311
254
|
};
|
|
312
|
-
},
|
|
255
|
+
}, _e = (e) => ({
|
|
313
256
|
tenantId: String(e.tenantId),
|
|
314
257
|
provider: String(e.provider),
|
|
315
258
|
providerInvoiceId: String(e.providerInvoiceId),
|
|
316
259
|
amountMinor: Number(e.amountMinor),
|
|
317
260
|
currency: String(e.currency),
|
|
318
261
|
status: String(e.status)
|
|
319
|
-
}),
|
|
320
|
-
upsert: (t) =>
|
|
321
|
-
let n = await e.query(
|
|
322
|
-
table:
|
|
323
|
-
predicate:
|
|
262
|
+
}), ve = (e) => ({
|
|
263
|
+
upsert: (t) => z(async () => {
|
|
264
|
+
let n = await e.query(B({
|
|
265
|
+
table: I,
|
|
266
|
+
predicate: v("providerInvoiceId", t.providerInvoiceId),
|
|
324
267
|
take: 1
|
|
325
268
|
}));
|
|
326
|
-
n[0] ? await e.update(
|
|
269
|
+
n[0] ? await e.update(I, String(n[0].id), {
|
|
327
270
|
amountMinor: t.amountMinor,
|
|
328
271
|
currency: t.currency,
|
|
329
272
|
status: t.status
|
|
330
|
-
}) : await e.insert(
|
|
331
|
-
id:
|
|
273
|
+
}) : await e.insert(I, {
|
|
274
|
+
id: R("binv"),
|
|
332
275
|
...t,
|
|
333
276
|
createdAt: /* @__PURE__ */ new Date()
|
|
334
277
|
});
|
|
335
278
|
}, "invoiceStore"),
|
|
336
|
-
listByTenant: (t) =>
|
|
337
|
-
table:
|
|
338
|
-
predicate:
|
|
279
|
+
listByTenant: (t) => z(async () => (await e.query(B({
|
|
280
|
+
table: I,
|
|
281
|
+
predicate: v("tenantId", t),
|
|
339
282
|
order: [{
|
|
340
283
|
column: "createdAt",
|
|
341
284
|
direction: "desc"
|
|
342
285
|
}]
|
|
343
|
-
}))).map(
|
|
344
|
-
}),
|
|
286
|
+
}))).map(_e), "invoiceStore")
|
|
287
|
+
}), H = (e, t, n) => `${e}${t}${n}`, ye = () => {
|
|
345
288
|
let e = /* @__PURE__ */ new Map();
|
|
346
289
|
return {
|
|
347
|
-
used: (t, n, r) =>
|
|
348
|
-
consume: (t, n, r, i, a) =>
|
|
349
|
-
let o =
|
|
290
|
+
used: (t, n, r) => f.sync(() => e.get(H(t, n, r))?.used ?? 0),
|
|
291
|
+
consume: (t, n, r, i, a) => f.sync(() => {
|
|
292
|
+
let o = H(t, n, r), s = e.get(o), c = s?.used ?? 0, l = c + i <= a;
|
|
350
293
|
return l && e.set(o, {
|
|
351
294
|
tenantId: t,
|
|
352
295
|
entitlementKey: n,
|
|
@@ -361,8 +304,8 @@ var k = (e, t, n, r) => ({
|
|
|
361
304
|
cost: i
|
|
362
305
|
};
|
|
363
306
|
}),
|
|
364
|
-
increment: (t, n, r, i) =>
|
|
365
|
-
let a =
|
|
307
|
+
increment: (t, n, r, i) => f.sync(() => {
|
|
308
|
+
let a = H(t, n, r), o = e.get(a), s = (o?.used ?? 0) + i;
|
|
366
309
|
return e.set(a, {
|
|
367
310
|
tenantId: t,
|
|
368
311
|
entitlementKey: n,
|
|
@@ -371,34 +314,34 @@ var k = (e, t, n, r) => ({
|
|
|
371
314
|
reportedToProvider: o?.reportedToProvider ?? 0
|
|
372
315
|
}), s;
|
|
373
316
|
}),
|
|
374
|
-
pending: () =>
|
|
375
|
-
markReported: (t, n, r, i) =>
|
|
376
|
-
let a =
|
|
317
|
+
pending: () => f.sync(() => [...e.values()].filter((e) => e.used > e.reportedToProvider)),
|
|
318
|
+
markReported: (t, n, r, i) => f.sync(() => {
|
|
319
|
+
let a = H(t, n, r), o = e.get(a);
|
|
377
320
|
o && e.set(a, {
|
|
378
321
|
...o,
|
|
379
322
|
reportedToProvider: i
|
|
380
323
|
});
|
|
381
324
|
})
|
|
382
325
|
};
|
|
383
|
-
},
|
|
326
|
+
}, be = (e) => ({
|
|
384
327
|
tenantId: String(e.tenantId),
|
|
385
328
|
entitlementKey: String(e.entitlementKey),
|
|
386
329
|
period: String(e.period),
|
|
387
330
|
used: Number(e.used ?? 0),
|
|
388
331
|
reportedToProvider: Number(e.reportedToProvider ?? 0)
|
|
389
|
-
}),
|
|
332
|
+
}), U = async (e, t, n, r) => (await e.query(B({
|
|
390
333
|
table: "_voltro_billing_usage",
|
|
391
|
-
predicate:
|
|
334
|
+
predicate: _(v("tenantId", t), v("entitlementKey", n), v("period", r)),
|
|
392
335
|
take: 1
|
|
393
|
-
})))[0] ?? null,
|
|
394
|
-
used: (t, n, r) =>
|
|
395
|
-
let i = await
|
|
336
|
+
})))[0] ?? null, xe = (e) => ({
|
|
337
|
+
used: (t, n, r) => z(async () => {
|
|
338
|
+
let i = await U(e, t, n, r);
|
|
396
339
|
return i ? Number(i.used ?? 0) : 0;
|
|
397
340
|
}, "usageStore"),
|
|
398
|
-
consume: (t, n, r, i, a) =>
|
|
341
|
+
consume: (t, n, r, i, a) => z(async () => {
|
|
399
342
|
for (let o = 0; o < 32; o++) {
|
|
400
343
|
o > 0 && await new Promise((e) => setTimeout(e, o));
|
|
401
|
-
let s = await
|
|
344
|
+
let s = await U(e, t, n, r), c = s ? Number(s.used ?? 0) : 0;
|
|
402
345
|
if (c + i > a) return {
|
|
403
346
|
allowed: !1,
|
|
404
347
|
entitlement: n,
|
|
@@ -410,7 +353,7 @@ var k = (e, t, n, r) => ({
|
|
|
410
353
|
if (await e.updateMany("_voltro_billing_usage", {
|
|
411
354
|
used: c + i,
|
|
412
355
|
updatedAt: /* @__PURE__ */ new Date()
|
|
413
|
-
}, { where:
|
|
356
|
+
}, { where: _(v("id", String(s.id)), v("used", c)) }) === 1) return {
|
|
414
357
|
allowed: !0,
|
|
415
358
|
entitlement: n,
|
|
416
359
|
limit: a,
|
|
@@ -418,7 +361,7 @@ var k = (e, t, n, r) => ({
|
|
|
418
361
|
cost: i
|
|
419
362
|
};
|
|
420
363
|
} else {
|
|
421
|
-
let o =
|
|
364
|
+
let o = R("buse"), s = await e.insertIgnore(L, {
|
|
422
365
|
id: o,
|
|
423
366
|
tenantId: t,
|
|
424
367
|
entitlementKey: n,
|
|
@@ -442,18 +385,18 @@ var k = (e, t, n, r) => ({
|
|
|
442
385
|
}
|
|
443
386
|
throw Error(`billing usage consume: contention on (${t}, ${n}, ${r}) exceeded 32 attempts`);
|
|
444
387
|
}, "usageStore"),
|
|
445
|
-
increment: (t, n, r, i) =>
|
|
388
|
+
increment: (t, n, r, i) => z(async () => {
|
|
446
389
|
for (let a = 0; a < 32; a++) {
|
|
447
390
|
a > 0 && await new Promise((e) => setTimeout(e, a));
|
|
448
|
-
let o = await
|
|
391
|
+
let o = await U(e, t, n, r);
|
|
449
392
|
if (o) {
|
|
450
393
|
let t = Number(o.used ?? 0);
|
|
451
394
|
if (await e.updateMany("_voltro_billing_usage", {
|
|
452
395
|
used: t + i,
|
|
453
396
|
updatedAt: /* @__PURE__ */ new Date()
|
|
454
|
-
}, { where:
|
|
397
|
+
}, { where: _(v("id", String(o.id)), v("used", t)) }) === 1) return t + i;
|
|
455
398
|
} else {
|
|
456
|
-
let a =
|
|
399
|
+
let a = R("buse"), o = await e.insertIgnore(L, {
|
|
457
400
|
id: a,
|
|
458
401
|
tenantId: t,
|
|
459
402
|
entitlementKey: n,
|
|
@@ -471,167 +414,90 @@ var k = (e, t, n, r) => ({
|
|
|
471
414
|
}
|
|
472
415
|
throw Error(`billing usage increment: contention on (${t}, ${n}, ${r}) exceeded 32 attempts`);
|
|
473
416
|
}, "usageStore"),
|
|
474
|
-
pending: () =>
|
|
475
|
-
markReported: (t, n, r, i) =>
|
|
476
|
-
let a = await
|
|
477
|
-
a && await e.update(
|
|
417
|
+
pending: () => z(async () => (await e.query(B({ table: L }))).map(be).filter((e) => e.used > e.reportedToProvider), "usageStore"),
|
|
418
|
+
markReported: (t, n, r, i) => z(async () => {
|
|
419
|
+
let a = await U(e, t, n, r);
|
|
420
|
+
a && await e.update(L, String(a.id), {
|
|
478
421
|
reportedToProvider: i,
|
|
479
422
|
updatedAt: /* @__PURE__ */ new Date()
|
|
480
423
|
});
|
|
481
424
|
}, "usageStore")
|
|
482
|
-
}),
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
attempt: 0,
|
|
495
|
-
nextRetryAt: r,
|
|
496
|
-
startedAt: i
|
|
497
|
-
}), !0)),
|
|
498
|
-
getByTenant: (t) => d.sync(() => {
|
|
499
|
-
for (let n of e.values()) if (n.tenantId === t) return n;
|
|
500
|
-
return null;
|
|
501
|
-
}),
|
|
502
|
-
due: (t) => d.sync(() => [...e.values()].filter((e) => e.nextRetryAt.getTime() <= t.getTime())),
|
|
503
|
-
advance: (t, n, r, i) => d.sync(() => {
|
|
504
|
-
let a = e.get(t);
|
|
505
|
-
return !a || a.attempt !== n ? !1 : (e.set(t, {
|
|
506
|
-
...a,
|
|
507
|
-
attempt: r,
|
|
508
|
-
nextRetryAt: i
|
|
509
|
-
}), !0);
|
|
510
|
-
}),
|
|
511
|
-
close: (t) => d.sync(() => {
|
|
512
|
-
e.delete(t);
|
|
513
|
-
})
|
|
514
|
-
};
|
|
515
|
-
}, Me = async (e, t) => (await e.query(H({
|
|
516
|
-
table: "_voltro_billing_dunning",
|
|
517
|
-
predicate: _("providerSubscriptionId", t),
|
|
518
|
-
take: 1
|
|
519
|
-
})))[0] ?? null, Ne = (e) => ({
|
|
520
|
-
open: (t, n, r, i) => V(async () => {
|
|
521
|
-
let a = B("bdun"), o = await e.insertIgnore(z, {
|
|
522
|
-
id: a,
|
|
523
|
-
tenantId: t,
|
|
524
|
-
providerSubscriptionId: n,
|
|
525
|
-
attempt: 0,
|
|
526
|
-
nextRetryAt: r,
|
|
527
|
-
startedAt: i,
|
|
528
|
-
updatedAt: i
|
|
529
|
-
}, { conflictColumns: ["providerSubscriptionId"] });
|
|
530
|
-
return String(o.id) === a;
|
|
531
|
-
}, "dunningStore"),
|
|
532
|
-
getByTenant: (t) => V(async () => {
|
|
533
|
-
let n = await e.query(H({
|
|
534
|
-
table: z,
|
|
535
|
-
predicate: _("tenantId", t),
|
|
536
|
-
take: 1
|
|
537
|
-
}));
|
|
538
|
-
return n[0] ? Ae(n[0]) : null;
|
|
539
|
-
}, "dunningStore"),
|
|
540
|
-
due: (t) => V(async () => (await e.query(H({
|
|
541
|
-
table: z,
|
|
542
|
-
predicate: b("nextRetryAt", t)
|
|
543
|
-
}))).map(Ae), "dunningStore"),
|
|
544
|
-
advance: (t, n, r, i) => V(async () => {
|
|
545
|
-
let a = await Me(e, t);
|
|
546
|
-
return a ? await e.updateMany(z, {
|
|
547
|
-
attempt: r,
|
|
548
|
-
nextRetryAt: i,
|
|
549
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
550
|
-
}, { where: g(_("id", String(a.id)), _("attempt", n)) }) === 1 : !1;
|
|
551
|
-
}, "dunningStore"),
|
|
552
|
-
close: (t) => V(async () => {
|
|
553
|
-
let n = await Me(e, t);
|
|
554
|
-
n && await e.delete(z, String(n.id));
|
|
555
|
-
}, "dunningStore")
|
|
556
|
-
}), Pe = () => ({
|
|
557
|
-
customers: ve(),
|
|
558
|
-
subscriptions: xe(),
|
|
559
|
-
invoices: we(),
|
|
560
|
-
usage: De(),
|
|
561
|
-
dunning: je()
|
|
562
|
-
}), Fe = (e) => ({
|
|
563
|
-
customers: be(e),
|
|
564
|
-
subscriptions: Ce(e),
|
|
565
|
-
invoices: Ee(e),
|
|
566
|
-
usage: ke(e),
|
|
567
|
-
dunning: Ne(e)
|
|
568
|
-
}), K = (e = /* @__PURE__ */ new Date()) => `${e.getUTCFullYear()}-${String(e.getUTCMonth() + 1).padStart(2, "0")}`, Ie = (e) => ({ stores: e ?? Pe() }), q = (e, t) => e.pipe(d.retry({
|
|
569
|
-
schedule: p.recurs(Math.max(0, t - 1)),
|
|
425
|
+
}), Se = () => ({
|
|
426
|
+
customers: ue(),
|
|
427
|
+
subscriptions: pe(),
|
|
428
|
+
invoices: ge(),
|
|
429
|
+
usage: ye()
|
|
430
|
+
}), W = (e) => ({
|
|
431
|
+
customers: fe(e),
|
|
432
|
+
subscriptions: he(e),
|
|
433
|
+
invoices: ve(e),
|
|
434
|
+
usage: xe(e)
|
|
435
|
+
}), G = (e = /* @__PURE__ */ new Date()) => `${e.getUTCFullYear()}-${String(e.getUTCMonth() + 1).padStart(2, "0")}`, Ce = (e) => ({ stores: e ?? Se() }), K = (e, t) => e.pipe(f.retry({
|
|
436
|
+
schedule: m.recurs(Math.max(0, t - 1)),
|
|
570
437
|
while: (e) => e.transient
|
|
571
|
-
})),
|
|
572
|
-
let { provider: i, plans: a } = t, o = t.attempts ?? 3, s = t.now ?? (() => /* @__PURE__ */ new Date()),
|
|
573
|
-
subscriptions: c.stores.subscriptions,
|
|
574
|
-
dunning: c.stores.dunning,
|
|
575
|
-
schedule: l
|
|
576
|
-
}), f = (e) => c.stores.subscriptions.getByTenant(e).pipe(d.map((e) => e !== null && (e.status === "active" || e.status === "trialing") ? e.plan : n)), p = (e) => c.stores.subscriptions.getByTenant(e), m = (e, n) => d.gen(function* () {
|
|
438
|
+
})), we = (t) => {
|
|
439
|
+
let { provider: i, plans: a } = t, o = t.attempts ?? 3, s = t.checkout, c = t.now ?? (() => /* @__PURE__ */ new Date()), l = Ce(t.stores), u = (e) => l.stores.subscriptions.getByTenant(e).pipe(f.map((e) => e !== null && (e.status === "active" || e.status === "trialing") ? e.plan : n)), ee = (e) => l.stores.subscriptions.getByTenant(e), d = (e, n) => f.gen(function* () {
|
|
577
440
|
if (t.resolveEntitlementLimit !== void 0) {
|
|
578
441
|
let r = yield* t.resolveEntitlementLimit(e, n);
|
|
579
442
|
if (r !== null) return r;
|
|
580
443
|
}
|
|
581
|
-
let r = yield*
|
|
444
|
+
let r = yield* u(e);
|
|
582
445
|
return a.entitlementLimit(r, n);
|
|
583
|
-
}),
|
|
584
|
-
return
|
|
585
|
-
}),
|
|
586
|
-
let i = yield*
|
|
446
|
+
}), p = (e, t, n) => f.gen(function* () {
|
|
447
|
+
return A(t, yield* d(e, t), yield* l.stores.usage.used(e, t, G(c())), n);
|
|
448
|
+
}), m = (e, t, n) => f.gen(function* () {
|
|
449
|
+
let i = yield* d(e, t);
|
|
587
450
|
if (!Number.isFinite(i) || n <= 0) return;
|
|
588
|
-
let a =
|
|
589
|
-
if (!o.allowed) return yield*
|
|
451
|
+
let a = G(c()), o = yield* l.stores.usage.consume(e, t, a, n, i);
|
|
452
|
+
if (!o.allowed) return yield* f.fail(new r({
|
|
590
453
|
entitlement: t,
|
|
591
454
|
limit: o.limit,
|
|
592
455
|
used: o.used,
|
|
593
456
|
cost: n
|
|
594
457
|
}));
|
|
595
|
-
}),
|
|
458
|
+
}), h = (e, t, n) => n <= 0 ? f.void : l.stores.usage.increment(e, t, G(c()), n).pipe(f.asVoid), g = () => f.gen(function* () {
|
|
596
459
|
if (!i.supportsMeteredUsage) return;
|
|
597
|
-
let e = yield*
|
|
460
|
+
let e = yield* l.stores.usage.pending();
|
|
598
461
|
for (let t of e) {
|
|
599
462
|
let e = t.used - t.reportedToProvider;
|
|
600
|
-
e <= 0 || (yield*
|
|
463
|
+
e <= 0 || (yield* K(i.reportUsage({
|
|
601
464
|
tenantId: t.tenantId,
|
|
602
465
|
entitlementKey: t.entitlementKey,
|
|
603
466
|
quantity: e
|
|
604
|
-
}), o), yield*
|
|
467
|
+
}), o), yield* l.stores.usage.markReported(t.tenantId, t.entitlementKey, t.period, t.used));
|
|
605
468
|
}
|
|
606
|
-
}),
|
|
469
|
+
}), te = (t) => f.gen(function* () {
|
|
607
470
|
let n = a.priceIdFor(t.plan);
|
|
608
|
-
if (n === null) return yield*
|
|
471
|
+
if (n === null) return yield* f.fail(new e({
|
|
609
472
|
source: "billing",
|
|
610
473
|
message: `plan '${t.plan}' has no provider priceId — not a paid plan`,
|
|
611
474
|
transient: !1
|
|
612
475
|
}));
|
|
613
|
-
let r = yield*
|
|
614
|
-
return yield*
|
|
476
|
+
let r = yield* l.stores.customers.getByTenant(t.tenantId);
|
|
477
|
+
return yield* K(i.createCheckoutSession({
|
|
615
478
|
tenantId: t.tenantId,
|
|
616
479
|
priceId: n,
|
|
617
480
|
successUrl: t.successUrl,
|
|
618
481
|
cancelUrl: t.cancelUrl,
|
|
619
|
-
...r === null ? {} : { providerCustomerId: r.providerCustomerId }
|
|
482
|
+
...r === null ? {} : { providerCustomerId: r.providerCustomerId },
|
|
483
|
+
...t.quantity === void 0 ? {} : { quantity: t.quantity },
|
|
484
|
+
...s?.adjustableQuantity === void 0 ? {} : { adjustableQuantity: s.adjustableQuantity },
|
|
485
|
+
...s?.trialDays === void 0 ? {} : { trialDays: s.trialDays }
|
|
620
486
|
}), o);
|
|
621
|
-
}), ne = (t, n) =>
|
|
622
|
-
let r = yield*
|
|
623
|
-
return r === null ? yield*
|
|
487
|
+
}), ne = (t, n) => f.gen(function* () {
|
|
488
|
+
let r = yield* l.stores.customers.getByTenant(t);
|
|
489
|
+
return r === null ? yield* f.fail(new e({
|
|
624
490
|
source: "billing",
|
|
625
491
|
message: `no provider customer linked for tenant '${t}'`,
|
|
626
492
|
transient: !1
|
|
627
|
-
})) : yield*
|
|
493
|
+
})) : yield* K(i.createPortalSession({
|
|
628
494
|
tenantId: t,
|
|
629
495
|
providerCustomerId: r.providerCustomerId,
|
|
630
496
|
returnUrl: n
|
|
631
497
|
}), o);
|
|
632
|
-
}),
|
|
498
|
+
}), _ = (e) => {
|
|
633
499
|
switch (e._tag) {
|
|
634
|
-
case "subscriptionUpserted": return
|
|
500
|
+
case "subscriptionUpserted": return l.stores.subscriptions.upsert({
|
|
635
501
|
tenantId: e.tenantId,
|
|
636
502
|
provider: i.name,
|
|
637
503
|
providerSubscriptionId: e.providerSubscriptionId,
|
|
@@ -642,91 +508,108 @@ var k = (e, t, n, r) => ({
|
|
|
642
508
|
currentPeriodEnd: e.currentPeriodEnd,
|
|
643
509
|
cancelAt: e.cancelAt
|
|
644
510
|
});
|
|
645
|
-
case "subscriptionCanceled": return
|
|
646
|
-
case "invoicePaid": return
|
|
511
|
+
case "subscriptionCanceled": return l.stores.subscriptions.markCanceled(e.providerSubscriptionId);
|
|
512
|
+
case "invoicePaid": return l.stores.invoices.upsert({
|
|
647
513
|
tenantId: e.tenantId,
|
|
648
514
|
provider: i.name,
|
|
649
515
|
providerInvoiceId: e.providerInvoiceId,
|
|
650
516
|
amountMinor: e.amountMinor,
|
|
651
517
|
currency: e.currency,
|
|
652
518
|
status: "paid"
|
|
653
|
-
})
|
|
654
|
-
case "invoicePaymentFailed": return
|
|
519
|
+
});
|
|
520
|
+
case "invoicePaymentFailed": return l.stores.invoices.upsert({
|
|
655
521
|
tenantId: e.tenantId,
|
|
656
522
|
provider: i.name,
|
|
657
523
|
providerInvoiceId: e.providerInvoiceId,
|
|
658
524
|
amountMinor: e.amountMinor,
|
|
659
525
|
currency: e.currency,
|
|
660
526
|
status: "open"
|
|
661
|
-
})
|
|
662
|
-
case "customerLinked": return
|
|
527
|
+
});
|
|
528
|
+
case "customerLinked": return l.stores.customers.upsert({
|
|
663
529
|
tenantId: e.tenantId,
|
|
664
530
|
provider: i.name,
|
|
665
531
|
providerCustomerId: e.providerCustomerId
|
|
666
532
|
});
|
|
667
533
|
}
|
|
668
|
-
},
|
|
669
|
-
let
|
|
670
|
-
if (
|
|
534
|
+
}, v = (t, n) => f.gen(function* () {
|
|
535
|
+
let r = yield* l.stores.subscriptions.getByTenant(t);
|
|
536
|
+
if (r === null) return yield* f.fail(new e({
|
|
671
537
|
source: "billing",
|
|
672
538
|
message: `no subscription for tenant '${t}' to change`,
|
|
673
539
|
transient: !1
|
|
674
540
|
}));
|
|
675
|
-
let
|
|
676
|
-
if (n.plan !== void 0 && !a.has(
|
|
541
|
+
let s = n.plan ?? r.plan, c = n.quantity ?? r.quantity;
|
|
542
|
+
if (n.plan !== void 0 && !a.has(s)) return yield* f.fail(new e({
|
|
677
543
|
source: "billing",
|
|
678
|
-
message: `unknown plan '${
|
|
544
|
+
message: `unknown plan '${s}' — not in the plan registry`,
|
|
679
545
|
transient: !1
|
|
680
546
|
}));
|
|
681
|
-
if (!Number.isInteger(
|
|
547
|
+
if (!Number.isInteger(c) || c <= 0) return yield* f.fail(new e({
|
|
682
548
|
source: "billing",
|
|
683
|
-
message: `seat quantity must be a positive integer, got ${
|
|
549
|
+
message: `seat quantity must be a positive integer, got ${c}`,
|
|
684
550
|
transient: !1
|
|
685
551
|
}));
|
|
686
|
-
let
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
...
|
|
552
|
+
let u = yield* K(i.updateSubscription({
|
|
553
|
+
providerSubscriptionId: r.providerSubscriptionId,
|
|
554
|
+
...n.plan === void 0 ? {} : { priceId: a.priceIdFor(s) ?? s },
|
|
555
|
+
...n.quantity === void 0 ? {} : { quantity: c },
|
|
556
|
+
proration: "prorate"
|
|
557
|
+
}), o);
|
|
558
|
+
return yield* l.stores.subscriptions.patchByTenant(t, {
|
|
559
|
+
...n.plan === void 0 ? {} : { plan: s },
|
|
560
|
+
quantity: u.quantity,
|
|
561
|
+
...u.currentPeriodStart === null ? {} : { currentPeriodStart: u.currentPeriodStart },
|
|
562
|
+
...u.currentPeriodEnd === null ? {} : { currentPeriodEnd: u.currentPeriodEnd }
|
|
696
563
|
}), {
|
|
697
564
|
tenantId: t,
|
|
698
|
-
plan:
|
|
699
|
-
quantity:
|
|
700
|
-
prorationMinor:
|
|
701
|
-
currency:
|
|
565
|
+
plan: s,
|
|
566
|
+
quantity: u.quantity,
|
|
567
|
+
prorationMinor: u.prorationMinor,
|
|
568
|
+
currency: u.currency
|
|
702
569
|
};
|
|
703
|
-
}), x = (e, t, n = s()) => b(e, { plan: t }, n), S = (e, t, n = s()) => b(e, { quantity: t }, n), C = (e, t = s()) => d.gen(function* () {
|
|
704
|
-
let n = yield* c.stores.subscriptions.getByTenant(e);
|
|
705
|
-
return n === null ? null : yield* ce(u(), e, n.providerSubscriptionId, t);
|
|
706
|
-
}), w = (e, t = s()) => d.gen(function* () {
|
|
707
|
-
let t = yield* c.stores.dunning.getByTenant(e);
|
|
708
|
-
t !== null && (yield* le(u(), t.providerSubscriptionId));
|
|
709
570
|
});
|
|
710
571
|
return {
|
|
711
572
|
service: {
|
|
712
|
-
subscription:
|
|
713
|
-
plan:
|
|
714
|
-
checkEntitlement:
|
|
715
|
-
consumeEntitlement:
|
|
716
|
-
reportUsage:
|
|
573
|
+
subscription: ee,
|
|
574
|
+
plan: u,
|
|
575
|
+
checkEntitlement: p,
|
|
576
|
+
consumeEntitlement: m,
|
|
577
|
+
reportUsage: h,
|
|
717
578
|
flushUsage: g,
|
|
718
|
-
startCheckout:
|
|
579
|
+
startCheckout: te,
|
|
719
580
|
portalUrl: ne,
|
|
720
|
-
applyEvent:
|
|
721
|
-
changePlan:
|
|
722
|
-
changeSeats:
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
581
|
+
applyEvent: _,
|
|
582
|
+
changePlan: (e, t) => v(e, { plan: t }),
|
|
583
|
+
changeSeats: (e, t) => v(e, { quantity: t }),
|
|
584
|
+
previewChange: (t, n) => f.gen(function* () {
|
|
585
|
+
let r = yield* l.stores.subscriptions.getByTenant(t);
|
|
586
|
+
if (r === null) return yield* f.fail(new e({
|
|
587
|
+
source: "billing",
|
|
588
|
+
message: `no subscription for tenant '${t}' to preview`,
|
|
589
|
+
transient: !1
|
|
590
|
+
}));
|
|
591
|
+
let s = n.plan ?? r.plan, c = yield* K(i.previewSubscriptionChange({
|
|
592
|
+
providerSubscriptionId: r.providerSubscriptionId,
|
|
593
|
+
...n.plan === void 0 ? {} : { priceId: a.priceIdFor(s) ?? s },
|
|
594
|
+
...n.quantity === void 0 ? {} : { quantity: n.quantity },
|
|
595
|
+
proration: "prorate"
|
|
596
|
+
}), o);
|
|
597
|
+
return {
|
|
598
|
+
tenantId: t,
|
|
599
|
+
plan: s,
|
|
600
|
+
quantity: c.quantity,
|
|
601
|
+
prorationMinor: c.prorationMinor,
|
|
602
|
+
currency: c.currency
|
|
603
|
+
};
|
|
604
|
+
}),
|
|
605
|
+
invoices: (e) => f.gen(function* () {
|
|
606
|
+
let t = yield* l.stores.customers.getByTenant(e);
|
|
607
|
+
return t === null ? [] : yield* K(i.listInvoices({ providerCustomerId: t.providerCustomerId }), o);
|
|
608
|
+
})
|
|
726
609
|
},
|
|
727
|
-
holder:
|
|
610
|
+
holder: l
|
|
728
611
|
};
|
|
729
|
-
},
|
|
612
|
+
}, Te = (e) => p.succeed(t, e), Ee = "_voltro_ai_usage", De = (e) => {
|
|
730
613
|
for (let [t, n] of Object.entries(e)) {
|
|
731
614
|
if (t.length === 0) throw Error("billing metering: a meter key must be non-empty");
|
|
732
615
|
if (n.from === "rpc") {
|
|
@@ -735,29 +618,29 @@ var k = (e, t, n, r) => ({
|
|
|
735
618
|
if (typeof n.table != "string" || n.table.length === 0) throw Error(`billing metering: cdc meter '${t}' needs a 'table'`);
|
|
736
619
|
} else if (n.from !== "ai") throw Error(`billing metering: meter '${t}' has unknown source '${String(n.from)}'`);
|
|
737
620
|
}
|
|
738
|
-
},
|
|
739
|
-
let i =
|
|
621
|
+
}, Oe = (e, t) => typeof e == "string" ? t === e : e.test(t), ke = (e, t, n) => Object.entries(e).filter(([, e]) => e.from === "rpc" && (e.kind === void 0 || e.kind === n) && Oe(e.match, t)).map(([e]) => e), Ae = (e, t, n) => Object.entries(e).filter(([, e]) => e.from === "cdc" && e.table === t && (e.op ?? "insert") === n).map(([e]) => e), je = (e) => Object.entries(e).filter(([, e]) => e.from === "ai").map(([e, t]) => [e, t.metric ?? "tokens"]), Me = (e) => e.tenantId, Ne = (e, t, n, r) => f.forEach(n, (n) => e.reportUsage(t, n, r).pipe(f.catchAll(() => f.void)), { discard: !0 }), Pe = (e, t) => (n, r) => {
|
|
622
|
+
let i = ke(t, r.tag, r.kind);
|
|
740
623
|
if (i.length === 0) return n;
|
|
741
|
-
let a =
|
|
742
|
-
return a === null ? n : n.pipe(
|
|
743
|
-
},
|
|
744
|
-
let r =
|
|
745
|
-
if (r.length === 0) return
|
|
624
|
+
let a = Me(r.subject);
|
|
625
|
+
return a === null ? n : n.pipe(f.tap(() => Ne(e, a, i, 1)));
|
|
626
|
+
}, Fe = (e, t) => (n) => {
|
|
627
|
+
let r = Ae(t, n.table, n.op);
|
|
628
|
+
if (r.length === 0) return f.void;
|
|
746
629
|
let i = n.new?.tenantId ?? n.old?.tenantId ?? null;
|
|
747
|
-
return i === null ?
|
|
748
|
-
},
|
|
749
|
-
let i =
|
|
630
|
+
return i === null ? f.void : Ne(e, i, r, 1);
|
|
631
|
+
}, Ie = (e) => new Date(Date.UTC(e.getUTCFullYear(), e.getUTCMonth(), 1, 0, 0, 0, 0)), Le = (e, t, n, r = () => /* @__PURE__ */ new Date()) => f.gen(function* () {
|
|
632
|
+
let i = je(n);
|
|
750
633
|
if (i.length === 0) return;
|
|
751
634
|
let a = r();
|
|
752
|
-
|
|
635
|
+
G(a);
|
|
753
636
|
let o = {
|
|
754
|
-
table:
|
|
755
|
-
predicate:
|
|
637
|
+
table: Ee,
|
|
638
|
+
predicate: re("calledAt", Ie(a)),
|
|
756
639
|
order: [],
|
|
757
640
|
take: void 0,
|
|
758
641
|
skip: void 0,
|
|
759
642
|
projection: void 0
|
|
760
|
-
}, s = yield*
|
|
643
|
+
}, s = yield* f.promise(() => Promise.resolve(t.query(o)).then((e) => e).catch(() => [])), c = /* @__PURE__ */ new Map();
|
|
761
644
|
for (let e of s) {
|
|
762
645
|
let t = e.tenantId ?? null;
|
|
763
646
|
if (t === null) continue;
|
|
@@ -770,17 +653,17 @@ var k = (e, t, n, r) => ({
|
|
|
770
653
|
for (let [t, n] of i) for (let [r, i] of c) {
|
|
771
654
|
let a = n === "costMicroUsd" ? i.cost : i.tokens;
|
|
772
655
|
if (a <= 0) continue;
|
|
773
|
-
let o = a - (yield* e.checkEntitlement(r, t, 0).pipe(
|
|
774
|
-
o > 0 && (yield* e.reportUsage(r, t, o).pipe(
|
|
656
|
+
let o = a - (yield* e.checkEntitlement(r, t, 0).pipe(f.map((e) => e.used), f.catchAll(() => f.succeed(0))));
|
|
657
|
+
o > 0 && (yield* e.reportUsage(r, t, o).pipe(f.catchAll(() => f.void)));
|
|
775
658
|
}
|
|
776
|
-
}),
|
|
659
|
+
}), Re = (e, t, n, r) => Le(e, t, n, r).pipe(f.andThen(e.flushUsage().pipe(f.catchAll(() => f.void)))), ze = (e) => Object.values(e).some((e) => e.from === "cdc"), Be = (e) => e === void 0 ? 0 : e === "unlimited" ? Infinity : e, q = (e) => {
|
|
777
660
|
let t = /* @__PURE__ */ new Map();
|
|
778
661
|
for (let [n, r] of Object.entries(e)) r.priceId !== void 0 && t.set(r.priceId, n);
|
|
779
662
|
return {
|
|
780
663
|
has: (t) => Object.prototype.hasOwnProperty.call(e, t),
|
|
781
664
|
entitlementLimit: (t, n) => {
|
|
782
665
|
let r = e[t];
|
|
783
|
-
return r === void 0 ? 0 :
|
|
666
|
+
return r === void 0 ? 0 : Be(r.entitlements[n]);
|
|
784
667
|
},
|
|
785
668
|
planForPriceId: (e) => t.get(e) ?? null,
|
|
786
669
|
priceIdFor: (t) => e[t]?.priceId ?? null,
|
|
@@ -791,14 +674,14 @@ var k = (e, t, n, r) => ({
|
|
|
791
674
|
currencyFor: (t) => (e[t]?.currency ?? "usd").toLowerCase(),
|
|
792
675
|
planIds: () => Object.keys(e)
|
|
793
676
|
};
|
|
794
|
-
},
|
|
795
|
-
id:
|
|
796
|
-
windowKey:
|
|
797
|
-
claimedBy:
|
|
798
|
-
claimedAt:
|
|
799
|
-
}).unique("billingFlushClaimWindow", ["windowKey"]),
|
|
677
|
+
}, Ve = () => q({ [n]: { entitlements: {} } }), J = "_voltro_billing_flush_claims", He = S(J, {
|
|
678
|
+
id: y({ scheme: "numeric" }),
|
|
679
|
+
windowKey: C(),
|
|
680
|
+
claimedBy: C(),
|
|
681
|
+
claimedAt: w().default("now")
|
|
682
|
+
}).unique("billingFlushClaimWindow", ["windowKey"]), Ue = (e, t) => `billing-flush:${Math.floor(e / Math.max(1, t))}`, We = async (e, t, n, r) => {
|
|
800
683
|
try {
|
|
801
|
-
return (await e.insertIgnore(
|
|
684
|
+
return (await e.insertIgnore(J, {
|
|
802
685
|
windowKey: t,
|
|
803
686
|
claimedBy: n,
|
|
804
687
|
claimedAt: new Date(r)
|
|
@@ -806,190 +689,306 @@ var k = (e, t, n, r) => ({
|
|
|
806
689
|
} catch {
|
|
807
690
|
return !0;
|
|
808
691
|
}
|
|
809
|
-
},
|
|
810
|
-
|
|
692
|
+
}, Ge = 3, Ke = 2e4, qe = (e) => e.client ?? new T(e.apiKey, {
|
|
693
|
+
maxNetworkRetries: Ge,
|
|
694
|
+
timeout: Ke,
|
|
695
|
+
appInfo: {
|
|
696
|
+
name: "voltro",
|
|
697
|
+
url: "https://voltro.dev"
|
|
698
|
+
}
|
|
699
|
+
}), Je = (e) => e instanceof T.errors.StripeConnectionError || e instanceof T.errors.StripeAPIError || e instanceof T.errors.StripeRateLimitError, Ye = (e) => e instanceof T.errors.StripeError ? e.code ?? e.type : void 0, Y = (t, n) => f.tryPromise({
|
|
700
|
+
try: n,
|
|
701
|
+
catch: (n) => new e({
|
|
702
|
+
source: t,
|
|
703
|
+
message: Xe(n),
|
|
704
|
+
transient: Je(n)
|
|
705
|
+
})
|
|
706
|
+
}), Xe = (e) => {
|
|
707
|
+
if (e instanceof T.errors.StripeError) {
|
|
708
|
+
let t = Ye(e);
|
|
709
|
+
return t === void 0 ? e.message : `${e.message} (${t})`;
|
|
710
|
+
}
|
|
711
|
+
return String(e?.message ?? e);
|
|
712
|
+
}, Ze = (e) => {
|
|
713
|
+
let t = e.items?.data?.[0];
|
|
811
714
|
return {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
pushed: n,
|
|
815
|
-
createCheckoutSession: (e) => d.succeed({ url: `${t}/checkout?tenant=${encodeURIComponent(e.tenantId)}&price=${encodeURIComponent(e.priceId)}` }),
|
|
816
|
-
createPortalSession: (e) => d.succeed({ url: `${t}/portal?customer=${encodeURIComponent(e.providerCustomerId)}` }),
|
|
817
|
-
reportUsage: (e) => d.sync(() => {
|
|
818
|
-
n.push(e);
|
|
819
|
-
}),
|
|
820
|
-
normalizeEvent: (e) => d.succeed(r(e) ? e : null)
|
|
715
|
+
start: X(t?.current_period_start),
|
|
716
|
+
end: X(t?.current_period_end)
|
|
821
717
|
};
|
|
822
|
-
},
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
for (let [n, r] of Object.entries(e)) r !== void 0 && t.set(n, r);
|
|
829
|
-
return t.toString();
|
|
830
|
-
}, st = (e, t, n) => d.tryPromise({
|
|
831
|
-
try: async () => {
|
|
832
|
-
let r = await fetch(`${at}${t}`, {
|
|
833
|
-
method: "POST",
|
|
834
|
-
headers: {
|
|
835
|
-
Authorization: `Bearer ${e}`,
|
|
836
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
837
|
-
},
|
|
838
|
-
body: ot(n)
|
|
839
|
-
}), i = await r.json();
|
|
840
|
-
if (!r.ok) {
|
|
841
|
-
let e = r.status >= 500 || r.status === 429, t = i.error?.message ?? `HTTP ${r.status}`;
|
|
842
|
-
throw Object.assign(Error(t), { transient: e });
|
|
843
|
-
}
|
|
844
|
-
return i;
|
|
845
|
-
},
|
|
846
|
-
catch: (e) => {
|
|
847
|
-
let t = e.transient ?? !0;
|
|
848
|
-
return X(String(e?.message ?? e), t);
|
|
849
|
-
}
|
|
850
|
-
}), ct = {
|
|
718
|
+
}, X = (e) => typeof e == "number" && Number.isFinite(e) ? /* @__PURE__ */ new Date(e * 1e3) : null, Qe = (e) => {
|
|
719
|
+
let t = e.items?.data ?? [];
|
|
720
|
+
if (t.length === 0) return 1;
|
|
721
|
+
let n = t.reduce((e, t) => e + (t.quantity ?? 0), 0);
|
|
722
|
+
return n > 0 ? n : 1;
|
|
723
|
+
}, $e = {
|
|
851
724
|
active: "active",
|
|
852
725
|
trialing: "trialing",
|
|
853
726
|
past_due: "pastDue",
|
|
854
727
|
unpaid: "pastDue",
|
|
855
728
|
canceled: "canceled",
|
|
856
729
|
incomplete: "incomplete",
|
|
857
|
-
incomplete_expired: "canceled"
|
|
858
|
-
|
|
859
|
-
|
|
730
|
+
incomplete_expired: "canceled",
|
|
731
|
+
paused: "pastDue"
|
|
732
|
+
}, Z = (e) => {
|
|
733
|
+
let t = e.metadata?.tenantId;
|
|
860
734
|
if (typeof t == "string" && t.length > 0) return t;
|
|
861
735
|
let n = e.client_reference_id;
|
|
862
736
|
return typeof n == "string" && n.length > 0 ? n : null;
|
|
863
|
-
},
|
|
864
|
-
let t =
|
|
865
|
-
return typeof t == "string"
|
|
866
|
-
},
|
|
867
|
-
let
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
if (typeof n != "string") return null;
|
|
874
|
-
let r = Z(Z(t.data)?.object);
|
|
875
|
-
if (r === null) return null;
|
|
876
|
-
switch (n) {
|
|
737
|
+
}, et = (e) => {
|
|
738
|
+
let t = e.items?.data?.[0]?.price;
|
|
739
|
+
return typeof t?.id == "string" ? t.id : null;
|
|
740
|
+
}, tt = (e, t) => {
|
|
741
|
+
let n = e.metadata?.plan;
|
|
742
|
+
if (typeof n == "string" && n.length > 0) return n;
|
|
743
|
+
let r = et(e);
|
|
744
|
+
return r !== null && t ? t(r) : null;
|
|
745
|
+
}, nt = (e, t) => {
|
|
746
|
+
switch (e.type) {
|
|
877
747
|
case "customer.subscription.created":
|
|
878
|
-
case "customer.subscription.updated":
|
|
879
|
-
|
|
880
|
-
|
|
748
|
+
case "customer.subscription.updated":
|
|
749
|
+
case "customer.subscription.resumed":
|
|
750
|
+
case "customer.subscription.paused": {
|
|
751
|
+
let n = e.data.object, r = Z(n), i = tt(n, t), a = $e[n.status];
|
|
752
|
+
if (r === null || i === null || a === void 0) return null;
|
|
753
|
+
let o = Ze(n);
|
|
754
|
+
return {
|
|
881
755
|
_tag: "subscriptionUpserted",
|
|
882
|
-
tenantId:
|
|
883
|
-
providerSubscriptionId: n,
|
|
884
|
-
plan:
|
|
885
|
-
status:
|
|
886
|
-
quantity:
|
|
887
|
-
currentPeriodStart:
|
|
888
|
-
currentPeriodEnd:
|
|
889
|
-
cancelAt:
|
|
756
|
+
tenantId: r,
|
|
757
|
+
providerSubscriptionId: n.id,
|
|
758
|
+
plan: i,
|
|
759
|
+
status: a,
|
|
760
|
+
quantity: Qe(n),
|
|
761
|
+
currentPeriodStart: o.start,
|
|
762
|
+
currentPeriodEnd: o.end,
|
|
763
|
+
cancelAt: X(n.cancel_at)
|
|
890
764
|
};
|
|
891
765
|
}
|
|
892
766
|
case "customer.subscription.deleted": {
|
|
893
|
-
let
|
|
894
|
-
return
|
|
767
|
+
let t = e.data.object, n = Z(t);
|
|
768
|
+
return n === null ? null : {
|
|
895
769
|
_tag: "subscriptionCanceled",
|
|
896
|
-
tenantId:
|
|
897
|
-
providerSubscriptionId:
|
|
770
|
+
tenantId: n,
|
|
771
|
+
providerSubscriptionId: t.id
|
|
898
772
|
};
|
|
899
773
|
}
|
|
900
774
|
case "invoice.paid":
|
|
901
775
|
case "invoice.payment_failed": {
|
|
902
|
-
let
|
|
903
|
-
return
|
|
904
|
-
_tag:
|
|
905
|
-
tenantId:
|
|
906
|
-
providerInvoiceId: t,
|
|
907
|
-
amountMinor:
|
|
908
|
-
currency:
|
|
776
|
+
let t = e.data.object, n = Z(t);
|
|
777
|
+
return n === null || typeof t.id != "string" ? null : {
|
|
778
|
+
_tag: e.type === "invoice.paid" ? "invoicePaid" : "invoicePaymentFailed",
|
|
779
|
+
tenantId: n,
|
|
780
|
+
providerInvoiceId: t.id,
|
|
781
|
+
amountMinor: t.amount_due,
|
|
782
|
+
currency: t.currency
|
|
909
783
|
};
|
|
910
784
|
}
|
|
911
785
|
case "customer.created": {
|
|
912
|
-
let
|
|
913
|
-
return
|
|
786
|
+
let t = e.data.object, n = Z(t);
|
|
787
|
+
return n === null ? null : {
|
|
914
788
|
_tag: "customerLinked",
|
|
915
|
-
tenantId:
|
|
916
|
-
providerCustomerId: t
|
|
789
|
+
tenantId: n,
|
|
790
|
+
providerCustomerId: t.id
|
|
917
791
|
};
|
|
918
792
|
}
|
|
919
793
|
default: return null;
|
|
920
794
|
}
|
|
921
|
-
},
|
|
922
|
-
|
|
795
|
+
}, rt = {
|
|
796
|
+
prorate: "create_prorations",
|
|
797
|
+
none: "none",
|
|
798
|
+
always_invoice: "always_invoice"
|
|
799
|
+
}, it = (t) => {
|
|
800
|
+
let n = qe(t), r = t.planForPriceId, i = (e) => n.subscriptions.retrieve(e, { expand: ["items.data.price"] }), a = (e, t) => {
|
|
801
|
+
let n = Ze(e), i = e.items?.data?.[0]?.price;
|
|
802
|
+
return {
|
|
803
|
+
plan: tt(e, r) ?? "free",
|
|
804
|
+
quantity: Qe(e),
|
|
805
|
+
prorationMinor: t,
|
|
806
|
+
currency: (i?.currency ?? "usd").toLowerCase(),
|
|
807
|
+
currentPeriodStart: n.start,
|
|
808
|
+
currentPeriodEnd: n.end
|
|
809
|
+
};
|
|
810
|
+
}, o = (e, t) => {
|
|
811
|
+
let n = e.items.data[0]?.id;
|
|
812
|
+
return {
|
|
813
|
+
items: [{
|
|
814
|
+
...n === void 0 ? {} : { id: n },
|
|
815
|
+
...t.priceId === void 0 ? {} : { price: t.priceId },
|
|
816
|
+
...t.quantity === void 0 ? {} : { quantity: t.quantity }
|
|
817
|
+
}],
|
|
818
|
+
proration_behavior: rt[t.proration ?? "prorate"],
|
|
819
|
+
...t.priceId !== void 0 && r ? { metadata: {
|
|
820
|
+
...e.metadata,
|
|
821
|
+
plan: r(t.priceId) ?? ""
|
|
822
|
+
} } : {}
|
|
823
|
+
};
|
|
824
|
+
};
|
|
923
825
|
return {
|
|
924
826
|
name: "stripe",
|
|
925
|
-
supportsMeteredUsage:
|
|
926
|
-
createCheckoutSession: (e) =>
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
827
|
+
supportsMeteredUsage: t.supportsMeteredUsage ?? !0,
|
|
828
|
+
createCheckoutSession: (e) => Y("stripe.checkout.sessions.create", async () => {
|
|
829
|
+
let t = await n.checkout.sessions.create({
|
|
830
|
+
mode: "subscription",
|
|
831
|
+
line_items: [{
|
|
832
|
+
price: e.priceId,
|
|
833
|
+
quantity: e.quantity ?? 1,
|
|
834
|
+
...e.adjustableQuantity ? { adjustable_quantity: {
|
|
835
|
+
enabled: !0,
|
|
836
|
+
minimum: e.adjustableQuantity.min,
|
|
837
|
+
maximum: e.adjustableQuantity.max
|
|
838
|
+
} } : {}
|
|
839
|
+
}],
|
|
840
|
+
success_url: e.successUrl,
|
|
841
|
+
cancel_url: e.cancelUrl,
|
|
842
|
+
client_reference_id: e.tenantId,
|
|
843
|
+
metadata: { tenantId: e.tenantId },
|
|
844
|
+
subscription_data: {
|
|
845
|
+
metadata: { tenantId: e.tenantId },
|
|
846
|
+
...e.trialDays === void 0 ? {} : { trial_period_days: e.trialDays }
|
|
847
|
+
},
|
|
848
|
+
...e.providerCustomerId === void 0 ? {} : { customer: e.providerCustomerId },
|
|
849
|
+
automatic_tax: { enabled: !0 },
|
|
850
|
+
allow_promotion_codes: !0
|
|
851
|
+
});
|
|
852
|
+
if (typeof t.url != "string") throw Error("checkout session has no url");
|
|
853
|
+
return { url: t.url };
|
|
854
|
+
}),
|
|
855
|
+
createPortalSession: (e) => Y("stripe.billingPortal.sessions.create", async () => ({ url: (await n.billingPortal.sessions.create({
|
|
941
856
|
customer: e.providerCustomerId,
|
|
942
857
|
return_url: e.returnUrl
|
|
943
|
-
}).
|
|
944
|
-
|
|
945
|
-
|
|
858
|
+
})).url })),
|
|
859
|
+
reportUsage: (e) => Y("stripe.billing.meterEvents.create", async () => {
|
|
860
|
+
await n.billing.meterEvents.create({
|
|
861
|
+
event_name: e.entitlementKey,
|
|
862
|
+
identifier: `${e.tenantId}:${e.entitlementKey}:${e.periodEnd?.toISOString() ?? "current"}`,
|
|
863
|
+
payload: {
|
|
864
|
+
value: String(e.quantity),
|
|
865
|
+
stripe_customer_id: e.tenantId
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
}),
|
|
869
|
+
updateSubscription: (e) => Y("stripe.subscriptions.update", async () => {
|
|
870
|
+
let t = await i(e.providerSubscriptionId), r = await n.subscriptions.update(e.providerSubscriptionId, o(t, e)), s = await ot(n, r);
|
|
871
|
+
return a(r, s);
|
|
872
|
+
}),
|
|
873
|
+
previewSubscriptionChange: (e) => Y("stripe.invoices.createPreview", async () => {
|
|
874
|
+
let t = await i(e.providerSubscriptionId), s = o(t, e), c = (await n.invoices.createPreview({
|
|
875
|
+
subscription: e.providerSubscriptionId,
|
|
876
|
+
subscription_details: {
|
|
877
|
+
items: s.items,
|
|
878
|
+
...s.proration_behavior === void 0 ? {} : { proration_behavior: s.proration_behavior }
|
|
879
|
+
}
|
|
880
|
+
})).lines.data.filter((e) => e.parent?.subscription_item_details?.proration === !0).reduce((e, t) => e + t.amount, 0);
|
|
881
|
+
return {
|
|
882
|
+
...a(t, c),
|
|
883
|
+
...e.quantity === void 0 ? {} : { quantity: e.quantity },
|
|
884
|
+
...e.priceId !== void 0 && r ? { plan: r(e.priceId) ?? "free" } : {}
|
|
885
|
+
};
|
|
886
|
+
}),
|
|
887
|
+
listInvoices: (e) => Y("stripe.invoices.list", async () => (await n.invoices.list({
|
|
888
|
+
customer: e.providerCustomerId,
|
|
889
|
+
limit: e.limit ?? 20
|
|
890
|
+
})).data.map((e) => ({
|
|
891
|
+
providerInvoiceId: e.id ?? "",
|
|
892
|
+
amountMinor: e.amount_due,
|
|
893
|
+
currency: e.currency,
|
|
894
|
+
status: e.status ?? "unknown",
|
|
895
|
+
createdAt: X(e.created),
|
|
896
|
+
hostedUrl: e.hosted_invoice_url ?? null,
|
|
897
|
+
pdfUrl: e.invoice_pdf ?? null
|
|
898
|
+
}))),
|
|
899
|
+
verifyWebhook: (t) => f.try({
|
|
900
|
+
try: () => n.webhooks.constructEvent(Buffer.from(t.rawBody), t.signatureHeader, t.secret),
|
|
901
|
+
catch: (t) => new e({
|
|
902
|
+
source: "stripe.webhooks.constructEvent",
|
|
903
|
+
message: String(t?.message ?? t),
|
|
904
|
+
transient: !1
|
|
905
|
+
})
|
|
906
|
+
}),
|
|
907
|
+
normalizeEvent: (e) => f.succeed(at(e) ? nt(e, r) : null)
|
|
908
|
+
};
|
|
909
|
+
}, at = (e) => typeof e == "object" && !!e && typeof e.type == "string" && typeof e.data == "object", ot = async (e, t) => {
|
|
910
|
+
try {
|
|
911
|
+
return (await e.invoices.createPreview({ subscription: t.id })).lines.data.filter((e) => e.parent?.subscription_item_details?.proration === !0).reduce((e, t) => e + t.amount, 0);
|
|
912
|
+
} catch {
|
|
913
|
+
return 0;
|
|
914
|
+
}
|
|
915
|
+
}, st = (e) => {
|
|
916
|
+
let t = e?.baseUrl ?? "https://mock.billing.local", n = [], r = [], i = (e) => typeof e == "object" && !!e && typeof e._tag == "string";
|
|
917
|
+
return {
|
|
918
|
+
name: "mock",
|
|
919
|
+
supportsMeteredUsage: e?.supportsMeteredUsage ?? !0,
|
|
920
|
+
pushed: n,
|
|
921
|
+
updates: r,
|
|
922
|
+
createCheckoutSession: (e) => f.succeed({ url: `${t}/checkout?tenant=${encodeURIComponent(e.tenantId)}&price=${encodeURIComponent(e.priceId)}` }),
|
|
923
|
+
createPortalSession: (e) => f.succeed({ url: `${t}/portal?customer=${encodeURIComponent(e.providerCustomerId)}` }),
|
|
924
|
+
reportUsage: (e) => f.sync(() => {
|
|
925
|
+
n.push(e);
|
|
926
|
+
}),
|
|
927
|
+
updateSubscription: (e) => f.sync(() => (r.push(e), {
|
|
928
|
+
plan: e.priceId ?? "mock-plan",
|
|
929
|
+
quantity: e.quantity ?? 1,
|
|
930
|
+
prorationMinor: 0,
|
|
931
|
+
currency: "usd",
|
|
932
|
+
currentPeriodStart: null,
|
|
933
|
+
currentPeriodEnd: null
|
|
946
934
|
})),
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
935
|
+
previewSubscriptionChange: (e) => f.succeed({
|
|
936
|
+
plan: e.priceId ?? "mock-plan",
|
|
937
|
+
quantity: e.quantity ?? 1,
|
|
938
|
+
prorationMinor: 0,
|
|
939
|
+
currency: "usd",
|
|
940
|
+
currentPeriodStart: null,
|
|
941
|
+
currentPeriodEnd: null
|
|
942
|
+
}),
|
|
943
|
+
listInvoices: () => f.succeed([]),
|
|
944
|
+
normalizeEvent: (e) => f.succeed(i(e) ? e : null)
|
|
953
945
|
};
|
|
954
|
-
},
|
|
946
|
+
}, ct = (e) => {
|
|
955
947
|
let { provider: t, env: n } = e;
|
|
956
948
|
if (t !== void 0 && typeof t == "object") return t;
|
|
957
949
|
if ((t ?? (n.STRIPE_SECRET_KEY ? "stripe" : "mock")) === "stripe") {
|
|
958
950
|
let t = e.apiKey ?? n.STRIPE_SECRET_KEY;
|
|
959
951
|
if (!t) throw Error("billingPlugin: provider 'stripe' needs an apiKey (option or STRIPE_SECRET_KEY env)");
|
|
960
|
-
return
|
|
952
|
+
return it({
|
|
953
|
+
apiKey: t,
|
|
954
|
+
...e.planForPriceId ? { planForPriceId: e.planForPriceId } : {}
|
|
955
|
+
});
|
|
961
956
|
}
|
|
962
|
-
return
|
|
963
|
-
},
|
|
964
|
-
id:
|
|
965
|
-
path:
|
|
966
|
-
provider:
|
|
967
|
-
payload:
|
|
957
|
+
return st();
|
|
958
|
+
}, lt = k({ scope: "@voltro/plugin-billing" }), ut = "billing", Q = "/billing/webhook", dt = (e) => E({
|
|
959
|
+
id: ut,
|
|
960
|
+
path: Q,
|
|
961
|
+
provider: O(),
|
|
962
|
+
payload: h.Unknown,
|
|
968
963
|
handler: async (t) => {
|
|
969
|
-
let n = await
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
964
|
+
let n = e.provider.verifyWebhook !== void 0 && e.webhookSecret !== null && e.webhookSecret !== void 0 ? await f.runPromise(e.provider.verifyWebhook({
|
|
965
|
+
rawBody: t.rawBody,
|
|
966
|
+
signatureHeader: t.headers["stripe-signature"] ?? "",
|
|
967
|
+
secret: e.webhookSecret ?? ""
|
|
968
|
+
})) : t.body, r = await f.runPromise(e.provider.normalizeEvent(n));
|
|
969
|
+
if (r === null) return;
|
|
970
|
+
await f.runPromise(e.service.applyEvent(r));
|
|
971
|
+
let i = e.onEvent?.[r._tag];
|
|
972
|
+
i !== void 0 && await f.runPromise(i(r).pipe(f.catchAllCause((e) => f.sync(() => {
|
|
973
|
+
lt.warn("billing onEvent side effect failed", {
|
|
974
|
+
event: r._tag,
|
|
976
975
|
cause: String(e)
|
|
977
976
|
});
|
|
978
977
|
}))));
|
|
979
978
|
}
|
|
980
|
-
}),
|
|
979
|
+
}), ft = (e) => D(dt(e), {
|
|
981
980
|
resolveSecret: () => Promise.resolve(e.webhookSecret),
|
|
982
981
|
...e.idempotencyCache === void 0 ? {} : { idempotencyCache: e.idempotencyCache },
|
|
983
982
|
log: (e) => {
|
|
984
|
-
e.status >= 400 &&
|
|
983
|
+
e.status >= 400 && lt.warn("billing webhook rejected", { ...e });
|
|
985
984
|
}
|
|
986
|
-
}),
|
|
985
|
+
}), pt = (e) => e === null ? null : {
|
|
987
986
|
plan: e.plan,
|
|
988
987
|
status: e.status,
|
|
989
988
|
quantity: e.quantity,
|
|
990
989
|
currentPeriodEnd: e.currentPeriodEnd ? e.currentPeriodEnd.toISOString() : null,
|
|
991
990
|
cancelAt: e.cancelAt ? e.cancelAt.toISOString() : null
|
|
992
|
-
},
|
|
991
|
+
}, $ = g([{
|
|
993
992
|
name: "STRIPE_SECRET_KEY",
|
|
994
993
|
required: !1,
|
|
995
994
|
secret: !0,
|
|
@@ -999,41 +998,40 @@ var k = (e, t, n, r) => ({
|
|
|
999
998
|
required: !1,
|
|
1000
999
|
secret: !0,
|
|
1001
1000
|
description: "Stripe webhook signing secret (whsec_…) for verifying webhook payloads."
|
|
1002
|
-
}]),
|
|
1003
|
-
let n = process.env,
|
|
1001
|
+
}]), mt = (t = {}) => {
|
|
1002
|
+
let n = process.env, p = q(t.plans ?? {}), m = ct({
|
|
1004
1003
|
...t.provider === void 0 ? {} : { provider: t.provider },
|
|
1005
1004
|
...t.apiKey === void 0 ? {} : { apiKey: t.apiKey },
|
|
1005
|
+
planForPriceId: p.planForPriceId,
|
|
1006
1006
|
env: n
|
|
1007
|
-
}),
|
|
1007
|
+
}), h = t.webhookSecret ?? $.read("STRIPE_WEBHOOK_SECRET") ?? null;
|
|
1008
1008
|
x({
|
|
1009
|
-
table:
|
|
1009
|
+
table: L,
|
|
1010
1010
|
timeColumn: "updatedAt",
|
|
1011
|
-
ttlMs:
|
|
1011
|
+
ttlMs: ie(process.env.VOLTRO_BILLING_USAGE_TTL_HOURS, 24 * 400),
|
|
1012
1012
|
label: "billing usage counters"
|
|
1013
1013
|
}), x({
|
|
1014
|
-
table:
|
|
1014
|
+
table: J,
|
|
1015
1015
|
timeColumn: "claimedAt",
|
|
1016
|
-
ttlMs:
|
|
1016
|
+
ttlMs: ie(process.env.VOLTRO_BILLING_FLUSH_CLAIM_TTL_HOURS, 1),
|
|
1017
1017
|
label: "billing flush claims"
|
|
1018
1018
|
});
|
|
1019
|
-
let
|
|
1020
|
-
|
|
1021
|
-
let { service: g, holder: _ } = Le({
|
|
1022
|
-
provider: f,
|
|
1019
|
+
let { service: g, holder: _ } = we({
|
|
1020
|
+
provider: m,
|
|
1023
1021
|
plans: p,
|
|
1024
|
-
dunningSchedule: h,
|
|
1025
1022
|
...t.attempts === void 0 ? {} : { attempts: t.attempts },
|
|
1023
|
+
...t.checkout === void 0 ? {} : { checkout: t.checkout },
|
|
1026
1024
|
...t.resolveEntitlementLimit === void 0 ? {} : { resolveEntitlementLimit: t.resolveEntitlementLimit }
|
|
1027
|
-
}),
|
|
1028
|
-
provider:
|
|
1025
|
+
}), v = Te(g), re = ft({
|
|
1026
|
+
provider: m,
|
|
1029
1027
|
service: g,
|
|
1030
|
-
webhookSecret:
|
|
1028
|
+
webhookSecret: h,
|
|
1031
1029
|
...t.onEvent === void 0 ? {} : { onEvent: t.onEvent }
|
|
1032
1030
|
}), y = {
|
|
1033
1031
|
method: "POST",
|
|
1034
|
-
path:
|
|
1032
|
+
path: Q,
|
|
1035
1033
|
handle: async (e) => {
|
|
1036
|
-
let t = await
|
|
1034
|
+
let t = await re({
|
|
1037
1035
|
method: e.method,
|
|
1038
1036
|
path: e.path,
|
|
1039
1037
|
headers: e.headers,
|
|
@@ -1048,40 +1046,63 @@ var k = (e, t, n, r) => ({
|
|
|
1048
1046
|
}
|
|
1049
1047
|
}, b = [
|
|
1050
1048
|
{
|
|
1051
|
-
...
|
|
1049
|
+
...ee,
|
|
1052
1050
|
execute: (e, t) => {
|
|
1053
1051
|
let n = e;
|
|
1054
1052
|
return g.startCheckout({
|
|
1055
1053
|
tenantId: t.request.subject.tenantId ?? "",
|
|
1056
1054
|
plan: n.plan,
|
|
1057
1055
|
successUrl: n.successUrl,
|
|
1058
|
-
cancelUrl: n.cancelUrl
|
|
1056
|
+
cancelUrl: n.cancelUrl,
|
|
1057
|
+
...n.quantity === void 0 ? {} : { quantity: n.quantity }
|
|
1059
1058
|
});
|
|
1060
1059
|
}
|
|
1061
1060
|
},
|
|
1062
1061
|
{
|
|
1063
|
-
...
|
|
1062
|
+
...c,
|
|
1064
1063
|
execute: (e, t) => {
|
|
1065
1064
|
let n = e;
|
|
1066
1065
|
return g.portalUrl(t.request.subject.tenantId ?? "", n.returnUrl);
|
|
1067
1066
|
}
|
|
1068
1067
|
},
|
|
1069
1068
|
{
|
|
1070
|
-
...
|
|
1071
|
-
execute: (e, t) => g.subscription(t.request.subject.tenantId ?? "").pipe(
|
|
1069
|
+
...d,
|
|
1070
|
+
execute: (e, t) => g.subscription(t.request.subject.tenantId ?? "").pipe(f.map((e) => ({ subscription: pt(e) })))
|
|
1072
1071
|
},
|
|
1073
1072
|
{
|
|
1074
|
-
...
|
|
1073
|
+
...l,
|
|
1074
|
+
execute: (e, t) => {
|
|
1075
|
+
let n = e;
|
|
1076
|
+
return g.previewChange(t.request.subject.tenantId ?? "", {
|
|
1077
|
+
...n.plan === void 0 ? {} : { plan: n.plan },
|
|
1078
|
+
...n.quantity === void 0 ? {} : { quantity: n.quantity }
|
|
1079
|
+
}).pipe(f.map((e) => ({
|
|
1080
|
+
plan: e.plan,
|
|
1081
|
+
quantity: e.quantity,
|
|
1082
|
+
prorationMinor: e.prorationMinor,
|
|
1083
|
+
currency: e.currency
|
|
1084
|
+
})));
|
|
1085
|
+
}
|
|
1086
|
+
},
|
|
1087
|
+
{
|
|
1088
|
+
...s,
|
|
1089
|
+
execute: (e, t) => g.invoices(t.request.subject.tenantId ?? "").pipe(f.map((e) => ({ invoices: e.map((e) => ({
|
|
1090
|
+
...e,
|
|
1091
|
+
createdAt: e.createdAt?.toISOString() ?? null
|
|
1092
|
+
})) })))
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
...u,
|
|
1075
1096
|
execute: (e, t) => {
|
|
1076
1097
|
let n = e;
|
|
1077
|
-
return g.reportUsage(t.request.subject.tenantId ?? "", n.key, n.quantity).pipe(
|
|
1098
|
+
return g.reportUsage(t.request.subject.tenantId ?? "", n.key, n.quantity).pipe(f.map(() => ({ ok: !0 })));
|
|
1078
1099
|
}
|
|
1079
1100
|
},
|
|
1080
1101
|
{
|
|
1081
1102
|
...a,
|
|
1082
1103
|
execute: (e, t) => {
|
|
1083
1104
|
let n = e;
|
|
1084
|
-
return g.changePlan(t.request.subject.tenantId ?? "", n.plan).pipe(
|
|
1105
|
+
return g.changePlan(t.request.subject.tenantId ?? "", n.plan).pipe(f.map((e) => ({
|
|
1085
1106
|
plan: e.plan,
|
|
1086
1107
|
quantity: e.quantity,
|
|
1087
1108
|
prorationMinor: e.prorationMinor,
|
|
@@ -1093,7 +1114,7 @@ var k = (e, t, n, r) => ({
|
|
|
1093
1114
|
...o,
|
|
1094
1115
|
execute: (e, t) => {
|
|
1095
1116
|
let n = e;
|
|
1096
|
-
return g.changeSeats(t.request.subject.tenantId ?? "", n.quantity).pipe(
|
|
1117
|
+
return g.changeSeats(t.request.subject.tenantId ?? "", n.quantity).pipe(f.map((e) => ({
|
|
1097
1118
|
plan: e.plan,
|
|
1098
1119
|
quantity: e.quantity,
|
|
1099
1120
|
prorationMinor: e.prorationMinor,
|
|
@@ -1101,33 +1122,33 @@ var k = (e, t, n, r) => ({
|
|
|
1101
1122
|
})));
|
|
1102
1123
|
}
|
|
1103
1124
|
}
|
|
1104
|
-
],
|
|
1125
|
+
], S = (e, t) => ({
|
|
1105
1126
|
kind: "json",
|
|
1106
1127
|
status: e,
|
|
1107
1128
|
data: { error: t }
|
|
1108
|
-
}),
|
|
1129
|
+
}), C = [{
|
|
1109
1130
|
method: "GET",
|
|
1110
1131
|
path: "/stats",
|
|
1111
1132
|
description: "Billing config: provider, declared plans, enforced tags",
|
|
1112
|
-
handler: () =>
|
|
1133
|
+
handler: () => f.succeed({
|
|
1113
1134
|
kind: "json",
|
|
1114
1135
|
data: {
|
|
1115
|
-
provider:
|
|
1116
|
-
supportsMeteredUsage:
|
|
1136
|
+
provider: m.name,
|
|
1137
|
+
supportsMeteredUsage: m.supportsMeteredUsage,
|
|
1117
1138
|
plans: p.planIds(),
|
|
1118
1139
|
enforce: t.enforce ? Object.keys(t.enforce) : [],
|
|
1119
|
-
webhookPath:
|
|
1140
|
+
webhookPath: Q
|
|
1120
1141
|
}
|
|
1121
1142
|
})
|
|
1122
1143
|
}, {
|
|
1123
1144
|
method: "GET",
|
|
1124
1145
|
path: "/usage",
|
|
1125
1146
|
description: "Pending (un-flushed) metered usage counters",
|
|
1126
|
-
handler: () => _.stores.usage.pending().pipe(
|
|
1147
|
+
handler: () => _.stores.usage.pending().pipe(f.map((e) => ({
|
|
1127
1148
|
kind: "json",
|
|
1128
1149
|
data: { usage: e }
|
|
1129
|
-
})),
|
|
1130
|
-
}],
|
|
1150
|
+
})), f.catchAll((e) => f.succeed(S(500, e.message))))
|
|
1151
|
+
}], w = [{
|
|
1131
1152
|
schema: e,
|
|
1132
1153
|
import: {
|
|
1133
1154
|
module: "@voltro/plugin-billing/errors",
|
|
@@ -1139,9 +1160,9 @@ var k = (e, t, n, r) => ({
|
|
|
1139
1160
|
module: "@voltro/plugin-billing/errors",
|
|
1140
1161
|
name: "EntitlementExceeded"
|
|
1141
1162
|
}
|
|
1142
|
-
}],
|
|
1143
|
-
D !== void 0 &&
|
|
1144
|
-
let O = D !== void 0 && Object.keys(D).length > 0 ?
|
|
1163
|
+
}], T = t.enforce, E = T !== void 0 && Object.keys(T).length > 0 ? N(T, g) : void 0, D = t.metering;
|
|
1164
|
+
D !== void 0 && De(D);
|
|
1165
|
+
let O = D !== void 0 && Object.keys(D).length > 0 ? Pe(g, D) : void 0, k = D !== void 0 && ze(D), A = te([O, E].filter((e) => e !== void 0)), j, M, P = [
|
|
1145
1166
|
"store:write",
|
|
1146
1167
|
"inspect:read",
|
|
1147
1168
|
"network:outbound:*",
|
|
@@ -1149,35 +1170,34 @@ var k = (e, t, n, r) => ({
|
|
|
1149
1170
|
...O === void 0 ? [] : ["rpc:intercept:query"],
|
|
1150
1171
|
...k ? ["store:changes:read"] : []
|
|
1151
1172
|
];
|
|
1152
|
-
return
|
|
1173
|
+
return ne({
|
|
1153
1174
|
name: t.name ? `@voltro/plugin-billing#${t.name}` : "@voltro/plugin-billing",
|
|
1154
1175
|
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.",
|
|
1155
|
-
permissions:
|
|
1156
|
-
declaredEnv:
|
|
1157
|
-
services:
|
|
1176
|
+
permissions: P,
|
|
1177
|
+
declaredEnv: $.declared,
|
|
1178
|
+
services: v,
|
|
1158
1179
|
routes: b,
|
|
1159
1180
|
rpcClientDescriptors: i,
|
|
1160
1181
|
httpRoutes: [y],
|
|
1161
|
-
inspectEndpoints:
|
|
1162
|
-
extendSchema: { tables: [...
|
|
1163
|
-
errorSchemas:
|
|
1182
|
+
inspectEndpoints: C,
|
|
1183
|
+
extendSchema: { tables: [...le(), He] },
|
|
1184
|
+
errorSchemas: w,
|
|
1164
1185
|
...A === void 0 ? {} : {
|
|
1165
1186
|
interceptMutation: A,
|
|
1166
1187
|
interceptAction: A
|
|
1167
1188
|
},
|
|
1168
1189
|
...O === void 0 ? {} : { interceptQuery: O },
|
|
1169
|
-
...k ? { onChangeEvent:
|
|
1190
|
+
...k ? { onChangeEvent: Fe(g, D) } : {},
|
|
1170
1191
|
bindDataStore: (e) => {
|
|
1171
|
-
_.stores =
|
|
1192
|
+
_.stores = W(e), j = e;
|
|
1172
1193
|
},
|
|
1173
|
-
onActivate: (e) =>
|
|
1194
|
+
onActivate: (e) => f.sync(() => {
|
|
1174
1195
|
e.logger.info("billing active", {
|
|
1175
|
-
provider:
|
|
1196
|
+
provider: m.name,
|
|
1176
1197
|
plans: p.planIds().length,
|
|
1177
|
-
enforce:
|
|
1198
|
+
enforce: T ? Object.keys(T).length : 0,
|
|
1178
1199
|
metering: D ? Object.keys(D).length : 0,
|
|
1179
|
-
|
|
1180
|
-
webhook: $
|
|
1200
|
+
webhook: Q
|
|
1181
1201
|
});
|
|
1182
1202
|
let n = t.flushIntervalMs ?? 6e4, r = D, i = r !== void 0 && Object.keys(r).length > 0;
|
|
1183
1203
|
if (n > 0) {
|
|
@@ -1187,15 +1207,15 @@ var k = (e, t, n, r) => ({
|
|
|
1187
1207
|
if (t === void 0) return;
|
|
1188
1208
|
let a = Date.now();
|
|
1189
1209
|
(async () => {
|
|
1190
|
-
await
|
|
1210
|
+
await We(t, Ue(a, n), e, a) && i && await f.runPromise(Re(g, t, r).pipe(f.catchAll(() => f.void)));
|
|
1191
1211
|
})();
|
|
1192
1212
|
}, n), M.unref?.();
|
|
1193
1213
|
}
|
|
1194
1214
|
}),
|
|
1195
|
-
onDeactivate: () =>
|
|
1215
|
+
onDeactivate: () => f.sync(() => {
|
|
1196
1216
|
M !== void 0 && (clearInterval(M), M = void 0);
|
|
1197
1217
|
})
|
|
1198
1218
|
});
|
|
1199
1219
|
};
|
|
1200
1220
|
//#endregion
|
|
1201
|
-
export {
|
|
1221
|
+
export { P as BILLING_CUSTOMERS_TABLE, J as BILLING_FLUSH_CLAIMS_TABLE, I as BILLING_INVOICES_TABLE, F as BILLING_SUBSCRIPTIONS_TABLE, L as BILLING_USAGE_TABLE, ut as BILLING_WEBHOOK_ID, Q as BILLING_WEBHOOK_PATH, e as BillingError, t as BillingService, n as DEFAULT_PLAN, r as EntitlementExceeded, ae as billingCustomersTable, He as billingFlushClaimsTable, se as billingInvoicesTable, mt as billingPlugin, Te as billingServiceLayer, oe as billingSubscriptionsTable, le as billingTables, ce as billingUsageTable, dt as billingWebhookDescriptor, we as buildBillingService, N as buildEnforceInterceptor, q as buildPlanRegistry, We as claimFlushWindow, W as dataStoreStores, Ve as emptyPlanRegistry, A as evaluateEntitlement, Ue as flushWindowKey, Se as memoryStores, st as mockProvider, ft as mountBillingWebhook, nt as normalizeStripeEvent, G as periodKey, M as requireEntitlement, ct as resolveProvider, it as stripeProvider };
|