@nehorai/credits 1.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 (114) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapters/generic.d.ts +18 -0
  3. package/dist/adapters/generic.d.ts.map +1 -0
  4. package/dist/adapters/generic.js +147 -0
  5. package/dist/adapters/generic.js.map +1 -0
  6. package/dist/adapters/index.d.ts +3 -0
  7. package/dist/adapters/index.d.ts.map +1 -0
  8. package/dist/adapters/index.js +2 -0
  9. package/dist/adapters/index.js.map +1 -0
  10. package/dist/adapters/types.d.ts +45 -0
  11. package/dist/adapters/types.d.ts.map +1 -0
  12. package/dist/adapters/types.js +8 -0
  13. package/dist/adapters/types.js.map +1 -0
  14. package/dist/auth/api-key.d.ts +37 -0
  15. package/dist/auth/api-key.d.ts.map +1 -0
  16. package/dist/auth/api-key.js +94 -0
  17. package/dist/auth/api-key.js.map +1 -0
  18. package/dist/auth/index.d.ts +8 -0
  19. package/dist/auth/index.d.ts.map +1 -0
  20. package/dist/auth/index.js +8 -0
  21. package/dist/auth/index.js.map +1 -0
  22. package/dist/auth/types.d.ts +31 -0
  23. package/dist/auth/types.d.ts.map +1 -0
  24. package/dist/auth/types.js +2 -0
  25. package/dist/auth/types.js.map +1 -0
  26. package/dist/config/costs.d.ts +61 -0
  27. package/dist/config/costs.d.ts.map +1 -0
  28. package/dist/config/costs.js +86 -0
  29. package/dist/config/costs.js.map +1 -0
  30. package/dist/config/index.d.ts +165 -0
  31. package/dist/config/index.d.ts.map +1 -0
  32. package/dist/config/index.js +286 -0
  33. package/dist/config/index.js.map +1 -0
  34. package/dist/core/deferred.d.ts +65 -0
  35. package/dist/core/deferred.d.ts.map +1 -0
  36. package/dist/core/deferred.js +72 -0
  37. package/dist/core/deferred.js.map +1 -0
  38. package/dist/core/errors.d.ts +78 -0
  39. package/dist/core/errors.d.ts.map +1 -0
  40. package/dist/core/errors.js +110 -0
  41. package/dist/core/errors.js.map +1 -0
  42. package/dist/core/index.d.ts +29 -0
  43. package/dist/core/index.d.ts.map +1 -0
  44. package/dist/core/index.js +28 -0
  45. package/dist/core/index.js.map +1 -0
  46. package/dist/core/operations.d.ts +36 -0
  47. package/dist/core/operations.d.ts.map +1 -0
  48. package/dist/core/operations.js +87 -0
  49. package/dist/core/operations.js.map +1 -0
  50. package/dist/core/types.d.ts +287 -0
  51. package/dist/core/types.d.ts.map +1 -0
  52. package/dist/core/types.js +93 -0
  53. package/dist/core/types.js.map +1 -0
  54. package/dist/index.d.ts +57 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +63 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/notifications/index.d.ts +76 -0
  59. package/dist/notifications/index.d.ts.map +1 -0
  60. package/dist/notifications/index.js +182 -0
  61. package/dist/notifications/index.js.map +1 -0
  62. package/dist/repository/index.d.ts +10 -0
  63. package/dist/repository/index.d.ts.map +1 -0
  64. package/dist/repository/index.js +11 -0
  65. package/dist/repository/index.js.map +1 -0
  66. package/dist/repository/memory/index.d.ts +70 -0
  67. package/dist/repository/memory/index.d.ts.map +1 -0
  68. package/dist/repository/memory/index.js +518 -0
  69. package/dist/repository/memory/index.js.map +1 -0
  70. package/dist/repository/types.d.ts +283 -0
  71. package/dist/repository/types.d.ts.map +1 -0
  72. package/dist/repository/types.js +39 -0
  73. package/dist/repository/types.js.map +1 -0
  74. package/dist/repository/utils.d.ts +22 -0
  75. package/dist/repository/utils.d.ts.map +1 -0
  76. package/dist/repository/utils.js +40 -0
  77. package/dist/repository/utils.js.map +1 -0
  78. package/dist/sdk/admin-client.d.ts +146 -0
  79. package/dist/sdk/admin-client.d.ts.map +1 -0
  80. package/dist/sdk/admin-client.js +196 -0
  81. package/dist/sdk/admin-client.js.map +1 -0
  82. package/dist/sdk/client.d.ts +144 -0
  83. package/dist/sdk/client.d.ts.map +1 -0
  84. package/dist/sdk/client.js +247 -0
  85. package/dist/sdk/client.js.map +1 -0
  86. package/dist/sdk/errors.d.ts +91 -0
  87. package/dist/sdk/errors.d.ts.map +1 -0
  88. package/dist/sdk/errors.js +185 -0
  89. package/dist/sdk/errors.js.map +1 -0
  90. package/dist/sdk/index.d.ts +13 -0
  91. package/dist/sdk/index.d.ts.map +1 -0
  92. package/dist/sdk/index.js +13 -0
  93. package/dist/sdk/index.js.map +1 -0
  94. package/dist/sdk/types.d.ts +110 -0
  95. package/dist/sdk/types.d.ts.map +1 -0
  96. package/dist/sdk/types.js +20 -0
  97. package/dist/sdk/types.js.map +1 -0
  98. package/dist/service/credits-service.d.ts +139 -0
  99. package/dist/service/credits-service.d.ts.map +1 -0
  100. package/dist/service/credits-service.js +372 -0
  101. package/dist/service/credits-service.js.map +1 -0
  102. package/dist/service/index.d.ts +3 -0
  103. package/dist/service/index.d.ts.map +1 -0
  104. package/dist/service/index.js +2 -0
  105. package/dist/service/index.js.map +1 -0
  106. package/dist/utils/error-utils.d.ts +48 -0
  107. package/dist/utils/error-utils.d.ts.map +1 -0
  108. package/dist/utils/error-utils.js +57 -0
  109. package/dist/utils/error-utils.js.map +1 -0
  110. package/dist/utils/index.d.ts +54 -0
  111. package/dist/utils/index.d.ts.map +1 -0
  112. package/dist/utils/index.js +72 -0
  113. package/dist/utils/index.js.map +1 -0
  114. package/package.json +69 -0
