@venturekit-pro/billing 0.0.38 → 0.0.40
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 +49 -0
- package/dist/dunning/schedule.d.ts +86 -0
- package/dist/dunning/schedule.d.ts.map +1 -0
- package/dist/dunning/schedule.js +95 -0
- package/dist/dunning/schedule.js.map +1 -0
- package/dist/entitlements/entitlements.d.ts +127 -0
- package/dist/entitlements/entitlements.d.ts.map +1 -0
- package/dist/entitlements/entitlements.js +160 -0
- package/dist/entitlements/entitlements.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/invoices/generator.d.ts.map +1 -1
- package/dist/invoices/generator.js +3 -1
- package/dist/invoices/generator.js.map +1 -1
- package/dist/subscriptions/manager.d.ts.map +1 -1
- package/dist/subscriptions/manager.js +3 -1
- package/dist/subscriptions/manager.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -64,6 +64,55 @@ const hasSupport = hasFeature(plans, 'free', 'support');
|
|
|
64
64
|
// → false
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
## Entitlements
|
|
68
|
+
|
|
69
|
+
Plan + per-tenant overrides → what a tenant may do, with HTTP-mapped refusals
|
|
70
|
+
you can throw straight from a route:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { createEntitlementsResolver } from '@venturekit-pro/billing';
|
|
74
|
+
|
|
75
|
+
const entitlements = createEntitlementsResolver({
|
|
76
|
+
plans,
|
|
77
|
+
getPlanId: (tenantId) => subscriptions.currentPlanId(tenantId),
|
|
78
|
+
getOverrides: (tenantId) => deals.overridesFor(tenantId), // { seats: { limit: 500 } }
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const ent = await entitlements.forSubject(ctx.tenant.id);
|
|
82
|
+
ent.require('api_access'); // 402 PLAN_UPGRADE_REQUIRED
|
|
83
|
+
await ent.requireWithinLimit('seats', () => members.count(tenantId)); // 403 PLAN_LIMIT_REACHED at the cap
|
|
84
|
+
ctx.tenant.quotas = ent.toQuotas({ seats: 'maxUsers' }); // feeds tenancy's quota middleware
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`EntitlementError` carries `details.featureKey` / `planId` / `limit` / `usage` for
|
|
88
|
+
the upgrade prompt and renders through `@venturekit/runtime`'s error boundary
|
|
89
|
+
without a runtime dependency. Call `entitlements.invalidate(tenantId)` after a
|
|
90
|
+
plan change.
|
|
91
|
+
|
|
92
|
+
## Dunning
|
|
93
|
+
|
|
94
|
+
Which payment reminder an unpaid invoice is due, for a cron to ask about every open
|
|
95
|
+
invoice. Pure and clock-free; the mail and the invoice model are yours.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { nextDunningStep, dunningScheduleRefusal } from '@venturekit-pro/billing';
|
|
99
|
+
|
|
100
|
+
const schedule = { enabled: true, offsetsDays: [-3, 7, 14, 30] }; // days from the due date
|
|
101
|
+
dunningScheduleRefusal(schedule.offsetsDays); // null, or why the setting is refused
|
|
102
|
+
|
|
103
|
+
const step = nextDunningStep({
|
|
104
|
+
dueDate: invoice.dueDate, // 'YYYY-MM-DD'
|
|
105
|
+
schedule,
|
|
106
|
+
sent: reminders.map((r) => ({ sentAtISO: r.sentAt, offsetDays: r.step })), // step null = sent by a person
|
|
107
|
+
today: todayIn(customer.timezone),
|
|
108
|
+
});
|
|
109
|
+
if (step !== null) await sendReminder(invoice, step); // and record { step } for next time
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The latest step whose day has come is due; each step goes once; steps skipped over
|
|
113
|
+
are gone (the schedule says *when to nudge*, not how many messages to catch up on);
|
|
114
|
+
and a reminder a person sent since the previous step covers the current one.
|
|
115
|
+
|
|
67
116
|
## Usage-to-Invoice Mapping
|
|
68
117
|
|
|
69
118
|
```typescript
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dunning schedule — when an unpaid invoice is due a payment reminder.
|
|
3
|
+
*
|
|
4
|
+
* Every product that invoices ends up chasing payment, and the rule is the same
|
|
5
|
+
* everywhere: a handful of **steps**, each a number of days from the due date
|
|
6
|
+
* (negative before it — "three days to go", positive after — "a week late"),
|
|
7
|
+
* each sent once, and never on top of a human who has already written. Payment
|
|
8
|
+
* processing, the mail itself and the invoice model are the app's; this module
|
|
9
|
+
* is only the decision, pure and clock-free, so a cron can ask it for every open
|
|
10
|
+
* invoice and a test can pin every edge.
|
|
11
|
+
*
|
|
12
|
+
* Three rules, in {@link nextDunningStep}:
|
|
13
|
+
*
|
|
14
|
+
* 1. **The latest step whose day has come is the candidate.** Steps skipped
|
|
15
|
+
* over — the cron was down, the schedule was edited — are gone: the schedule
|
|
16
|
+
* describes *when to nudge*, not a quota of messages to catch up on.
|
|
17
|
+
* 2. **Each step goes once.** A step the schedule already sent (or a later one:
|
|
18
|
+
* a step sent a day late is still that step) is not due again.
|
|
19
|
+
* 3. **Never over a person.** A reminder somebody sent by hand since the
|
|
20
|
+
* previous step's day has done that stretch's nudging; the step is skipped.
|
|
21
|
+
*
|
|
22
|
+
* Days are compared as `YYYY-MM-DD` strings in whatever zone the caller renders
|
|
23
|
+
* them in — the app decides what "today" is for its customers (their business
|
|
24
|
+
* zone, not the server's), and passes it in.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const schedule = { enabled: true, offsetsDays: [-3, 7, 14, 30] };
|
|
29
|
+
* const step = nextDunningStep({
|
|
30
|
+
* dueDate: invoice.dueDate,
|
|
31
|
+
* schedule,
|
|
32
|
+
* sent: reminders.map((r) => ({ sentAtISO: r.sentAt, offsetDays: r.offsetDays })),
|
|
33
|
+
* today: todayIn('Africa/Casablanca'),
|
|
34
|
+
* });
|
|
35
|
+
* if (step !== null) await sendReminder(invoice, step);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
/** The steps of a dunning schedule, in days from the invoice's due date. */
|
|
39
|
+
export interface DunningSchedule {
|
|
40
|
+
/** Off means no automatic reminder at all; by-hand reminders are unaffected. */
|
|
41
|
+
enabled: boolean;
|
|
42
|
+
/** Days from the due date; negative is before it. Any order, duplicates ignored. */
|
|
43
|
+
offsetsDays: readonly number[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A reminder already sent about the invoice: when, and — for one the schedule
|
|
47
|
+
* sent — which step it was. `offsetDays: null` is a reminder a person sent.
|
|
48
|
+
*/
|
|
49
|
+
export interface DunningReminderSent {
|
|
50
|
+
sentAtISO: string;
|
|
51
|
+
offsetDays: number | null;
|
|
52
|
+
}
|
|
53
|
+
export interface NextDunningStepInput {
|
|
54
|
+
/** The invoice's due date: `YYYY-MM-DD`, or an ISO instant whose date part is used. */
|
|
55
|
+
dueDate: string;
|
|
56
|
+
schedule: DunningSchedule;
|
|
57
|
+
/** Every reminder already sent about this invoice, by the schedule or by hand. */
|
|
58
|
+
sent: readonly DunningReminderSent[];
|
|
59
|
+
/** Today, `YYYY-MM-DD`, in the zone the app chases in. */
|
|
60
|
+
today: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The bounds a schedule is kept within: a handful of steps, none absurdly far from
|
|
64
|
+
* the due date. Apps that expose the schedule as a setting apply the same bounds on
|
|
65
|
+
* the form ({@link dunningScheduleRefusal}).
|
|
66
|
+
*/
|
|
67
|
+
export declare const DUNNING_SCHEDULE_LIMITS: {
|
|
68
|
+
readonly maxSteps: 8;
|
|
69
|
+
readonly minOffsetDays: -60;
|
|
70
|
+
readonly maxOffsetDays: 365;
|
|
71
|
+
};
|
|
72
|
+
/** Why a schedule's steps are refused, or `null` when they are acceptable. */
|
|
73
|
+
export declare function dunningScheduleRefusal(offsetsDays: readonly number[]): string | null;
|
|
74
|
+
/** The steps as the schedule applies them: distinct, ascending. */
|
|
75
|
+
export declare function normalizeDunningSteps(offsetsDays: readonly number[]): number[];
|
|
76
|
+
/** The `YYYY-MM-DD` part of a date or instant. */
|
|
77
|
+
export declare function dayOf(dateOrInstant: string): string;
|
|
78
|
+
/** `YYYY-MM-DD` moved by `days`, computed in UTC so the calendar arithmetic is zone-free. */
|
|
79
|
+
export declare function addDays(day: string, days: number): string;
|
|
80
|
+
/**
|
|
81
|
+
* The step due today for an invoice, or `null` — see the module note for the
|
|
82
|
+
* three rules. The invoice's own state (paid, void, draft) is the caller's to
|
|
83
|
+
* check first: this decides *which* reminder, not *whether* the invoice is owed.
|
|
84
|
+
*/
|
|
85
|
+
export declare function nextDunningStep({ dueDate, schedule, sent, today }: NextDunningStepInput): number | null;
|
|
86
|
+
//# sourceMappingURL=schedule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/dunning/schedule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,OAAO,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,eAAe,CAAC;IAC1B,kFAAkF;IAClF,IAAI,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACrC,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;CAI1B,CAAC;AAEX,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAQpF;AAED,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE9E;AAED,kDAAkD;AAClD,wBAAgB,KAAK,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,6FAA6F;AAC7F,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,oBAAoB,GAAG,MAAM,GAAG,IAAI,CAcvG"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dunning schedule — when an unpaid invoice is due a payment reminder.
|
|
3
|
+
*
|
|
4
|
+
* Every product that invoices ends up chasing payment, and the rule is the same
|
|
5
|
+
* everywhere: a handful of **steps**, each a number of days from the due date
|
|
6
|
+
* (negative before it — "three days to go", positive after — "a week late"),
|
|
7
|
+
* each sent once, and never on top of a human who has already written. Payment
|
|
8
|
+
* processing, the mail itself and the invoice model are the app's; this module
|
|
9
|
+
* is only the decision, pure and clock-free, so a cron can ask it for every open
|
|
10
|
+
* invoice and a test can pin every edge.
|
|
11
|
+
*
|
|
12
|
+
* Three rules, in {@link nextDunningStep}:
|
|
13
|
+
*
|
|
14
|
+
* 1. **The latest step whose day has come is the candidate.** Steps skipped
|
|
15
|
+
* over — the cron was down, the schedule was edited — are gone: the schedule
|
|
16
|
+
* describes *when to nudge*, not a quota of messages to catch up on.
|
|
17
|
+
* 2. **Each step goes once.** A step the schedule already sent (or a later one:
|
|
18
|
+
* a step sent a day late is still that step) is not due again.
|
|
19
|
+
* 3. **Never over a person.** A reminder somebody sent by hand since the
|
|
20
|
+
* previous step's day has done that stretch's nudging; the step is skipped.
|
|
21
|
+
*
|
|
22
|
+
* Days are compared as `YYYY-MM-DD` strings in whatever zone the caller renders
|
|
23
|
+
* them in — the app decides what "today" is for its customers (their business
|
|
24
|
+
* zone, not the server's), and passes it in.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const schedule = { enabled: true, offsetsDays: [-3, 7, 14, 30] };
|
|
29
|
+
* const step = nextDunningStep({
|
|
30
|
+
* dueDate: invoice.dueDate,
|
|
31
|
+
* schedule,
|
|
32
|
+
* sent: reminders.map((r) => ({ sentAtISO: r.sentAt, offsetDays: r.offsetDays })),
|
|
33
|
+
* today: todayIn('Africa/Casablanca'),
|
|
34
|
+
* });
|
|
35
|
+
* if (step !== null) await sendReminder(invoice, step);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* The bounds a schedule is kept within: a handful of steps, none absurdly far from
|
|
40
|
+
* the due date. Apps that expose the schedule as a setting apply the same bounds on
|
|
41
|
+
* the form ({@link dunningScheduleRefusal}).
|
|
42
|
+
*/
|
|
43
|
+
export const DUNNING_SCHEDULE_LIMITS = {
|
|
44
|
+
maxSteps: 8,
|
|
45
|
+
minOffsetDays: -60,
|
|
46
|
+
maxOffsetDays: 365,
|
|
47
|
+
};
|
|
48
|
+
/** Why a schedule's steps are refused, or `null` when they are acceptable. */
|
|
49
|
+
export function dunningScheduleRefusal(offsetsDays) {
|
|
50
|
+
const { maxSteps, minOffsetDays, maxOffsetDays } = DUNNING_SCHEDULE_LIMITS;
|
|
51
|
+
if (offsetsDays.length > maxSteps)
|
|
52
|
+
return `At most ${maxSteps} reminder steps`;
|
|
53
|
+
if (offsetsDays.some((d) => !Number.isInteger(d) || d < minOffsetDays || d > maxOffsetDays)) {
|
|
54
|
+
return `Each reminder step is a whole number of days between ${minOffsetDays} and ${maxOffsetDays}`;
|
|
55
|
+
}
|
|
56
|
+
if (new Set(offsetsDays).size !== offsetsDays.length)
|
|
57
|
+
return 'Reminder steps must be distinct';
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
/** The steps as the schedule applies them: distinct, ascending. */
|
|
61
|
+
export function normalizeDunningSteps(offsetsDays) {
|
|
62
|
+
return [...new Set(offsetsDays)].sort((a, b) => a - b);
|
|
63
|
+
}
|
|
64
|
+
/** The `YYYY-MM-DD` part of a date or instant. */
|
|
65
|
+
export function dayOf(dateOrInstant) {
|
|
66
|
+
return dateOrInstant.slice(0, 10);
|
|
67
|
+
}
|
|
68
|
+
/** `YYYY-MM-DD` moved by `days`, computed in UTC so the calendar arithmetic is zone-free. */
|
|
69
|
+
export function addDays(day, days) {
|
|
70
|
+
const d = new Date(`${day}T00:00:00Z`);
|
|
71
|
+
d.setUTCDate(d.getUTCDate() + days);
|
|
72
|
+
return d.toISOString().slice(0, 10);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The step due today for an invoice, or `null` — see the module note for the
|
|
76
|
+
* three rules. The invoice's own state (paid, void, draft) is the caller's to
|
|
77
|
+
* check first: this decides *which* reminder, not *whether* the invoice is owed.
|
|
78
|
+
*/
|
|
79
|
+
export function nextDunningStep({ dueDate, schedule, sent, today }) {
|
|
80
|
+
if (!schedule.enabled)
|
|
81
|
+
return null;
|
|
82
|
+
const steps = normalizeDunningSteps(schedule.offsetsDays);
|
|
83
|
+
const due = dayOf(dueDate);
|
|
84
|
+
const dayFor = (offset) => addDays(due, offset);
|
|
85
|
+
const index = steps.filter((offset) => dayFor(offset) <= today).length - 1;
|
|
86
|
+
if (index < 0)
|
|
87
|
+
return null;
|
|
88
|
+
const step = steps[index];
|
|
89
|
+
if (sent.some((r) => r.offsetDays !== null && r.offsetDays >= step))
|
|
90
|
+
return null;
|
|
91
|
+
const previousStepDay = index > 0 ? dayFor(steps[index - 1]) : null;
|
|
92
|
+
const byHandSince = sent.some((r) => r.offsetDays === null && (previousStepDay === null || dayOf(r.sentAtISO) > previousStepDay));
|
|
93
|
+
return byHandSince ? null : step;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/dunning/schedule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entitlements — what a tenant (or customer) may do right now, resolved
|
|
3
|
+
* from its plan plus any per-tenant overrides, cached, and enforceable
|
|
4
|
+
* from a route with the right HTTP answer.
|
|
5
|
+
*
|
|
6
|
+
* The feature gate (`createFeatureGate`) answers "is feature X in plan P";
|
|
7
|
+
* this layer adds what a product needs around it:
|
|
8
|
+
*
|
|
9
|
+
* - **who is on which plan** — `getPlanId(subjectId)` is the app's
|
|
10
|
+
* lookup (subscription row, tenant column), cached per subject;
|
|
11
|
+
* - **per-tenant overrides** — a negotiated deal ("500 seats on Pro")
|
|
12
|
+
* or a temporary grant, as `{ featureKey: { enabled?, limit? } }`;
|
|
13
|
+
* - **HTTP-mapped refusals** — {@link EntitlementError} renders as
|
|
14
|
+
* `402 PLAN_UPGRADE_REQUIRED` (feature not in plan) or
|
|
15
|
+
* `403 PLAN_LIMIT_REACHED` (limit exhausted) through the runtime's
|
|
16
|
+
* error boundary, with `details.featureKey` / `details.planId` /
|
|
17
|
+
* `details.limit` for the upgrade prompt — no `@venturekit/runtime`
|
|
18
|
+
* import needed (structural marker);
|
|
19
|
+
* - **adapters** — `toQuotas()` feeds `@venturekit-pro/tenancy`'s quota
|
|
20
|
+
* middleware, `limitOf()` feeds rate-limit presets.
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* const entitlements = createEntitlementsResolver({
|
|
24
|
+
* plans,
|
|
25
|
+
* getPlanId: (tenantId) => subscriptions.currentPlanId(tenantId),
|
|
26
|
+
* getOverrides: (tenantId) => tenantSettings.get(tenantId).then((s) => s.planOverrides),
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // in a route
|
|
30
|
+
* const ent = await entitlements.forSubject(ctx.tenant.id);
|
|
31
|
+
* ent.require('api_access'); // 402 if not in plan
|
|
32
|
+
* await ent.requireWithinLimit('seats', () => members.count(tenantId)); // 403 at the cap
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
import type { PlanDefinition } from '../plans/index.js';
|
|
36
|
+
/** Same value as `@venturekit/runtime`'s `VENTURE_ERROR_MARKER` — the boundary renders marked errors. */
|
|
37
|
+
declare const VENTURE_ERROR_MARKER: unique symbol;
|
|
38
|
+
export type EntitlementErrorCode = 'PLAN_UPGRADE_REQUIRED' | 'PLAN_LIMIT_REACHED' | 'PLAN_UNKNOWN';
|
|
39
|
+
/**
|
|
40
|
+
* Thrown by `require*`. Rendered by `@venturekit/runtime`'s error boundary
|
|
41
|
+
* as `{ error: { code, message, details } }` with the HTTP status below.
|
|
42
|
+
*/
|
|
43
|
+
export declare class EntitlementError extends Error {
|
|
44
|
+
readonly code: EntitlementErrorCode;
|
|
45
|
+
readonly details: {
|
|
46
|
+
planId: string | null;
|
|
47
|
+
featureKey: string;
|
|
48
|
+
limit?: number | null;
|
|
49
|
+
usage?: number;
|
|
50
|
+
};
|
|
51
|
+
readonly [VENTURE_ERROR_MARKER]: true;
|
|
52
|
+
readonly statusCode: number;
|
|
53
|
+
constructor(code: EntitlementErrorCode, message: string, details: {
|
|
54
|
+
planId: string | null;
|
|
55
|
+
featureKey: string;
|
|
56
|
+
limit?: number | null;
|
|
57
|
+
usage?: number;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/** Per-subject adjustments layered over the plan. `null` limit = unlimited. */
|
|
61
|
+
export type EntitlementOverrides = Record<string, {
|
|
62
|
+
enabled?: boolean;
|
|
63
|
+
limit?: number | null;
|
|
64
|
+
}>;
|
|
65
|
+
export interface ResolvedFeature {
|
|
66
|
+
featureKey: string;
|
|
67
|
+
enabled: boolean;
|
|
68
|
+
/** `null` = unlimited; `undefined` when the feature is disabled. */
|
|
69
|
+
limit: number | null | undefined;
|
|
70
|
+
/** Where the value came from. */
|
|
71
|
+
source: 'plan' | 'override' | 'absent';
|
|
72
|
+
}
|
|
73
|
+
export interface LimitCheck {
|
|
74
|
+
allowed: boolean;
|
|
75
|
+
limit: number | null;
|
|
76
|
+
usage: number;
|
|
77
|
+
remaining: number | null;
|
|
78
|
+
}
|
|
79
|
+
export interface Entitlements {
|
|
80
|
+
subjectId: string;
|
|
81
|
+
planId: string | null;
|
|
82
|
+
plan: PlanDefinition | null;
|
|
83
|
+
features: Record<string, ResolvedFeature>;
|
|
84
|
+
has(featureKey: string): boolean;
|
|
85
|
+
/** `null` = unlimited, `undefined` = feature not available. */
|
|
86
|
+
limitOf(featureKey: string): number | null | undefined;
|
|
87
|
+
/** Throws `EntitlementError` (402) when the feature is not available. */
|
|
88
|
+
require(featureKey: string): void;
|
|
89
|
+
/** Compare usage to the limit; `allowed` is also `true` for unlimited features. */
|
|
90
|
+
checkLimit(featureKey: string, usage: number): LimitCheck;
|
|
91
|
+
/**
|
|
92
|
+
* Fetch usage only when the feature has a finite limit, then enforce it
|
|
93
|
+
* (403 at the cap, 402 when not in the plan). Returns the check for
|
|
94
|
+
* headers / UI hints.
|
|
95
|
+
*/
|
|
96
|
+
requireWithinLimit(featureKey: string, getUsage: () => Promise<number> | number): Promise<LimitCheck>;
|
|
97
|
+
/**
|
|
98
|
+
* The finite limits as a plain map — the shape `@venturekit-pro/tenancy`'s
|
|
99
|
+
* `TenantContext.quotas` / `createQuotaMiddleware` reads. Optional
|
|
100
|
+
* `keyMap` renames feature keys to quota keys (`{ seats: 'maxUsers' }`).
|
|
101
|
+
*/
|
|
102
|
+
toQuotas(keyMap?: Record<string, string>): Record<string, number>;
|
|
103
|
+
}
|
|
104
|
+
/** Pure resolution: plan features, then overrides on top. */
|
|
105
|
+
export declare function resolveEntitlements(input: {
|
|
106
|
+
subjectId: string;
|
|
107
|
+
plan: PlanDefinition | null;
|
|
108
|
+
overrides?: EntitlementOverrides;
|
|
109
|
+
}): Entitlements;
|
|
110
|
+
export interface EntitlementsResolverOptions {
|
|
111
|
+
plans: PlanDefinition[];
|
|
112
|
+
/** The subject's current plan id, or `null` when none (free tier / trial expired). */
|
|
113
|
+
getPlanId: (subjectId: string) => Promise<string | null> | string | null;
|
|
114
|
+
getOverrides?: (subjectId: string) => Promise<EntitlementOverrides | null | undefined> | EntitlementOverrides | null | undefined;
|
|
115
|
+
/** Per-subject cache lifetime in ms. Default 60 000. `0` disables caching. */
|
|
116
|
+
ttlMs?: number;
|
|
117
|
+
/** Clock override for tests. */
|
|
118
|
+
now?: () => number;
|
|
119
|
+
}
|
|
120
|
+
export interface EntitlementsResolver {
|
|
121
|
+
forSubject(subjectId: string): Promise<Entitlements>;
|
|
122
|
+
/** Drop one subject (after a plan change) or everything. */
|
|
123
|
+
invalidate(subjectId?: string): void;
|
|
124
|
+
}
|
|
125
|
+
export declare function createEntitlementsResolver(options: EntitlementsResolverOptions): EntitlementsResolver;
|
|
126
|
+
export {};
|
|
127
|
+
//# sourceMappingURL=entitlements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.d.ts","sourceRoot":"","sources":["../../src/entitlements/entitlements.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entitlements — what a tenant (or customer) may do right now, resolved
|
|
3
|
+
* from its plan plus any per-tenant overrides, cached, and enforceable
|
|
4
|
+
* from a route with the right HTTP answer.
|
|
5
|
+
*
|
|
6
|
+
* The feature gate (`createFeatureGate`) answers "is feature X in plan P";
|
|
7
|
+
* this layer adds what a product needs around it:
|
|
8
|
+
*
|
|
9
|
+
* - **who is on which plan** — `getPlanId(subjectId)` is the app's
|
|
10
|
+
* lookup (subscription row, tenant column), cached per subject;
|
|
11
|
+
* - **per-tenant overrides** — a negotiated deal ("500 seats on Pro")
|
|
12
|
+
* or a temporary grant, as `{ featureKey: { enabled?, limit? } }`;
|
|
13
|
+
* - **HTTP-mapped refusals** — {@link EntitlementError} renders as
|
|
14
|
+
* `402 PLAN_UPGRADE_REQUIRED` (feature not in plan) or
|
|
15
|
+
* `403 PLAN_LIMIT_REACHED` (limit exhausted) through the runtime's
|
|
16
|
+
* error boundary, with `details.featureKey` / `details.planId` /
|
|
17
|
+
* `details.limit` for the upgrade prompt — no `@venturekit/runtime`
|
|
18
|
+
* import needed (structural marker);
|
|
19
|
+
* - **adapters** — `toQuotas()` feeds `@venturekit-pro/tenancy`'s quota
|
|
20
|
+
* middleware, `limitOf()` feeds rate-limit presets.
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* const entitlements = createEntitlementsResolver({
|
|
24
|
+
* plans,
|
|
25
|
+
* getPlanId: (tenantId) => subscriptions.currentPlanId(tenantId),
|
|
26
|
+
* getOverrides: (tenantId) => tenantSettings.get(tenantId).then((s) => s.planOverrides),
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // in a route
|
|
30
|
+
* const ent = await entitlements.forSubject(ctx.tenant.id);
|
|
31
|
+
* ent.require('api_access'); // 402 if not in plan
|
|
32
|
+
* await ent.requireWithinLimit('seats', () => members.count(tenantId)); // 403 at the cap
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
/** Same value as `@venturekit/runtime`'s `VENTURE_ERROR_MARKER` — the boundary renders marked errors. */
|
|
36
|
+
const VENTURE_ERROR_MARKER = Symbol.for('venturekit.error');
|
|
37
|
+
/**
|
|
38
|
+
* Thrown by `require*`. Rendered by `@venturekit/runtime`'s error boundary
|
|
39
|
+
* as `{ error: { code, message, details } }` with the HTTP status below.
|
|
40
|
+
*/
|
|
41
|
+
export class EntitlementError extends Error {
|
|
42
|
+
code;
|
|
43
|
+
details;
|
|
44
|
+
[VENTURE_ERROR_MARKER] = true;
|
|
45
|
+
statusCode;
|
|
46
|
+
constructor(code, message, details) {
|
|
47
|
+
super(message);
|
|
48
|
+
this.code = code;
|
|
49
|
+
this.details = details;
|
|
50
|
+
this.name = 'EntitlementError';
|
|
51
|
+
this.statusCode = code === 'PLAN_LIMIT_REACHED' ? 403 : code === 'PLAN_UNKNOWN' ? 403 : 402;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Pure resolution: plan features, then overrides on top. */
|
|
55
|
+
export function resolveEntitlements(input) {
|
|
56
|
+
const features = {};
|
|
57
|
+
for (const f of input.plan?.features ?? []) {
|
|
58
|
+
features[f.featureKey] = fromPlanFeature(f);
|
|
59
|
+
}
|
|
60
|
+
for (const [key, o] of Object.entries(input.overrides ?? {})) {
|
|
61
|
+
const base = features[key];
|
|
62
|
+
const enabled = o.enabled ?? base?.enabled ?? true;
|
|
63
|
+
features[key] = {
|
|
64
|
+
featureKey: key,
|
|
65
|
+
enabled,
|
|
66
|
+
limit: enabled ? (o.limit !== undefined ? o.limit : (base?.limit ?? null)) : undefined,
|
|
67
|
+
source: 'override',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const planId = input.plan?.id ?? null;
|
|
71
|
+
const has = (key) => features[key]?.enabled === true;
|
|
72
|
+
const limitOf = (key) => (has(key) ? features[key].limit : undefined);
|
|
73
|
+
const checkLimit = (key, usage) => {
|
|
74
|
+
const limit = limitOf(key);
|
|
75
|
+
if (limit === undefined)
|
|
76
|
+
return { allowed: false, limit: 0, usage, remaining: 0 };
|
|
77
|
+
if (limit === null)
|
|
78
|
+
return { allowed: true, limit: null, usage, remaining: null };
|
|
79
|
+
return { allowed: usage < limit, limit, usage, remaining: Math.max(0, limit - usage) };
|
|
80
|
+
};
|
|
81
|
+
const require = (key) => {
|
|
82
|
+
if (has(key))
|
|
83
|
+
return;
|
|
84
|
+
throw new EntitlementError(planId ? 'PLAN_UPGRADE_REQUIRED' : 'PLAN_UNKNOWN', planId
|
|
85
|
+
? `'${key}' is not included in the ${input.plan?.name ?? planId} plan`
|
|
86
|
+
: `No plan is active for this account, so '${key}' is not available`, { planId, featureKey: key });
|
|
87
|
+
};
|
|
88
|
+
return {
|
|
89
|
+
subjectId: input.subjectId,
|
|
90
|
+
planId,
|
|
91
|
+
plan: input.plan,
|
|
92
|
+
features,
|
|
93
|
+
has,
|
|
94
|
+
limitOf,
|
|
95
|
+
require,
|
|
96
|
+
checkLimit,
|
|
97
|
+
async requireWithinLimit(key, getUsage) {
|
|
98
|
+
require(key);
|
|
99
|
+
const limit = limitOf(key);
|
|
100
|
+
if (limit === null || limit === undefined)
|
|
101
|
+
return { allowed: true, limit: null, usage: 0, remaining: null };
|
|
102
|
+
const usage = await getUsage();
|
|
103
|
+
const check = checkLimit(key, usage);
|
|
104
|
+
if (!check.allowed) {
|
|
105
|
+
throw new EntitlementError('PLAN_LIMIT_REACHED', `'${key}' limit reached (${usage}/${limit})`, {
|
|
106
|
+
planId,
|
|
107
|
+
featureKey: key,
|
|
108
|
+
limit,
|
|
109
|
+
usage,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return check;
|
|
113
|
+
},
|
|
114
|
+
toQuotas(keyMap = {}) {
|
|
115
|
+
const out = {};
|
|
116
|
+
for (const f of Object.values(features)) {
|
|
117
|
+
if (f.enabled && typeof f.limit === 'number')
|
|
118
|
+
out[keyMap[f.featureKey] ?? f.featureKey] = f.limit;
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function fromPlanFeature(f) {
|
|
125
|
+
return {
|
|
126
|
+
featureKey: f.featureKey,
|
|
127
|
+
enabled: f.enabled,
|
|
128
|
+
limit: f.enabled ? (f.limit ?? null) : undefined,
|
|
129
|
+
source: 'plan',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export function createEntitlementsResolver(options) {
|
|
133
|
+
const ttlMs = options.ttlMs ?? 60_000;
|
|
134
|
+
const now = options.now ?? Date.now;
|
|
135
|
+
const plansById = new Map(options.plans.map((p) => [p.id, p]));
|
|
136
|
+
const cache = new Map();
|
|
137
|
+
return {
|
|
138
|
+
async forSubject(subjectId) {
|
|
139
|
+
const hit = cache.get(subjectId);
|
|
140
|
+
if (hit && now() - hit.at < ttlMs)
|
|
141
|
+
return hit.value;
|
|
142
|
+
const [planId, overrides] = await Promise.all([
|
|
143
|
+
options.getPlanId(subjectId),
|
|
144
|
+
options.getOverrides ? options.getOverrides(subjectId) : undefined,
|
|
145
|
+
]);
|
|
146
|
+
const plan = planId ? (plansById.get(planId) ?? null) : null;
|
|
147
|
+
const value = resolveEntitlements({ subjectId, plan, overrides: overrides ?? undefined });
|
|
148
|
+
if (ttlMs > 0)
|
|
149
|
+
cache.set(subjectId, { value, at: now() });
|
|
150
|
+
return value;
|
|
151
|
+
},
|
|
152
|
+
invalidate(subjectId) {
|
|
153
|
+
if (subjectId === undefined)
|
|
154
|
+
cache.clear();
|
|
155
|
+
else
|
|
156
|
+
cache.delete(subjectId);
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=entitlements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.js","sourceRoot":"","sources":["../../src/entitlements/entitlements.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,10 @@ export { createUsageTracker, createMemoryUsageStore, } from './usage/tracker.js'
|
|
|
28
28
|
export type { UsageRecord, UsageSummary, UsageStore, } from './usage/tracker.js';
|
|
29
29
|
export { createFeatureGate, } from './gating/feature-gate.js';
|
|
30
30
|
export type { FeatureCheckResult, FeatureGateOptions, } from './gating/feature-gate.js';
|
|
31
|
+
export { resolveEntitlements, createEntitlementsResolver, EntitlementError, } from './entitlements/entitlements.js';
|
|
32
|
+
export type { Entitlements, EntitlementOverrides, EntitlementErrorCode, EntitlementsResolver, EntitlementsResolverOptions, ResolvedFeature, LimitCheck, } from './entitlements/entitlements.js';
|
|
33
|
+
export { nextDunningStep, dunningScheduleRefusal, normalizeDunningSteps, DUNNING_SCHEDULE_LIMITS, } from './dunning/schedule.js';
|
|
34
|
+
export type { DunningSchedule, DunningReminderSent, NextDunningStepInput, } from './dunning/schedule.js';
|
|
31
35
|
/**
|
|
32
36
|
* Returns the path to the billing migration SQL file.
|
|
33
37
|
* Used by `vk migrate` to auto-create billing tables
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,WAAW,EACX,eAAe,EACf,UAAU,EACV,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpE,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,eAAe,GAChB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,YAAY,EACZ,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACX,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,WAAW,EACX,eAAe,EACf,UAAU,EACV,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpE,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,eAAe,GAChB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,YAAY,EACZ,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACX,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,gBAAgB,GACjB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,2BAA2B,EAC3B,eAAe,EACf,UAAU,GACX,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAE/B;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD"}
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,10 @@ export { createInvoiceGenerator, createMemoryInvoiceStore, } from './invoices/ge
|
|
|
31
31
|
export { createUsageTracker, createMemoryUsageStore, } from './usage/tracker.js';
|
|
32
32
|
// Feature gating
|
|
33
33
|
export { createFeatureGate, } from './gating/feature-gate.js';
|
|
34
|
+
// Entitlements (plan + overrides → what a tenant may do, HTTP-mapped refusals)
|
|
35
|
+
export { resolveEntitlements, createEntitlementsResolver, EntitlementError, } from './entitlements/entitlements.js';
|
|
36
|
+
// Dunning (which payment reminder an unpaid invoice is due — pure, for a cron)
|
|
37
|
+
export { nextDunningStep, dunningScheduleRefusal, normalizeDunningSteps, DUNNING_SCHEDULE_LIMITS, } from './dunning/schedule.js';
|
|
34
38
|
/**
|
|
35
39
|
* Returns the path to the billing migration SQL file.
|
|
36
40
|
* Used by `vk migrate` to auto-create billing tables
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,QAAQ;AACR,cAAc,kBAAkB,CAAC;AAEjC,0BAA0B;AAC1B,OAAO,EACL,WAAW,EACX,eAAe,EACf,UAAU,EACV,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAG1B,0BAA0B;AAC1B,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAOpC,qBAAqB;AACrB,OAAO,EACL,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAMjC,iBAAiB;AACjB,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAO5B,iBAAiB;AACjB,OAAO,EACL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAMlC;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AAC5C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,QAAQ;AACR,cAAc,kBAAkB,CAAC;AAEjC,0BAA0B;AAC1B,OAAO,EACL,WAAW,EACX,eAAe,EACf,UAAU,EACV,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAG1B,0BAA0B;AAC1B,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAOpC,qBAAqB;AACrB,OAAO,EACL,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAMjC,iBAAiB;AACjB,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAO5B,iBAAiB;AACjB,OAAO,EACL,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAMlC,+EAA+E;AAC/E,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,gBAAgB,GACjB,MAAM,gCAAgC,CAAC;AAWxC,+EAA+E;AAC/E,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAO/B;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/invoices/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/invoices/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAkC,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACzC,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB;IAmBnE;;OAEG;kCAEW,MAAM,QACZ,cAAc,SACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SACtB;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GACtE,OAAO,CAAC,OAAO,CAAC;IA6DnB;;OAEG;wBACuB,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAuC/D;;OAEG;wBACuB,MAAM,WAAW,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBpE;;OAEG;oBACmB,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAa/C;;OAEG;8BAC6B,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAI3D;;OAEG;mBACkB,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;EAIxD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,YAAY,CAwBvD"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Generates invoices from subscription plans and usage data.
|
|
5
5
|
* Handles tax calculation, line items, and invoice numbering.
|
|
6
6
|
*/
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
7
8
|
import { mapUsageToLineItems } from '../plans/index.js';
|
|
8
9
|
/**
|
|
9
10
|
* Create an invoice generator
|
|
@@ -11,7 +12,8 @@ import { mapUsageToLineItems } from '../plans/index.js';
|
|
|
11
12
|
export function createInvoiceGenerator(options) {
|
|
12
13
|
const { store, prefix = 'INV-', taxRate = 0, defaultCurrency = 'USD', defaultDueDays = 30, } = options;
|
|
13
14
|
function generateId() {
|
|
14
|
-
|
|
15
|
+
// Primary key: CSPRNG, not `Math.random` (predictable + collision-prone).
|
|
16
|
+
return `inv-${randomUUID()}`;
|
|
15
17
|
}
|
|
16
18
|
function calculateTax(subtotal, rate) {
|
|
17
19
|
return Math.round(subtotal * (rate / 100));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/invoices/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/invoices/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/subscriptions/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/subscriptions/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,uBAAuB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9C,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAChE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,IAAI,EACjB,SAAS,EAAE,IAAI,EACf,UAAU,GAAE,IAAiB,GAC5B,eAAe,CAqBjB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B;IAgBzE;;OAEG;kBACiB,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC;IAmDnE;;OAEG;YACW,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAInD;;OAEG;8BAC6B,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAIrE;;OAEG;+BAEe,MAAM,aACX,MAAM,YACP;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAChC,OAAO,CAAC;QAAE,YAAY,EAAE,YAAY,CAAC;QAAC,SAAS,CAAC,EAAE,eAAe,CAAA;KAAE,CAAC;IAyCvE;;OAEG;2BAEe,MAAM,YACZ;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACjD,OAAO,CAAC,YAAY,CAAC;IA2BxB;;OAEG;0BACyB,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAa1D;;OAEG;2BAC0B,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAa3D;;OAEG;qCAEe,MAAM,aACX,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC;EAe9B;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,iBAAiB,CA6BjE"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Storage backend is pluggable via SubscriptionStore interface.
|
|
8
8
|
*/
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
9
10
|
/**
|
|
10
11
|
* Calculate proration for a mid-cycle plan change
|
|
11
12
|
*/
|
|
@@ -41,7 +42,8 @@ export function createSubscriptionManager(options) {
|
|
|
41
42
|
return plan;
|
|
42
43
|
}
|
|
43
44
|
function generateId() {
|
|
44
|
-
|
|
45
|
+
// Primary key: CSPRNG, not `Math.random` (predictable + collision-prone).
|
|
46
|
+
return `sub-${randomUUID()}`;
|
|
45
47
|
}
|
|
46
48
|
return {
|
|
47
49
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/subscriptions/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/subscriptions/manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venturekit-pro/billing",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.40",
|
|
4
4
|
"description": "Invoicing, plans, usage tracking, and feature gating for VentureKit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@venturekit/core": "0.0.
|
|
33
|
+
"@venturekit/core": "0.0.40"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^26.5.1",
|