@nehorai/credits 1.2.0 → 1.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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapters/index.cjs +463 -0
  3. package/dist/adapters/index.cjs.map +1 -0
  4. package/dist/adapters/index.d.cts +66 -0
  5. package/dist/adapters/index.d.ts +66 -3
  6. package/dist/adapters/index.js +435 -1
  7. package/dist/adapters/index.js.map +1 -1
  8. package/dist/auth/index.cjs +96 -0
  9. package/dist/auth/index.cjs.map +1 -0
  10. package/dist/auth/{api-key.d.ts → index.d.cts} +9 -6
  11. package/dist/auth/index.d.ts +37 -5
  12. package/dist/auth/index.js +65 -7
  13. package/dist/auth/index.js.map +1 -1
  14. package/dist/core/index.cjs +522 -0
  15. package/dist/core/index.cjs.map +1 -0
  16. package/dist/core/index.d.cts +119 -0
  17. package/dist/core/index.d.ts +115 -25
  18. package/dist/core/index.js +475 -27
  19. package/dist/core/index.js.map +1 -1
  20. package/dist/{core/deferred.d.ts → deferred-C7rrRfkm.d.cts} +7 -6
  21. package/dist/{core/deferred.js → deferred-C7rrRfkm.d.ts} +23 -29
  22. package/dist/index.cjs +2514 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +437 -0
  25. package/dist/index.d.ts +429 -50
  26. package/dist/index.js +2407 -63
  27. package/dist/index.js.map +1 -1
  28. package/dist/repository/index.cjs +819 -0
  29. package/dist/repository/index.cjs.map +1 -0
  30. package/dist/repository/{memory/index.d.ts → index.d.cts} +35 -5
  31. package/dist/repository/index.d.ts +97 -7
  32. package/dist/repository/index.js +786 -10
  33. package/dist/repository/index.js.map +1 -1
  34. package/dist/sdk/index.cjs +608 -0
  35. package/dist/sdk/index.cjs.map +1 -0
  36. package/dist/sdk/index.d.cts +495 -0
  37. package/dist/sdk/index.d.ts +491 -9
  38. package/dist/sdk/index.js +568 -12
  39. package/dist/sdk/index.js.map +1 -1
  40. package/dist/service/index.cjs +675 -0
  41. package/dist/service/index.cjs.map +1 -0
  42. package/dist/service/{credits-service.d.ts → index.d.cts} +25 -8
  43. package/dist/service/index.d.ts +156 -3
  44. package/dist/service/index.js +646 -1
  45. package/dist/service/index.js.map +1 -1
  46. package/dist/{core/types.d.ts → types-BBxIWHK2.d.cts} +25 -24
  47. package/dist/types-BBxIWHK2.d.ts +277 -0
  48. package/dist/types-D1vdeBcA.d.cts +305 -0
  49. package/dist/{auth/types.d.ts → types-OZU3I5OM.d.cts} +5 -4
  50. package/dist/types-OZU3I5OM.d.ts +32 -0
  51. package/dist/{repository/types.d.ts → types-aJsyv8df.d.ts} +35 -13
  52. package/package.json +21 -19
  53. package/dist/adapters/generic.d.ts +0 -18
  54. package/dist/adapters/generic.d.ts.map +0 -1
  55. package/dist/adapters/generic.js +0 -151
  56. package/dist/adapters/generic.js.map +0 -1
  57. package/dist/adapters/index.d.ts.map +0 -1
  58. package/dist/adapters/types.d.ts +0 -45
  59. package/dist/adapters/types.d.ts.map +0 -1
  60. package/dist/adapters/types.js +0 -8
  61. package/dist/adapters/types.js.map +0 -1
  62. package/dist/auth/api-key.d.ts.map +0 -1
  63. package/dist/auth/api-key.js +0 -94
  64. package/dist/auth/api-key.js.map +0 -1
  65. package/dist/auth/index.d.ts.map +0 -1
  66. package/dist/auth/types.d.ts.map +0 -1
  67. package/dist/auth/types.js +0 -2
  68. package/dist/auth/types.js.map +0 -1
  69. package/dist/config/costs.d.ts +0 -56
  70. package/dist/config/costs.d.ts.map +0 -1
  71. package/dist/config/costs.js +0 -71
  72. package/dist/config/costs.js.map +0 -1
  73. package/dist/config/index.d.ts +0 -184
  74. package/dist/config/index.d.ts.map +0 -1
  75. package/dist/config/index.js +0 -342
  76. package/dist/config/index.js.map +0 -1
  77. package/dist/config/provider.d.ts +0 -12
  78. package/dist/config/provider.d.ts.map +0 -1
  79. package/dist/config/provider.js +0 -14
  80. package/dist/config/provider.js.map +0 -1
  81. package/dist/core/deferred.d.ts.map +0 -1
  82. package/dist/core/deferred.js.map +0 -1
  83. package/dist/core/errors.d.ts +0 -78
  84. package/dist/core/errors.d.ts.map +0 -1
  85. package/dist/core/errors.js +0 -110
  86. package/dist/core/errors.js.map +0 -1
  87. package/dist/core/index.d.ts.map +0 -1
  88. package/dist/core/operations.d.ts +0 -36
  89. package/dist/core/operations.d.ts.map +0 -1
  90. package/dist/core/operations.js +0 -88
  91. package/dist/core/operations.js.map +0 -1
  92. package/dist/core/types.d.ts.map +0 -1
  93. package/dist/core/types.js +0 -82
  94. package/dist/core/types.js.map +0 -1
  95. package/dist/index.d.ts.map +0 -1
  96. package/dist/notifications/index.d.ts +0 -76
  97. package/dist/notifications/index.d.ts.map +0 -1
  98. package/dist/notifications/index.js +0 -174
  99. package/dist/notifications/index.js.map +0 -1
  100. package/dist/repository/index.d.ts.map +0 -1
  101. package/dist/repository/memory/index.d.ts.map +0 -1
  102. package/dist/repository/memory/index.js +0 -518
  103. package/dist/repository/memory/index.js.map +0 -1
  104. package/dist/repository/types.d.ts.map +0 -1
  105. package/dist/repository/types.js +0 -39
  106. package/dist/repository/types.js.map +0 -1
  107. package/dist/repository/utils.d.ts +0 -22
  108. package/dist/repository/utils.d.ts.map +0 -1
  109. package/dist/repository/utils.js +0 -40
  110. package/dist/repository/utils.js.map +0 -1
  111. package/dist/sdk/admin-client.d.ts +0 -146
  112. package/dist/sdk/admin-client.d.ts.map +0 -1
  113. package/dist/sdk/admin-client.js +0 -196
  114. package/dist/sdk/admin-client.js.map +0 -1
  115. package/dist/sdk/client.d.ts +0 -144
  116. package/dist/sdk/client.d.ts.map +0 -1
  117. package/dist/sdk/client.js +0 -247
  118. package/dist/sdk/client.js.map +0 -1
  119. package/dist/sdk/errors.d.ts +0 -91
  120. package/dist/sdk/errors.d.ts.map +0 -1
  121. package/dist/sdk/errors.js +0 -185
  122. package/dist/sdk/errors.js.map +0 -1
  123. package/dist/sdk/index.d.ts.map +0 -1
  124. package/dist/sdk/types.d.ts +0 -110
  125. package/dist/sdk/types.d.ts.map +0 -1
  126. package/dist/sdk/types.js +0 -20
  127. package/dist/sdk/types.js.map +0 -1
  128. package/dist/service/credits-service.d.ts.map +0 -1
  129. package/dist/service/credits-service.js +0 -368
  130. package/dist/service/credits-service.js.map +0 -1
  131. package/dist/service/index.d.ts.map +0 -1
  132. package/dist/utils/error-utils.d.ts +0 -48
  133. package/dist/utils/error-utils.d.ts.map +0 -1
  134. package/dist/utils/error-utils.js +0 -57
  135. package/dist/utils/error-utils.js.map +0 -1
  136. package/dist/utils/index.d.ts +0 -54
  137. package/dist/utils/index.d.ts.map +0 -1
  138. package/dist/utils/index.js +0 -72
  139. package/dist/utils/index.js.map +0 -1
