master-zapier-plan-draft/packages/zappier/src/billing/stripe.ts
George Lambert b4150c8250 Milestone 0: import zappier billing, Verae middleware, and Zapier research
Compose-ready workspace: packages/zappier (rate card, portal, Stripe),
packages/verae-zapier-middleware (timestamp + NATS), packages/verae-zapier
(CLI app), vendor/zapier-platform, and research/zapier vendor corpus.

Gate 0 structure checks pass. Product code and research are not yet wired.
2026-09-09 02:37:36 -04:00

41 lines
1.4 KiB
TypeScript

import { UsageEntry } from '../usage';
export const METER_EVENT_NAME = 'zappier.api_cents';
export interface MeterEventClient {
createMeterEvent(params: {
eventName: string;
customerId: string;
value: string;
/** Stripe-side dedup key; events with the same identifier are dropped. */
identifier?: string;
}): Promise<void>;
}
export function computeBillableCents(entries: UsageEntry[], monthlyCreditCents: number): number {
const totalCents = entries.reduce((sum, e) => sum + e.cents, 0);
return Math.max(0, totalCents - monthlyCreditCents);
}
export function computeDelta(billableCents: number, previouslyReportedCents: number): number {
return Math.max(0, billableCents - previouslyReportedCents);
}
// Public API: retained for API compatibility. The monthly billing job now uses
// the delta-based path in src/jobs/report-usage.ts (reportMonthlyUsage), which
// shares computeBillableCents with this function. Do not remove.
export async function reportUsage(
client: MeterEventClient,
stripeCustomerId: string,
entries: UsageEntry[],
monthlyCreditCents: number,
): Promise<number> {
const billable = computeBillableCents(entries, monthlyCreditCents);
if (billable <= 0) return 0;
await client.createMeterEvent({
eventName: METER_EVENT_NAME,
customerId: stripeCustomerId,
value: String(billable),
});
return billable;
}