@fonderie/billing 5.3.1 → 6.0.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/README.md +34 -0
- package/brain/outcomes.md +71 -0
- package/brain/signatures.md +191 -17
- package/dist/{index-Byy5mBE4.d.ts → index-BdNYDuhk.d.ts} +107 -9
- package/dist/{index-DjAGcrSi.d.cts → index-Ca4pXx07.d.cts} +107 -9
- package/dist/index.cjs +1097 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +137 -15
- package/dist/index.d.ts +137 -15
- package/dist/index.js +1076 -145
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.cjs +180 -0
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +1 -1
- package/dist/middlewares/index.d.ts +1 -1
- package/dist/middlewares/index.js +180 -0
- package/dist/middlewares/index.js.map +1 -1
- package/dist/migrations/sql/006_wallet.sql +85 -0
- package/dist/types.cjs +17 -3
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +34 -7
- package/dist/types.d.ts +34 -7
- package/dist/types.js +13 -2
- package/dist/types.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { Middleware, IFonderieContext } from '@fonderie/core';
|
|
2
2
|
import { IStoreAdapter } from '@fonderie/store';
|
|
3
|
-
import { SubscriberType, PolicyEntry } from './types.cjs';
|
|
3
|
+
import { SubscriberType, BillingInterval, PolicyEntry, IWalletRate } from './types.cjs';
|
|
4
4
|
|
|
5
5
|
interface IBillingEvent {
|
|
6
6
|
type: string;
|
|
7
7
|
subscription: INormalizedSubscription | null;
|
|
8
|
+
payment?: INormalizedPayment | null;
|
|
9
|
+
}
|
|
10
|
+
interface INormalizedPayment {
|
|
11
|
+
sessionId: string;
|
|
12
|
+
providerTxId: string | null;
|
|
13
|
+
amountTotal: bigint | null;
|
|
14
|
+
currency: string | null;
|
|
15
|
+
paymentStatus: string | null;
|
|
16
|
+
metadata: Record<string, string>;
|
|
8
17
|
}
|
|
9
18
|
interface INormalizedSubscription {
|
|
10
19
|
subscriberType: SubscriberType;
|
|
@@ -21,14 +30,14 @@ interface INormalizedSubscription {
|
|
|
21
30
|
currentPeriodEnd: Date;
|
|
22
31
|
cancelAtPeriodEnd: boolean;
|
|
23
32
|
trialEndsAt: Date | null;
|
|
24
|
-
interval:
|
|
33
|
+
interval: BillingInterval;
|
|
25
34
|
}
|
|
26
35
|
interface IResolvedPrice {
|
|
27
36
|
priceId: string;
|
|
28
37
|
lookupKey: string | null;
|
|
29
|
-
unitAmount:
|
|
38
|
+
unitAmount: bigint;
|
|
30
39
|
currency: string;
|
|
31
|
-
interval:
|
|
40
|
+
interval: BillingInterval;
|
|
32
41
|
nickname: string | null;
|
|
33
42
|
productId: string;
|
|
34
43
|
active: boolean;
|
|
@@ -54,6 +63,20 @@ interface IBillingProvider {
|
|
|
54
63
|
}): Promise<{
|
|
55
64
|
url: string;
|
|
56
65
|
}>;
|
|
66
|
+
createPaymentCheckoutSession?(opts: {
|
|
67
|
+
customerId: string;
|
|
68
|
+
amount: bigint;
|
|
69
|
+
currency: string;
|
|
70
|
+
name: string;
|
|
71
|
+
quantity?: number;
|
|
72
|
+
priceId?: string;
|
|
73
|
+
metadata: Record<string, string>;
|
|
74
|
+
successUrl: string;
|
|
75
|
+
cancelUrl: string;
|
|
76
|
+
}): Promise<{
|
|
77
|
+
url: string;
|
|
78
|
+
sessionId: string;
|
|
79
|
+
}>;
|
|
57
80
|
resolvePriceById(priceId: string): Promise<IResolvedPrice | null>;
|
|
58
81
|
resolvePricesByLookupKey(lookupKeys: string[]): Promise<Map<string, IResolvedPrice>>;
|
|
59
82
|
updateSubscription(opts: {
|
|
@@ -88,11 +111,12 @@ interface IBillingPlanPrice {
|
|
|
88
111
|
/** Stripe price id. Used for hydration and as a lookup_key fallback. */
|
|
89
112
|
priceId?: string;
|
|
90
113
|
/**
|
|
91
|
-
* Display amount in
|
|
92
|
-
*
|
|
93
|
-
*
|
|
114
|
+
* Display amount in the smallest currency unit (bigint, e.g. 1999n = $19.99) —
|
|
115
|
+
* the seed value written to fonderie_plans and the fallback shown (flagged
|
|
116
|
+
* pricingStale) when hydration is off or Stripe is unreachable. When
|
|
117
|
+
* hydration resolves a live price, the live amount wins.
|
|
94
118
|
*/
|
|
95
|
-
amount?:
|
|
119
|
+
amount?: bigint;
|
|
96
120
|
}
|
|
97
121
|
/**
|
|
98
122
|
* Read-through pricing: amount/currency come from Stripe (source of truth) rather
|
|
@@ -113,6 +137,28 @@ interface IBillingPlanDefaults {
|
|
|
113
137
|
warnAt?: number;
|
|
114
138
|
buffer?: number;
|
|
115
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Per-plan wallet economics. Requires config.wallet to be set — a plan-level
|
|
142
|
+
* wallet without the global opt-in is ignored (with a boot warning).
|
|
143
|
+
*/
|
|
144
|
+
interface IBillingPlanWallet {
|
|
145
|
+
/** Overrides the global wallet currency for this plan's grants and rates. */
|
|
146
|
+
currency?: string;
|
|
147
|
+
/** Display precision override. */
|
|
148
|
+
precision?: number;
|
|
149
|
+
/**
|
|
150
|
+
* Credits auto-granted once per grantPeriod, applied lazily by withBilling
|
|
151
|
+
* on the subscriber's first request of the period. Only granted while the
|
|
152
|
+
* subscription is active or trialing (no new credit while payment fails).
|
|
153
|
+
*/
|
|
154
|
+
grantAmount?: bigint;
|
|
155
|
+
/** Grant cadence for grantAmount. Default 'month'. */
|
|
156
|
+
grantPeriod?: 'month' | 'week' | 'day';
|
|
157
|
+
/** How far below zero rate debits may take the balance. Default 0n (block at zero). */
|
|
158
|
+
overdraftLimit?: bigint;
|
|
159
|
+
/** Per-metric unit costs, e.g. { 'sms:send': { cost: 75n, unit: 'msg' } }. */
|
|
160
|
+
rates?: Record<string, IWalletRate>;
|
|
161
|
+
}
|
|
116
162
|
interface IBillingPlan {
|
|
117
163
|
name: string;
|
|
118
164
|
description?: string;
|
|
@@ -122,6 +168,7 @@ interface IBillingPlan {
|
|
|
122
168
|
yearly?: IBillingPlanPrice;
|
|
123
169
|
defaults?: IBillingPlanDefaults;
|
|
124
170
|
policy?: Record<string, PolicyEntry>;
|
|
171
|
+
wallet?: IBillingPlanWallet;
|
|
125
172
|
metadata?: Record<string, unknown>;
|
|
126
173
|
}
|
|
127
174
|
type RateLimitBackendConfig = 'memory' | 'db' | ICounterBackend;
|
|
@@ -129,6 +176,56 @@ interface IBillingNotificationsConfig {
|
|
|
129
176
|
warnAt?: boolean;
|
|
130
177
|
softHit?: boolean;
|
|
131
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* A purchasable credit top-up, synced to fonderie_credit_packs at boot (same
|
|
181
|
+
* pattern as plans). Purchases go through the provider's one-time checkout;
|
|
182
|
+
* the payment webhook credits `credits` to the buyer's wallet.
|
|
183
|
+
*/
|
|
184
|
+
interface IBillingCreditPack {
|
|
185
|
+
/** Stable identifier used by POST /billing/wallet/checkout, e.g. 'small'. */
|
|
186
|
+
id: string;
|
|
187
|
+
name: string;
|
|
188
|
+
/** Wallet credits granted on purchase, in the smallest wallet unit. */
|
|
189
|
+
credits: bigint;
|
|
190
|
+
/** Purchase price in the provider's smallest currency unit. */
|
|
191
|
+
priceAmount: bigint;
|
|
192
|
+
/**
|
|
193
|
+
* ISO 4217 PAYMENT currency for the provider charge; defaults to the
|
|
194
|
+
* buyer's wallet currency. Credits always land in the buyer's wallet
|
|
195
|
+
* currency regardless of what the charge was priced in.
|
|
196
|
+
*/
|
|
197
|
+
currency?: string;
|
|
198
|
+
/** Existing provider Price id — used instead of the ad-hoc priceAmount. */
|
|
199
|
+
priceId?: string;
|
|
200
|
+
/** Inactive packs stay in the DB but can no longer be checked out. */
|
|
201
|
+
active?: boolean;
|
|
202
|
+
metadata?: Record<string, unknown>;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Opt-in stored-value wallet. Presence of this object activates the wallet
|
|
206
|
+
* subsystem (routes, credit packs, per-plan grants and rates); leaving it out
|
|
207
|
+
* changes nothing for existing subscription-only consumers.
|
|
208
|
+
*/
|
|
209
|
+
interface IBillingWalletConfig {
|
|
210
|
+
/** Default wallet currency when a plan doesn't override it. Default 'USD'. */
|
|
211
|
+
currency?: string;
|
|
212
|
+
/** Display precision — decimal places of the smallest unit. Default 2. */
|
|
213
|
+
precision?: number;
|
|
214
|
+
/**
|
|
215
|
+
* Bearer token guarding POST /billing/wallet/grant (manual support/ops
|
|
216
|
+
* grants). The route is only registered when a token is configured.
|
|
217
|
+
*/
|
|
218
|
+
adminToken?: string;
|
|
219
|
+
/**
|
|
220
|
+
* Signing secret for POST /billing/webhook/payment. REQUIRED for pack
|
|
221
|
+
* purchases: the route answers 500 until it is set, and it deliberately
|
|
222
|
+
* does NOT fall back to the subscription webhook's secret — per-endpoint
|
|
223
|
+
* secrets keep a delivery captured for one endpoint from replaying
|
|
224
|
+
* against the other.
|
|
225
|
+
*/
|
|
226
|
+
webhookSecret?: string;
|
|
227
|
+
creditPacks?: IBillingCreditPack[];
|
|
228
|
+
}
|
|
132
229
|
interface IBillingConfig {
|
|
133
230
|
provider: IBillingProvider;
|
|
134
231
|
plans: IBillingPlan[];
|
|
@@ -140,6 +237,7 @@ interface IBillingConfig {
|
|
|
140
237
|
};
|
|
141
238
|
notifications?: IBillingNotificationsConfig;
|
|
142
239
|
pricing?: IBillingPricingConfig;
|
|
240
|
+
wallet?: IBillingWalletConfig;
|
|
143
241
|
}
|
|
144
242
|
declare const MESSAGE_KEYS: {
|
|
145
243
|
readonly limitWarning: "billing.limit-warning";
|
|
@@ -153,4 +251,4 @@ declare function requirePlan(plans: string | string[], store: IStoreAdapter, ctx
|
|
|
153
251
|
|
|
154
252
|
declare function withBilling(store: IStoreAdapter, config: IBillingConfig, backend: ICounterBackend): Middleware;
|
|
155
253
|
|
|
156
|
-
export { type BillingMessageKey as B, type IBillingConfig as I, MESSAGE_KEYS as M, type RateLimitBackendConfig as R, type IBillingProvider as a, type IResolvedPrice as b, type IBillingEvent as c, type
|
|
254
|
+
export { type BillingMessageKey as B, type IBillingConfig as I, MESSAGE_KEYS as M, type RateLimitBackendConfig as R, type IBillingProvider as a, type IResolvedPrice as b, type IBillingEvent as c, type IBillingPlan as d, type ICounterBackend as e, type IBillingCreditPack as f, type IBillingNotificationsConfig as g, type IBillingPlanDefaults as h, type IBillingPlanPrice as i, type IBillingPlanWallet as j, type IBillingPricingConfig as k, type IBillingWalletConfig as l, type INormalizedPayment as m, requirePlan as r, withBilling as w };
|