@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,93 @@
1
+ /**
2
+ * Portable credits types - framework and database agnostic
3
+ *
4
+ * These types use standard JavaScript types (string, Date) instead of
5
+ * Firebase-specific types (Timestamp). This makes the credits system
6
+ * portable to other environments without Firebase dependencies.
7
+ *
8
+ * Note: Firestore Timestamp is handled by the credits-firestore adapter.
9
+ */
10
+ // ==================== Utility Functions ====================
11
+ /**
12
+ * Calculate available credits from balance, bonus, and reserved amounts.
13
+ *
14
+ * Available = balance + bonusCredits - reserved
15
+ *
16
+ * @param balance - Regular monthly credits
17
+ * @param bonusCredits - Purchased/admin credits
18
+ * @param reserved - Credits locked for in-flight operations
19
+ * @returns Available credits for new operations
20
+ */
21
+ export function calculateAvailableCredits(balance, bonusCredits, reserved) {
22
+ return balance + bonusCredits - reserved;
23
+ }
24
+ /**
25
+ * Convert various timestamp formats to ISO string.
26
+ *
27
+ * Handles:
28
+ * - Date objects
29
+ * - ISO string (returned as-is)
30
+ * - Timestamp-like objects with toDate() method (Firebase)
31
+ * - undefined/null (returns current time)
32
+ *
33
+ * @param value - Value to convert
34
+ * @returns ISO 8601 string
35
+ */
36
+ export function toPortableTimestamp(value) {
37
+ if (!value) {
38
+ return new Date().toISOString();
39
+ }
40
+ if (typeof value === "string") {
41
+ return value;
42
+ }
43
+ if (value instanceof Date) {
44
+ return value.toISOString();
45
+ }
46
+ if (typeof value === "object" &&
47
+ value !== null &&
48
+ "toDate" in value &&
49
+ typeof value.toDate === "function") {
50
+ return value.toDate().toISOString();
51
+ }
52
+ return new Date().toISOString();
53
+ }
54
+ /**
55
+ * Convert various timestamp formats to Date object.
56
+ *
57
+ * Handles:
58
+ * - Date objects (returned as-is)
59
+ * - ISO string
60
+ * - Timestamp-like objects with toDate() method (Firebase)
61
+ * - Invalid values (returns current date)
62
+ *
63
+ * @param value - Value to convert
64
+ * @returns Date object
65
+ */
66
+ export function toDate(value) {
67
+ if (value instanceof Date) {
68
+ return value;
69
+ }
70
+ if (typeof value === "string") {
71
+ return new Date(value);
72
+ }
73
+ if (typeof value === "object" &&
74
+ value !== null &&
75
+ "toDate" in value &&
76
+ typeof value.toDate === "function") {
77
+ return value.toDate();
78
+ }
79
+ return new Date();
80
+ }
81
+ // ==================== Constants ====================
82
+ /**
83
+ * Constants for credit system configuration
84
+ */
85
+ export const CREDIT_CONSTANTS = {
86
+ /** Grace period in days after subscription expires before downgrade */
87
+ SUBSCRIPTION_GRACE_PERIOD_DAYS: 3,
88
+ /** Low balance notification threshold */
89
+ LOW_BALANCE_THRESHOLD: 10,
90
+ /** Cooldown in hours between low balance notifications */
91
+ LOW_BALANCE_NOTIFICATION_COOLDOWN_HOURS: 24,
92
+ };
93
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,8DAA8D;AAE9D;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAe,EACf,YAAoB,EACpB,QAAgB;IAEhB,OAAO,OAAO,GAAG,YAAY,GAAG,QAAQ,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC;IAED,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,QAAQ,IAAI,KAAK;QACjB,OAAQ,KAAgC,CAAC,MAAM,KAAK,UAAU,EAC9D,CAAC;QACD,OAAQ,KAAgC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC;IAClE,CAAC;IAED,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,KAAc;IACnC,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,QAAQ,IAAI,KAAK;QACjB,OAAQ,KAAgC,CAAC,MAAM,KAAK,UAAU,EAC9D,CAAC;QACD,OAAQ,KAAgC,CAAC,MAAM,EAAE,CAAC;IACpD,CAAC;IAED,OAAO,IAAI,IAAI,EAAE,CAAC;AACpB,CAAC;AAgSD,sDAAsD;AAEtD;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,uEAAuE;IACvE,8BAA8B,EAAE,CAAC;IACjC,yCAAyC;IACzC,qBAAqB,EAAE,EAAE;IACzB,0DAA0D;IAC1D,uCAAuC,EAAE,EAAE;CACnC,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @nehorai/credits - Framework-agnostic credits system
3
+ *
4
+ * Provides a complete credits/billing system with:
5
+ * - Two-phase commit for safe credit deduction
6
+ * - Journal-based audit trail
7
+ * - Subscription tier management
8
+ * - Notification hooks
9
+ * - REST API SDK
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import {
14
+ * CreditsService,
15
+ * createInMemoryCreditRepository,
16
+ * CreditError,
17
+ * } from '@nehorai/credits';
18
+ *
19
+ * const repository = createInMemoryCreditRepository();
20
+ * const service = new CreditsService(repository);
21
+ *
22
+ * // Check credits
23
+ * const check = await service.checkCredits(userId, 10);
24
+ * if (!check.hasCredits) {
25
+ * throw new Error(`Need ${check.shortfall} more credits`);
26
+ * }
27
+ *
28
+ * // Reserve and execute
29
+ * const reservation = await service.reserveCredits(userId, 10, 'story_generation');
30
+ * try {
31
+ * await doWork();
32
+ * await service.commitCredits(userId, reservation.id);
33
+ * } catch (error) {
34
+ * await service.releaseCredits(userId, reservation.id);
35
+ * throw error;
36
+ * }
37
+ * ```
38
+ */
39
+ export * from "./core";
40
+ export { getConfig, initializeConfig, loadConfigFromEnv, getValidOperationTypes, isValidOperationType, getConfigOperationCost, getConfigTierConfig, getConfigMonthlyLimit, isFeatureEnabled, resetConfig, type CreditSystemConfig, } from "./config";
41
+ export { getOperationCosts, getOperationCost, getTierConfig, getMonthlyLimit, getDefaultFreeCredits, getReservationExpiryMs, TIER_CONFIGS, DEFAULT_FREE_CREDITS, RESERVATION_EXPIRY_MS, } from "./config/costs";
42
+ export type { ICreditRepository, CreditRepositoryFactory, CreateReservationInput, CreateTransactionInput, CreateUsageLogInput, CreateJournalEntryInput, UsageLogQuery, JournalEntryQuery, CreditBalanceUpdate, TierUpdateInput, } from "./repository/types";
43
+ export { toClientUserCredits } from "./repository/types";
44
+ export { generateId, getNextMonthlyReset } from "./repository/utils";
45
+ export { InMemoryCreditRepository, createInMemoryCreditRepository, } from "./repository/memory";
46
+ export * from "./auth";
47
+ export * from "./service";
48
+ export * from "./adapters";
49
+ export { registerNotificationHandler, clearNotificationHandlers, clearCooldownState, checkAndNotifyLowBalance, notifySubscriptionExpiring, notifySubscriptionExpired, ConsoleNotificationHandler, type CreditNotificationEvent, type ICreditNotificationHandler, } from "./notifications";
50
+ export { CreditsClient } from "./sdk/client";
51
+ export { AdminCreditsClient } from "./sdk/admin-client";
52
+ export type { CreditsClientConfig, AdminCreditsClientConfig, UserCredits, CreditReservation, CreditCheckResult as SDKCreditCheckResult, ReservationResult, PaginationOptions, UsageHistoryEntry as SDKUsageHistoryEntry, UsageHistoryResponse as SDKUsageHistoryResponse, ApiResponse, SDKErrorCodeType, SubscriptionTier as SDKSubscriptionTier, } from "./sdk/types";
53
+ export type { CreditsConfig, ListUsersResponse, ListUsersOptions, } from "./sdk/admin-client";
54
+ export { SDKErrorCode } from "./sdk/types";
55
+ export { CreditsSDKError, NetworkError, AuthenticationError, AuthorizationError, InsufficientCreditsError as SDKInsufficientCreditsError, ReservationNotFoundError as SDKReservationNotFoundError, ReservationExpiredError as SDKReservationExpiredError, ValidationError, ServerError, parseApiError, } from "./sdk/errors";
56
+ export { getTotalCredits, generateRequestId, parseCreditError, isCreditErrorMessage, isPreviewMode, createDummyReservation, type CreditErrorInfo, } from "./utils";
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,cAAc,QAAQ,CAAC;AAGvB,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,KAAK,kBAAkB,GACxB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EACV,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EACL,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAG7B,cAAc,QAAQ,CAAC;AAGvB,cAAc,WAAW,CAAC;AAG1B,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,0BAA0B,EAC1B,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,GAChC,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,IAAI,oBAAoB,EACzC,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,IAAI,oBAAoB,EACzC,oBAAoB,IAAI,uBAAuB,EAC/C,WAAW,EACX,gBAAgB,EAChB,gBAAgB,IAAI,mBAAmB,GACxC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,IAAI,2BAA2B,EACvD,wBAAwB,IAAI,2BAA2B,EACvD,uBAAuB,IAAI,0BAA0B,EACrD,eAAe,EACf,WAAW,EACX,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,KAAK,eAAe,GACrB,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,63 @@
1
+ /**
2
+ * @nehorai/credits - Framework-agnostic credits system
3
+ *
4
+ * Provides a complete credits/billing system with:
5
+ * - Two-phase commit for safe credit deduction
6
+ * - Journal-based audit trail
7
+ * - Subscription tier management
8
+ * - Notification hooks
9
+ * - REST API SDK
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import {
14
+ * CreditsService,
15
+ * createInMemoryCreditRepository,
16
+ * CreditError,
17
+ * } from '@nehorai/credits';
18
+ *
19
+ * const repository = createInMemoryCreditRepository();
20
+ * const service = new CreditsService(repository);
21
+ *
22
+ * // Check credits
23
+ * const check = await service.checkCredits(userId, 10);
24
+ * if (!check.hasCredits) {
25
+ * throw new Error(`Need ${check.shortfall} more credits`);
26
+ * }
27
+ *
28
+ * // Reserve and execute
29
+ * const reservation = await service.reserveCredits(userId, 10, 'story_generation');
30
+ * try {
31
+ * await doWork();
32
+ * await service.commitCredits(userId, reservation.id);
33
+ * } catch (error) {
34
+ * await service.releaseCredits(userId, reservation.id);
35
+ * throw error;
36
+ * }
37
+ * ```
38
+ */
39
+ // ==================== Core ====================
40
+ export * from "./core";
41
+ // ==================== Config ====================
42
+ export { getConfig, initializeConfig, loadConfigFromEnv, getValidOperationTypes, isValidOperationType, getConfigOperationCost, getConfigTierConfig, getConfigMonthlyLimit, isFeatureEnabled, resetConfig, } from "./config";
43
+ export { getOperationCosts, getOperationCost, getTierConfig, getMonthlyLimit, getDefaultFreeCredits, getReservationExpiryMs, TIER_CONFIGS, DEFAULT_FREE_CREDITS, RESERVATION_EXPIRY_MS, } from "./config/costs";
44
+ export { toClientUserCredits } from "./repository/types";
45
+ export { generateId, getNextMonthlyReset } from "./repository/utils";
46
+ export { InMemoryCreditRepository, createInMemoryCreditRepository, } from "./repository/memory";
47
+ // ==================== Auth ====================
48
+ export * from "./auth";
49
+ // ==================== Service ====================
50
+ export * from "./service";
51
+ // ==================== Adapters ====================
52
+ export * from "./adapters";
53
+ // ==================== Notifications ====================
54
+ export { registerNotificationHandler, clearNotificationHandlers, clearCooldownState, checkAndNotifyLowBalance, notifySubscriptionExpiring, notifySubscriptionExpired, ConsoleNotificationHandler, } from "./notifications";
55
+ // ==================== SDK ====================
56
+ // Export SDK (excluding types that conflict with core)
57
+ export { CreditsClient } from "./sdk/client";
58
+ export { AdminCreditsClient } from "./sdk/admin-client";
59
+ export { SDKErrorCode } from "./sdk/types";
60
+ export { CreditsSDKError, NetworkError, AuthenticationError, AuthorizationError, InsufficientCreditsError as SDKInsufficientCreditsError, ReservationNotFoundError as SDKReservationNotFoundError, ReservationExpiredError as SDKReservationExpiredError, ValidationError, ServerError, parseApiError, } from "./sdk/errors";
61
+ // ==================== Utils ====================
62
+ export { getTotalCredits, generateRequestId, parseCreditError, isCreditErrorMessage, isPreviewMode, createDummyReservation, } from "./utils";
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,iDAAiD;AACjD,cAAc,QAAQ,CAAC;AAEvB,mDAAmD;AACnD,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,GAEZ,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAgBxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EACL,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAE7B,iDAAiD;AACjD,cAAc,QAAQ,CAAC;AAEvB,oDAAoD;AACpD,cAAc,WAAW,CAAC;AAE1B,qDAAqD;AACrD,cAAc,YAAY,CAAC;AAE3B,0DAA0D;AAC1D,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,0BAA0B,EAC1B,yBAAyB,EACzB,0BAA0B,GAG3B,MAAM,iBAAiB,CAAC;AAEzB,gDAAgD;AAChD,uDAAuD;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAoBxD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,IAAI,2BAA2B,EACvD,wBAAwB,IAAI,2BAA2B,EACvD,uBAAuB,IAAI,0BAA0B,EACrD,eAAe,EACf,WAAW,EACX,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,kDAAkD;AAClD,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,sBAAsB,GAEvB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Notification event types
3
+ */
4
+ export type CreditNotificationEvent = {
5
+ type: "low_balance";
6
+ userId: string;
7
+ balance: number;
8
+ threshold: number;
9
+ } | {
10
+ type: "balance_depleted";
11
+ userId: string;
12
+ } | {
13
+ type: "subscription_expiring";
14
+ userId: string;
15
+ expiresAt: Date;
16
+ daysRemaining: number;
17
+ } | {
18
+ type: "subscription_expired";
19
+ userId: string;
20
+ wasDowngraded: boolean;
21
+ };
22
+ /**
23
+ * Notification handler interface
24
+ * Implementations can send emails, push notifications, etc.
25
+ */
26
+ export interface ICreditNotificationHandler {
27
+ /**
28
+ * Handle a notification event
29
+ * @param event - The notification event
30
+ */
31
+ handleNotification(event: CreditNotificationEvent): Promise<void>;
32
+ }
33
+ /**
34
+ * Register a notification handler
35
+ */
36
+ export declare function registerNotificationHandler(handler: ICreditNotificationHandler): void;
37
+ /**
38
+ * Clear all notification handlers (for testing)
39
+ */
40
+ export declare function clearNotificationHandlers(): void;
41
+ /**
42
+ * Clear cooldown state (for testing)
43
+ */
44
+ export declare function clearCooldownState(): void;
45
+ /**
46
+ * Check and trigger low balance notification if needed
47
+ * Call this after commit operations
48
+ *
49
+ * @param userId - User ID
50
+ * @param newBalance - Balance after the operation
51
+ * @param threshold - Custom threshold (defaults to 10)
52
+ */
53
+ export declare function checkAndNotifyLowBalance(userId: string, newBalance: number, threshold?: 10): Promise<void>;
54
+ /**
55
+ * Trigger subscription expiring notification
56
+ *
57
+ * @param userId - User ID
58
+ * @param expiresAt - When subscription expires
59
+ * @param daysRemaining - Days until expiry
60
+ */
61
+ export declare function notifySubscriptionExpiring(userId: string, expiresAt: Date, daysRemaining: number): Promise<void>;
62
+ /**
63
+ * Trigger subscription expired notification
64
+ *
65
+ * @param userId - User ID
66
+ * @param wasDowngraded - Whether the user was downgraded to free tier
67
+ */
68
+ export declare function notifySubscriptionExpired(userId: string, wasDowngraded: boolean): Promise<void>;
69
+ /**
70
+ * Console notification handler for development/testing
71
+ * Logs notifications to console
72
+ */
73
+ export declare class ConsoleNotificationHandler implements ICreditNotificationHandler {
74
+ handleNotification(event: CreditNotificationEvent): Promise<void>;
75
+ }
76
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GACD;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,uBAAuB,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB,GACD;IACE,IAAI,EAAE,sBAAsB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE;AAyFD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,0BAA0B,GAClC,IAAI,CAEN;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAyBD;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,SAAS,KAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,IAAI,EACf,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;GAGG;AACH,qBAAa,0BAA2B,YAAW,0BAA0B;IACrE,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;CA2BxE"}
@@ -0,0 +1,182 @@
1
+ import { CREDIT_CONSTANTS } from "../core/types";
2
+ /**
3
+ * In-memory cooldown tracker
4
+ * In production, this should be stored in a persistent store
5
+ */
6
+ const cooldownState = new Map();
7
+ /**
8
+ * Default notification threshold for low balance
9
+ */
10
+ const LOW_BALANCE_THRESHOLD = CREDIT_CONSTANTS.LOW_BALANCE_THRESHOLD;
11
+ /**
12
+ * Cooldown period in milliseconds (24 hours)
13
+ */
14
+ const NOTIFICATION_COOLDOWN_MS = CREDIT_CONSTANTS.LOW_BALANCE_NOTIFICATION_COOLDOWN_HOURS * 60 * 60 * 1000;
15
+ /**
16
+ * Check if a notification is allowed (not in cooldown)
17
+ */
18
+ function isNotificationAllowed(userId, eventType) {
19
+ const state = cooldownState.get(userId);
20
+ if (!state)
21
+ return true;
22
+ const now = Date.now();
23
+ let lastNotification;
24
+ switch (eventType) {
25
+ case "lowBalance":
26
+ lastNotification = state.lastLowBalanceNotification;
27
+ break;
28
+ case "depleted":
29
+ lastNotification = state.lastDepletedNotification;
30
+ break;
31
+ case "expiring":
32
+ lastNotification = state.lastExpiringNotification;
33
+ break;
34
+ }
35
+ if (!lastNotification)
36
+ return true;
37
+ return now - lastNotification.getTime() > NOTIFICATION_COOLDOWN_MS;
38
+ }
39
+ /**
40
+ * Record that a notification was sent
41
+ */
42
+ function recordNotification(userId, eventType) {
43
+ const state = cooldownState.get(userId) || {};
44
+ const now = new Date();
45
+ switch (eventType) {
46
+ case "lowBalance":
47
+ state.lastLowBalanceNotification = now;
48
+ break;
49
+ case "depleted":
50
+ state.lastDepletedNotification = now;
51
+ break;
52
+ case "expiring":
53
+ state.lastExpiringNotification = now;
54
+ break;
55
+ }
56
+ cooldownState.set(userId, state);
57
+ }
58
+ /**
59
+ * Default notification handlers registry
60
+ * Handlers can be registered at application startup
61
+ */
62
+ const notificationHandlers = [];
63
+ /**
64
+ * Register a notification handler
65
+ */
66
+ export function registerNotificationHandler(handler) {
67
+ notificationHandlers.push(handler);
68
+ }
69
+ /**
70
+ * Clear all notification handlers (for testing)
71
+ */
72
+ export function clearNotificationHandlers() {
73
+ notificationHandlers.length = 0;
74
+ }
75
+ /**
76
+ * Clear cooldown state (for testing)
77
+ */
78
+ export function clearCooldownState() {
79
+ cooldownState.clear();
80
+ }
81
+ /**
82
+ * Dispatch a notification event to all handlers
83
+ * Runs asynchronously without blocking
84
+ */
85
+ async function dispatchNotification(event) {
86
+ if (notificationHandlers.length === 0) {
87
+ // No handlers registered - log for debugging
88
+ console.debug(`[Credits] No notification handlers registered for: ${event.type}`);
89
+ return;
90
+ }
91
+ // Run handlers in parallel
92
+ await Promise.allSettled(notificationHandlers.map((handler) => handler.handleNotification(event).catch((error) => {
93
+ console.error(`[Credits] Notification handler error:`, error);
94
+ })));
95
+ }
96
+ /**
97
+ * Check and trigger low balance notification if needed
98
+ * Call this after commit operations
99
+ *
100
+ * @param userId - User ID
101
+ * @param newBalance - Balance after the operation
102
+ * @param threshold - Custom threshold (defaults to 10)
103
+ */
104
+ export async function checkAndNotifyLowBalance(userId, newBalance, threshold = LOW_BALANCE_THRESHOLD) {
105
+ // Check if balance is depleted
106
+ if (newBalance <= 0 && isNotificationAllowed(userId, "depleted")) {
107
+ recordNotification(userId, "depleted");
108
+ await dispatchNotification({
109
+ type: "balance_depleted",
110
+ userId,
111
+ });
112
+ return; // Don't also send low balance notification
113
+ }
114
+ // Check if balance is below threshold
115
+ if (newBalance > 0 && newBalance <= threshold && isNotificationAllowed(userId, "lowBalance")) {
116
+ recordNotification(userId, "lowBalance");
117
+ await dispatchNotification({
118
+ type: "low_balance",
119
+ userId,
120
+ balance: newBalance,
121
+ threshold,
122
+ });
123
+ }
124
+ }
125
+ /**
126
+ * Trigger subscription expiring notification
127
+ *
128
+ * @param userId - User ID
129
+ * @param expiresAt - When subscription expires
130
+ * @param daysRemaining - Days until expiry
131
+ */
132
+ export async function notifySubscriptionExpiring(userId, expiresAt, daysRemaining) {
133
+ if (!isNotificationAllowed(userId, "expiring")) {
134
+ return;
135
+ }
136
+ recordNotification(userId, "expiring");
137
+ await dispatchNotification({
138
+ type: "subscription_expiring",
139
+ userId,
140
+ expiresAt,
141
+ daysRemaining,
142
+ });
143
+ }
144
+ /**
145
+ * Trigger subscription expired notification
146
+ *
147
+ * @param userId - User ID
148
+ * @param wasDowngraded - Whether the user was downgraded to free tier
149
+ */
150
+ export async function notifySubscriptionExpired(userId, wasDowngraded) {
151
+ await dispatchNotification({
152
+ type: "subscription_expired",
153
+ userId,
154
+ wasDowngraded,
155
+ });
156
+ }
157
+ /**
158
+ * Console notification handler for development/testing
159
+ * Logs notifications to console
160
+ */
161
+ export class ConsoleNotificationHandler {
162
+ async handleNotification(event) {
163
+ switch (event.type) {
164
+ case "low_balance":
165
+ console.log(`[Credits Notification] Low balance alert for user ${event.userId}: ` +
166
+ `${event.balance} credits remaining (threshold: ${event.threshold})`);
167
+ break;
168
+ case "balance_depleted":
169
+ console.log(`[Credits Notification] Balance depleted for user ${event.userId}`);
170
+ break;
171
+ case "subscription_expiring":
172
+ console.log(`[Credits Notification] Subscription expiring for user ${event.userId}: ` +
173
+ `${event.daysRemaining} days remaining`);
174
+ break;
175
+ case "subscription_expired":
176
+ console.log(`[Credits Notification] Subscription expired for user ${event.userId}: ` +
177
+ `downgraded=${event.wasDowngraded}`);
178
+ break;
179
+ }
180
+ }
181
+ }
182
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Credits repository - barrel exports
3
+ *
4
+ * Provides database-agnostic interface for credits storage
5
+ */
6
+ export type { ICreditRepository, CreditRepositoryFactory, CreateReservationInput, CreateTransactionInput, CreateUsageLogInput, CreateJournalEntryInput, UsageLogQuery, JournalEntryQuery, CreditBalanceUpdate, TierUpdateInput, } from "./types";
7
+ export { toClientUserCredits } from "./types";
8
+ export { generateId, toDate, getNextMonthlyReset } from "./utils";
9
+ export { InMemoryCreditRepository, createInMemoryCreditRepository, } from "./memory";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,GAChB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGlE,OAAO,EACL,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,UAAU,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Credits repository - barrel exports
3
+ *
4
+ * Provides database-agnostic interface for credits storage
5
+ */
6
+ export { toClientUserCredits } from "./types";
7
+ // Shared utilities
8
+ export { generateId, toDate, getNextMonthlyReset } from "./utils";
9
+ // In-memory implementation (for testing and prototyping)
10
+ export { InMemoryCreditRepository, createInMemoryCreditRepository, } from "./memory";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,mBAAmB;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAElE,yDAAyD;AACzD,OAAO,EACL,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,UAAU,CAAC"}
@@ -0,0 +1,70 @@
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 type { PortableUserCredits, PortableReservation, PortableTransaction, PortableJournalEntry, PortableUsageLog, SubscriptionTier, ReservationStatus, MonthlyResetResult, SubscriptionExpiryResult } from "../../core/types";
13
+ import type { ICreditRepository, CreateReservationInput, CreateTransactionInput, CreateUsageLogInput, CreateJournalEntryInput, UsageLogQuery, JournalEntryQuery, CreditBalanceUpdate, TierUpdateInput } from "../types";
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 declare class InMemoryCreditRepository implements ICreditRepository {
21
+ private users;
22
+ private reservations;
23
+ private transactions;
24
+ private usageLogs;
25
+ private journalEntries;
26
+ getUserCredits(userId: string): Promise<PortableUserCredits | null>;
27
+ initializeUserCredits(userId: string, tier: SubscriptionTier, initialBalance: number): Promise<PortableUserCredits>;
28
+ updateUserCredits(userId: string, updates: CreditBalanceUpdate): Promise<void>;
29
+ updateUserTier(userId: string, input: TierUpdateInput): Promise<void>;
30
+ createReservation(input: CreateReservationInput): Promise<PortableReservation>;
31
+ getReservation(userId: string, reservationId: string): Promise<PortableReservation | null>;
32
+ updateReservationStatus(userId: string, reservationId: string, status: ReservationStatus, completedAt?: Date): Promise<void>;
33
+ reserveCreditsAtomic(userId: string, amount: number, operationType: string, expiresAt: Date): Promise<PortableReservation>;
34
+ commitReservationAtomic(userId: string, reservationId: string): Promise<void>;
35
+ releaseReservationAtomic(userId: string, reservationId: string): Promise<void>;
36
+ addCreditsAtomic(userId: string, amount: number, description: string, paymentRef?: string): Promise<void>;
37
+ createTransaction(input: CreateTransactionInput): Promise<PortableTransaction>;
38
+ getTransactions(userId: string, limit?: number, offset?: number): Promise<PortableTransaction[]>;
39
+ logUsage(input: CreateUsageLogInput): Promise<PortableUsageLog>;
40
+ getUsageLogs(query: UsageLogQuery): Promise<PortableUsageLog[]>;
41
+ getUsageLogsCount(query: Omit<UsageLogQuery, "limit" | "offset">): Promise<number>;
42
+ createJournalEntry(input: CreateJournalEntryInput): Promise<PortableJournalEntry>;
43
+ getJournalEntries(query: JournalEntryQuery): Promise<PortableJournalEntry[]>;
44
+ getJournalEntriesCount(query: Omit<JournalEntryQuery, "limit" | "offset">): Promise<number>;
45
+ findAndExpireReservations(_batchSize?: number, _maxIterations?: number): Promise<{
46
+ expiredCount: number;
47
+ creditsReleased: number;
48
+ errors: string[];
49
+ }>;
50
+ atomicMonthlyReset(userId: string, tier: SubscriptionTier, expectedResetAt: Date | string): Promise<MonthlyResetResult>;
51
+ checkAndHandleSubscriptionExpiry(userId: string, gracePeriodDays?: number): Promise<SubscriptionExpiryResult>;
52
+ /**
53
+ * Clear all data (useful for testing)
54
+ */
55
+ clear(): void;
56
+ /**
57
+ * Get all users (useful for testing/debugging)
58
+ */
59
+ getAllUsers(): PortableUserCredits[];
60
+ /**
61
+ * Get all reservations for a user (useful for testing)
62
+ */
63
+ getAllReservations(userId: string): PortableReservation[];
64
+ }
65
+ /**
66
+ * Create a new in-memory repository instance
67
+ * Each call creates a fresh, isolated instance
68
+ */
69
+ export declare function createInMemoryCreditRepository(): InMemoryCreditRepository;
70
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/repository/memory/index.ts"],"names":[],"mappings":"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"}