@venturekit-pro/billing 0.0.0-dev.20260323005827
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/LICENSE +19 -0
- package/README.md +93 -0
- package/dist/gating/feature-gate.d.ts +53 -0
- package/dist/gating/feature-gate.d.ts.map +1 -0
- package/dist/gating/feature-gate.js +92 -0
- package/dist/gating/feature-gate.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/invoices/generator.d.ts +70 -0
- package/dist/invoices/generator.d.ts.map +1 -0
- package/dist/invoices/generator.js +190 -0
- package/dist/invoices/generator.js.map +1 -0
- package/dist/plans/index.d.ts +124 -0
- package/dist/plans/index.d.ts.map +1 -0
- package/dist/plans/index.js +116 -0
- package/dist/plans/index.js.map +1 -0
- package/dist/subscriptions/manager.d.ts +98 -0
- package/dist/subscriptions/manager.d.ts.map +1 -0
- package/dist/subscriptions/manager.js +245 -0
- package/dist/subscriptions/manager.js.map +1 -0
- package/dist/types/config.d.ts +36 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +8 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/invoice.d.ts +78 -0
- package/dist/types/invoice.d.ts.map +1 -0
- package/dist/types/invoice.js +5 -0
- package/dist/types/invoice.js.map +1 -0
- package/dist/types/payment.d.ts +33 -0
- package/dist/types/payment.d.ts.map +1 -0
- package/dist/types/payment.js +8 -0
- package/dist/types/payment.js.map +1 -0
- package/dist/types/subscription.d.ts +87 -0
- package/dist/types/subscription.d.ts.map +1 -0
- package/dist/types/subscription.js +5 -0
- package/dist/types/subscription.js.map +1 -0
- package/dist/usage/tracker.d.ts +75 -0
- package/dist/usage/tracker.d.ts.map +1 -0
- package/dist/usage/tracker.js +91 -0
- package/dist/usage/tracker.js.map +1 -0
- package/package.json +39 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
Copyright 2024 VentureKit
|
|
8
|
+
|
|
9
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
you may not use this file except in compliance with the License.
|
|
11
|
+
You may obtain a copy of the License at
|
|
12
|
+
|
|
13
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
|
|
15
|
+
Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
See the License for the specific language governing permissions and
|
|
19
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @venturekit-pro/billing
|
|
2
|
+
|
|
3
|
+
> **Warning:** This package is in active development and not production-ready. APIs may change without notice.
|
|
4
|
+
|
|
5
|
+
Billing and invoicing for [VentureKit](https://venturekit.dev) — plan definitions, feature limits, usage-to-invoice mapping, and auto-migration support.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @venturekit-pro/billing@dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
`@venturekit-pro/billing` provides:
|
|
16
|
+
|
|
17
|
+
- **Plan definitions** — `definePlans()` with feature limits and pricing tiers
|
|
18
|
+
- **Subscription management** — create, upgrade, downgrade, cancel, pause, resume
|
|
19
|
+
- **Invoice generation** — from plan + usage, with tax calculation
|
|
20
|
+
- **Usage tracking** — record and meter feature usage
|
|
21
|
+
- **Feature gating** — plan-based and usage-based access control
|
|
22
|
+
- **Auto-migrations** — billing tables created automatically via `vk migrate`
|
|
23
|
+
|
|
24
|
+
> **Note:** This package handles invoicing and plan management. Payment processing is NOT included — integrate any payment provider separately.
|
|
25
|
+
|
|
26
|
+
## Defining Plans
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { definePlans } from '@venturekit-pro/billing';
|
|
30
|
+
|
|
31
|
+
const plans = definePlans([
|
|
32
|
+
{
|
|
33
|
+
id: 'free',
|
|
34
|
+
name: 'Free',
|
|
35
|
+
features: {
|
|
36
|
+
projects: { limit: 3 },
|
|
37
|
+
storage: { limit: 1_000_000_000 }, // 1 GB
|
|
38
|
+
apiRequests: { limit: 10_000, period: 'month' },
|
|
39
|
+
support: false,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'pro',
|
|
44
|
+
name: 'Pro',
|
|
45
|
+
features: {
|
|
46
|
+
projects: { limit: 50 },
|
|
47
|
+
storage: { limit: 100_000_000_000 }, // 100 GB
|
|
48
|
+
apiRequests: { limit: 1_000_000, period: 'month' },
|
|
49
|
+
support: true,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Feature Checking
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { getFeatureLimit, hasFeature } from '@venturekit-pro/billing';
|
|
59
|
+
|
|
60
|
+
const maxProjects = getFeatureLimit(plans, 'free', 'projects');
|
|
61
|
+
// → 3
|
|
62
|
+
|
|
63
|
+
const hasSupport = hasFeature(plans, 'free', 'support');
|
|
64
|
+
// → false
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Usage-to-Invoice Mapping
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { mapUsageToLineItems } from '@venturekit-pro/billing';
|
|
71
|
+
|
|
72
|
+
const lineItems = mapUsageToLineItems(currentUsage, planFeatures);
|
|
73
|
+
// Returns structured line items for invoice generation
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Auto-Migrations
|
|
77
|
+
|
|
78
|
+
When `@venturekit-pro/billing` is added to a project, `vk migrate` automatically discovers and applies billing-related database tables:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { getBillingMigrationsDir } from '@venturekit-pro/billing';
|
|
82
|
+
|
|
83
|
+
const migrationsDir = getBillingMigrationsDir();
|
|
84
|
+
// Returns path to SQL migration files
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API Reference
|
|
88
|
+
|
|
89
|
+
See the [API reference](https://venturekit.dev/api-reference/billing) for full documentation.
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
Apache-2.0 — see [LICENSE](../../LICENSE) for details.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VentureKit Feature Gating
|
|
3
|
+
*
|
|
4
|
+
* Runtime feature checks against subscription plans.
|
|
5
|
+
* Integrates with plans and usage to enforce limits.
|
|
6
|
+
*/
|
|
7
|
+
import type { PlanDefinition } from '../plans/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Feature check result
|
|
10
|
+
*/
|
|
11
|
+
export interface FeatureCheckResult {
|
|
12
|
+
/** Whether access is allowed */
|
|
13
|
+
allowed: boolean;
|
|
14
|
+
/** Reason if denied */
|
|
15
|
+
reason?: string;
|
|
16
|
+
/** Current usage (if limit-based) */
|
|
17
|
+
currentUsage?: number;
|
|
18
|
+
/** Feature limit (null = unlimited) */
|
|
19
|
+
limit?: number | null;
|
|
20
|
+
/** Remaining quota (if limit-based) */
|
|
21
|
+
remaining?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Feature gate options
|
|
25
|
+
*/
|
|
26
|
+
export interface FeatureGateOptions {
|
|
27
|
+
/** Available plans */
|
|
28
|
+
plans: PlanDefinition[];
|
|
29
|
+
/** Get current usage for a feature (optional, for limit checking) */
|
|
30
|
+
getUsage?: (customerId: string, featureKey: string) => Promise<number>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a feature gate
|
|
34
|
+
*/
|
|
35
|
+
export declare function createFeatureGate(options: FeatureGateOptions): {
|
|
36
|
+
/**
|
|
37
|
+
* Check if a feature is available on a plan
|
|
38
|
+
*/
|
|
39
|
+
check(planId: string, featureKey: string): FeatureCheckResult;
|
|
40
|
+
/**
|
|
41
|
+
* Check if usage is within limits (async — queries current usage)
|
|
42
|
+
*/
|
|
43
|
+
checkUsage(planId: string, featureKey: string, customerId: string): Promise<FeatureCheckResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Require a feature — throws if not available
|
|
46
|
+
*/
|
|
47
|
+
require(planId: string, featureKey: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Require usage within limits — throws if exceeded
|
|
50
|
+
*/
|
|
51
|
+
requireUsage(planId: string, featureKey: string, customerId: string): Promise<void>;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=feature-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-gate.d.ts","sourceRoot":"","sources":["../../src/gating/feature-gate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACxE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB;IAQzD;;OAEG;kBACW,MAAM,cAAc,MAAM,GAAG,kBAAkB;IAiB7D;;OAEG;uBAEO,MAAM,cACF,MAAM,cACN,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC;IA2C9B;;OAEG;oBACa,MAAM,cAAc,MAAM,GAAG,IAAI;IAOjD;;OAEG;yBAEO,MAAM,cACF,MAAM,cACN,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;EAOnB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VentureKit Feature Gating
|
|
3
|
+
*
|
|
4
|
+
* Runtime feature checks against subscription plans.
|
|
5
|
+
* Integrates with plans and usage to enforce limits.
|
|
6
|
+
*/
|
|
7
|
+
import { getFeatureLimit, hasFeature } from '../plans/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create a feature gate
|
|
10
|
+
*/
|
|
11
|
+
export function createFeatureGate(options) {
|
|
12
|
+
const { plans, getUsage } = options;
|
|
13
|
+
function getPlan(planId) {
|
|
14
|
+
return plans.find(p => p.id === planId) ?? null;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
/**
|
|
18
|
+
* Check if a feature is available on a plan
|
|
19
|
+
*/
|
|
20
|
+
check(planId, featureKey) {
|
|
21
|
+
const plan = getPlan(planId);
|
|
22
|
+
if (!plan) {
|
|
23
|
+
return { allowed: false, reason: `Plan '${planId}' not found` };
|
|
24
|
+
}
|
|
25
|
+
if (!hasFeature(plan, featureKey)) {
|
|
26
|
+
return { allowed: false, reason: `Feature '${featureKey}' is not included in the '${plan.name}' plan` };
|
|
27
|
+
}
|
|
28
|
+
const limit = getFeatureLimit(plan, featureKey);
|
|
29
|
+
return {
|
|
30
|
+
allowed: true,
|
|
31
|
+
limit: limit ?? null,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Check if usage is within limits (async — queries current usage)
|
|
36
|
+
*/
|
|
37
|
+
async checkUsage(planId, featureKey, customerId) {
|
|
38
|
+
const plan = getPlan(planId);
|
|
39
|
+
if (!plan) {
|
|
40
|
+
return { allowed: false, reason: `Plan '${planId}' not found` };
|
|
41
|
+
}
|
|
42
|
+
if (!hasFeature(plan, featureKey)) {
|
|
43
|
+
return { allowed: false, reason: `Feature '${featureKey}' is not included in the '${plan.name}' plan` };
|
|
44
|
+
}
|
|
45
|
+
const limit = getFeatureLimit(plan, featureKey);
|
|
46
|
+
// Unlimited feature
|
|
47
|
+
if (limit === null) {
|
|
48
|
+
return { allowed: true, limit: null };
|
|
49
|
+
}
|
|
50
|
+
// No usage getter provided — just check feature existence
|
|
51
|
+
if (!getUsage) {
|
|
52
|
+
return { allowed: true, limit };
|
|
53
|
+
}
|
|
54
|
+
const currentUsage = await getUsage(customerId, featureKey);
|
|
55
|
+
const remaining = Math.max(0, (limit ?? 0) - currentUsage);
|
|
56
|
+
if (currentUsage >= (limit ?? 0)) {
|
|
57
|
+
return {
|
|
58
|
+
allowed: false,
|
|
59
|
+
reason: `Usage limit reached for '${featureKey}' (${currentUsage}/${limit})`,
|
|
60
|
+
currentUsage,
|
|
61
|
+
limit,
|
|
62
|
+
remaining: 0,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
allowed: true,
|
|
67
|
+
currentUsage,
|
|
68
|
+
limit,
|
|
69
|
+
remaining,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Require a feature — throws if not available
|
|
74
|
+
*/
|
|
75
|
+
require(planId, featureKey) {
|
|
76
|
+
const result = this.check(planId, featureKey);
|
|
77
|
+
if (!result.allowed) {
|
|
78
|
+
throw new Error(result.reason);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
/**
|
|
82
|
+
* Require usage within limits — throws if exceeded
|
|
83
|
+
*/
|
|
84
|
+
async requireUsage(planId, featureKey, customerId) {
|
|
85
|
+
const result = await this.checkUsage(planId, featureKey, customerId);
|
|
86
|
+
if (!result.allowed) {
|
|
87
|
+
throw new Error(result.reason);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=feature-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-gate.js","sourceRoot":"","sources":["../../src/gating/feature-gate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @venturekit-pro/billing
|
|
3
|
+
*
|
|
4
|
+
* Invoicing, plans, usage tracking, and feature gating for VentureKit.
|
|
5
|
+
*
|
|
6
|
+
* Core features:
|
|
7
|
+
* - Plan definitions with feature limits
|
|
8
|
+
* - Feature-to-invoice-item mapping (generic for most apps)
|
|
9
|
+
* - Subscription lifecycle management
|
|
10
|
+
* - Invoice generation from plan + usage
|
|
11
|
+
* - Usage tracking and metering
|
|
12
|
+
* - Feature gating (plan-based + usage-based)
|
|
13
|
+
* - Auto-creates billing tables via vk migrate
|
|
14
|
+
*
|
|
15
|
+
* This package does NOT implement payment processing.
|
|
16
|
+
* Integrate any payment provider separately.
|
|
17
|
+
*
|
|
18
|
+
* Documentation: https://venturekit.dev
|
|
19
|
+
*/
|
|
20
|
+
export * from './types/index.js';
|
|
21
|
+
export { definePlans, getFeatureLimit, hasFeature, mapUsageToLineItems, } from './plans/index.js';
|
|
22
|
+
export type { PlanDefinition, PlanFeature } from './plans/index.js';
|
|
23
|
+
export { createSubscriptionManager, createMemorySubscriptionStore, calculateProration, } from './subscriptions/manager.js';
|
|
24
|
+
export type { SubscriptionStore, SubscriptionManagerOptions, ProrationResult, } from './subscriptions/manager.js';
|
|
25
|
+
export { createInvoiceGenerator, createMemoryInvoiceStore, } from './invoices/generator.js';
|
|
26
|
+
export type { InvoiceStore, InvoiceGeneratorOptions, } from './invoices/generator.js';
|
|
27
|
+
export { createUsageTracker, createMemoryUsageStore, } from './usage/tracker.js';
|
|
28
|
+
export type { UsageRecord, UsageSummary, UsageStore, } from './usage/tracker.js';
|
|
29
|
+
export { createFeatureGate, } from './gating/feature-gate.js';
|
|
30
|
+
export type { FeatureCheckResult, FeatureGateOptions, } from './gating/feature-gate.js';
|
|
31
|
+
/**
|
|
32
|
+
* Returns the path to the billing migration SQL file.
|
|
33
|
+
* Used by `vk migrate` to auto-create billing tables
|
|
34
|
+
* when @venturekit-pro/billing is added to a project.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getBillingMigrationsDir(): string;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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;AAElC;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAGhD"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @venturekit-pro/billing
|
|
3
|
+
*
|
|
4
|
+
* Invoicing, plans, usage tracking, and feature gating for VentureKit.
|
|
5
|
+
*
|
|
6
|
+
* Core features:
|
|
7
|
+
* - Plan definitions with feature limits
|
|
8
|
+
* - Feature-to-invoice-item mapping (generic for most apps)
|
|
9
|
+
* - Subscription lifecycle management
|
|
10
|
+
* - Invoice generation from plan + usage
|
|
11
|
+
* - Usage tracking and metering
|
|
12
|
+
* - Feature gating (plan-based + usage-based)
|
|
13
|
+
* - Auto-creates billing tables via vk migrate
|
|
14
|
+
*
|
|
15
|
+
* This package does NOT implement payment processing.
|
|
16
|
+
* Integrate any payment provider separately.
|
|
17
|
+
*
|
|
18
|
+
* Documentation: https://venturekit.dev
|
|
19
|
+
*/
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
// Types
|
|
23
|
+
export * from './types/index.js';
|
|
24
|
+
// Plans & feature mapping
|
|
25
|
+
export { definePlans, getFeatureLimit, hasFeature, mapUsageToLineItems, } from './plans/index.js';
|
|
26
|
+
// Subscription management
|
|
27
|
+
export { createSubscriptionManager, createMemorySubscriptionStore, calculateProration, } from './subscriptions/manager.js';
|
|
28
|
+
// Invoice generation
|
|
29
|
+
export { createInvoiceGenerator, createMemoryInvoiceStore, } from './invoices/generator.js';
|
|
30
|
+
// Usage tracking
|
|
31
|
+
export { createUsageTracker, createMemoryUsageStore, } from './usage/tracker.js';
|
|
32
|
+
// Feature gating
|
|
33
|
+
export { createFeatureGate, } from './gating/feature-gate.js';
|
|
34
|
+
/**
|
|
35
|
+
* Returns the path to the billing migration SQL file.
|
|
36
|
+
* Used by `vk migrate` to auto-create billing tables
|
|
37
|
+
* when @venturekit-pro/billing is added to a project.
|
|
38
|
+
*/
|
|
39
|
+
export function getBillingMigrationsDir() {
|
|
40
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
41
|
+
return path.join(__dirname, 'migrations');
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VentureKit Invoice Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates invoices from subscription plans and usage data.
|
|
5
|
+
* Handles tax calculation, line items, and invoice numbering.
|
|
6
|
+
*/
|
|
7
|
+
import type { Invoice, CreateInvoiceInput } from '../types/invoice.js';
|
|
8
|
+
import type { PlanDefinition } from '../plans/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Invoice store interface
|
|
11
|
+
*/
|
|
12
|
+
export interface InvoiceStore {
|
|
13
|
+
create(invoice: Invoice): Promise<Invoice>;
|
|
14
|
+
get(id: string): Promise<Invoice | null>;
|
|
15
|
+
getByCustomer(customerId: string): Promise<Invoice[]>;
|
|
16
|
+
update(id: string, updates: Partial<Invoice>): Promise<void>;
|
|
17
|
+
getNextNumber(prefix: string): Promise<string>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Invoice generator options
|
|
21
|
+
*/
|
|
22
|
+
export interface InvoiceGeneratorOptions {
|
|
23
|
+
store: InvoiceStore;
|
|
24
|
+
/** Invoice number prefix (e.g., "INV-") */
|
|
25
|
+
prefix?: string;
|
|
26
|
+
/** Default tax rate as percentage (e.g., 20 for 20%) */
|
|
27
|
+
taxRate?: number;
|
|
28
|
+
/** Default currency */
|
|
29
|
+
defaultCurrency?: string;
|
|
30
|
+
/** Days until due (default: 30) */
|
|
31
|
+
defaultDueDays?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create an invoice generator
|
|
35
|
+
*/
|
|
36
|
+
export declare function createInvoiceGenerator(options: InvoiceGeneratorOptions): {
|
|
37
|
+
/**
|
|
38
|
+
* Generate an invoice from a plan and usage
|
|
39
|
+
*/
|
|
40
|
+
generateFromUsage(customerId: string, plan: PlanDefinition, usage: Record<string, number>, opts?: {
|
|
41
|
+
subscriptionId?: string;
|
|
42
|
+
taxRate?: number;
|
|
43
|
+
currency?: string;
|
|
44
|
+
}): Promise<Invoice>;
|
|
45
|
+
/**
|
|
46
|
+
* Create a custom invoice with explicit line items
|
|
47
|
+
*/
|
|
48
|
+
createCustom(input: CreateInvoiceInput): Promise<Invoice>;
|
|
49
|
+
/**
|
|
50
|
+
* Mark an invoice as paid
|
|
51
|
+
*/
|
|
52
|
+
markPaid(invoiceId: string, amount?: number): Promise<Invoice>;
|
|
53
|
+
/**
|
|
54
|
+
* Void an invoice
|
|
55
|
+
*/
|
|
56
|
+
void(invoiceId: string): Promise<Invoice>;
|
|
57
|
+
/**
|
|
58
|
+
* Get invoices for a customer
|
|
59
|
+
*/
|
|
60
|
+
getByCustomer(customerId: string): Promise<Invoice[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Get an invoice by ID
|
|
63
|
+
*/
|
|
64
|
+
get(invoiceId: string): Promise<Invoice | null>;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* In-memory invoice store (for dev/testing)
|
|
68
|
+
*/
|
|
69
|
+
export declare function createMemoryInvoiceStore(): InvoiceStore;
|
|
70
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/invoices/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,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;IAkBnE;;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"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VentureKit Invoice Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates invoices from subscription plans and usage data.
|
|
5
|
+
* Handles tax calculation, line items, and invoice numbering.
|
|
6
|
+
*/
|
|
7
|
+
import { mapUsageToLineItems } from '../plans/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create an invoice generator
|
|
10
|
+
*/
|
|
11
|
+
export function createInvoiceGenerator(options) {
|
|
12
|
+
const { store, prefix = 'INV-', taxRate = 0, defaultCurrency = 'USD', defaultDueDays = 30, } = options;
|
|
13
|
+
function generateId() {
|
|
14
|
+
return `inv-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
15
|
+
}
|
|
16
|
+
function calculateTax(subtotal, rate) {
|
|
17
|
+
return Math.round(subtotal * (rate / 100));
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
/**
|
|
21
|
+
* Generate an invoice from a plan and usage
|
|
22
|
+
*/
|
|
23
|
+
async generateFromUsage(customerId, plan, usage, opts) {
|
|
24
|
+
const currency = opts?.currency ?? plan.currency ?? defaultCurrency;
|
|
25
|
+
const rate = opts?.taxRate ?? taxRate;
|
|
26
|
+
// Base plan line item
|
|
27
|
+
const lineItems = [
|
|
28
|
+
{
|
|
29
|
+
id: `li-base-${Date.now()}`,
|
|
30
|
+
description: `${plan.name} plan (${plan.interval}ly)`,
|
|
31
|
+
quantity: 1,
|
|
32
|
+
unitPrice: plan.price,
|
|
33
|
+
amount: plan.price,
|
|
34
|
+
taxRate: rate,
|
|
35
|
+
taxAmount: calculateTax(plan.price, rate),
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
// Overage line items from usage
|
|
39
|
+
const overageItems = mapUsageToLineItems(plan, usage);
|
|
40
|
+
for (const item of overageItems) {
|
|
41
|
+
lineItems.push({
|
|
42
|
+
id: `li-${item.featureKey}-${Date.now()}`,
|
|
43
|
+
description: item.description,
|
|
44
|
+
quantity: item.quantity,
|
|
45
|
+
unitPrice: item.unitPrice,
|
|
46
|
+
amount: item.amount,
|
|
47
|
+
taxRate: rate,
|
|
48
|
+
taxAmount: calculateTax(item.amount, rate),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const subtotal = lineItems.reduce((sum, li) => sum + li.amount, 0);
|
|
52
|
+
const tax = lineItems.reduce((sum, li) => sum + (li.taxAmount ?? 0), 0);
|
|
53
|
+
const total = subtotal + tax;
|
|
54
|
+
const invoiceNumber = await store.getNextNumber(prefix);
|
|
55
|
+
const now = new Date();
|
|
56
|
+
const dueDate = new Date(now);
|
|
57
|
+
dueDate.setDate(dueDate.getDate() + defaultDueDays);
|
|
58
|
+
const invoice = {
|
|
59
|
+
id: generateId(),
|
|
60
|
+
number: invoiceNumber,
|
|
61
|
+
customerId,
|
|
62
|
+
subscriptionId: opts?.subscriptionId,
|
|
63
|
+
status: 'open',
|
|
64
|
+
currency,
|
|
65
|
+
subtotal,
|
|
66
|
+
tax,
|
|
67
|
+
total,
|
|
68
|
+
amountPaid: 0,
|
|
69
|
+
amountDue: total,
|
|
70
|
+
lineItems,
|
|
71
|
+
dueDate,
|
|
72
|
+
createdAt: now,
|
|
73
|
+
updatedAt: now,
|
|
74
|
+
};
|
|
75
|
+
return store.create(invoice);
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* Create a custom invoice with explicit line items
|
|
79
|
+
*/
|
|
80
|
+
async createCustom(input) {
|
|
81
|
+
const currency = input.currency ?? defaultCurrency;
|
|
82
|
+
const lineItems = input.lineItems.map((li, i) => ({
|
|
83
|
+
...li,
|
|
84
|
+
id: `li-custom-${Date.now()}-${i}`,
|
|
85
|
+
taxRate: li.taxRate ?? taxRate,
|
|
86
|
+
taxAmount: calculateTax(li.amount, li.taxRate ?? taxRate),
|
|
87
|
+
}));
|
|
88
|
+
const subtotal = lineItems.reduce((sum, li) => sum + li.amount, 0);
|
|
89
|
+
const tax = lineItems.reduce((sum, li) => sum + (li.taxAmount ?? 0), 0);
|
|
90
|
+
const total = subtotal + tax;
|
|
91
|
+
const invoiceNumber = await store.getNextNumber(prefix);
|
|
92
|
+
const now = new Date();
|
|
93
|
+
const dueDate = input.dueDate ?? new Date(now.getTime() + defaultDueDays * 86400000);
|
|
94
|
+
const invoice = {
|
|
95
|
+
id: generateId(),
|
|
96
|
+
number: invoiceNumber,
|
|
97
|
+
customerId: input.customerId,
|
|
98
|
+
status: 'open',
|
|
99
|
+
currency,
|
|
100
|
+
subtotal,
|
|
101
|
+
tax,
|
|
102
|
+
total,
|
|
103
|
+
amountPaid: 0,
|
|
104
|
+
amountDue: total,
|
|
105
|
+
lineItems,
|
|
106
|
+
dueDate,
|
|
107
|
+
createdAt: now,
|
|
108
|
+
updatedAt: now,
|
|
109
|
+
metadata: input.metadata,
|
|
110
|
+
};
|
|
111
|
+
return store.create(invoice);
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* Mark an invoice as paid
|
|
115
|
+
*/
|
|
116
|
+
async markPaid(invoiceId, amount) {
|
|
117
|
+
const invoice = await store.get(invoiceId);
|
|
118
|
+
if (!invoice)
|
|
119
|
+
throw new Error(`Invoice '${invoiceId}' not found`);
|
|
120
|
+
const paidAmount = amount ?? invoice.total;
|
|
121
|
+
const newAmountPaid = invoice.amountPaid + paidAmount;
|
|
122
|
+
const newAmountDue = invoice.total - newAmountPaid;
|
|
123
|
+
const newStatus = newAmountDue <= 0 ? 'paid' : 'open';
|
|
124
|
+
await store.update(invoiceId, {
|
|
125
|
+
amountPaid: newAmountPaid,
|
|
126
|
+
amountDue: Math.max(0, newAmountDue),
|
|
127
|
+
status: newStatus,
|
|
128
|
+
paidAt: newStatus === 'paid' ? new Date() : undefined,
|
|
129
|
+
updatedAt: new Date(),
|
|
130
|
+
});
|
|
131
|
+
return (await store.get(invoiceId));
|
|
132
|
+
},
|
|
133
|
+
/**
|
|
134
|
+
* Void an invoice
|
|
135
|
+
*/
|
|
136
|
+
async void(invoiceId) {
|
|
137
|
+
const invoice = await store.get(invoiceId);
|
|
138
|
+
if (!invoice)
|
|
139
|
+
throw new Error(`Invoice '${invoiceId}' not found`);
|
|
140
|
+
if (invoice.status === 'paid')
|
|
141
|
+
throw new Error('Cannot void a paid invoice');
|
|
142
|
+
await store.update(invoiceId, {
|
|
143
|
+
status: 'void',
|
|
144
|
+
updatedAt: new Date(),
|
|
145
|
+
});
|
|
146
|
+
return (await store.get(invoiceId));
|
|
147
|
+
},
|
|
148
|
+
/**
|
|
149
|
+
* Get invoices for a customer
|
|
150
|
+
*/
|
|
151
|
+
async getByCustomer(customerId) {
|
|
152
|
+
return store.getByCustomer(customerId);
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Get an invoice by ID
|
|
156
|
+
*/
|
|
157
|
+
async get(invoiceId) {
|
|
158
|
+
return store.get(invoiceId);
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* In-memory invoice store (for dev/testing)
|
|
164
|
+
*/
|
|
165
|
+
export function createMemoryInvoiceStore() {
|
|
166
|
+
const invoices = new Map();
|
|
167
|
+
let counter = 0;
|
|
168
|
+
return {
|
|
169
|
+
async create(invoice) {
|
|
170
|
+
invoices.set(invoice.id, { ...invoice });
|
|
171
|
+
return invoice;
|
|
172
|
+
},
|
|
173
|
+
async get(id) {
|
|
174
|
+
return invoices.get(id) ?? null;
|
|
175
|
+
},
|
|
176
|
+
async getByCustomer(customerId) {
|
|
177
|
+
return Array.from(invoices.values()).filter(i => i.customerId === customerId);
|
|
178
|
+
},
|
|
179
|
+
async update(id, updates) {
|
|
180
|
+
const existing = invoices.get(id);
|
|
181
|
+
if (existing)
|
|
182
|
+
invoices.set(id, { ...existing, ...updates });
|
|
183
|
+
},
|
|
184
|
+
async getNextNumber(prefix) {
|
|
185
|
+
counter++;
|
|
186
|
+
return `${prefix}${String(counter).padStart(6, '0')}`;
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/invoices/generator.ts"],"names":[],"mappings":"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"}
|