@@ -0,0 +1,305 @@
1
+ import { C as CreditSource, J as JournalReferenceType, a as CreditOperationType, P as PortableTransaction, A as AIProviderType, S as SubscriptionTier, b as PortableUserCredits, c as PortableReservation, R as ReservationStatus, d as PortableUsageLog, M as MonthlyResetResult, e as SubscriptionExpiryResult, f as PortableJournalEntry } from './types-BBxIWHK2.cjs';
2
+
3
+ /**
4
+ * Input for creating a credit reservation
5
+ */
6
+ interface CreateReservationInput {
7
+ userId: string;
8
+ amount: number;
9
+ operationType: CreditOperationType;
10
+ expiresAt: Date;
11
+ }
12
+ /**
13
+ * Input for creating a credit transaction
14
+ */
15
+ interface CreateTransactionInput {
16
+ userId: string;
17
+ type: PortableTransaction["type"];
18
+ amount: number;
19
+ description: string;
20
+ paymentRef?: string;
21
+ previousBalance: number;
22
+ newBalance: number;
23
+ }
24
+ /**
25
+ * Input for logging usage
26
+ */
27
+ interface CreateUsageLogInput {
28
+ userId: string;
29
+ operationType: CreditOperationType;
30
+ provider: AIProviderType;
31
+ creditsUsed: number;
32
+ success: boolean;
33
+ errorMessage?: string;
34
+ resourceId?: string;
35
+ resourceType?: string;
36
+ requestId?: string;
37
+ metadata?: Record<string, unknown>;
38
+ }
39
+ /**
40
+ * Query options for usage logs
41
+ */
42
+ interface UsageLogQuery {
43
+ userId?: string;
44
+ operationType?: CreditOperationType;
45
+ success?: boolean;
46
+ limit?: number;
47
+ offset?: number;
48
+ startDate?: Date;
49
+ endDate?: Date;
50
+ }
51
+ /**
52
+ * Input for creating a journal entry
53
+ */
54
+ interface CreateJournalEntryInput {
55
+ userId: string;
56
+ entryType: "debit" | "credit";
57
+ amount: number;
58
+ balanceAfter: number;
59
+ source: CreditSource;
60
+ referenceId: string;
61
+ referenceType: JournalReferenceType;
62
+ description: string;
63
+ metadata?: Record<string, unknown>;
64
+ }
65
+ /**
66
+ * Query options for journal entries
67
+ */
68
+ interface JournalEntryQuery {
69
+ userId: string;
70
+ source?: CreditSource;
71
+ referenceType?: JournalReferenceType;
72
+ limit?: number;
73
+ offset?: number;
74
+ startDate?: Date;
75
+ endDate?: Date;
76
+ }
77
+ /**
78
+ * Partial update for user credits balance
79
+ */
80
+ interface CreditBalanceUpdate {
81
+ balance?: number;
82
+ bonusCredits?: number;
83
+ reserved?: number;
84
+ tier?: SubscriptionTier;
85
+ monthlyLimit?: number;
86
+ monthlyUsed?: number;
87
+ monthlyResetAt?: Date | string;
88
+ subscriptionExpiresAt?: Date | string | null;
89
+ /** Increment balance by this amount (alternative to absolute value) */
90
+ balanceIncrement?: number;
91
+ /** Increment bonusCredits by this amount (alternative to absolute value) */
92
+ bonusCreditsIncrement?: number;
93
+ /** Increment reserved by this amount (alternative to absolute value) */
94
+ reservedIncrement?: number;
95
+ /** Increment monthlyUsed by this amount */
96
+ monthlyUsedIncrement?: number;
97
+ }
98
+ /**
99
+ * Input for tier update
100
+ */
101
+ interface TierUpdateInput {
102
+ tier: SubscriptionTier;
103
+ monthlyLimit: number;
104
+ balance?: number;
105
+ monthlyUsed?: number;
106
+ subscriptionExpiresAt?: Date | string | null;
107
+ }
108
+ /**
109
+ * Repository interface for credits database operations
110
+ *
111
+ * Implementations can use any database (Firestore, PostgreSQL, etc.)
112
+ * All methods should handle their own error handling and transactions
113
+ */
114
+ interface ICreditRepository {
115
+ /**
116
+ * Get user credits balance
117
+ * @param userId - User ID
118
+ * @returns User credits or null if not found
119
+ */
120
+ getUserCredits(userId: string): Promise<PortableUserCredits | null>;
121
+ /**
122
+ * Initialize credits for a new user
123
+ * @param userId - User ID
124
+ * @param tier - Initial subscription tier
125
+ * @param initialBalance - Initial credit balance
126
+ * @returns Initialized user credits
127
+ */
128
+ initializeUserCredits(userId: string, tier: SubscriptionTier, initialBalance: number): Promise<PortableUserCredits>;
129
+ /**
130
+ * Update user credits balance
131
+ * @param userId - User ID
132
+ * @param updates - Partial updates to apply
133
+ */
134
+ updateUserCredits(userId: string, updates: CreditBalanceUpdate): Promise<void>;
135
+ /**
136
+ * Update user subscription tier
137
+ * @param userId - User ID
138
+ * @param input - Tier update data
139
+ */
140
+ updateUserTier(userId: string, input: TierUpdateInput): Promise<void>;
141
+ /**
142
+ * Create a credit reservation (phase 1 of two-phase commit)
143
+ * @param input - Reservation data
144
+ * @returns Created reservation
145
+ */
146
+ createReservation(input: CreateReservationInput): Promise<PortableReservation>;
147
+ /**
148
+ * Get a reservation by ID
149
+ * @param userId - User ID
150
+ * @param reservationId - Reservation ID
151
+ * @returns Reservation or null
152
+ */
153
+ getReservation(userId: string, reservationId: string): Promise<PortableReservation | null>;
154
+ /**
155
+ * Update reservation status
156
+ * @param userId - User ID
157
+ * @param reservationId - Reservation ID
158
+ * @param status - New status
159
+ * @param completedAt - Completion timestamp
160
+ */
161
+ updateReservationStatus(userId: string, reservationId: string, status: ReservationStatus, completedAt?: Date): Promise<void>;
162
+ /**
163
+ * Reserve credits atomically (creates reservation + updates balance in transaction)
164
+ * @param userId - User ID
165
+ * @param amount - Credits to reserve
166
+ * @param operationType - Operation type for tracking
167
+ * @param expiresAt - Reservation expiry time
168
+ * @returns Created reservation
169
+ * @throws Error if insufficient credits
170
+ */
171
+ reserveCreditsAtomic(userId: string, amount: number, operationType: CreditOperationType, expiresAt: Date): Promise<PortableReservation>;
172
+ /**
173
+ * Commit a reservation atomically (deducts credits + marks reservation committed)
174
+ * @param userId - User ID
175
+ * @param reservationId - Reservation ID
176
+ * @throws Error if reservation not found or not in reserved state
177
+ */
178
+ commitReservationAtomic(userId: string, reservationId: string): Promise<void>;
179
+ /**
180
+ * Release a reservation atomically (releases reserved credits + marks reservation released)
181
+ * @param userId - User ID
182
+ * @param reservationId - Reservation ID
183
+ */
184
+ releaseReservationAtomic(userId: string, reservationId: string): Promise<void>;
185
+ /**
186
+ * Add credits atomically (creates transaction + updates balance)
187
+ * @param userId - User ID
188
+ * @param amount - Credits to add
189
+ * @param description - Transaction description
190
+ * @param paymentRef - Optional payment reference
191
+ */
192
+ addCreditsAtomic(userId: string, amount: number, description: string, paymentRef?: string): Promise<void>;
193
+ /**
194
+ * Deduct credits from a user's balance atomically.
195
+ *
196
+ * Splits the deduction across `balance` and `bonusCredits`, draining
197
+ * `balance` (monthly, resets each cycle) first so persistent bonus
198
+ * credits survive longer. Runs in a single atomic transaction so
199
+ * concurrent deducts cannot drive either field negative.
200
+ *
201
+ * Callers are responsible for writing any audit record (journal /
202
+ * transaction) — this method only moves credits.
203
+ *
204
+ * @param userId - User ID
205
+ * @param amount - Credits to deduct (positive)
206
+ * @returns Combined totals (balance + bonusCredits) before and after.
207
+ * @throws If user has no credits doc or insufficient credits
208
+ */
209
+ deductCreditsAtomic(userId: string, amount: number): Promise<{
210
+ previousBalance: number;
211
+ newBalance: number;
212
+ }>;
213
+ /**
214
+ * Create a credit transaction record
215
+ * @param input - Transaction data
216
+ * @returns Created transaction
217
+ */
218
+ createTransaction(input: CreateTransactionInput): Promise<PortableTransaction>;
219
+ /**
220
+ * Get user's transaction history
221
+ * @param userId - User ID
222
+ * @param limit - Max results
223
+ * @param offset - Skip results
224
+ * @returns List of transactions
225
+ */
226
+ getTransactions(userId: string, limit?: number, offset?: number): Promise<PortableTransaction[]>;
227
+ /**
228
+ * Log a usage event
229
+ * @param input - Usage log data
230
+ * @returns Created usage log
231
+ */
232
+ logUsage(input: CreateUsageLogInput): Promise<PortableUsageLog>;
233
+ /**
234
+ * Query usage logs
235
+ * @param query - Query parameters
236
+ * @returns List of usage logs
237
+ */
238
+ getUsageLogs(query: UsageLogQuery): Promise<PortableUsageLog[]>;
239
+ /**
240
+ * Get usage log count (for pagination)
241
+ * @param query - Query parameters (without limit/offset)
242
+ * @returns Count of matching logs
243
+ */
244
+ getUsageLogsCount(query: Omit<UsageLogQuery, "limit" | "offset">): Promise<number>;
245
+ /**
246
+ * Find and expire reservations past their expiration time
247
+ * Used by cron job to clean up stale reservations
248
+ * @param batchSize - Maximum number of reservations to process per batch (default: 100)
249
+ * @param maxIterations - Maximum number of pagination iterations to prevent infinite loops (default: 100)
250
+ * @returns Cleanup results with counts and errors
251
+ */
252
+ findAndExpireReservations(batchSize?: number, maxIterations?: number): Promise<{
253
+ expiredCount: number;
254
+ creditsReleased: number;
255
+ errors: string[];
256
+ }>;
257
+ /**
258
+ * Atomically perform monthly reset if needed
259
+ * Uses optimistic locking to prevent race conditions
260
+ *
261
+ * @param userId - User ID
262
+ * @param tier - User's current subscription tier (for determining new balance)
263
+ * @param expectedResetAt - The expected monthlyResetAt value (for optimistic locking)
264
+ * @returns Result indicating whether reset was performed and updated credits
265
+ */
266
+ atomicMonthlyReset(userId: string, tier: SubscriptionTier, expectedResetAt: Date | string): Promise<MonthlyResetResult>;
267
+ /**
268
+ * Check and handle subscription expiry with grace period
269
+ * Auto-downgrades expired subscriptions after grace period
270
+ *
271
+ * @param userId - User ID
272
+ * @param gracePeriodDays - Days to allow after expiry before downgrade (default: 3)
273
+ * @returns Result indicating whether downgrade occurred
274
+ */
275
+ checkAndHandleSubscriptionExpiry(userId: string, gracePeriodDays?: number): Promise<SubscriptionExpiryResult>;
276
+ /**
277
+ * Create a journal entry for audit trail
278
+ * @param input - Journal entry data
279
+ * @returns Created journal entry
280
+ */
281
+ createJournalEntry(input: CreateJournalEntryInput): Promise<PortableJournalEntry>;
282
+ /**
283
+ * Get journal entries for a user
284
+ * @param query - Query parameters
285
+ * @returns List of journal entries
286
+ */
287
+ getJournalEntries(query: JournalEntryQuery): Promise<PortableJournalEntry[]>;
288
+ /**
289
+ * Get journal entry count for pagination
290
+ * @param query - Query parameters (without limit/offset)
291
+ * @returns Count of matching entries
292
+ */
293
+ getJournalEntriesCount(query: Omit<JournalEntryQuery, "limit" | "offset">): Promise<number>;
294
+ }
295
+ /**
296
+ * Factory type for creating repository instances
297
+ */
298
+ type CreditRepositoryFactory = () => ICreditRepository;
299
+ /**
300
+ * Convert PortableUserCredits to client-safe format
301
+ * Utility function that implementations can use
302
+ */
303
+ declare function toClientUserCredits(credits: PortableUserCredits): PortableUserCredits;
304
+
305
+ export { type CreateJournalEntryInput as C, type ICreditRepository as I, type JournalEntryQuery as J, type TierUpdateInput as T, type UsageLogQuery as U, type CreateReservationInput as a, type CreateTransactionInput as b, type CreateUsageLogInput as c, type CreditBalanceUpdate as d, type CreditRepositoryFactory as e, toClientUserCredits as t };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Authenticated user information for credits operations
3
3
  */
