import { RequestHandler } from 'express'; import { PricingContext, Quote, quoteCall } from './pricing'; import { UsageRepo } from './usage'; export function meter( endpointId: string, repo: UsageRepo, pricing: PricingContext, onRecord?: (entry: { customerId: string; endpointId: string; cents: number }) => void, ): RequestHandler { return (req, res, next) => { const customer = req.customer; if (!customer) { res.status(401).json({ error: 'unauthenticated' }); return; } const metadataBytes = Buffer.byteLength( JSON.stringify(req.body?.metadata ?? {}), 'utf8', ); const files = (req.files as Express.Multer.File[] | undefined) ?? []; const attachmentBytes = files.reduce((sum, f) => sum + f.size, 0); let quote: Quote; try { quote = quoteCall( pricing, customer.tierId, endpointId, { metadataBytes, attachmentBytes }, customer.multiplierOverride, ); } catch (err) { res.status(403).json({ error: (err as Error).message }); return; } const entry = { customerId: customer.id, endpointId, cents: quote.totalCents, metadataBytes, attachmentBytes, timestamp: new Date(), }; repo.record(entry); onRecord?.({ customerId: customer.id, endpointId, cents: quote.totalCents }); res.locals.quote = quote; next(); }; }