@@ -0,0 +1,518 @@
1
+ /**
2
+ * In-Memory Credit Repository Implementation
3
+ *
4
+ * A database-agnostic implementation of ICreditRepository for testing and prototyping.
5
+ * All data is stored in memory and lost when the process restarts.
6
+ *
7
+ * Usage:
8
+ * - Unit tests without database dependency
9
+ * - Local development and prototyping
10
+ * - Reference implementation for custom repositories
11
+ */
12
+ import { generateId, toDate, getNextMonthlyReset } from "../utils";
13
+ import { getConfig, getConfigMonthlyLimit } from "../../config";
14
+ /**
15
+ * In-Memory implementation of ICreditRepository
16
+ *
17
+ * Implements all repository methods using Map-based storage.
18
+ * Useful for testing and as a reference implementation.
19
+ */
20
+ export class InMemoryCreditRepository {
21
+ users = new Map();
22
+ reservations = new Map();
23
+ transactions = new Map();
24
+ usageLogs = [];
25
+ journalEntries = new Map();
26
+ // ==================== User Credits ====================
27
+ async getUserCredits(userId) {
28
+ return this.users.get(userId) ?? null;
29
+ }
30
+ async initializeUserCredits(userId, tier, initialBalance) {
31
+ const now = new Date().toISOString();
32
+ const credits = {
33
+ userId,
34
+ balance: initialBalance,
35
+ bonusCredits: 0,
36
+ reserved: 0,
37
+ tier,
38
+ monthlyLimit: getConfigMonthlyLimit(tier),
39
+ monthlyUsed: 0,
40
+ monthlyResetAt: getNextMonthlyReset().toISOString(),
41
+ subscriptionExpiresAt: null,
42
+ createdAt: now,
43
+ updatedAt: now,
44
+ };
45
+ this.users.set(userId, credits);
46
+ return credits;
47
+ }
48
+ async updateUserCredits(userId, updates) {
49
+ const credits = this.users.get(userId);
50
+ if (!credits) {
51
+ throw new Error(`User ${userId} not found`);
52
+ }
53
+ const now = new Date().toISOString();
54
+ // Apply absolute updates
55
+ if (updates.balance !== undefined)
56
+ credits.balance = updates.balance;
57
+ if (updates.bonusCredits !== undefined)
58
+ credits.bonusCredits = updates.bonusCredits;
59
+ if (updates.reserved !== undefined)
60
+ credits.reserved = updates.reserved;
61
+ if (updates.tier !== undefined)
62
+ credits.tier = updates.tier;
63
+ if (updates.monthlyLimit !== undefined)
64
+ credits.monthlyLimit = updates.monthlyLimit;
65
+ if (updates.monthlyUsed !== undefined)
66
+ credits.monthlyUsed = updates.monthlyUsed;
67
+ if (updates.monthlyResetAt !== undefined) {
68
+ credits.monthlyResetAt = updates.monthlyResetAt instanceof Date
69
+ ? updates.monthlyResetAt.toISOString()
70
+ : updates.monthlyResetAt;
71
+ }
72
+ if (updates.subscriptionExpiresAt !== undefined) {
73
+ if (updates.subscriptionExpiresAt === null) {
74
+ credits.subscriptionExpiresAt = null;
75
+ }
76
+ else {
77
+ credits.subscriptionExpiresAt = updates.subscriptionExpiresAt instanceof Date
78
+ ? updates.subscriptionExpiresAt.toISOString()
79
+ : updates.subscriptionExpiresAt;
80
+ }
81
+ }
82
+ // Apply increments
83
+ if (updates.balanceIncrement !== undefined) {
84
+ credits.balance += updates.balanceIncrement;
85
+ }
86
+ if (updates.bonusCreditsIncrement !== undefined) {
87
+ credits.bonusCredits += updates.bonusCreditsIncrement;
88
+ }
89
+ if (updates.reservedIncrement !== undefined) {
90
+ credits.reserved += updates.reservedIncrement;
91
+ }
92
+ if (updates.monthlyUsedIncrement !== undefined) {
93
+ credits.monthlyUsed += updates.monthlyUsedIncrement;
94
+ }
95
+ credits.updatedAt = now;
96
+ this.users.set(userId, credits);
97
+ }
98
+ async updateUserTier(userId, input) {
99
+ const credits = this.users.get(userId);
100
+ if (!credits) {
101
+ throw new Error(`User ${userId} not found`);
102
+ }
103
+ credits.tier = input.tier;
104
+ credits.monthlyLimit = input.monthlyLimit;
105
+ if (input.balance !== undefined)
106
+ credits.balance = input.balance;
107
+ if (input.monthlyUsed !== undefined)
108
+ credits.monthlyUsed = input.monthlyUsed;
109
+ if (input.subscriptionExpiresAt !== undefined) {
110
+ if (input.subscriptionExpiresAt === null) {
111
+ credits.subscriptionExpiresAt = null;
112
+ }
113
+ else {
114
+ credits.subscriptionExpiresAt = input.subscriptionExpiresAt instanceof Date
115
+ ? input.subscriptionExpiresAt.toISOString()
116
+ : input.subscriptionExpiresAt;
117
+ }
118
+ }
119
+ credits.updatedAt = new Date().toISOString();
120
+ this.users.set(userId, credits);
121
+ }
122
+ // ==================== Reservations ====================
123
+ async createReservation(input) {
124
+ const now = new Date().toISOString();
125
+ const reservation = {
126
+ id: generateId(),
127
+ userId: input.userId,
128
+ amount: input.amount,
129
+ operationType: input.operationType,
130
+ status: "reserved",
131
+ createdAt: now,
132
+ expiresAt: input.expiresAt.toISOString(),
133
+ };
134
+ if (!this.reservations.has(input.userId)) {
135
+ this.reservations.set(input.userId, new Map());
136
+ }
137
+ this.reservations.get(input.userId).set(reservation.id, reservation);
138
+ return reservation;
139
+ }
140
+ async getReservation(userId, reservationId) {
141
+ const userReservations = this.reservations.get(userId);
142
+ if (!userReservations)
143
+ return null;
144
+ return userReservations.get(reservationId) ?? null;
145
+ }
146
+ async updateReservationStatus(userId, reservationId, status, completedAt) {
147
+ const userReservations = this.reservations.get(userId);
148
+ if (!userReservations) {
149
+ throw new Error(`No reservations found for user ${userId}`);
150
+ }
151
+ const reservation = userReservations.get(reservationId);
152
+ if (!reservation) {
153
+ throw new Error(`Reservation ${reservationId} not found`);
154
+ }
155
+ reservation.status = status;
156
+ if (completedAt)
157
+ reservation.completedAt = completedAt.toISOString();
158
+ userReservations.set(reservationId, reservation);
159
+ }
160
+ // ==================== Atomic Operations ====================
161
+ async reserveCreditsAtomic(userId, amount, operationType, expiresAt) {
162
+ const credits = this.users.get(userId);
163
+ if (!credits) {
164
+ throw new Error(`User ${userId} not found`);
165
+ }
166
+ // Calculate available credits (balance + bonusCredits - reserved)
167
+ const available = credits.balance + credits.bonusCredits - credits.reserved;
168
+ if (available < amount) {
169
+ throw new Error(`Insufficient credits. Available: ${available}, Required: ${amount}`);
170
+ }
171
+ // Create reservation
172
+ const reservation = await this.createReservation({
173
+ userId,
174
+ amount,
175
+ operationType,
176
+ expiresAt,
177
+ });
178
+ // Update reserved amount
179
+ credits.reserved += amount;
180
+ credits.updatedAt = new Date().toISOString();
181
+ this.users.set(userId, credits);
182
+ return reservation;
183
+ }
184
+ async commitReservationAtomic(userId, reservationId) {
185
+ const credits = this.users.get(userId);
186
+ if (!credits) {
187
+ throw new Error(`User ${userId} not found`);
188
+ }
189
+ const reservation = await this.getReservation(userId, reservationId);
190
+ if (!reservation) {
191
+ throw new Error(`Reservation ${reservationId} not found`);
192
+ }
193
+ if (reservation.status !== "reserved") {
194
+ throw new Error(`Cannot commit reservation in ${reservation.status} state`);
195
+ }
196
+ const amount = reservation.amount;
197
+ // Deduct from balance (bonus credits first logic can be added if needed)
198
+ credits.balance -= amount;
199
+ credits.reserved -= amount;
200
+ credits.monthlyUsed += amount;
201
+ credits.updatedAt = new Date().toISOString();
202
+ this.users.set(userId, credits);
203
+ // Update reservation status
204
+ await this.updateReservationStatus(userId, reservationId, "committed", new Date());
205
+ }
206
+ async releaseReservationAtomic(userId, reservationId) {
207
+ const credits = this.users.get(userId);
208
+ if (!credits) {
209
+ throw new Error(`User ${userId} not found`);
210
+ }
211
+ const reservation = await this.getReservation(userId, reservationId);
212
+ if (!reservation) {
213
+ throw new Error(`Reservation ${reservationId} not found`);
214
+ }
215
+ if (reservation.status !== "reserved") {
216
+ // Already processed, no-op
217
+ return;
218
+ }
219
+ // Release reserved credits
220
+ credits.reserved -= reservation.amount;
221
+ credits.updatedAt = new Date().toISOString();
222
+ this.users.set(userId, credits);
223
+ // Update reservation status
224
+ await this.updateReservationStatus(userId, reservationId, "released", new Date());
225
+ }
226
+ async addCreditsAtomic(userId, amount, description, paymentRef) {
227
+ const credits = this.users.get(userId);
228
+ if (!credits) {
229
+ throw new Error(`User ${userId} not found`);
230
+ }
231
+ const previousBalance = credits.bonusCredits;
232
+ credits.bonusCredits += amount;
233
+ credits.updatedAt = new Date().toISOString();
234
+ this.users.set(userId, credits);
235
+ // Create transaction
236
+ await this.createTransaction({
237
+ userId,
238
+ type: "purchase",
239
+ amount,
240
+ description,
241
+ paymentRef,
242
+ previousBalance,
243
+ newBalance: credits.bonusCredits,
244
+ });
245
+ }
246
+ // ==================== Transactions ====================
247
+ async createTransaction(input) {
248
+ const transaction = {
249
+ id: generateId(),
250
+ userId: input.userId,
251
+ type: input.type,
252
+ amount: input.amount,
253
+ description: input.description,
254
+ paymentRef: input.paymentRef,
255
+ previousBalance: input.previousBalance,
256
+ newBalance: input.newBalance,
257
+ createdAt: new Date().toISOString(),
258
+ };
259
+ if (!this.transactions.has(input.userId)) {
260
+ this.transactions.set(input.userId, []);
261
+ }
262
+ this.transactions.get(input.userId).push(transaction);
263
+ return transaction;
264
+ }
265
+ async getTransactions(userId, limit = 50, offset = 0) {
266
+ const userTransactions = this.transactions.get(userId) ?? [];
267
+ // Sort by createdAt descending (most recent first)
268
+ const sorted = [...userTransactions].sort((a, b) => {
269
+ const aDate = toDate(a.createdAt).getTime();
270
+ const bDate = toDate(b.createdAt).getTime();
271
+ return bDate - aDate;
272
+ });
273
+ return sorted.slice(offset, offset + limit);
274
+ }
275
+ // ==================== Usage Logs ====================
276
+ async logUsage(input) {
277
+ const log = {
278
+ id: generateId(),
279
+ userId: input.userId,
280
+ operationType: input.operationType,
281
+ provider: input.provider,
282
+ creditsUsed: input.creditsUsed,
283
+ success: input.success,
284
+ errorMessage: input.errorMessage,
285
+ resourceId: input.resourceId,
286
+ resourceType: input.resourceType,
287
+ requestId: input.requestId,
288
+ metadata: input.metadata,
289
+ createdAt: new Date().toISOString(),
290
+ };
291
+ this.usageLogs.push(log);
292
+ return log;
293
+ }
294
+ async getUsageLogs(query) {
295
+ let results = [...this.usageLogs];
296
+ // Apply filters
297
+ if (query.userId) {
298
+ results = results.filter((log) => log.userId === query.userId);
299
+ }
300
+ if (query.operationType) {
301
+ results = results.filter((log) => log.operationType === query.operationType);
302
+ }
303
+ if (query.success !== undefined) {
304
+ results = results.filter((log) => log.success === query.success);
305
+ }
306
+ if (query.startDate) {
307
+ const startTime = query.startDate.getTime();
308
+ results = results.filter((log) => toDate(log.createdAt).getTime() >= startTime);
309
+ }
310
+ if (query.endDate) {
311
+ const endTime = query.endDate.getTime();
312
+ results = results.filter((log) => toDate(log.createdAt).getTime() <= endTime);
313
+ }
314
+ // Sort by createdAt descending
315
+ results.sort((a, b) => {
316
+ return toDate(b.createdAt).getTime() - toDate(a.createdAt).getTime();
317
+ });
318
+ // Apply pagination
319
+ const offset = query.offset ?? 0;
320
+ const limit = query.limit ?? 50;
321
+ return results.slice(offset, offset + limit);
322
+ }
323
+ async getUsageLogsCount(query) {
324
+ const results = await this.getUsageLogs({ ...query, limit: Infinity, offset: 0 });
325
+ return results.length;
326
+ }
327
+ // ==================== Journal Entries ====================
328
+ async createJournalEntry(input) {
329
+ const entry = {
330
+ id: generateId(),
331
+ userId: input.userId,
332
+ entryType: input.entryType,
333
+ amount: input.amount,
334
+ balanceAfter: input.balanceAfter,
335
+ source: input.source,
336
+ referenceId: input.referenceId,
337
+ referenceType: input.referenceType,
338
+ description: input.description,
339
+ metadata: input.metadata,
340
+ createdAt: new Date().toISOString(),
341
+ };
342
+ if (!this.journalEntries.has(input.userId)) {
343
+ this.journalEntries.set(input.userId, []);
344
+ }
345
+ this.journalEntries.get(input.userId).push(entry);
346
+ return entry;
347
+ }
348
+ async getJournalEntries(query) {
349
+ let results = this.journalEntries.get(query.userId) ?? [];
350
+ // Apply filters
351
+ if (query.source) {
352
+ results = results.filter((entry) => entry.source === query.source);
353
+ }
354
+ if (query.referenceType) {
355
+ results = results.filter((entry) => entry.referenceType === query.referenceType);
356
+ }
357
+ if (query.startDate) {
358
+ const startTime = query.startDate.getTime();
359
+ results = results.filter((entry) => toDate(entry.createdAt).getTime() >= startTime);
360
+ }
361
+ if (query.endDate) {
362
+ const endTime = query.endDate.getTime();
363
+ results = results.filter((entry) => toDate(entry.createdAt).getTime() <= endTime);
364
+ }
365
+ // Sort by createdAt descending
366
+ results = [...results].sort((a, b) => {
367
+ return toDate(b.createdAt).getTime() - toDate(a.createdAt).getTime();
368
+ });
369
+ // Apply pagination
370
+ const offset = query.offset ?? 0;
371
+ const limit = query.limit ?? 50;
372
+ return results.slice(offset, offset + limit);
373
+ }
374
+ async getJournalEntriesCount(query) {
375
+ const results = await this.getJournalEntries({
376
+ ...query,
377
+ limit: Infinity,
378
+ offset: 0,
379
+ });
380
+ return results.length;
381
+ }
382
+ // ==================== Cleanup Operations ====================
383
+ async findAndExpireReservations(_batchSize = 100, _maxIterations = 100) {
384
+ const now = new Date();
385
+ let expiredCount = 0;
386
+ let creditsReleased = 0;
387
+ const errors = [];
388
+ for (const [userId, userReservations] of this.reservations) {
389
+ for (const [reservationId, reservation] of userReservations) {
390
+ if (reservation.status === "reserved" &&
391
+ toDate(reservation.expiresAt).getTime() < now.getTime()) {
392
+ try {
393
+ // Release the reservation
394
+ await this.releaseReservationAtomic(userId, reservationId);
395
+ // Mark as expired instead of released
396
+ reservation.status = "expired";
397
+ userReservations.set(reservationId, reservation);
398
+ expiredCount++;
399
+ creditsReleased += reservation.amount;
400
+ }
401
+ catch (error) {
402
+ errors.push(`Failed to expire reservation ${reservationId}: ${error}`);
403
+ }
404
+ }
405
+ }
406
+ }
407
+ return { expiredCount, creditsReleased, errors };
408
+ }
409
+ // ==================== Atomic Monthly Reset ====================
410
+ async atomicMonthlyReset(userId, tier, expectedResetAt) {
411
+ const credits = this.users.get(userId);
412
+ if (!credits) {
413
+ throw new Error(`User ${userId} not found`);
414
+ }
415
+ // Optimistic locking: check if expectedResetAt matches current value
416
+ const currentResetAt = toDate(credits.monthlyResetAt).getTime();
417
+ const expected = toDate(expectedResetAt).getTime();
418
+ if (currentResetAt !== expected) {
419
+ // Another request already performed the reset
420
+ return { wasReset: false, credits };
421
+ }
422
+ // Perform the reset
423
+ const newBalance = getConfigMonthlyLimit(tier);
424
+ const nextReset = getNextMonthlyReset();
425
+ credits.balance = newBalance === Infinity ? credits.balance : newBalance;
426
+ credits.monthlyUsed = 0;
427
+ credits.monthlyResetAt = nextReset.toISOString();
428
+ credits.updatedAt = new Date().toISOString();
429
+ this.users.set(userId, credits);
430
+ return { wasReset: true, credits };
431
+ }
432
+ // ==================== Subscription Expiry ====================
433
+ async checkAndHandleSubscriptionExpiry(userId, gracePeriodDays = 3) {
434
+ const credits = this.users.get(userId);
435
+ if (!credits) {
436
+ throw new Error(`User ${userId} not found`);
437
+ }
438
+ // Free tier doesn't expire
439
+ if (credits.tier === "free" || !credits.subscriptionExpiresAt) {
440
+ return {
441
+ wasDowngraded: false,
442
+ inGracePeriod: false,
443
+ graceDaysRemaining: 0,
444
+ credits,
445
+ };
446
+ }
447
+ const now = new Date();
448
+ const expiresAt = toDate(credits.subscriptionExpiresAt);
449
+ const daysSinceExpiry = (now.getTime() - expiresAt.getTime()) / (1000 * 60 * 60 * 24);
450
+ if (daysSinceExpiry <= 0) {
451
+ // Not expired yet
452
+ return {
453
+ wasDowngraded: false,
454
+ inGracePeriod: false,
455
+ graceDaysRemaining: 0,
456
+ credits,
457
+ };
458
+ }
459
+ if (daysSinceExpiry <= gracePeriodDays) {
460
+ // In grace period
461
+ return {
462
+ wasDowngraded: false,
463
+ inGracePeriod: true,
464
+ graceDaysRemaining: Math.ceil(gracePeriodDays - daysSinceExpiry),
465
+ credits,
466
+ };
467
+ }
468
+ // Grace period expired - downgrade to free
469
+ const config = getConfig();
470
+ const freeTierConfig = config.tierConfigs.free;
471
+ credits.tier = "free";
472
+ credits.monthlyLimit = freeTierConfig.monthlyCredits;
473
+ credits.balance = Math.min(credits.balance, freeTierConfig.monthlyCredits);
474
+ credits.subscriptionExpiresAt = null;
475
+ credits.updatedAt = new Date().toISOString();
476
+ this.users.set(userId, credits);
477
+ return {
478
+ wasDowngraded: true,
479
+ inGracePeriod: false,
480
+ graceDaysRemaining: 0,
481
+ credits,
482
+ };
483
+ }
484
+ // ==================== Testing Utilities ====================
485
+ /**
486
+ * Clear all data (useful for testing)
487
+ */
488
+ clear() {
489
+ this.users.clear();
490
+ this.reservations.clear();
491
+ this.transactions.clear();
492
+ this.usageLogs = [];
493
+ this.journalEntries.clear();
494
+ }
495
+ /**
496
+ * Get all users (useful for testing/debugging)
497
+ */
498
+ getAllUsers() {
499
+ return Array.from(this.users.values());
500
+ }
501
+ /**
502
+ * Get all reservations for a user (useful for testing)
503
+ */
504
+ getAllReservations(userId) {
505
+ const userReservations = this.reservations.get(userId);
506
+ if (!userReservations)
507
+ return [];
508
+ return Array.from(userReservations.values());
509
+ }
510
+ }
511
+ /**
512
+ * Create a new in-memory repository instance
513
+ * Each call creates a fresh, isolated instance
514
+ */
515
+ export function createInMemoryCreditRepository() {
516
+ return new InMemoryCreditRepository();
517
+ }
518
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/repository/memory/index.ts"],"names":[],"mappings":"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"}