@schematichq/schematic-typescript-node 1.6.1 → 1.6.3

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.
Files changed (82) hide show
  1. package/README.md +2 -0
  2. package/dist/api/resources/billing/client/requests/CreateInvoiceRequestBody.d.ts +1 -0
  3. package/dist/api/resources/credits/client/requests/AcquireCreditLeaseRequestBody.d.ts +1 -0
  4. package/dist/api/resources/credits/client/requests/ExtendCreditLeaseRequestBody.d.ts +3 -0
  5. package/dist/api/resources/entitlements/client/requests/CreateBillingLinkedPlanEntitlementRequestBody.d.ts +5 -1
  6. package/dist/api/resources/entitlements/client/requests/CreatePlanEntitlementRequestBody.d.ts +5 -1
  7. package/dist/api/resources/entitlements/client/requests/UpdatePlanEntitlementRequestBody.d.ts +5 -1
  8. package/dist/api/resources/features/client/requests/CheckAndReserveFlagRequestBody.d.ts +4 -2
  9. package/dist/api/types/BillingArrearsCadence.d.ts +1 -0
  10. package/dist/api/types/BillingCreditGrantReason.d.ts +3 -0
  11. package/dist/api/types/BillingCreditResponseData.d.ts +1 -0
  12. package/dist/api/types/BillingPlanCreditGrantBillingMode.d.ts +5 -0
  13. package/dist/api/types/BillingPlanCreditGrantPriceTierResponseData.d.ts +10 -0
  14. package/dist/api/types/BillingPlanCreditGrantResponseData.d.ts +12 -0
  15. package/dist/api/types/ChangeSubscriptionInternalRequestBody.d.ts +2 -0
  16. package/dist/api/types/ChangeSubscriptionRequestBody.d.ts +2 -0
  17. package/dist/api/types/CompanyFeatureUsageExportMetadataVisibleColumnsItem.d.ts +1 -0
  18. package/dist/api/types/CompanyPlanCreditGrantView.d.ts +3 -0
  19. package/dist/api/types/CreateBillingPlanCreditGrantRequestBody.d.ts +11 -1
  20. package/dist/api/types/CreateEntitlementInBundleRequestBody.d.ts +5 -1
  21. package/dist/api/types/CreditEventLedgerResponseData.d.ts +2 -0
  22. package/dist/api/types/CreditGrantPriceTierRequestBody.d.ts +8 -0
  23. package/dist/api/types/CreditTransferReason.d.ts +7 -0
  24. package/dist/api/types/InvoiceRequestBody.d.ts +1 -0
  25. package/dist/api/types/InvoiceResponseData.d.ts +2 -0
  26. package/dist/api/types/ManagePlanRequest.d.ts +2 -0
  27. package/dist/api/types/PlanCreditGrantView.d.ts +3 -0
  28. package/dist/api/types/PlanEntitlementResponseData.d.ts +5 -1
  29. package/dist/api/types/PreviewSubscriptionFinanceResponseData.d.ts +2 -0
  30. package/dist/api/types/RulesengineComparableOperator.d.ts +11 -0
  31. package/dist/api/types/RulesengineCondition.d.ts +1 -1
  32. package/dist/api/types/UpcomingInvoiceResponseData.d.ts +2 -0
  33. package/dist/api/types/UpdateBillingPlanCreditGrantRequestBody.d.ts +11 -1
  34. package/dist/api/types/UsageBasedEntitlementRequestBody.d.ts +5 -1
  35. package/dist/api/types/UsageBasedEntitlementResponseData.d.ts +1 -1
  36. package/dist/api/types/index.d.ts +5 -0
  37. package/dist/cache/redis.d.ts +11 -0
  38. package/dist/credits/check.d.ts +10 -5
  39. package/dist/credits/index.d.ts +3 -3
  40. package/dist/credits/lease-manager.d.ts +74 -2
  41. package/dist/credits/lease-store.d.ts +27 -11
  42. package/dist/credits/redis-lease-store.d.ts +2 -2
  43. package/dist/credits/types.d.ts +1 -0
  44. package/dist/index.js +12 -10
  45. package/dist/serialization/resources/billing/client/requests/CreateInvoiceRequestBody.d.ts +1 -0
  46. package/dist/serialization/resources/credits/client/requests/ExtendCreditLeaseRequestBody.d.ts +1 -0
  47. package/dist/serialization/resources/entitlements/client/requests/CreateBillingLinkedPlanEntitlementRequestBody.d.ts +4 -0
  48. package/dist/serialization/resources/entitlements/client/requests/CreatePlanEntitlementRequestBody.d.ts +4 -0
  49. package/dist/serialization/resources/entitlements/client/requests/UpdatePlanEntitlementRequestBody.d.ts +4 -0
  50. package/dist/serialization/resources/features/client/requests/CheckAndReserveFlagRequestBody.d.ts +1 -0
  51. package/dist/serialization/types/BillingArrearsCadence.d.ts +1 -1
  52. package/dist/serialization/types/BillingCreditGrantReason.d.ts +1 -1
  53. package/dist/serialization/types/BillingCreditResponseData.d.ts +2 -0
  54. package/dist/serialization/types/BillingPlanCreditGrantBillingMode.d.ts +7 -0
  55. package/dist/serialization/types/BillingPlanCreditGrantPriceTierResponseData.d.ts +12 -0
  56. package/dist/serialization/types/BillingPlanCreditGrantResponseData.d.ts +10 -0
  57. package/dist/serialization/types/ChangeSubscriptionInternalRequestBody.d.ts +1 -0
  58. package/dist/serialization/types/ChangeSubscriptionRequestBody.d.ts +1 -0
  59. package/dist/serialization/types/CompanyFeatureUsageExportMetadataVisibleColumnsItem.d.ts +1 -1
  60. package/dist/serialization/types/CompanyPlanCreditGrantView.d.ts +5 -0
  61. package/dist/serialization/types/CreateBillingPlanCreditGrantRequestBody.d.ts +8 -0
  62. package/dist/serialization/types/CreateEntitlementInBundleRequestBody.d.ts +4 -0
  63. package/dist/serialization/types/CreditEventLedgerResponseData.d.ts +3 -0
  64. package/dist/serialization/types/CreditGrantPriceTierRequestBody.d.ts +11 -0
  65. package/dist/serialization/types/CreditTransferReason.d.ts +7 -0
  66. package/dist/serialization/types/InvoiceRequestBody.d.ts +1 -0
  67. package/dist/serialization/types/InvoiceResponseData.d.ts +1 -0
  68. package/dist/serialization/types/ManagePlanRequest.d.ts +1 -0
  69. package/dist/serialization/types/PlanCreditGrantView.d.ts +5 -0
  70. package/dist/serialization/types/PlanEntitlementResponseData.d.ts +4 -0
  71. package/dist/serialization/types/PreviewSubscriptionFinanceResponseData.d.ts +1 -0
  72. package/dist/serialization/types/RulesengineComparableOperator.d.ts +7 -0
  73. package/dist/serialization/types/RulesengineCondition.d.ts +2 -2
  74. package/dist/serialization/types/UpcomingInvoiceResponseData.d.ts +1 -0
  75. package/dist/serialization/types/UpdateBillingPlanCreditGrantRequestBody.d.ts +8 -0
  76. package/dist/serialization/types/UsageBasedEntitlementRequestBody.d.ts +4 -0
  77. package/dist/serialization/types/index.d.ts +5 -0
  78. package/dist/wasm/rulesengine.d.ts +1 -0
  79. package/dist/wasm/rulesengine.js +34 -4
  80. package/dist/wasm/rulesengine_bg.wasm.d.ts +2 -0
  81. package/dist/wrapper.d.ts +50 -16
  82. package/package.json +3 -3
