Part · billing.usageWhat's actually behind
What's actually behind billing.usage
The part exactly as partkit add billing.usage vendors it into your repo — verified, locked, every byte readable. Nothing here is mocked.
billing.usagev1.1.0
✓ attested🔒 read-only↑ ctrlai upgradebilling.usage@1
Lives at parts/billing.usage/ in your repo — open, owned, readable. Not buried in node_modules. 587 lines of source you can audit.
content hash
bf603c07a8…51c1eapinned in parts.lock — ctrlai guard fails CI if a single byte changestested against
node 25.3.0stripe 22.2.1parts/billing.usage/src/index.tstypescript · 1,593 bytes/**
* billing.usage — public interface. The ONLY legal import surface.
* Contract: ../contract.json · What your app must provide: ../seams.md
*
* The vendor-neutral metered-usage ledger: record events idempotently, aggregate
* per subject/meter/period, and report unreported usage to a biller (Stripe
* Meters) out-of-band. The ledger is the source of truth — invoice from it
* yourself or push to Stripe; the biller is an adapter, not the foundation.
*/
import { adapter } from "../adapters/selected/adapter";
import { makeUsage } from "./internal/usage";
import type { SqlExecutor, UsageMeter } from "./internal/types";
export { UsageError } from "./internal/errors";
export type { UsageErrorCode } from "./internal/errors";
export type {
RecordedUsage,
RecordUsageInput,
ReportDueOptions,
SqlExecutor,
UsageMeter,
UsageReport,
UsageSummaryQuery,
UsageTotal,
UsageTotalQuery,
} from "./internal/types";
/**
* Bind the usage meter to a database connection (the SqlExecutor seam).
* Constructing it performs no I/O and never throws (contract invariant 1) — the
* database is touched only when a method runs, so it is serverless-safe.
*
* const meter = usage(db);
* await meter.record({ subjectId, meter: "api.request", quantity: 1, idempotencyKey: reqId });
* const t = await meter.total({ subjectId, meter: "api.request", since, until });
* // …then drive reportDue() from jobs.queue or a cron to push to the biller:
* await meter.reportDue();
*/
export function usage(db: SqlExecutor): UsageMeter {
return makeUsage(db, adapter);
}