business-as-code
Version:
Primitives for expressing business logic and processes as code
79 lines • 2.67 kB
JavaScript
/**
* Pricing — discriminated union with five factory variants.
*
* outcome — pay on delivery; tiers by complexity (S/M/L)
* subscription — recurring plan + optional metered overage
* perInvocation — flat per-call with included-tier ladder
* composite — one-time base + metered events
* percent-of — proportional charge against a realised basis
* (invoice amount, collected amount, transaction volume)
* with optional cap / floor
*
* Each factory returns a typed Pricing value with discriminator on .kind.
*/
export const Pricing = {
outcome(opts) {
if (opts.sla !== undefined) {
return { kind: 'outcome', tiers: opts.tiers, sla: opts.sla };
}
return { kind: 'outcome', tiers: opts.tiers };
},
subscription(opts) {
const result = {
kind: 'subscription',
plan: opts.plan,
};
if (opts.metered !== undefined)
result.metered = opts.metered;
if (opts.sla !== undefined)
result.sla = opts.sla;
return result;
},
perInvocation(opts) {
return { kind: 'per-invocation', tiers: opts.tiers };
},
composite(opts) {
return { kind: 'composite', base: opts.base, metered: opts.metered };
},
/**
* Percent-of-basis pricing — proportional charge against a realised
* basis (e.g. invoice amount, collected amount, transaction volume).
*
* The metering runtime resolves `basis` to a concrete bigint at
* settlement time, then computes the charge as
* `(realised_basis * rateBasisPoints) / 10000`, optionally clamped by
* `cap` / `floor`.
*
* @example AR Service: 2% of collected funds
* ```ts
* Pricing.percentOf({ basis: 'collected-amount', rateBasisPoints: 200 })
* ```
*
* @example Capped: 0.75% of transaction volume, max $50/event
* ```ts
* Pricing.percentOf({
* basis: 'transaction-volume',
* rateBasisPoints: 75,
* cap: { amount: 5000n, currency: 'USD' },
* })
* ```
*/
percentOf(opts) {
const result = {
kind: 'percent-of',
basis: opts.basis,
rateBasisPoints: opts.rateBasisPoints,
};
if (opts.cap !== undefined)
result.cap = opts.cap;
if (opts.floor !== undefined)
result.floor = opts.floor;
return result;
},
};
/** Convenience: build a Money value from a bigint + currency. */
export const money = (amount, currency = 'USD') => ({
amount,
currency,
});
//# sourceMappingURL=pricing.js.map