@@ -33,7 +33,7 @@ export interface CreditCheckDeps {
33
33
  * check. Otherwise `creditId` + `consumptionRate` + `eventSubtype` come
34
34
  * straight off the entitlement — no structural flag scan.
35
35
  * 2. Acquire (or reuse) a lease for `(company, creditId)`.
36
- * 3. Try to reserve `quantity × consumptionRate` from the lease.
36
+ * 3. Try to reserve `ceil(quantity) × consumptionRate` from the lease.
37
37
  * 4. Run the WASM rules engine against a substituted company snapshot
38
38
  * (`credit_balances[creditId] = lease.localRemaining` *before* the
39
39
  * reservation we just made was debited), gating with `credit_cost` so the
@@ -45,9 +45,14 @@ export declare function checkWithLease(deps: CreditCheckDeps, key: string, evalC
45
45
  * Build the preflight options envelope for a client-side rules evaluation.
46
46
  * With an `eventSubtype` the quantity goes out as the `event_usage` pair so
47
47
  * the engine matches it to the subtype's condition; without one it goes out
48
- * as the generic `usage` knob. Exported so `client.check`'s fallback path can
49
- * thread the same preflight through a plain flag check — any client-side
50
- * evaluation (datastream, replicator) honors it even when the lease path
51
- * can't run.
48
+ * as the generic `usage` knob. Exported so `client.check`'s fallback path and
49
+ * the server-mode check-and-reserve body can thread the same preflight — any
50
+ * evaluation path honors it even when the lease path can't run.
51
+ *
52
+ * The quantity rounds up here, once, so every consumer of this envelope asks
53
+ * the same whole-unit question: the engine takes an integer, the REST body
54
+ * takes an integer, and the settling Track event bills `ceil(actual)`. A
55
+ * preflight is an upper bound, so rounding up is also the only safe direction
56
+ * — the check must not pass on less usage than the action is about to record.
52
57
  */
53
58
  export declare function buildPreflightOptions(options: CheckOptions): CheckFlagOptions | undefined;
@@ -1,7 +1,7 @@
1
- export { LeaseStore, leaseKey, type LeaseEntry, type ILeaseStore } from "./lease-store";
1
+ export { LeaseStore, leaseKey, type LeaseEntry, type ILeaseStore, type ReserveResult } from "./lease-store";
2
2
  export { ReservationStore, type IReservationStore } from "./reservation-store";
3
- export { CreditLeaseManager } from "./lease-manager";
3
+ export { CreditLeaseManager, settleWithin, unrefTimer } from "./lease-manager";
4
4
  export { RedisLeaseStore } from "./redis-lease-store";
5
5
  export { RedisReservationStore } from "./redis-reservation-store";
6
- export { DEFAULT_LEASE_DURATION_MS, DEFAULT_LEASE_SIZE, DEFAULT_LOW_WATER_MARK, DEFAULT_PREWARM_POLL_INTERVAL_MS, DEFAULT_PREWARM_RESOLVE_TIMEOUT_MS, DEFAULT_RESERVATION_TTL_MS, DEFAULT_SWEEP_INTERVAL_MS, MAX_RESERVATION_TTL_MS, RESERVATION_TTL_SKEW_ALLOWANCE_MS, } from "./types";
6
+ export { DEFAULT_LEASE_DURATION_MS, DEFAULT_LEASE_SIZE, DEFAULT_LOW_WATER_MARK, DEFAULT_PREWARM_POLL_INTERVAL_MS, DEFAULT_PREWARM_RESOLVE_TIMEOUT_MS, DEFAULT_RESERVATION_TTL_MS, DEFAULT_SWEEP_INTERVAL_MS, MAX_RESERVATION_TTL_MS, RESERVATION_TTL_SKEW_ALLOWANCE_MS, SHUTDOWN_DRAIN_TIMEOUT_MS, } from "./types";
7
7
  export type { CreditLeaseConfig, CreditLeaseMode, ResolvedLeaseConfig, Reservation, CheckOptions, CheckResult, OnAcquireFailure, TrackWithReservationOptions, } from "./types";
@@ -2,6 +2,15 @@ import type { CreditsClient } from "../api/resources/credits/client/Client";
2
2
  import type { Logger } from "../logger";
3
3
  import { type ILeaseStore, type LeaseEntry } from "./lease-store";
4
4
  import { type CreditLeaseConfig, type ResolvedLeaseConfig } from "./types";
5
+ /** Drop a timer's hold on the event loop where the runtime has one (Node). */
6
+ export declare function unrefTimer(timer: ReturnType<typeof setTimeout>): void;
7
+ /**
8
+ * Await `promises`, giving up after `timeoutMs`. Reports whether everything
9
+ * landed, so a caller winding down can say what it is abandoning. Abandoned
10
+ * work is not cancelled — promises have no cancellation — it just stops being
11
+ * waited on.
12
+ */
13
+ export declare function settleWithin(promises: Promise<unknown>[], timeoutMs: number): Promise<boolean>;
5
14
  /**
6
15
  * Owns the lifecycle of `credit_lease` rows for a single client: acquire on
7
16
  * first use or after expiry, extend when the local view dips below the low
@@ -20,6 +29,8 @@ export declare class CreditLeaseManager {
20
29
  private readonly config;
21
30
  private readonly inflightAcquire;
22
31
  private readonly inflightExtend;
32
+ private readonly background;
33
+ private stopped;
23
34
  constructor(opts: {
24
35
  creditsClient: CreditsClient;
25
36
  leaseStore: ILeaseStore;
@@ -48,12 +59,71 @@ export declare class CreditLeaseManager {
48
59
  * that figure (a single check just failed a reserve for that many
49
60
  * credits — extend opportunistically instead of waiting for the next
50
61
  * sub-watermark check).
62
+ * A caller arriving while an extend is in flight joins it. If its own
63
+ * shortfall is larger than what that extend asked for, it waits the flight
64
+ * out and then issues exactly one follow-up extend for the remaining
65
+ * difference — otherwise it would inherit a tranche-sized ask and fail its
66
+ * post-extend retry with credits still sitting on the server. A flight it
67
+ * finds on the way back is only joined if that one covers the shortfall
68
+ * too; a smaller one is waited out, never inherited.
51
69
  * Returns the in-flight promise so callers can await it or fire-and-forget.
52
70
  * Never rejects (it is often fire-and-forget — a rejection would surface
53
71
  * as an unhandled promise rejection).
54
72
  */
55
- maybeExtendInBackground(companyId: string, creditTypeId: string, requiredCredits?: number, requestOptions?: CreditsClient.RequestOptions): Promise<LeaseEntry | undefined>;
73
+ maybeExtendInBackground(companyId: string, creditTypeId: string, requiredCredits?: number, requestOptions?: CreditsClient.RequestOptions, joinDeadlineMs?: number): Promise<LeaseEntry | undefined>;
74
+ private extendIfNeeded;
75
+ /** When a joiner's wait on a shared flight runs out, or undefined for no cap. */
76
+ private joinDeadline;
77
+ /**
78
+ * Await a flight somebody else is running, giving up at `deadline`. Giving
79
+ * up abandons only our wait: the flight keeps running for the callers still
80
+ * on it, and whatever it installs is there for our next check to read.
81
+ */
82
+ private joinWithin;
83
+ /**
84
+ * Read the slot, reporting `undefined` when the read fails or the lease is
85
+ * absent or expired. An expired lease is never extended: the server treats
86
+ * it as released (its remainder already refunded to the company balance),
87
+ * so the right move is a fresh acquire, which the next check's
88
+ * `acquireIfNeeded` performs. Extending would at best waste a wire call and
89
+ * at worst resurrect a stale local row.
90
+ */
91
+ private readLiveLease;
92
+ /** Whether `entry` sits low enough to warrant an extend. */
93
+ private needsExtend;
94
+ /**
95
+ * Register and run an extend as the slot's in-flight one. The cleanup is
96
+ * identity-guarded rather than an unconditional `delete`: a joiner whose
97
+ * shortfall outran this flight registers a follow-up for the same key, and
98
+ * this flight's `finally` must not evict it.
99
+ */
100
+ private startExtend;
101
+ /**
102
+ * Re-read the slot now that this flight owns it, and extend only if the
103
+ * fresh row still warrants one. The row that decided this extend was read
104
+ * before the flight was registered, so an extend that landed in that gap,
105
+ * clearing its own flight on the way out, would otherwise be followed by a
106
+ * second extend, under a new idempotency key, for a lease it already topped
107
+ * up. The registered `requestedAdditional` stands: a joiner compares its
108
+ * shortfall against that figure, so the wire body has to carry it.
109
+ */
110
+ private recheckAndExtend;
56
111
  private extend;
112
+ /** Hold a reference to unawaited work so `drain()` can wait it out. */
113
+ private track;
114
+ /**
115
+ * Refuse new lease work. Idempotent, and paired with `drain()`: stopping
116
+ * first is what makes the drain terminate, since nothing can enqueue
117
+ * behind it.
118
+ */
119
+ stop(): void;
120
+ /**
121
+ * Wait out lease work already on the wire, so a close releases what that
122
+ * work installs instead of orphaning it. Bounded: whatever has not landed
123
+ * by `timeoutMs` is abandoned rather than stalling the caller's shutdown,
124
+ * and the credits it holds fall back to server-side expiry.
125
+ */
126
+ drain(timeoutMs?: number): Promise<void>;
57
127
  /**
58
128
  * Release every live lease held in the store. ONLY safe when the store is
59
129
  * per-process (in-memory): those leases are exclusively this process's, so
@@ -63,6 +133,8 @@ export declare class CreditLeaseManager {
63
133
  * drawing on the same leases — and is excluded by the `list` capability
64
134
  * check (only the in-memory store implements it). Best-effort: failures
65
135
  * are logged and the lease falls back to server-side expiry.
136
+ * Bounded by `timeoutMs`, so a store or wire call that never lands cannot
137
+ * hold a closing client open; whatever is abandoned expires server-side.
66
138
  */
67
- releaseAllLocalLeases(): Promise<void>;
139
+ releaseAllLocalLeases(timeoutMs?: number): Promise<void>;
68
140
  }
@@ -21,6 +21,14 @@ export interface LeaseEntry {
21
21
  localRemainingCredits: number;
22
22
  expiresAt: Date;
23
23
  }
24
+ /**
25
+ * Outcome of a successful `tryReserve`: the post-debit balance plus the ID of
26
+ * the lease the credits actually came out of.
27
+ */
28
+ export interface ReserveResult {
29
+ balance: number;
30
+ leaseId: string;
31
+ }
24
32
  /** Backing-store contract shared by `LeaseStore` (in-memory) and `RedisLeaseStore` (shared). */
25
33
  export interface ILeaseStore {
26
34
  get(companyId: string, creditTypeId: string): Promise<LeaseEntry | undefined> | LeaseEntry | undefined;
@@ -65,15 +73,23 @@ export interface ILeaseStore {
65
73
  drop(companyId: string, creditTypeId: string): Promise<void>;
66
74
  /**
67
75
  * Atomically check-and-debit `credits` from the lease's remaining balance.
68
- * Returns the post-debit `localRemainingCredits` on success, or `null` if
69
- * there is no live lease, the balance is insufficient, or `credits` is not
70
- * a finite non-negative number (NaN must never reach the debit — it slips
71
- * through every numeric comparison and would poison the balance into
72
- * allowing everything). Returning the balance rather than a boolean lets
73
- * the caller derive the pre-debit figure (`returned + credits`) without a
74
- * follow-up read.
76
+ * Returns the post-debit `localRemainingCredits` together with the
77
+ * `leaseId` the debit landed on, or `null` if there is no live lease, the
78
+ * balance is insufficient, or `credits` is not a finite non-negative
79
+ * number (NaN must never reach the debit — it slips through every numeric
80
+ * comparison and would poison the balance into allowing everything).
81
+ * Returning the balance rather than a boolean lets the caller derive the
82
+ * pre-debit figure (`returned + credits`) without a follow-up read.
83
+ *
84
+ * The debit is NOT keyed by lease ID: it charges whichever lease occupies
85
+ * the slot at that moment, which need not be the one the caller's acquire
86
+ * handed back — the slot's lease can be replaced in between (by the
87
+ * sweeper, or by a sibling pod on a shared backend). The caller MUST
88
+ * therefore pin its reservation to the returned `leaseId`, never to the
89
+ * acquired one: the settle refund, the sweep refund, and the Track event's
90
+ * `lease_id` all have to name the lease that was actually charged.
75
91
  */
76
- tryReserve(companyId: string, creditTypeId: string, credits: number): Promise<number | null>;
92
+ tryReserve(companyId: string, creditTypeId: string, credits: number): Promise<ReserveResult | null>;
77
93
  /**
78
94
  * Refund credits to the slot's lease balance (clamped at `grantedAmount`).
79
95
  * When `leaseId` is supplied, the refund applies ONLY if the slot still
@@ -126,10 +142,10 @@ export declare class LeaseStore implements ILeaseStore {
126
142
  drop(companyId: string, creditTypeId: string): Promise<void>;
127
143
  /**
128
144
  * Attempt to reserve `credits` from the local remaining balance.
129
- * Returns the post-debit balance on success, `null` if there isn't enough
130
- * remaining (see `ILeaseStore.tryReserve`).
145
+ * Returns the post-debit balance and the charged lease's ID on success,
146
+ * `null` if there isn't enough remaining (see `ILeaseStore.tryReserve`).
131
147
  */
132
- tryReserve(companyId: string, creditTypeId: string, credits: number): Promise<number | null>;
148
+ tryReserve(companyId: string, creditTypeId: string, credits: number): Promise<ReserveResult | null>;
133
149
  /**
134
150
  * Refund credits back to the local balance (capped at grantedAmount).
135
151
  * When `leaseId` is given, the refund is dropped if the slot now holds a
@@ -1,5 +1,5 @@
1
1
  import type { RedisClient } from "../cache/redis";
2
- import { type ILeaseStore, type LeaseEntry } from "./lease-store";
2
+ import { type ILeaseStore, type LeaseEntry, type ReserveResult } from "./lease-store";
3
3
  /**
4
4
  * Redis-backed lease store. One hash per `(companyId, creditTypeId)` slot, with
5
5
  * atomic mutations via single-key Lua scripts so it stays correct on both
@@ -25,6 +25,6 @@ export declare class RedisLeaseStore implements ILeaseStore {
25
25
  replace(entry: Omit<LeaseEntry, "localRemainingCredits">): Promise<boolean>;
26
26
  extend(companyId: string, creditTypeId: string, grantedAmount: number, newExpiresAt?: Date, leaseId?: string): Promise<void>;
27
27
  drop(companyId: string, creditTypeId: string): Promise<void>;
28
- tryReserve(companyId: string, creditTypeId: string, credits: number): Promise<number | null>;
28
+ tryReserve(companyId: string, creditTypeId: string, credits: number): Promise<ReserveResult | null>;
29
29
  refund(companyId: string, creditTypeId: string, credits: number, leaseId?: string): Promise<void>;
30
30
  }
@@ -20,6 +20,7 @@ export declare const DEFAULT_LOW_WATER_MARK: number;
20
20
  export declare const DEFAULT_SWEEP_INTERVAL_MS: number;
21
21
  export declare const DEFAULT_PREWARM_RESOLVE_TIMEOUT_MS: number;
22
22
  export declare const DEFAULT_PREWARM_POLL_INTERVAL_MS: number;
23
+ export declare const SHUTDOWN_DRAIN_TIMEOUT_MS: number;
23
24
  /**
24
25
  * Where a credit hold lives for a `check()` that passes `usage`.
25
26
  * - `client`: local leases over DataStream — the SDK acquires a tranche of