@nehorai/credits 2.1.0 → 3.0.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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapters/index.cjs +3 -2
  3. package/dist/adapters/index.cjs.map +1 -1
  4. package/dist/adapters/index.d.cts +2 -2
  5. package/dist/adapters/index.d.ts +2 -2
  6. package/dist/adapters/index.js +3 -2
  7. package/dist/adapters/index.js.map +1 -1
  8. package/dist/core/index.cjs +218 -2
  9. package/dist/core/index.cjs.map +1 -1
  10. package/dist/core/index.d.cts +183 -5
  11. package/dist/core/index.d.ts +183 -5
  12. package/dist/core/index.js +199 -2
  13. package/dist/core/index.js.map +1 -1
  14. package/dist/index.cjs +477 -59
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +6 -6
  17. package/dist/index.d.ts +6 -6
  18. package/dist/index.js +456 -59
  19. package/dist/index.js.map +1 -1
  20. package/dist/repository/index.cjs +394 -44
  21. package/dist/repository/index.cjs.map +1 -1
  22. package/dist/repository/index.d.cts +36 -7
  23. package/dist/repository/index.d.ts +36 -7
  24. package/dist/repository/index.js +391 -43
  25. package/dist/repository/index.js.map +1 -1
  26. package/dist/sdk/index.cjs +1 -0
  27. package/dist/sdk/index.cjs.map +1 -1
  28. package/dist/sdk/index.d.cts +2 -2
  29. package/dist/sdk/index.d.ts +2 -2
  30. package/dist/sdk/index.js +1 -0
  31. package/dist/sdk/index.js.map +1 -1
  32. package/dist/service/index.cjs +33 -20
  33. package/dist/service/index.cjs.map +1 -1
  34. package/dist/service/index.d.cts +2 -2
  35. package/dist/service/index.d.ts +2 -2
  36. package/dist/service/index.js +33 -20
  37. package/dist/service/index.js.map +1 -1
  38. package/dist/{types-Dzc443vy.d.cts → types-C3sxDvNb.d.cts} +43 -2
  39. package/dist/{types-Dzc443vy.d.ts → types-C3sxDvNb.d.ts} +43 -2
  40. package/dist/{types-BhCdep_t.d.ts → types-CY-oHIMA.d.ts} +55 -4
  41. package/dist/{types-wtksMa4n.d.cts → types-DOjguhEX.d.cts} +55 -4
  42. package/package.json +70 -71
@@ -1,6 +1,6 @@
1
- import { I as ICreditRepository, b as AddCreditsV2Input, a as AddCreditsOutcome, l as ReservationTransitionOptions, C as CommitOutcome, R as ReleaseOutcome, m as ReserveCreditsV2Input, n as ReserveOutcome, g as CreditBalanceUpdate, o as TierUpdateInput, d as CreateReservationInput, i as ExpireReservationV2Options, E as ExpireOutcome, A as AddCreditsAtomicOptions, e as CreateTransactionInput, f as CreateUsageLogInput, U as UsageLogQuery, c as CreateJournalEntryInput, J as JournalEntryQuery } from '../types-wtksMa4n.cjs';
2
- export { h as CreditRepositoryFactory, j as ICreditRepositoryCreditsV2, k as ICreditRepositoryV2, s as reservationJournalKey, t as supportsCreditsV2, u as supportsIdempotentCredit, v as toClientUserCredits } from '../types-wtksMa4n.cjs';
3
- import { c as PortableUserCredits, S as SubscriptionTier, a as PortableReservation, R as ReservationStatus, P as PortableTransaction, d as PortableUsageLog, f as PortableJournalEntry, M as MonthlyResetResult, e as SubscriptionExpiryResult } from '../types-Dzc443vy.cjs';
1
+ import { I as ICreditRepository, b as AddCreditsV2Input, a as AddCreditsOutcome, m as ReservationTransitionOptions, C as CommitOutcome, R as ReleaseOutcome, n as ReserveCreditsV2Input, o as ReserveOutcome, g as CreditBalanceUpdate, h as CreditPolicyOptions, p as TierUpdateInput, d as CreateReservationInput, j as ExpireReservationV2Options, E as ExpireOutcome, A as AddCreditsAtomicOptions, D as DeductJournalInput, e as CreateTransactionInput, f as CreateUsageLogInput, U as UsageLogQuery, c as CreateJournalEntryInput, J as JournalEntryQuery } from '../types-DOjguhEX.cjs';
2
+ export { i as CreditRepositoryFactory, k as ICreditRepositoryCreditsV2, l as ICreditRepositoryV2, t as reservationJournalKey, u as supportsCreditsV2, v as supportsIdempotentCredit, w as toClientUserCredits } from '../types-DOjguhEX.cjs';
3
+ import { c as PortableUserCredits, S as SubscriptionTier, a as PortableReservation, R as ReservationStatus, P as PortableTransaction, d as PortableUsageLog, f as PortableJournalEntry, M as MonthlyResetResult, e as SubscriptionExpiryResult } from '../types-C3sxDvNb.cjs';
4
4
 
