Billing
VentureKit provides billing support through @venturekit-pro/billing with plan definitions, feature limits, and usage-to-invoice mapping.
npm install @venturekit-pro/billing@devOverview
Section titled “Overview”@venturekit-pro/billing handles plan logic and invoicing, not payment processing. It provides:
- Plan definitions with feature limits
- Feature checking (
hasFeature,getFeatureLimit) - Usage-to-invoice-item mapping
- Auto-migration support for billing database tables
Integrate any payment provider separately when needed.
Defining Plans
Section titled “Defining Plans”import { definePlans } from '@venturekit-pro/billing';
const plans = definePlans([ { id: 'free', name: 'Free', features: { projects: { limit: 3 }, storage: { limit: 1_000_000_000 }, // 1 GB apiRequests: { limit: 10_000, period: 'month' }, customDomains: false, support: false, }, }, { id: 'pro', name: 'Pro', features: { projects: { limit: 50 }, storage: { limit: 100_000_000_000 }, // 100 GB apiRequests: { limit: 1_000_000, period: 'month' }, customDomains: true, support: true, }, }, { id: 'enterprise', name: 'Enterprise', features: { projects: { limit: -1 }, // Unlimited storage: { limit: -1 }, apiRequests: { limit: -1 }, customDomains: true, support: true, }, },]);Feature Checking
Section titled “Feature Checking”Use in handlers to enforce plan limits:
import { handler } from '@venturekit/runtime';import { getFeatureLimit, hasFeature } from '@venturekit-pro/billing';
export const main = handler(async (body, ctx, logger) => { const userPlan = 'free'; // Resolve from tenant/user
// Check boolean feature if (!hasFeature(plans, userPlan, 'customDomains')) { throw new ForbiddenError('Custom domains require a Pro plan'); }
// Check numeric limit const maxProjects = getFeatureLimit(plans, userPlan, 'projects'); const currentCount = await getProjectCount(ctx.user!.id); if (maxProjects !== -1 && currentCount >= maxProjects) { throw new ForbiddenError(`Project limit reached (${maxProjects})`); }
return { allowed: true };}, { scopes: ['projects.write'] });Usage-to-Invoice Mapping
Section titled “Usage-to-Invoice Mapping”Generate invoice line items from usage data:
import { mapUsageToLineItems } from '@venturekit-pro/billing';
const lineItems = mapUsageToLineItems(currentUsage, planFeatures);// Returns structured line items for invoice generationAuto-Migrations
Section titled “Auto-Migrations”When @venturekit-pro/billing is installed, vk migrate discovers and applies billing-related database tables automatically:
import { getBillingMigrationsDir } from '@venturekit-pro/billing';
const migrationsDir = getBillingMigrationsDir();Combining with Tenancy
Section titled “Combining with Tenancy”Billing works well with @venturekit-pro/tenancy for per-tenant plan enforcement:
import { createTenantMiddleware, createQuotaMiddleware } from '@venturekit-pro/tenancy';import { getFeatureLimit } from '@venturekit-pro/billing';
export const main = handler(async (_body, ctx, logger) => { const tenant = ctx.tenant!; const plan = tenant.metadata.plan as string; const limit = getFeatureLimit(plans, plan, 'apiRequests');
return { tenantId: tenant.id, plan, apiRequestLimit: limit };}, { scopes: ['api.read'], middleware: [ createTenantMiddleware({ strategy: 'subdomain' }), createQuotaMiddleware(), ],});