@billfn/core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ErrorRegistry, type SuperfunctionError } from '@superfunctions/errors';
1
+ import { SuperfunctionError, type ErrorRegistry } from '@superfunctions/errors';
2
2
  declare const definitions: readonly [{
3
3
  readonly code: "BILLFN_VALIDATION_ERROR";
4
4
  readonly httpStatus: 400;
@@ -53,6 +53,8 @@ export declare function createBillFnError(input: {
53
53
  code: (typeof definitions)[number]['code'];
54
54
  message?: string;
55
55
  details?: Record<string, unknown>;
56
+ /** Overrides the code's registered retryability for an error a retry recovers from. */
57
+ retryable?: boolean;
56
58
  }): SuperfunctionError;
57
59
  export {};
58
60
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACxB,MAAM,wBAAwB,CAAC;AAEhC,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6DP,CAAC;AAEX,eAAO,MAAM,mBAAmB,EAAE,aAAqD,CAAC;AAExF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,GAAG,kBAAkB,CAOrB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,kBAAkB,EAClB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAEhC,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6DP,CAAC;AAEX,eAAO,MAAM,mBAAmB,EAAE,aAAqD,CAAC;AAExF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,uFAAuF;IACvF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,kBAAkB,CAiBrB"}
package/dist/errors.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createErrorRegistry, createTypedError } from '@superfunctions/errors';
1
+ import { createErrorRegistry, createTypedError, SuperfunctionError } from '@superfunctions/errors';
2
2
  const definitions = [
3
3
  {
4
4
  code: 'BILLFN_VALIDATION_ERROR',
@@ -63,11 +63,21 @@ const definitions = [
63
63
  ];
64
64
  export const billFnErrorRegistry = createErrorRegistry([...definitions]);
65
65
  export function createBillFnError(input) {
66
- return createTypedError({
66
+ const error = createTypedError({
67
67
  code: input.code,
68
68
  message: input.message,
69
69
  details: input.details,
70
70
  registry: billFnErrorRegistry
71
71
  });
72
+ if (input.retryable === undefined || input.retryable === error.retryable) {
73
+ return error;
74
+ }
75
+ return new SuperfunctionError({
76
+ code: error.code,
77
+ message: error.message,
78
+ status: error.status,
79
+ retryable: input.retryable,
80
+ details: error.details
81
+ });
72
82
  }
73
83
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAGjB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,GAAG;IAClB;QACE,IAAI,EAAE,yBAAyB;QAC/B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,IAAI;KAChB;IACD;QACE,IAAI,EAAE,6BAA6B;QACnC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,kCAAkC;QACxC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,8BAA8B;QACpC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,4BAA4B;QAClC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,gCAAgC;QACtC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAkB,mBAAmB,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;AAExF,MAAM,UAAU,iBAAiB,CAAC,KAIjC;IACC,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,mBAAmB;KAC9B,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAEnB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,GAAG;IAClB;QACE,IAAI,EAAE,yBAAyB;QAC/B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,IAAI;KAChB;IACD;QACE,IAAI,EAAE,6BAA6B;QACnC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,kCAAkC;QACxC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,8BAA8B;QACpC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,4BAA4B;QAClC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,gCAAgC;QACtC,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,KAAK;KACjB;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAkB,mBAAmB,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;AAExF,MAAM,UAAU,iBAAiB,CAAC,KAMjC;IACC,MAAM,KAAK,GAAG,gBAAgB,CAAC;QAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,mBAAmB;KAC9B,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,kBAAkB,CAAC;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { Adapter } from '@superfunctions/db';
2
+ import type { MetricsEmitter } from '@superfunctions/metrics';
3
+ import type { BillFnBillingEvent, BillFnCatalog, BillFnCreateGrantRequest, BillFnEntitlementGrant, BillFnEntitlementGrantSummary, BillFnEntitlementGrantKind, BillFnEntitlementSnapshot, BillFnOperator, BillFnRevokeGrantRequest } from './types.js';
4
+ /** The service dependencies grants use; the billing event and duplicate-key helpers are the service's own. */
5
+ export interface GrantDeps {
6
+ db: Adapter;
7
+ namespace: string;
8
+ catalog: BillFnCatalog;
9
+ now: () => Date;
10
+ metrics: MetricsEmitter;
11
+ /** Records the event through `db` when given (a transaction), otherwise through the service's adapter. */
12
+ recordBillingEvent(event: BillFnBillingEvent, db?: Adapter): Promise<void>;
13
+ isDuplicateRecordError(error: unknown): boolean;
14
+ }
15
+ export type GrantCreateInput = {
16
+ planKey: string;
17
+ kind: BillFnEntitlementGrantKind;
18
+ expiresAt: string;
19
+ operator: BillFnOperator | null;
20
+ reason: string | null;
21
+ };
22
+ /**
23
+ * Validates a grant request before any write, so a refused request creates no billing account. The expiry's
24
+ * position against now is checked separately (`requireFutureExpiry`), after `repairGrantEvents`.
25
+ */
26
+ export declare function readCreateGrantInput(deps: GrantDeps, input: BillFnCreateGrantRequest): GrantCreateInput;
27
+ /** Refuses a grant whose expiry is not after now. */
28
+ export declare function requireFutureExpiry(deps: GrantDeps, input: GrantCreateInput): void;
29
+ /**
30
+ * Records the account's grant events that are missing. Without transactions a grant change commits before its
31
+ * billing event, and a change whose event write fails stands (see `commitWithEvent`). Every grant create and
32
+ * revoke runs this first, before it checks the expiry or reads the grant it acts on, and every entitlements read
33
+ * runs it through `listRepairedGrants`: whatever that request then does, the account's earlier creations and
34
+ * revocations, also of grants that have since expired or been revoked, have their events. The events' ids and
35
+ * payloads derive from the stored grant, so a recorded event is kept and none is written twice. With
36
+ * transactions each change commits with its event and there is nothing to repair. Best effort: finding the
37
+ * missing events and writing each one fail on their own, a failed write skips no other event, and a repair that
38
+ * cannot write leaves the events to a later one and never fails the request. Pass the account's grants when
39
+ * already read.
40
+ */
41
+ export declare function repairGrantEvents(deps: GrantDeps, billingAccountId: string, grants?: BillFnEntitlementGrant[]): Promise<void>;
42
+ /**
43
+ * The account's grants for an entitlements read: their missing events are repaired first (see
44
+ * `repairGrantEvents`), and their status is derived after that, so a grant that ends during the repair reads
45
+ * as ended.
46
+ */
47
+ export declare function listRepairedGrants(deps: GrantDeps, billingAccountId: string): Promise<BillFnEntitlementGrant[]>;
48
+ /**
49
+ * Stores a grant. A trial's id is derived from its billing account, so the
50
+ * unique id refuses a second trial even when two requests race. Comps take
51
+ * numbered ids (`grant_comp_<account>_<n>`): a comp is refused while the
52
+ * latest one is active, and a new one claims the next number, so of two racing
53
+ * comps the unique id stores one and refuses the other. The grant and its
54
+ * creation event commit together (see `commitWithEvent`); without transactions
55
+ * the caller runs `repairGrantEvents` first, and a request refused by a racing
56
+ * grant records that grant's creation event.
57
+ */
58
+ export declare function insertGrant(deps: GrantDeps, billingAccountId: string, input: GrantCreateInput): Promise<BillFnEntitlementGrant>;
59
+ /**
60
+ * Revokes a comp. A revoked comp is returned unchanged; a racing revoke is applied once. Without transactions the
61
+ * account's unrecorded grant events are recorded first, also when the grant is then not found.
62
+ */
63
+ export declare function revokeGrant(deps: GrantDeps, input: BillFnRevokeGrantRequest): Promise<BillFnEntitlementGrant>;
64
+ /** The account's grants, newest first, with their derived status. */
65
+ export declare function listGrants(deps: GrantDeps, billingAccountId: string): Promise<BillFnEntitlementGrant[]>;
66
+ /** A grant as its billing subject sees it: without the operator, reasons or revoking operator. */
67
+ export declare function toGrantSummary(grant: BillFnEntitlementGrant): BillFnEntitlementGrantSummary;
68
+ /**
69
+ * The account's entitlements: the paid snapshot while it is not `inactive`
70
+ * (paid supersedes a grant), otherwise the active grant's plan (`trialing` for
71
+ * a trial, `active` for a comp) until the grant's expiry. Without an active
72
+ * grant the paid snapshot stands; an account with ended grants and no paid
73
+ * snapshot is `inactive` with no features or limits. Grants are read only when
74
+ * the paid snapshot does not decide, unless the caller passes them.
75
+ */
76
+ export declare function applyGrants(deps: GrantDeps, billingAccountId: string, paid: BillFnEntitlementSnapshot | null, grants?: BillFnEntitlementGrant[]): Promise<BillFnEntitlementSnapshot | null>;
77
+ //# sourceMappingURL=grants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,yBAAyB,EACzB,cAAc,EACd,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAQpB,8GAA8G;AAC9G,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,aAAa,CAAC;IACvB,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,OAAO,EAAE,cAAc,CAAC;IACxB,0GAA0G;IAC1G,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,EAAE,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACjD;AAKD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,0BAA0B,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,wBAAwB,GAAG,gBAAgB,CAqBvG;AAED,qDAAqD;AACrD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,QAI3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,sBAAsB,EAAE,iBA8BnH;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,qCAKjF;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,mCA6CnG;AAwBD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,wBAAwB,mCA0DjF;AAgDD,qEAAqE;AACrE,wBAAsB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAW7G;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,KAAK,EAAE,sBAAsB,GAAG,6BAA6B,CAU3F;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,SAAS,EACf,gBAAgB,EAAE,MAAM,EACxB,IAAI,EAAE,yBAAyB,GAAG,IAAI,EACtC,MAAM,CAAC,EAAE,sBAAsB,EAAE,GAChC,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAyC3C"}
package/dist/grants.js ADDED
@@ -0,0 +1,459 @@
1
+ import { createBillFnError } from './errors.js';
2
+ import { resolvePlan, toIsoString } from './helpers.js';
3
+ const GRANTS_TABLE = 'entitlementGrants';
4
+ const BILLING_EVENTS_TABLE = 'billingEvents';
5
+ const GRANT_KINDS = new Set(['trial', 'comp']);
6
+ const REVOKE_ATTEMPTS = 3;
7
+ const CREATE_ATTEMPTS = 3;
8
+ /**
9
+ * Validates a grant request before any write, so a refused request creates no billing account. The expiry's
10
+ * position against now is checked separately (`requireFutureExpiry`), after `repairGrantEvents`.
11
+ */
12
+ export function readCreateGrantInput(deps, input) {
13
+ if (typeof input.billingAccountId !== 'string' || input.billingAccountId.length === 0) {
14
+ throw validation('billingAccountId must be a non-empty string');
15
+ }
16
+ if (!GRANT_KINDS.has(input.kind)) {
17
+ throw validation("kind must be 'trial' or 'comp'");
18
+ }
19
+ if (typeof input.planKey !== 'string' || !resolvePlan(deps.catalog, input.planKey)) {
20
+ throw createBillFnError({ code: 'BILLFN_NOT_FOUND', message: `Plan not found: ${String(input.planKey)}` });
21
+ }
22
+ const expiresAt = typeof input.expiresAt === 'string' ? Date.parse(input.expiresAt) : Number.NaN;
23
+ if (!Number.isFinite(expiresAt)) {
24
+ throw validation('expiresAt must be an ISO 8601 time');
25
+ }
26
+ return {
27
+ planKey: input.planKey,
28
+ kind: input.kind,
29
+ expiresAt: toIsoString(new Date(expiresAt)),
30
+ operator: readOperator(input.operator),
31
+ reason: readReason(input.reason)
32
+ };
33
+ }
34
+ /** Refuses a grant whose expiry is not after now. */
35
+ export function requireFutureExpiry(deps, input) {
36
+ if (Date.parse(input.expiresAt) <= deps.now().getTime()) {
37
+ throw validation('expiresAt must be in the future');
38
+ }
39
+ }
40
+ /**
41
+ * Records the account's grant events that are missing. Without transactions a grant change commits before its
42
+ * billing event, and a change whose event write fails stands (see `commitWithEvent`). Every grant create and
43
+ * revoke runs this first, before it checks the expiry or reads the grant it acts on, and every entitlements read
44
+ * runs it through `listRepairedGrants`: whatever that request then does, the account's earlier creations and
45
+ * revocations, also of grants that have since expired or been revoked, have their events. The events' ids and
46
+ * payloads derive from the stored grant, so a recorded event is kept and none is written twice. With
47
+ * transactions each change commits with its event and there is nothing to repair. Best effort: finding the
48
+ * missing events and writing each one fail on their own, a failed write skips no other event, and a repair that
49
+ * cannot write leaves the events to a later one and never fails the request. Pass the account's grants when
50
+ * already read.
51
+ */
52
+ export async function repairGrantEvents(deps, billingAccountId, grants) {
53
+ if (deps.db.capabilities.transactions.supported) {
54
+ return;
55
+ }
56
+ let missing;
57
+ try {
58
+ const events = (grants ?? (await listGrants(deps, billingAccountId))).flatMap((grant) => grant.revokedAt ? [grantCreatedEvent(grant), grantRevokedEvent(grant)] : [grantCreatedEvent(grant)]);
59
+ if (events.length === 0) {
60
+ return;
61
+ }
62
+ const recorded = await deps.db.findMany({
63
+ model: BILLING_EVENTS_TABLE,
64
+ where: [{ field: 'id', operator: 'in', value: events.map((event) => event.id) }],
65
+ namespace: deps.namespace
66
+ });
67
+ const recordedIds = new Set(recorded.map((event) => event.id));
68
+ missing = events.filter((candidate) => !recordedIds.has(candidate.id));
69
+ }
70
+ catch {
71
+ deps.metrics.track('grant.event_deferred', { type: 'repair' });
72
+ return;
73
+ }
74
+ for (const event of missing) {
75
+ try {
76
+ await deps.recordBillingEvent(event);
77
+ }
78
+ catch {
79
+ deps.metrics.track('grant.event_deferred', { type: event.type });
80
+ }
81
+ }
82
+ }
83
+ /**
84
+ * The account's grants for an entitlements read: their missing events are repaired first (see
85
+ * `repairGrantEvents`), and their status is derived after that, so a grant that ends during the repair reads
86
+ * as ended.
87
+ */
88
+ export async function listRepairedGrants(deps, billingAccountId) {
89
+ const grants = await listGrants(deps, billingAccountId);
90
+ await repairGrantEvents(deps, billingAccountId, grants);
91
+ const now = deps.now();
92
+ return grants.map((grant) => withStatus(grant, now));
93
+ }
94
+ /**
95
+ * Stores a grant. A trial's id is derived from its billing account, so the
96
+ * unique id refuses a second trial even when two requests race. Comps take
97
+ * numbered ids (`grant_comp_<account>_<n>`): a comp is refused while the
98
+ * latest one is active, and a new one claims the next number, so of two racing
99
+ * comps the unique id stores one and refuses the other. The grant and its
100
+ * creation event commit together (see `commitWithEvent`); without transactions
101
+ * the caller runs `repairGrantEvents` first, and a request refused by a racing
102
+ * grant records that grant's creation event.
103
+ */
104
+ export async function insertGrant(deps, billingAccountId, input) {
105
+ for (let attempt = 0; attempt < CREATE_ATTEMPTS; attempt += 1) {
106
+ const id = input.kind === 'trial' ? trialGrantId(billingAccountId) : await nextCompId(deps, billingAccountId);
107
+ const timestamp = toIsoString(deps.now());
108
+ const record = {
109
+ id,
110
+ billingAccountId,
111
+ planKey: input.planKey,
112
+ kind: input.kind,
113
+ startsAt: timestamp,
114
+ expiresAt: input.expiresAt,
115
+ revokedAt: null,
116
+ operator: input.operator,
117
+ reason: input.reason,
118
+ revokedBy: null,
119
+ revokeReason: null,
120
+ createdAt: timestamp,
121
+ updatedAt: timestamp
122
+ };
123
+ try {
124
+ await commitWithEvent(deps, grantCreatedEvent(record), async (db) => {
125
+ await db.create({ model: GRANTS_TABLE, data: record, namespace: deps.namespace });
126
+ return true;
127
+ });
128
+ }
129
+ catch (error) {
130
+ if (!deps.isDuplicateRecordError(error)) {
131
+ throw error;
132
+ }
133
+ const existing = await findGrant(deps, billingAccountId, record.id);
134
+ if (existing) {
135
+ await recordCommittedEvent(deps, grantCreatedEvent(existing));
136
+ }
137
+ if (input.kind === 'trial') {
138
+ throw conflict('A trial was already granted to this billing account', 'trial_already_granted', record.id);
139
+ }
140
+ // The comp that took this number is active, or (read stale) it ended and the next number is free.
141
+ if (!existing || withStatus(existing, deps.now()).status === 'active') {
142
+ throw activeCompExists(record.id);
143
+ }
144
+ continue;
145
+ }
146
+ deps.metrics.track('grant.created', { kind: record.kind });
147
+ return withStatus(record, deps.now());
148
+ }
149
+ throw createBillFnError({ code: 'BILLFN_CONFLICT', message: 'Unable to create the grant after multiple retries' });
150
+ }
151
+ /**
152
+ * The id of the account's next comp. Comp n is created only while comp n-1 is
153
+ * not active, so the latest comp is the only one that can be active; while it
154
+ * is, the account's active comp is refused.
155
+ */
156
+ async function nextCompId(deps, billingAccountId) {
157
+ const prefix = compGrantIdPrefix(billingAccountId);
158
+ let latest;
159
+ let latestNumber = 0;
160
+ for (const grant of await listGrants(deps, billingAccountId)) {
161
+ const number = grant.kind === 'comp' && grant.id.startsWith(prefix) ? Number(grant.id.slice(prefix.length)) : 0;
162
+ if (Number.isSafeInteger(number) && number > latestNumber) {
163
+ latest = grant;
164
+ latestNumber = number;
165
+ }
166
+ }
167
+ if (latest?.status === 'active') {
168
+ throw activeCompExists(latest.id);
169
+ }
170
+ return `${prefix}${latestNumber + 1}`;
171
+ }
172
+ /**
173
+ * Revokes a comp. A revoked comp is returned unchanged; a racing revoke is applied once. Without transactions the
174
+ * account's unrecorded grant events are recorded first, also when the grant is then not found.
175
+ */
176
+ export async function revokeGrant(deps, input) {
177
+ if (typeof input.billingAccountId !== 'string' || input.billingAccountId.length === 0) {
178
+ throw validation('billingAccountId must be a non-empty string');
179
+ }
180
+ if (typeof input.grantId !== 'string' || input.grantId.length === 0) {
181
+ throw validation('grantId must be a non-empty string');
182
+ }
183
+ const operator = readOperator(input.operator);
184
+ const reason = readReason(input.reason);
185
+ await repairGrantEvents(deps, input.billingAccountId);
186
+ for (let attempt = 0; attempt < REVOKE_ATTEMPTS; attempt += 1) {
187
+ const existing = await findGrant(deps, input.billingAccountId, input.grantId);
188
+ if (!existing) {
189
+ throw createBillFnError({ code: 'BILLFN_NOT_FOUND', message: 'Grant not found' });
190
+ }
191
+ if (existing.kind !== 'comp') {
192
+ throw createBillFnError({
193
+ code: 'BILLFN_VALIDATION_ERROR',
194
+ message: 'Only a comp grant can be revoked',
195
+ details: { reason: 'grant_not_revocable' }
196
+ });
197
+ }
198
+ if (existing.revokedAt) {
199
+ await recordCommittedEvent(deps, grantRevokedEvent(existing));
200
+ return withStatus(existing, deps.now());
201
+ }
202
+ const now = deps.now();
203
+ const revoked = {
204
+ ...existing,
205
+ revokedAt: toIsoString(now),
206
+ revokedBy: operator,
207
+ revokeReason: reason,
208
+ // Strictly later than the stored time, so a racing revoke's compare-and-set on it fails.
209
+ updatedAt: laterThan(now, existing.updatedAt)
210
+ };
211
+ const applied = await commitWithEvent(deps, grantRevokedEvent(revoked), async (db) => {
212
+ const updated = await db.updateMany({
213
+ model: GRANTS_TABLE,
214
+ where: [
215
+ { field: 'id', operator: 'eq', value: existing.id },
216
+ { field: 'updatedAt', operator: 'eq', value: existing.updatedAt }
217
+ ],
218
+ data: {
219
+ revokedAt: revoked.revokedAt,
220
+ revokedBy: revoked.revokedBy,
221
+ revokeReason: revoked.revokeReason,
222
+ updatedAt: revoked.updatedAt
223
+ },
224
+ namespace: deps.namespace
225
+ });
226
+ return updated === 1;
227
+ });
228
+ if (applied) {
229
+ deps.metrics.track('grant.revoked', { kind: revoked.kind });
230
+ return withStatus(revoked, now);
231
+ }
232
+ }
233
+ throw createBillFnError({ code: 'BILLFN_CONFLICT', message: 'Unable to revoke the grant after multiple retries' });
234
+ }
235
+ /**
236
+ * Applies a grant change and records its billing event. Where the adapter
237
+ * supports transactions (memory, Prisma, Kysely, Drizzle Postgres) both commit
238
+ * in one transaction, so a failed event write leaves no grant change and the
239
+ * request fails. Without transactions (Drizzle SQLite) nothing can undo the
240
+ * change safely, so the committed change is the outcome: the grant stores its
241
+ * operator and reasons, a failed event write is retried once, and the request
242
+ * succeeds. An event still unrecorded derives from the grant and is recorded
243
+ * once by the account's next grant create or revoke or entitlements read
244
+ * (`repairGrantEvents`). Returns whether `write` applied the change; an
245
+ * unapplied change records no event.
246
+ */
247
+ async function commitWithEvent(deps, event, write) {
248
+ if (deps.db.capabilities.transactions.supported) {
249
+ return deps.db.transaction(async (transaction) => {
250
+ const db = transaction;
251
+ if (!(await write(db))) {
252
+ return false;
253
+ }
254
+ await deps.recordBillingEvent(event, db);
255
+ return true;
256
+ });
257
+ }
258
+ if (!(await write(deps.db))) {
259
+ return false;
260
+ }
261
+ await recordCommittedEvent(deps, event);
262
+ return true;
263
+ }
264
+ /**
265
+ * Records the event of a committed grant change: retried once, then left to `repairGrantEvents`. Never fails
266
+ * the request, whose outcome is the committed change.
267
+ */
268
+ async function recordCommittedEvent(deps, event) {
269
+ for (let attempt = 0; attempt < 2; attempt += 1) {
270
+ try {
271
+ await deps.recordBillingEvent(event);
272
+ return;
273
+ }
274
+ catch {
275
+ // Retried once, then deferred.
276
+ }
277
+ }
278
+ deps.metrics.track('grant.event_deferred', { type: event.type });
279
+ }
280
+ /** The account's grants, newest first, with their derived status. */
281
+ export async function listGrants(deps, billingAccountId) {
282
+ const records = await deps.db.findMany({
283
+ model: GRANTS_TABLE,
284
+ where: [{ field: 'billingAccountId', operator: 'eq', value: billingAccountId }],
285
+ orderBy: [{ field: 'createdAt', direction: 'desc' }],
286
+ namespace: deps.namespace
287
+ });
288
+ const now = deps.now();
289
+ return records
290
+ .map((record) => withStatus(record, now))
291
+ .sort((left, right) => compareTimes(right.createdAt, left.createdAt) || right.id.localeCompare(left.id));
292
+ }
293
+ /** A grant as its billing subject sees it: without the operator, reasons or revoking operator. */
294
+ export function toGrantSummary(grant) {
295
+ return {
296
+ id: grant.id,
297
+ kind: grant.kind,
298
+ planKey: grant.planKey,
299
+ status: grant.status,
300
+ startsAt: grant.startsAt,
301
+ expiresAt: grant.expiresAt,
302
+ revokedAt: grant.revokedAt ?? null
303
+ };
304
+ }
305
+ /**
306
+ * The account's entitlements: the paid snapshot while it is not `inactive`
307
+ * (paid supersedes a grant), otherwise the active grant's plan (`trialing` for
308
+ * a trial, `active` for a comp) until the grant's expiry. Without an active
309
+ * grant the paid snapshot stands; an account with ended grants and no paid
310
+ * snapshot is `inactive` with no features or limits. Grants are read only when
311
+ * the paid snapshot does not decide, unless the caller passes them.
312
+ */
313
+ export async function applyGrants(deps, billingAccountId, paid, grants) {
314
+ if (paid && paid.status !== 'inactive') {
315
+ return paid;
316
+ }
317
+ const candidates = grants ?? (await listGrants(deps, billingAccountId));
318
+ const active = selectActiveGrant(candidates);
319
+ if (active) {
320
+ const plan = resolvePlan(deps.catalog, active.planKey);
321
+ return {
322
+ id: paid?.id ?? `ent_${billingAccountId}`,
323
+ billingAccountId,
324
+ planKey: active.planKey,
325
+ status: active.kind === 'trial' ? 'trialing' : 'active',
326
+ // A plan removed from the catalog after the grant entitles nothing.
327
+ features: { ...(plan?.features ?? {}) },
328
+ limits: { ...(plan?.limits ?? {}) },
329
+ effectiveAt: active.startsAt,
330
+ expiresAt: active.expiresAt,
331
+ sourceEventId: `grant:${active.id}`,
332
+ grant: { id: active.id, kind: active.kind, expiresAt: active.expiresAt },
333
+ createdAt: paid?.createdAt ?? active.createdAt,
334
+ updatedAt: active.updatedAt
335
+ };
336
+ }
337
+ if (paid || candidates.length === 0) {
338
+ return paid;
339
+ }
340
+ const latest = candidates[0];
341
+ return {
342
+ id: `ent_${billingAccountId}`,
343
+ billingAccountId,
344
+ planKey: latest.planKey,
345
+ status: 'inactive',
346
+ features: {},
347
+ limits: {},
348
+ effectiveAt: latest.revokedAt ?? latest.expiresAt,
349
+ expiresAt: latest.revokedAt ?? latest.expiresAt,
350
+ sourceEventId: `grant:${latest.id}`,
351
+ createdAt: latest.createdAt,
352
+ updatedAt: latest.updatedAt
353
+ };
354
+ }
355
+ /** A comp before a trial, then the later expiry; racing comps resolve the same way on every read. */
356
+ function selectActiveGrant(grants) {
357
+ return grants
358
+ .filter((grant) => grant.status === 'active')
359
+ .sort((left, right) => (left.kind === right.kind ? 0 : left.kind === 'comp' ? -1 : 1) ||
360
+ compareTimes(right.expiresAt, left.expiresAt) ||
361
+ left.id.localeCompare(right.id))[0];
362
+ }
363
+ function withStatus(record, now) {
364
+ const expiresAt = Date.parse(record.expiresAt);
365
+ const status = record.revokedAt
366
+ ? 'revoked'
367
+ : Number.isFinite(expiresAt) && expiresAt > now.getTime()
368
+ ? 'active'
369
+ : 'expired';
370
+ return { ...record, status };
371
+ }
372
+ async function findGrant(deps, billingAccountId, grantId) {
373
+ return deps.db.findOne({
374
+ model: GRANTS_TABLE,
375
+ where: [
376
+ { field: 'id', operator: 'eq', value: grantId },
377
+ { field: 'billingAccountId', operator: 'eq', value: billingAccountId }
378
+ ],
379
+ namespace: deps.namespace
380
+ });
381
+ }
382
+ function trialGrantId(billingAccountId) {
383
+ return `grant_trial_${billingAccountId}`;
384
+ }
385
+ function compGrantIdPrefix(billingAccountId) {
386
+ return `grant_comp_${billingAccountId}_`;
387
+ }
388
+ function activeCompExists(grantId) {
389
+ return conflict('An active comp already exists for this billing account', 'active_comp_exists', grantId);
390
+ }
391
+ function grantCreatedEvent(grant) {
392
+ return {
393
+ id: `evt_grant_created_${grant.id}`,
394
+ billingAccountId: grant.billingAccountId,
395
+ type: 'billfn.grant.created',
396
+ payload: {
397
+ grantId: grant.id,
398
+ kind: grant.kind,
399
+ planKey: grant.planKey,
400
+ startsAt: grant.startsAt,
401
+ expiresAt: grant.expiresAt,
402
+ operator: grant.operator ?? null,
403
+ reason: grant.reason ?? null
404
+ },
405
+ createdAt: grant.createdAt
406
+ };
407
+ }
408
+ function grantRevokedEvent(grant) {
409
+ return {
410
+ id: `evt_grant_revoked_${grant.id}`,
411
+ billingAccountId: grant.billingAccountId,
412
+ type: 'billfn.grant.revoked',
413
+ payload: {
414
+ grantId: grant.id,
415
+ kind: grant.kind,
416
+ planKey: grant.planKey,
417
+ operator: grant.revokedBy ?? null,
418
+ reason: grant.revokeReason ?? null
419
+ },
420
+ createdAt: grant.revokedAt ?? grant.updatedAt
421
+ };
422
+ }
423
+ function readOperator(operator) {
424
+ if (operator === undefined) {
425
+ return null;
426
+ }
427
+ if (typeof operator !== 'object' || operator === null || typeof operator.id !== 'string' || operator.id.length === 0) {
428
+ throw validation('operator.id must be a non-empty string');
429
+ }
430
+ return {
431
+ id: operator.id,
432
+ ...(typeof operator.type === 'string' ? { type: operator.type } : {}),
433
+ ...(typeof operator.requestId === 'string' ? { requestId: operator.requestId } : {})
434
+ };
435
+ }
436
+ function readReason(reason) {
437
+ if (reason === undefined) {
438
+ return null;
439
+ }
440
+ if (typeof reason !== 'string') {
441
+ throw validation('reason must be a string');
442
+ }
443
+ return reason;
444
+ }
445
+ function laterThan(now, previous) {
446
+ const previousTime = Date.parse(previous);
447
+ const time = Number.isFinite(previousTime) && now.getTime() <= previousTime ? previousTime + 1 : now.getTime();
448
+ return toIsoString(new Date(time));
449
+ }
450
+ function compareTimes(left, right) {
451
+ return (Date.parse(left) || 0) - (Date.parse(right) || 0);
452
+ }
453
+ function validation(message) {
454
+ return createBillFnError({ code: 'BILLFN_VALIDATION_ERROR', message });
455
+ }
456
+ function conflict(message, reason, grantId) {
457
+ return createBillFnError({ code: 'BILLFN_CONFLICT', message, details: { reason, grantId } });
458
+ }
459
+ //# sourceMappingURL=grants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.js","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@ import type { BillFnConfig, BillFnInstance } from './types.js';
2
2
  export type * from './types.js';
3
3
  export { getSchema, getSchemaMap } from './schema.js';
4
4
  export { createBillFnError, billFnErrorRegistry } from './errors.js';
5
- export { createBillFnReconciliationWorker } from './service.js';
5
+ export { BILLFN_IMPORTED_AT_METADATA_KEY, BILLFN_IMPORT_PENDING_METADATA_KEY, BILLFN_IMPORT_REPLAY_UNFINISHED_REASON, createBillFnReconciliationWorker } from './service.js';
6
6
  export declare function createBillFn(config: BillFnConfig): BillFnInstance;
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,gCAAgC,EAAE,MAAM,cAAc,CAAC;AAEhE,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAyBjE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EACL,+BAA+B,EAC/B,kCAAkC,EAClC,sCAAsC,EACtC,gCAAgC,EACjC,MAAM,cAAc,CAAC;AAEtB,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAkCjE"}