tasq/node_modules/agentic-flow/dist/billing/index.js

205 lines
7.2 KiB
JavaScript

/**
* Agentic-Jujutsu Billing System
* Complete economic system for subscriptions, metering, and payments
*
* TypeScript implementation for npm package
*/
import { EventEmitter } from 'events';
import { PricingManager } from './pricing/tiers.js';
import { MeteringEngine } from './metering/engine.js';
import { SubscriptionManager } from './subscriptions/manager.js';
import { CouponManager } from './coupons/manager.js';
import { PaymentProcessor, PaymentProviderFactory } from './payments/processor.js';
import { StorageAdapterFactory } from './storage/adapters.js';
import { PaymentProvider } from './types.js';
// Re-export all types
export * from './types.js';
export { PricingManager, DEFAULT_TIERS } from './pricing/tiers.js';
export { MeteringEngine } from './metering/engine.js';
export { SubscriptionManager } from './subscriptions/manager.js';
export { CouponManager } from './coupons/manager.js';
export { PaymentProcessor, PaymentProviderFactory } from './payments/processor.js';
export { StorageAdapterFactory } from './storage/adapters.js';
/**
* Main Billing System Class
* Orchestrates all billing components
*/
export class BillingSystem extends EventEmitter {
pricing;
metering;
subscriptions;
coupons;
payments;
storage;
config;
constructor(config) {
super();
// Default configuration
this.config = {
currency: 'USD',
taxRate: 0,
gracePeriodDays: 3,
enableMetering: true,
enableCoupons: true,
enableOverages: true,
overageRate: 1.5,
softLimitPercent: 80,
hardLimitPercent: 100,
storageBackend: 'memory',
paymentProvider: PaymentProvider.Stripe,
...config
};
// Initialize storage
this.storage = this.initializeStorage();
// Initialize components
this.pricing = new PricingManager();
this.metering = new MeteringEngine(this.storage, {
enabled: this.config.enableMetering,
softLimitPercent: this.config.softLimitPercent,
hardLimitPercent: this.config.hardLimitPercent
});
this.subscriptions = new SubscriptionManager(this.storage, this.pricing);
this.coupons = new CouponManager(this.storage);
this.payments = new PaymentProcessor({
provider: this.config.paymentProvider
}, this.storage);
// Forward events
this.setupEventForwarding();
}
/**
* Create a new subscription with payment
*/
async subscribe(params) {
const { userId, tier, billingCycle, paymentMethodId, couponCode } = params;
// Calculate price
let price = this.pricing.calculatePrice(tier, billingCycle);
// Apply coupon if provided
let discount = 0;
if (couponCode && this.config.enableCoupons) {
const validation = await this.coupons.validateCoupon(couponCode, tier, price);
if (validation.valid) {
discount = validation.discountAmount;
price = validation.finalAmount;
await this.coupons.applyCoupon(couponCode);
}
}
// Create subscription
const subscription = await this.subscriptions.createSubscription({
userId,
tier,
billingCycle,
paymentMethodId,
couponCode
});
// Process payment
const payment = await this.payments.processPayment({
subscriptionId: subscription.id,
userId,
amount: price,
currency: this.config.currency,
paymentMethodId,
description: `${tier} subscription - ${billingCycle}`,
metadata: {
tier,
billingCycle,
discount
}
});
return { subscription, payment };
}
/**
* Record usage for a subscription
*/
async recordUsage(params) {
await this.metering.recordUsage(params);
}
/**
* Check quota before operation
*/
async checkQuota(subscriptionId, metric) {
const subscription = await this.subscriptions.getSubscription(subscriptionId);
if (!subscription)
return false;
const result = await this.metering.checkQuota(subscriptionId, metric, subscription.limits);
return result.allowed;
}
/**
* Get usage summary
*/
async getUsageSummary(subscriptionId) {
const subscription = await this.subscriptions.getSubscription(subscriptionId);
if (!subscription) {
throw new Error('Subscription not found');
}
return this.metering.getUsageSummary(subscriptionId, subscription.limits);
}
/**
* Upgrade subscription
*/
async upgrade(subscriptionId, newTier) {
const subscription = await this.subscriptions.upgradeSubscription(subscriptionId, newTier);
// Calculate and charge prorated amount
const pricingTier = this.pricing.getTier(newTier);
// Payment logic here
return subscription;
}
/**
* Cancel subscription
*/
async cancel(subscriptionId, immediate = false) {
return this.subscriptions.cancelSubscription(subscriptionId, immediate);
}
/**
* Shutdown billing system
*/
async shutdown() {
await this.metering.stop();
}
initializeStorage() {
switch (this.config.storageBackend) {
case 'memory':
return StorageAdapterFactory.createMemory();
case 'agentdb':
// In production, initialize with actual AgentDB instance
return StorageAdapterFactory.createMemory();
case 'sqlite':
// In production, initialize with SQLite path
return StorageAdapterFactory.createMemory();
default:
return StorageAdapterFactory.createMemory();
}
}
setupEventForwarding() {
// Forward metering events
this.metering.on('usage.recorded', (data) => this.emit('usage.recorded', data));
this.metering.on('quota.warning', (data) => this.emit('quota.warning', data));
this.metering.on('quota.exceeded', (data) => this.emit('quota.exceeded', data));
// Forward subscription events
this.subscriptions.on('subscription.created', (data) => this.emit('subscription.created', data));
this.subscriptions.on('subscription.upgraded', (data) => this.emit('subscription.upgraded', data));
this.subscriptions.on('subscription.downgraded', (data) => this.emit('subscription.downgraded', data));
this.subscriptions.on('subscription.canceled', (data) => this.emit('subscription.canceled', data));
this.subscriptions.on('subscription.renewed', (data) => this.emit('subscription.renewed', data));
}
}
/**
* Create a billing system instance
*/
export function createBillingSystem(config) {
return new BillingSystem(config);
}
/**
* Default export
*/
export default {
BillingSystem,
createBillingSystem,
PricingManager,
MeteringEngine,
SubscriptionManager,
CouponManager,
PaymentProcessor,
PaymentProviderFactory,
StorageAdapterFactory
};
//# sourceMappingURL=index.js.map