4
- export interface CreditsUser {
4
+ interface CreditsUser {
5
5
  id: string;
6
6
  email?: string | null;
7
7
  name?: string | null;
@@ -11,7 +11,7 @@ export interface CreditsUser {
11
11
  *
12
12
  * Implementations can use any auth system (NextAuth, JWT, API keys, etc.)
13
13
  */
14
- export interface ICreditsAuthProvider {
14
+ interface ICreditsAuthProvider {
15
15
  /**
16
16
  * Get the currently authenticated user
17
17
  * @returns User information or null if not authenticated
@@ -27,5 +27,6 @@ export interface ICreditsAuthProvider {
27
27
  /**
28
28
  * Factory type for creating auth provider instances
29
29
  */
30
- export type CreditsAuthProviderFactory = () => ICreditsAuthProvider;
31
- //# sourceMappingURL=types.d.ts.map
30
+ type CreditsAuthProviderFactory = () => ICreditsAuthProvider;
31
+
32
+ export type { CreditsAuthProviderFactory as C, ICreditsAuthProvider as I, CreditsUser as a };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Authenticated user information for credits operations
3
+ */
4
+ interface CreditsUser {
5
+ id: string;
6
+ email?: string | null;
7
+ name?: string | null;
8
+ }
9
+ /**
10
+ * Auth provider interface for credits system
11
+ *
12
+ * Implementations can use any auth system (NextAuth, JWT, API keys, etc.)
13
+ */
14
+ interface ICreditsAuthProvider {
15
+ /**
16
+ * Get the currently authenticated user
17
+ * @returns User information or null if not authenticated
18
+ */
19
+ getCurrentUser(): Promise<CreditsUser | null>;
20
+ /**
21
+ * Verify if a user has admin access for credits management
22
+ * @param userId - User ID to check
23
+ * @returns True if user has admin access
24
+ */
25
+ verifyAdminAccess(userId: string): Promise<boolean>;
26
+ }
27
+ /**
28
+ * Factory type for creating auth provider instances
29
+ */
30
+ type CreditsAuthProviderFactory = () => ICreditsAuthProvider;
31
+
32
+ export type { CreditsAuthProviderFactory as C, ICreditsAuthProvider as I, CreditsUser as a };
@@ -1,8 +1,9 @@
1
- import type { PortableUserCredits, PortableReservation, PortableTransaction, PortableUsageLog, PortableJournalEntry, CreditOperationType, SubscriptionTier, ReservationStatus, AIProviderType, MonthlyResetResult, SubscriptionExpiryResult, CreditSource, JournalReferenceType } from "../core/types.js";
1
+ import { C as CreditSource, J as JournalReferenceType, a as CreditOperationType, P as PortableTransaction, A as AIProviderType, S as SubscriptionTier, b as PortableUserCredits, c as PortableReservation, R as ReservationStatus, d as PortableUsageLog, M as MonthlyResetResult, e as SubscriptionExpiryResult, f as PortableJournalEntry } from './types-BBxIWHK2.js';
2
+
2
3
  /**
3
4
  * Input for creating a credit reservation
4
5
  */
5
- export interface CreateReservationInput {
6
+ interface CreateReservationInput {
6
7
  userId: string;
7
8
  amount: number;
8
9
  operationType: CreditOperationType;
@@ -11,7 +12,7 @@ export interface CreateReservationInput {
11
12
  /**
12
13
  * Input for creating a credit transaction
13
14
  */
14
- export interface CreateTransactionInput {
15
+ interface CreateTransactionInput {
15
16
  userId: string;
16
17
  type: PortableTransaction["type"];
17
18
  amount: number;
@@ -23,7 +24,7 @@ export interface CreateTransactionInput {
23
24
  /**
24
25
  * Input for logging usage
25
26
  */
26
- export interface CreateUsageLogInput {
27
+ interface CreateUsageLogInput {
27
28
  userId: string;
28
29
  operationType: CreditOperationType;
29
30
  provider: AIProviderType;
@@ -38,7 +39,7 @@ export interface CreateUsageLogInput {
38
39
  /**
39
40
  * Query options for usage logs
40
41
  */
41
- export interface UsageLogQuery {
42
+ interface UsageLogQuery {
42
43
  userId?: string;
43
44
  operationType?: CreditOperationType;
44
45
  success?: boolean;
@@ -50,7 +51,7 @@ export interface UsageLogQuery {
50
51
  /**
51
52
  * Input for creating a journal entry
52
53
  */
53
- export interface CreateJournalEntryInput {
54
+ interface CreateJournalEntryInput {
54
55
  userId: string;
55
56
  entryType: "debit" | "credit";
56
57
  amount: number;
@@ -64,7 +65,7 @@ export interface CreateJournalEntryInput {
64
65
  /**
65
66
  * Query options for journal entries
66
67
  */
67
- export interface JournalEntryQuery {
68
+ interface JournalEntryQuery {
68
69
  userId: string;
69
70
  source?: CreditSource;
70
71
  referenceType?: JournalReferenceType;
@@ -76,7 +77,7 @@ export interface JournalEntryQuery {
76
77
  /**
77
78
  * Partial update for user credits balance
78
79
  */
79
- export interface CreditBalanceUpdate {
80
+ interface CreditBalanceUpdate {
80
81
  balance?: number;
81
82
  bonusCredits?: number;
82
83
  reserved?: number;
@@ -97,7 +98,7 @@ export interface CreditBalanceUpdate {
97
98
  /**
98
99
  * Input for tier update
99
100
  */
100
- export interface TierUpdateInput {
101
+ interface TierUpdateInput {
101
102
  tier: SubscriptionTier;
102
103
  monthlyLimit: number;
103
104
  balance?: number;
@@ -110,7 +111,7 @@ export interface TierUpdateInput {
110
111
  * Implementations can use any database (Firestore, PostgreSQL, etc.)
111
112
  * All methods should handle their own error handling and transactions
112
113
  */
113
- export interface ICreditRepository {
114
+ interface ICreditRepository {
114
115
  /**
115
116
  * Get user credits balance
116
117
  * @param userId - User ID
@@ -189,6 +190,26 @@ export interface ICreditRepository {
189
190
  * @param paymentRef - Optional payment reference
190
191
  */
191
192
  addCreditsAtomic(userId: string, amount: number, description: string, paymentRef?: string): Promise<void>;
193
+ /**
194
+ * Deduct credits from a user's balance atomically.
195
+ *
196
+ * Splits the deduction across `balance` and `bonusCredits`, draining
197
+ * `balance` (monthly, resets each cycle) first so persistent bonus
198
+ * credits survive longer. Runs in a single atomic transaction so
199
+ * concurrent deducts cannot drive either field negative.
200
+ *
201
+ * Callers are responsible for writing any audit record (journal /
202
+ * transaction) — this method only moves credits.
203
+ *
204
+ * @param userId - User ID
205
+ * @param amount - Credits to deduct (positive)
206
+ * @returns Combined totals (balance + bonusCredits) before and after.
207
+ * @throws If user has no credits doc or insufficient credits
208
+ */
209
+ deductCreditsAtomic(userId: string, amount: number): Promise<{
210
+ previousBalance: number;
211
+ newBalance: number;
212
+ }>;
192
213
  /**
193
214
  * Create a credit transaction record
194
215
  * @param input - Transaction data
@@ -274,10 +295,11 @@ export interface ICreditRepository {
274
295
  /**
275
296
  * Factory type for creating repository instances
276
297
  */
277
- export type CreditRepositoryFactory = () => ICreditRepository;
298
+ type CreditRepositoryFactory = () => ICreditRepository;
278
299
  /**
279
300
  * Convert PortableUserCredits to client-safe format
280
301
  * Utility function that implementations can use
281
302
  */
282
- export declare function toClientUserCredits(credits: PortableUserCredits): PortableUserCredits;
283
- //# sourceMappingURL=types.d.ts.map
303
+ declare function toClientUserCredits(credits: PortableUserCredits): PortableUserCredits;
304
+
305
+ export { type CreateJournalEntryInput as C, type ICreditRepository as I, type JournalEntryQuery as J, type TierUpdateInput as T, type UsageLogQuery as U, type CreateReservationInput as a, type CreateTransactionInput as b, type CreateUsageLogInput as c, type CreditBalanceUpdate as d, type CreditRepositoryFactory as e, toClientUserCredits as t };
package/package.json CHANGED
@@ -1,48 +1,50 @@
1
1
  {
2
2
  "name": "@nehorai/credits",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
- "main": "./dist/index.js",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
6
7
  "types": "./dist/index.d.ts",
7
8
  "exports": {
8
9
  ".": {
9
10
  "types": "./dist/index.d.ts",
10
11
  "import": "./dist/index.js",
11
- "require": "./dist/index.js",
12
- "default": "./dist/index.js"
12
+ "require": "./dist/index.cjs"
13
13
  },
14
14
  "./core": {
15
15
  "types": "./dist/core/index.d.ts",
16
16
  "import": "./dist/core/index.js",
17
- "default": "./dist/core/index.js"
17
+ "require": "./dist/core/index.cjs"
18
18
  },
19
19
  "./repository": {
20
20
  "types": "./dist/repository/index.d.ts",
21
21
  "import": "./dist/repository/index.js",
22
- "default": "./dist/repository/index.js"
22
+ "require": "./dist/repository/index.cjs"
23
23
  },
24
24
  "./auth": {
25
25
  "types": "./dist/auth/index.d.ts",
26
26
  "import": "./dist/auth/index.js",
27
- "default": "./dist/auth/index.js"
27
+ "require": "./dist/auth/index.cjs"
28
28
  },
29
29
  "./service": {
30
30
  "types": "./dist/service/index.d.ts",
31
31
  "import": "./dist/service/index.js",
32
- "default": "./dist/service/index.js"
32
+ "require": "./dist/service/index.cjs"
33
33
  },
34
34
  "./adapters": {
35
35
  "types": "./dist/adapters/index.d.ts",
36
36
  "import": "./dist/adapters/index.js",
37
- "default": "./dist/adapters/index.js"
37
+ "require": "./dist/adapters/index.cjs"
38
38
  },
39
39
  "./sdk": {
40
40
  "types": "./dist/sdk/index.d.ts",
41
41
  "import": "./dist/sdk/index.js",
42
- "default": "./dist/sdk/index.js"
42
+ "require": "./dist/sdk/index.cjs"
43
43
  }
44
44
  },
45
- "files": ["dist"],
45
+ "files": [
46
+ "dist"
47
+ ],
46
48
  "license": "MIT",
47
49
  "author": "Nehorai Hadad",
48
50
  "repository": {
@@ -50,13 +52,6 @@
50
52
  "url": "https://github.com/NehoraiHadad/nehorai-plugins",
51
53
  "directory": "packages/credits"
52
54
  },
53
- "scripts": {
54
- "build": "tsc",
55
- "test": "vitest run",
56
- "test:watch": "vitest",
57
- "typecheck": "tsc --noEmit",
58
- "prepublishOnly": "pnpm build"
59
- },
60
55
  "dependencies": {
61
56
  "zod": "^3.24.2"
62
57
  },
@@ -64,5 +59,12 @@
64
59
  "typescript": "^5.7.3",
65
60
  "vitest": "^3.0.5",
66
61
  "@types/node": "^22.13.4"
62
+ },
63
+ "scripts": {
64
+ "build": "tsup",
65
+ "dev": "tsup --watch",
66
+ "typecheck": "tsc --noEmit",
67
+ "test": "vitest run",
68
+ "test:watch": "vitest"
67
69
  }
68
- }
70
+ }
@@ -1,18 +0,0 @@
1
- /**
2
- * Generic credits adapter - framework agnostic
3
- *
4
- * This adapter uses standard JavaScript APIs and works in any
5
- * JavaScript environment (Node.js, browser, etc.).
6
- */
7
- import type { CreditsAdapter, CreditsAdapterConfig } from "./types.js";
8
- /**
9
- * Create a generic credits adapter
10
- *
11
- * This adapter:
12
- * - Authenticates users via the provided auth provider
13
- * - Reserves credits before action execution
14
- * - Commits credits on success, releases on failure
15
- * - Logs usage asynchronously via the deferred executor
16
- */
17
- export declare function createGenericAdapter(config: CreditsAdapterConfig): CreditsAdapter;
18
- //# sourceMappingURL=generic.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generic.d.ts","sourceRoot":"","sources":["../../src/adapters/generic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAgB,cAAc,EAAE,oBAAoB,EAAuB,MAAM,YAAY,CAAC;AAgB1G;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAqIjF"}