5
5
  /**
6
6
  * One reservation flow for both repository generations.
@@ -62,6 +62,7 @@ declare function addCreditsThroughRepository(repository: ICreditRepository, inpu
62
62
  * These are pure functions with no server-only dependencies,
63
63
  * making them safe to use in any repository implementation.
64
64
  */
65
+
65
66
  /**
66
67
  * Generate a unique ID
67
68
  * Uses timestamp + random string for uniqueness
@@ -77,6 +78,27 @@ declare function toDate(value: Date | string | unknown): Date;
77
78
  * Used for calculating monthly reset dates
78
79
  */
79
80
  declare function getNextMonthlyReset(from?: Date): Date;
81
+ /** Result of validating a balance update. */
82
+ interface BalanceValidationResult {
83
+ valid: boolean;
84
+ errors: string[];
85
+ }
86
+ /**
87
+ * Whether an update leaves a valid account: no negative field, and `reserved` covered
88
+ * by `balance + bonusCredits`, which is the floor outstanding holds put under the
89
+ * balance. An increment is applied on top of the absolute value when a call names both.
90
+ *
91
+ * An update is a delta the caller asked for, so one that cannot be honoured is refused,
92
+ * as a deduct is. Only tier writes and resets stop at the floor: they state a target.
93
+ *
94
+ * A negative balance increment is a charge, so it draws only on the balance above
95
+ * `expiredHoldBacking`: those credits are expired and leave when their hold closes, so
96
+ * charging them would hand the charge back. An absolute balance replaces the field and
97
+ * the marks with it, so only an increment on the stored balance meets this limit.
98
+ */
99
+ declare function validateBalanceUpdate(current: Pick<PortableUserCredits, "balance" | "bonusCredits" | "reserved" | "expiredHoldBacking">, updates: CreditBalanceUpdate): BalanceValidationResult;
100
+ /** Refuse an update {@link validateBalanceUpdate} finds invalid. */
101
+ declare function assertValidBalanceUpdate(current: Pick<PortableUserCredits, "balance" | "bonusCredits" | "reserved" | "expiredHoldBacking">, updates: CreditBalanceUpdate): void;
80
102
 
81
103
  /**
82
104
  * In-Memory Credit Repository Implementation
@@ -92,6 +114,8 @@ declare function getNextMonthlyReset(from?: Date): Date;
92
114
 
93
115
  declare class InMemoryCreditRepository implements ICreditRepository {
94
116
  private readonly store;
117
+ private readonly options;
118
+ constructor(options?: CreditPolicyOptions);
95
119
  /**
96
120
  * A copy, never the live record.
97
121
  *
@@ -157,9 +181,10 @@ declare class InMemoryCreditRepository implements ICreditRepository {
157
181
  * that *is* the idempotent no-op the caller asked for.
158
182
  */
159
183
  addCreditsAtomic(userId: string, amount: number, description: string, paymentRef?: string, options?: AddCreditsAtomicOptions): Promise<void>;
160
- deductCreditsAtomic(userId: string, amount: number): Promise<{
184
+ deductCreditsAtomic(userId: string, amount: number, journal?: DeductJournalInput): Promise<{
161
185
  previousBalance: number;
162
186
  newBalance: number;
187
+ journalEntryId?: string;
163
188
  }>;
164
189
  createTransaction(input: CreateTransactionInput): Promise<PortableTransaction>;
165
190
  /** The unguarded writer, for `addCreditsV2` — which has moved the balance. */
@@ -192,7 +217,11 @@ declare class InMemoryCreditRepository implements ICreditRepository {
192
217
  creditsReleased: number;
193
218
  errors: string[];
194
219
  }>;
195
- atomicMonthlyReset(userId: string, tier: SubscriptionTier, expectedResetAt: Date | string): Promise<MonthlyResetResult>;
220
+ /**
221
+ * @param _tier - Not trusted. The caller read it earlier and the account may
222
+ * have changed tier since, so the reset uses the tier stored on the account.
223
+ */
224
+ atomicMonthlyReset(userId: string, _tier: SubscriptionTier, expectedResetAt: Date | string): Promise<MonthlyResetResult>;
196
225
  checkAndHandleSubscriptionExpiry(userId: string, gracePeriodDays?: number): Promise<SubscriptionExpiryResult>;
197
226
  /**
198
227
  * Clear all data (useful for testing)
@@ -221,6 +250,6 @@ declare class InMemoryCreditRepository implements ICreditRepository {
221
250
  * Create a new in-memory repository instance
222
251
  * Each call creates a fresh, isolated instance
223
252
  */
224
- declare function createInMemoryCreditRepository(): InMemoryCreditRepository;
253
+ declare function createInMemoryCreditRepository(options?: CreditPolicyOptions): InMemoryCreditRepository;
225
254
 
226
- export { AddCreditsAtomicOptions, AddCreditsV2Input, CreateJournalEntryInput, CreateReservationInput, CreateTransactionInput, CreateUsageLogInput, CreditBalanceUpdate, ExpireReservationV2Options, ICreditRepository, InMemoryCreditRepository, JournalEntryQuery, ReservationTransitionOptions, ReserveCreditsV2Input, TierUpdateInput, UsageLogQuery, addCreditsThroughRepository, commitThroughRepository, createInMemoryCreditRepository, generateId, getNextMonthlyReset, releaseThroughRepository, reserveThroughRepository, toDate };
255
+ export { AddCreditsAtomicOptions, AddCreditsV2Input, type BalanceValidationResult, CreateJournalEntryInput, CreateReservationInput, CreateTransactionInput, CreateUsageLogInput, CreditBalanceUpdate, DeductJournalInput, ExpireReservationV2Options, ICreditRepository, InMemoryCreditRepository, JournalEntryQuery, ReservationTransitionOptions, ReserveCreditsV2Input, TierUpdateInput, UsageLogQuery, addCreditsThroughRepository, assertValidBalanceUpdate, commitThroughRepository, createInMemoryCreditRepository, generateId, getNextMonthlyReset, releaseThroughRepository, reserveThroughRepository, toDate, validateBalanceUpdate };
@@ -1,6 +1,6 @@
1
- import { I as ICreditRepository, b as AddCreditsV2Input, a as AddCreditsOutcome, l as ReservationTransitionOptions, C as CommitOutcome, R as ReleaseOutcome, m as ReserveCreditsV2Input, n as ReserveOutcome, g as CreditBalanceUpdate, o as TierUpdateInput, d as CreateReservationInput, i as ExpireReservationV2Options, E as ExpireOutcome, A as AddCreditsAtomicOptions, e as CreateTransactionInput, f as CreateUsageLogInput, U as UsageLogQuery, c as CreateJournalEntryInput, J as JournalEntryQuery } from '../types-BhCdep_t.js';
2
- export { h as CreditRepositoryFactory, j as ICreditRepositoryCreditsV2, k as ICreditRepositoryV2, s as reservationJournalKey, t as supportsCreditsV2, u as supportsIdempotentCredit, v as toClientUserCredits } from '../types-BhCdep_t.js';
3
- import { c as PortableUserCredits, S as SubscriptionTier, a as PortableReservation, R as ReservationStatus, P as PortableTransaction, d as PortableUsageLog, f as PortableJournalEntry, M as MonthlyResetResult, e as SubscriptionExpiryResult } from '../types-Dzc443vy.js';
1
+ import { I as ICreditRepository, b as AddCreditsV2Input, a as AddCreditsOutcome, m as ReservationTransitionOptions, C as CommitOutcome, R as ReleaseOutcome, n as ReserveCreditsV2Input, o as ReserveOutcome, g as CreditBalanceUpdate, h as CreditPolicyOptions, p as TierUpdateInput, d as CreateReservationInput, j as ExpireReservationV2Options, E as ExpireOutcome, A as AddCreditsAtomicOptions, D as DeductJournalInput, e as CreateTransactionInput, f as CreateUsageLogInput, U as UsageLogQuery, c as CreateJournalEntryInput, J as JournalEntryQuery } from '../types-CY-oHIMA.js';
2
+ export { i as CreditRepositoryFactory, k as ICreditRepositoryCreditsV2, l as ICreditRepositoryV2, t as reservationJournalKey, u as supportsCreditsV2, v as supportsIdempotentCredit, w as toClientUserCredits } from '../types-CY-oHIMA.js';
3
+ import { c as PortableUserCredits, S as SubscriptionTier, a as PortableReservation, R as ReservationStatus, P as PortableTransaction, d as PortableUsageLog, f as PortableJournalEntry, M as MonthlyResetResult, e as SubscriptionExpiryResult } from '../types-C3sxDvNb.js';
4
4
 
5
5
  /**
6
6
  * One reservation flow for both repository generations.
@@ -62,6 +62,7 @@ declare function addCreditsThroughRepository(repository: ICreditRepository, inpu
62
62
  * These are pure functions with no server-only dependencies,
63
63
  * making them safe to use in any repository implementation.
64
64
  */
65
+
65
66
  /**
66
67
  * Generate a unique ID
67
68
  * Uses timestamp + random string for uniqueness
@@ -77,6 +78,27 @@ declare function toDate(value: Date | string | unknown): Date;
77
78
  * Used for calculating monthly reset dates
78
79
  */
79
80
  declare function getNextMonthlyReset(from?: Date): Date;
81
+ /** Result of validating a balance update. */
82
+ interface BalanceValidationResult {
83
+ valid: boolean;
84
+ errors: string[];
85
+ }
86
+ /**
87
+ * Whether an update leaves a valid account: no negative field, and `reserved` covered
88
+ * by `balance + bonusCredits`, which is the floor outstanding holds put under the
89
+ * balance. An increment is applied on top of the absolute value when a call names both.
90
+ *
91
+ * An update is a delta the caller asked for, so one that cannot be honoured is refused,
92
+ * as a deduct is. Only tier writes and resets stop at the floor: they state a target.
93
+ *
94
+ * A negative balance increment is a charge, so it draws only on the balance above
95
+ * `expiredHoldBacking`: those credits are expired and leave when their hold closes, so
96
+ * charging them would hand the charge back. An absolute balance replaces the field and
97
+ * the marks with it, so only an increment on the stored balance meets this limit.
98
+ */
99
+ declare function validateBalanceUpdate(current: Pick<PortableUserCredits, "balance" | "bonusCredits" | "reserved" | "expiredHoldBacking">, updates: CreditBalanceUpdate): BalanceValidationResult;
100
+ /** Refuse an update {@link validateBalanceUpdate} finds invalid. */
101
+ declare function assertValidBalanceUpdate(current: Pick<PortableUserCredits, "balance" | "bonusCredits" | "reserved" | "expiredHoldBacking">, updates: CreditBalanceUpdate): void;
80
102
 
81
103
  /**
82
104
  * In-Memory Credit Repository Implementation
@@ -92,6 +114,8 @@ declare function getNextMonthlyReset(from?: Date): Date;
92
114
 
93
115
  declare class InMemoryCreditRepository implements ICreditRepository {
94
116
  private readonly store;
117
+ private readonly options;
118
+ constructor(options?: CreditPolicyOptions);
95
119
  /**
96
120
  * A copy, never the live record.
97
121
  *
@@ -157,9 +181,10 @@ declare class InMemoryCreditRepository implements ICreditRepository {
157
181
  * that *is* the idempotent no-op the caller asked for.
158
182
  */
159
183
  addCreditsAtomic(userId: string, amount: number, description: string, paymentRef?: string, options?: AddCreditsAtomicOptions): Promise<void>;
160
- deductCreditsAtomic(userId: string, amount: number): Promise<{
184
+ deductCreditsAtomic(userId: string, amount: number, journal?: DeductJournalInput): Promise<{
161
185
  previousBalance: number;
162
186
  newBalance: number;
187
+ journalEntryId?: string;
163
188
  }>;
164
189
  createTransaction(input: CreateTransactionInput): Promise<PortableTransaction>;
165
190
  /** The unguarded writer, for `addCreditsV2` — which has moved the balance. */
@@ -192,7 +217,11 @@ declare class InMemoryCreditRepository implements ICreditRepository {
192
217
  creditsReleased: number;
193
218
  errors: string[];
194
219
  }>;
195
- atomicMonthlyReset(userId: string, tier: SubscriptionTier, expectedResetAt: Date | string): Promise<MonthlyResetResult>;
220
+ /**
221
+ * @param _tier - Not trusted. The caller read it earlier and the account may
222
+ * have changed tier since, so the reset uses the tier stored on the account.
223
+ */
224
+ atomicMonthlyReset(userId: string, _tier: SubscriptionTier, expectedResetAt: Date | string): Promise<MonthlyResetResult>;
196
225
  checkAndHandleSubscriptionExpiry(userId: string, gracePeriodDays?: number): Promise<SubscriptionExpiryResult>;
197
226
  /**
198
227
  * Clear all data (useful for testing)
@@ -221,6 +250,6 @@ declare class InMemoryCreditRepository implements ICreditRepository {
221
250
  * Create a new in-memory repository instance
222
251
  * Each call creates a fresh, isolated instance
223
252
  */
224
- declare function createInMemoryCreditRepository(): InMemoryCreditRepository;
253
+ declare function createInMemoryCreditRepository(options?: CreditPolicyOptions): InMemoryCreditRepository;
225
254
 
226
- export { AddCreditsAtomicOptions, AddCreditsV2Input, CreateJournalEntryInput, CreateReservationInput, CreateTransactionInput, CreateUsageLogInput, CreditBalanceUpdate, ExpireReservationV2Options, ICreditRepository, InMemoryCreditRepository, JournalEntryQuery, ReservationTransitionOptions, ReserveCreditsV2Input, TierUpdateInput, UsageLogQuery, addCreditsThroughRepository, commitThroughRepository, createInMemoryCreditRepository, generateId, getNextMonthlyReset, releaseThroughRepository, reserveThroughRepository, toDate };
255
+ export { AddCreditsAtomicOptions, AddCreditsV2Input, type BalanceValidationResult, CreateJournalEntryInput, CreateReservationInput, CreateTransactionInput, CreateUsageLogInput, CreditBalanceUpdate, DeductJournalInput, ExpireReservationV2Options, ICreditRepository, InMemoryCreditRepository, JournalEntryQuery, ReservationTransitionOptions, ReserveCreditsV2Input, TierUpdateInput, UsageLogQuery, addCreditsThroughRepository, assertValidBalanceUpdate, commitThroughRepository, createInMemoryCreditRepository, generateId, getNextMonthlyReset, releaseThroughRepository, reserveThroughRepository, toDate, validateBalanceUpdate };