@nehorai/credits 1.3.0 → 1.5.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 (43) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +153 -153
  3. package/dist/adapters/index.cjs +13 -3
  4. package/dist/adapters/index.cjs.map +1 -1
  5. package/dist/adapters/index.d.cts +2 -2
  6. package/dist/adapters/index.d.ts +2 -2
  7. package/dist/adapters/index.js +13 -3
  8. package/dist/adapters/index.js.map +1 -1
  9. package/dist/auth/index.cjs.map +1 -1
  10. package/dist/auth/index.js.map +1 -1
  11. package/dist/core/index.cjs +13 -3
  12. package/dist/core/index.cjs.map +1 -1
  13. package/dist/core/index.d.cts +3 -3
  14. package/dist/core/index.d.ts +3 -3
  15. package/dist/core/index.js +13 -3
  16. package/dist/core/index.js.map +1 -1
  17. package/dist/index.cjs +88 -19
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +74 -15
  20. package/dist/index.d.ts +74 -15
  21. package/dist/index.js +79 -19
  22. package/dist/index.js.map +1 -1
  23. package/dist/repository/index.cjs +50 -11
  24. package/dist/repository/index.cjs.map +1 -1
  25. package/dist/repository/index.d.cts +3 -3
  26. package/dist/repository/index.d.ts +3 -3
  27. package/dist/repository/index.js +50 -11
  28. package/dist/repository/index.js.map +1 -1
  29. package/dist/sdk/index.cjs.map +1 -1
  30. package/dist/sdk/index.d.cts +2 -2
  31. package/dist/sdk/index.d.ts +2 -2
  32. package/dist/sdk/index.js.map +1 -1
  33. package/dist/service/index.cjs +60 -12
  34. package/dist/service/index.cjs.map +1 -1
  35. package/dist/service/index.d.cts +18 -3
  36. package/dist/service/index.d.ts +18 -3
  37. package/dist/service/index.js +60 -12
  38. package/dist/service/index.js.map +1 -1
  39. package/dist/{types-BBxIWHK2.d.cts → types-DgQtamEe.d.cts} +16 -3
  40. package/dist/{types-BBxIWHK2.d.ts → types-DgQtamEe.d.ts} +16 -3
  41. package/dist/{types-D1vdeBcA.d.cts → types-KgNdBuEF.d.cts} +1 -1
  42. package/dist/{types-aJsyv8df.d.ts → types-fW2JNmmr.d.ts} +1 -1
  43. package/package.json +1 -1
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { S as SubscriptionTier, T as TierConfig, c as PortableReservation } from './types-BBxIWHK2.cjs';
2
- export { A as AIProviderType, g as CreditCheckResult, a as CreditOperationType, C as CreditSource, J as JournalReferenceType, M as MonthlyResetResult, f as PortableJournalEntry, P as PortableTransaction, d as PortableUsageLog, b as PortableUserCredits, R as ReservationStatus, h as ResourceType, g as SDKCreditCheckResult, e as SubscriptionExpiryResult, i as TransactionType, U as UsageHistoryEntry, j as UsageHistoryResponse, b as UserCredits, W as WithCreditsOptions, k as calculateAvailableCredits, t as toDate, l as toPortableTimestamp } from './types-BBxIWHK2.cjs';
1
+ import { S as SubscriptionTier, T as TierConfig, c as PortableReservation } from './types-DgQtamEe.cjs';
2
+ export { A as AIProviderType, B as BuiltinTier, g as CreditCheckResult, a as CreditOperationType, C as CreditSource, J as JournalReferenceType, M as MonthlyResetResult, f as PortableJournalEntry, P as PortableTransaction, d as PortableUsageLog, b as PortableUserCredits, R as ReservationStatus, h as ResourceType, g as SDKCreditCheckResult, e as SubscriptionExpiryResult, i as TransactionType, U as UsageHistoryEntry, j as UsageHistoryResponse, b as UserCredits, W as WithCreditsOptions, k as calculateAvailableCredits, t as toDate, l as toPortableTimestamp } from './types-DgQtamEe.cjs';
3
3
  export { CreditError, CreditErrorCode, CreditErrorCodeType, commitReservationWithJournal, createInsufficientCreditsError, createInvalidOperationTypeError, createReservationAlreadyProcessedError, createReservationExpiredError, createReservationNotFoundError, createUserNotFoundError, isCreditError, isInsufficientCreditsError, releaseReservationWithJournal, reserveCreditsForOperation } from './core/index.cjs';
4
4
  export { D as DeferredExecutor, c as createDeferredExecutor, g as genericDeferred, n as noopDeferred, s as synchronousDeferred } from './deferred-C7rrRfkm.cjs';
5
5
  import { z } from 'zod';
6
- export { C as CreateJournalEntryInput, a as CreateReservationInput, b as CreateTransactionInput, c as CreateUsageLogInput, d as CreditBalanceUpdate, e as CreditRepositoryFactory, I as ICreditRepository, J as JournalEntryQuery, T as TierUpdateInput, U as UsageLogQuery, t as toClientUserCredits } from './types-D1vdeBcA.cjs';
6
+ export { C as CreateJournalEntryInput, a as CreateReservationInput, b as CreateTransactionInput, c as CreateUsageLogInput, d as CreditBalanceUpdate, e as CreditRepositoryFactory, I as ICreditRepository, J as JournalEntryQuery, T as TierUpdateInput, U as UsageLogQuery, t as toClientUserCredits } from './types-KgNdBuEF.cjs';
7
7
  export { InMemoryCreditRepository, createInMemoryCreditRepository, generateId, getNextMonthlyReset } from './repository/index.cjs';
8
8
  export { C as CreditsAuthProviderFactory, a as CreditsUser, I as ICreditsAuthProvider } from './types-OZU3I5OM.cjs';
9
9
  export { ApiKeyCreditsProvider, createApiKeyProvider, verifyAdminApiKey, verifyBearerToken } from './auth/index.cjs';
@@ -29,21 +29,30 @@ declare const creditSystemConfigSchema: z.ZodObject<{
29
29
  /**
30
30
  * Tier configurations
31
31
  */
32
- tierConfigs: z.ZodRecord<z.ZodEnum<["free", "basic", "premium", "unlimited"]>, z.ZodObject<{
33
- tier: z.ZodEnum<["free", "basic", "premium", "unlimited"]>;
32
+ tierConfigs: z.ZodRecord<z.ZodString, z.ZodObject<{
33
+ tier: z.ZodString;
34
34
  monthlyCredits: z.ZodNumber;
35
35
  priceUsd: z.ZodNumber;
36
36
  features: z.ZodArray<z.ZodString, "many">;
37
+ isFree: z.ZodOptional<z.ZodBoolean>;
38
+ unlimited: z.ZodOptional<z.ZodBoolean>;
39
+ isDefault: z.ZodOptional<z.ZodBoolean>;
37
40
  }, "strip", z.ZodTypeAny, {
38
- tier: "free" | "basic" | "premium" | "unlimited";
41
+ tier: string;
39
42
  monthlyCredits: number;
40
43
  priceUsd: number;
41
44
  features: string[];
45
+ unlimited?: boolean | undefined;
46
+ isFree?: boolean | undefined;
47
+ isDefault?: boolean | undefined;
42
48
  }, {
43
- tier: "free" | "basic" | "premium" | "unlimited";
49
+ tier: string;
44
50
  monthlyCredits: number;
45
51
  priceUsd: number;
46
52
  features: string[];
53
+ unlimited?: boolean | undefined;
54
+ isFree?: boolean | undefined;
55
+ isDefault?: boolean | undefined;
47
56
  }>>;
48
57
  /**
49
58
  * Reservation expiry time in milliseconds
@@ -87,12 +96,15 @@ declare const creditSystemConfigSchema: z.ZodObject<{
87
96
  }, "strip", z.ZodTypeAny, {
88
97
  operationCosts: Record<string, number>;
89
98
  operationLabels: Record<string, string>;
90
- tierConfigs: Partial<Record<"free" | "basic" | "premium" | "unlimited", {
91
- tier: "free" | "basic" | "premium" | "unlimited";
99
+ tierConfigs: Record<string, {
100
+ tier: string;
92
101
  monthlyCredits: number;
93
102
  priceUsd: number;
94
103
  features: string[];
95
- }>>;
104
+ unlimited?: boolean | undefined;
105
+ isFree?: boolean | undefined;
106
+ isDefault?: boolean | undefined;
107
+ }>;
96
108
  features: {
97
109
  journalEntries: boolean;
98
110
  notifications: boolean;
@@ -106,12 +118,15 @@ declare const creditSystemConfigSchema: z.ZodObject<{
106
118
  lowBalanceNotificationCooldownHours: number;
107
119
  }, {
108
120
  operationCosts: Record<string, number>;
109
- tierConfigs: Partial<Record<"free" | "basic" | "premium" | "unlimited", {
110
- tier: "free" | "basic" | "premium" | "unlimited";
121
+ tierConfigs: Record<string, {
122
+ tier: string;
111
123
  monthlyCredits: number;
112
124
  priceUsd: number;
113
125
  features: string[];
114
- }>>;
126
+ unlimited?: boolean | undefined;
127
+ isFree?: boolean | undefined;
128
+ isDefault?: boolean | undefined;
129
+ }>;
115
130
  operationLabels?: Record<string, string> | undefined;
116
131
  features?: {
117
132
  journalEntries?: boolean | undefined;
@@ -165,7 +180,41 @@ declare function isValidOperationType(type: string): boolean;
165
180
  */
166
181
  declare function getConfigOperationCost(operationType: string): number;
167
182
  /**
168
- * Get tier configuration from configuration
183
+ * Get all valid tier ids from configuration
184
+ * Returns the keys of the tierConfigs object
185
+ */
186
+ declare function getValidTiers(): string[];
187
+ /**
188
+ * Check if a tier id is valid (configured in the system)
189
+ */
190
+ declare function isValidTier(tier: string): boolean;
191
+ /**
192
+ * Check if a tier is the free/default tier.
193
+ * Falls back to priceUsd === 0 when the isFree flag is not set.
194
+ */
195
+ declare function isFreeTier(tier: SubscriptionTier): boolean;
196
+ /**
197
+ * Check if a tier is unlimited.
198
+ * Falls back to monthlyCredits === 0 when the unlimited flag is not set.
199
+ */
200
+ declare function isUnlimitedTier(tier: SubscriptionTier): boolean;
201
+ /**
202
+ * Get the tier assigned to brand-new users.
203
+ * Prefers the tier flagged isDefault, then the first isFree tier, then "free".
204
+ */
205
+ declare function getDefaultTier(): SubscriptionTier;
206
+ /**
207
+ * Magic balance assigned to unlimited tiers on upgrade.
208
+ * Kept at 999999 for back-compat with stored/displayed balances.
209
+ */
210
+ declare const UNLIMITED_BALANCE_SENTINEL = 999999;
211
+ /**
212
+ * Get the magic balance assigned to unlimited tiers on upgrade.
213
+ */
214
+ declare function getUnlimitedSentinelBalance(): number;
215
+ /**
216
+ * Get tier configuration from configuration.
217
+ * Falls back to the default tier (with a warning) if the tier is unknown.
169
218
  */
170
219
  declare function getConfigTierConfig(tier: SubscriptionTier): TierConfig;
171
220
  /**
@@ -173,6 +222,16 @@ declare function getConfigTierConfig(tier: SubscriptionTier): TierConfig;
173
222
  * Returns Infinity for unlimited tier
174
223
  */
175
224
  declare function getConfigMonthlyLimit(tier: SubscriptionTier): number;
225
+ /**
226
+ * Runtime zod validator for tier ids. Validates against the LIVE config keys
227
+ * at parse time, so apps that add tiers via config get correct validation.
228
+ */
229
+ declare const tierSchema: z.ZodType<SubscriptionTier>;
230
+ /**
231
+ * Parse/validate a tier id against the live config keys.
232
+ * @throws ZodError if the tier is not configured
233
+ */
234
+ declare function parseTier(value: unknown): SubscriptionTier;
176
235
  /**
177
236
  * Check if a feature is enabled
178
237
  */
@@ -434,4 +493,4 @@ declare function isPreviewMode(data: unknown): boolean;
434
493
  */
435
494
  declare function createDummyReservation(userId: string, operationType: string): PortableReservation;
436
495
 
437
- export { ConsoleNotificationHandler, type CreditErrorInfo, type CreditNotificationEvent, PortableReservation as CreditReservation, type CreditSystemConfig, type ICreditConfigProvider, type ICreditNotificationHandler, type OperationCostInfo, PortableReservation, SubscriptionTier as SDKSubscriptionTier, SubscriptionTier, TierConfig, checkAndNotifyLowBalance, clearConfigProvider, clearCooldownState, clearNotificationHandlers, createDummyReservation, generateRequestId, getConfig, getConfigMonthlyLimit, getConfigOperationCost, getConfigProvider, getConfigTierConfig, getDefaultFreeCredits, getMonthlyLimit, getOperationCost, getOperationCosts, getOperationCostsWithLabels, getOperationLabel, getOperationLabels, getReservationExpiryMs, getTierConfig, getTotalCredits, getValidOperationTypes, initializeConfig, isCreditErrorMessage, isFeatureEnabled, isPreviewMode, isValidOperationType, loadConfigFromEnv, notifySubscriptionExpired, notifySubscriptionExpiring, parseCreditError, registerConfigProvider, registerNotificationHandler, resetConfig };
496
+ export { ConsoleNotificationHandler, type CreditErrorInfo, type CreditNotificationEvent, PortableReservation as CreditReservation, type CreditSystemConfig, type ICreditConfigProvider, type ICreditNotificationHandler, type OperationCostInfo, PortableReservation, SubscriptionTier as SDKSubscriptionTier, SubscriptionTier, TierConfig, UNLIMITED_BALANCE_SENTINEL, checkAndNotifyLowBalance, clearConfigProvider, clearCooldownState, clearNotificationHandlers, createDummyReservation, generateRequestId, getConfig, getConfigMonthlyLimit, getConfigOperationCost, getConfigProvider, getConfigTierConfig, getDefaultFreeCredits, getDefaultTier, getMonthlyLimit, getOperationCost, getOperationCosts, getOperationCostsWithLabels, getOperationLabel, getOperationLabels, getReservationExpiryMs, getTierConfig, getTotalCredits, getUnlimitedSentinelBalance, getValidOperationTypes, getValidTiers, initializeConfig, isCreditErrorMessage, isFeatureEnabled, isFreeTier, isPreviewMode, isUnlimitedTier, isValidOperationType, isValidTier, loadConfigFromEnv, notifySubscriptionExpired, notifySubscriptionExpiring, parseCreditError, parseTier, registerConfigProvider, registerNotificationHandler, resetConfig, tierSchema };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { S as SubscriptionTier, T as TierConfig, c as PortableReservation } from './types-BBxIWHK2.js';
2
- export { A as AIProviderType, g as CreditCheckResult, a as CreditOperationType, C as CreditSource, J as JournalReferenceType, M as MonthlyResetResult, f as PortableJournalEntry, P as PortableTransaction, d as PortableUsageLog, b as PortableUserCredits, R as ReservationStatus, h as ResourceType, g as SDKCreditCheckResult, e as SubscriptionExpiryResult, i as TransactionType, U as UsageHistoryEntry, j as UsageHistoryResponse, b as UserCredits, W as WithCreditsOptions, k as calculateAvailableCredits, t as toDate, l as toPortableTimestamp } from './types-BBxIWHK2.js';
1
+ import { S as SubscriptionTier, T as TierConfig, c as PortableReservation } from './types-DgQtamEe.js';
2
+ export { A as AIProviderType, B as BuiltinTier, g as CreditCheckResult, a as CreditOperationType, C as CreditSource, J as JournalReferenceType, M as MonthlyResetResult, f as PortableJournalEntry, P as PortableTransaction, d as PortableUsageLog, b as PortableUserCredits, R as ReservationStatus, h as ResourceType, g as SDKCreditCheckResult, e as SubscriptionExpiryResult, i as TransactionType, U as UsageHistoryEntry, j as UsageHistoryResponse, b as UserCredits, W as WithCreditsOptions, k as calculateAvailableCredits, t as toDate, l as toPortableTimestamp } from './types-DgQtamEe.js';
3
3
  export { CreditError, CreditErrorCode, CreditErrorCodeType, commitReservationWithJournal, createInsufficientCreditsError, createInvalidOperationTypeError, createReservationAlreadyProcessedError, createReservationExpiredError, createReservationNotFoundError, createUserNotFoundError, isCreditError, isInsufficientCreditsError, releaseReservationWithJournal, reserveCreditsForOperation } from './core/index.js';
4
4
  export { D as DeferredExecutor, c as createDeferredExecutor, g as genericDeferred, n as noopDeferred, s as synchronousDeferred } from './deferred-C7rrRfkm.js';
5
5
  import { z } from 'zod';
6
- export { C as CreateJournalEntryInput, a as CreateReservationInput, b as CreateTransactionInput, c as CreateUsageLogInput, d as CreditBalanceUpdate, e as CreditRepositoryFactory, I as ICreditRepository, J as JournalEntryQuery, T as TierUpdateInput, U as UsageLogQuery, t as toClientUserCredits } from './types-aJsyv8df.js';
6
+ export { C as CreateJournalEntryInput, a as CreateReservationInput, b as CreateTransactionInput, c as CreateUsageLogInput, d as CreditBalanceUpdate, e as CreditRepositoryFactory, I as ICreditRepository, J as JournalEntryQuery, T as TierUpdateInput, U as UsageLogQuery, t as toClientUserCredits } from './types-fW2JNmmr.js';
7
7
  export { InMemoryCreditRepository, createInMemoryCreditRepository, generateId, getNextMonthlyReset } from './repository/index.js';
8
8
  export { C as CreditsAuthProviderFactory, a as CreditsUser, I as ICreditsAuthProvider } from './types-OZU3I5OM.js';
9
9
  export { ApiKeyCreditsProvider, createApiKeyProvider, verifyAdminApiKey, verifyBearerToken } from './auth/index.js';
@@ -29,21 +29,30 @@ declare const creditSystemConfigSchema: z.ZodObject<{
29
29
  /**
30
30
  * Tier configurations
31
31
  */
32
- tierConfigs: z.ZodRecord<z.ZodEnum<["free", "basic", "premium", "unlimited"]>, z.ZodObject<{
33
- tier: z.ZodEnum<["free", "basic", "premium", "unlimited"]>;
32
+ tierConfigs: z.ZodRecord<z.ZodString, z.ZodObject<{
33
+ tier: z.ZodString;
34
34
  monthlyCredits: z.ZodNumber;
35
35
  priceUsd: z.ZodNumber;
36
36
  features: z.ZodArray<z.ZodString, "many">;
37
+ isFree: z.ZodOptional<z.ZodBoolean>;
38
+ unlimited: z.ZodOptional<z.ZodBoolean>;
39
+ isDefault: z.ZodOptional<z.ZodBoolean>;
37
40
  }, "strip", z.ZodTypeAny, {
38
- tier: "free" | "basic" | "premium" | "unlimited";
41
+ tier: string;
39
42
  monthlyCredits: number;
40
43
  priceUsd: number;
41
44
  features: string[];
45
+ unlimited?: boolean | undefined;
46
+ isFree?: boolean | undefined;
47
+ isDefault?: boolean | undefined;
42
48
  }, {
43
- tier: "free" | "basic" | "premium" | "unlimited";
49
+ tier: string;
44
50
  monthlyCredits: number;
45
51
  priceUsd: number;
46
52
  features: string[];
53
+ unlimited?: boolean | undefined;
54
+ isFree?: boolean | undefined;
55
+ isDefault?: boolean | undefined;
47
56
  }>>;
48
57
  /**
49
58
  * Reservation expiry time in milliseconds
@@ -87,12 +96,15 @@ declare const creditSystemConfigSchema: z.ZodObject<{
87
96
  }, "strip", z.ZodTypeAny, {
88
97
  operationCosts: Record<string, number>;
89
98
  operationLabels: Record<string, string>;
90
- tierConfigs: Partial<Record<"free" | "basic" | "premium" | "unlimited", {
91
- tier: "free" | "basic" | "premium" | "unlimited";
99
+ tierConfigs: Record<string, {
100
+ tier: string;
92
101
  monthlyCredits: number;
93
102
  priceUsd: number;
94
103
  features: string[];
95
- }>>;
104
+ unlimited?: boolean | undefined;
105
+ isFree?: boolean | undefined;
106
+ isDefault?: boolean | undefined;
107
+ }>;
96
108
  features: {
97
109
  journalEntries: boolean;
98
110
  notifications: boolean;
@@ -106,12 +118,15 @@ declare const creditSystemConfigSchema: z.ZodObject<{
106
118
  lowBalanceNotificationCooldownHours: number;
107
119
  }, {
108
120
  operationCosts: Record<string, number>;
109
- tierConfigs: Partial<Record<"free" | "basic" | "premium" | "unlimited", {
110
- tier: "free" | "basic" | "premium" | "unlimited";
121
+ tierConfigs: Record<string, {
122
+ tier: string;
111
123
  monthlyCredits: number;
112
124
  priceUsd: number;
113
125
  features: string[];
114
- }>>;
126
+ unlimited?: boolean | undefined;
127
+ isFree?: boolean | undefined;
128
+ isDefault?: boolean | undefined;
129
+ }>;
115
130
  operationLabels?: Record<string, string> | undefined;
116
131
  features?: {
117
132
  journalEntries?: boolean | undefined;
@@ -165,7 +180,41 @@ declare function isValidOperationType(type: string): boolean;
165
180
  */
166
181
  declare function getConfigOperationCost(operationType: string): number;
167
182
  /**
168
- * Get tier configuration from configuration
183
+ * Get all valid tier ids from configuration
184
+ * Returns the keys of the tierConfigs object
185
+ */
186
+ declare function getValidTiers(): string[];
187
+ /**
188
+ * Check if a tier id is valid (configured in the system)
189
+ */
190
+ declare function isValidTier(tier: string): boolean;
191
+ /**
192
+ * Check if a tier is the free/default tier.
193
+ * Falls back to priceUsd === 0 when the isFree flag is not set.
194
+ */
195
+ declare function isFreeTier(tier: SubscriptionTier): boolean;
196
+ /**
197
+ * Check if a tier is unlimited.
198
+ * Falls back to monthlyCredits === 0 when the unlimited flag is not set.
199
+ */
200
+ declare function isUnlimitedTier(tier: SubscriptionTier): boolean;
201
+ /**
202
+ * Get the tier assigned to brand-new users.
203
+ * Prefers the tier flagged isDefault, then the first isFree tier, then "free".
204
+ */
205
+ declare function getDefaultTier(): SubscriptionTier;
206
+ /**
207
+ * Magic balance assigned to unlimited tiers on upgrade.
208
+ * Kept at 999999 for back-compat with stored/displayed balances.
209
+ */
210
+ declare const UNLIMITED_BALANCE_SENTINEL = 999999;
211
+ /**
212
+ * Get the magic balance assigned to unlimited tiers on upgrade.
213
+ */
214
+ declare function getUnlimitedSentinelBalance(): number;
215
+ /**
216
+ * Get tier configuration from configuration.
217
+ * Falls back to the default tier (with a warning) if the tier is unknown.
169
218
  */
170
219
  declare function getConfigTierConfig(tier: SubscriptionTier): TierConfig;
171
220
  /**
@@ -173,6 +222,16 @@ declare function getConfigTierConfig(tier: SubscriptionTier): TierConfig;
173
222
  * Returns Infinity for unlimited tier
174
223
  */
175
224
  declare function getConfigMonthlyLimit(tier: SubscriptionTier): number;
225
+ /**
226
+ * Runtime zod validator for tier ids. Validates against the LIVE config keys
227
+ * at parse time, so apps that add tiers via config get correct validation.
228
+ */
229
+ declare const tierSchema: z.ZodType<SubscriptionTier>;
230
+ /**
231
+ * Parse/validate a tier id against the live config keys.
232
+ * @throws ZodError if the tier is not configured
233
+ */
234
+ declare function parseTier(value: unknown): SubscriptionTier;
176
235
  /**
177
236
  * Check if a feature is enabled
178
237
  */
@@ -434,4 +493,4 @@ declare function isPreviewMode(data: unknown): boolean;
434
493
  */
435
494
  declare function createDummyReservation(userId: string, operationType: string): PortableReservation;
436
495
 
437
- export { ConsoleNotificationHandler, type CreditErrorInfo, type CreditNotificationEvent, PortableReservation as CreditReservation, type CreditSystemConfig, type ICreditConfigProvider, type ICreditNotificationHandler, type OperationCostInfo, PortableReservation, SubscriptionTier as SDKSubscriptionTier, SubscriptionTier, TierConfig, checkAndNotifyLowBalance, clearConfigProvider, clearCooldownState, clearNotificationHandlers, createDummyReservation, generateRequestId, getConfig, getConfigMonthlyLimit, getConfigOperationCost, getConfigProvider, getConfigTierConfig, getDefaultFreeCredits, getMonthlyLimit, getOperationCost, getOperationCosts, getOperationCostsWithLabels, getOperationLabel, getOperationLabels, getReservationExpiryMs, getTierConfig, getTotalCredits, getValidOperationTypes, initializeConfig, isCreditErrorMessage, isFeatureEnabled, isPreviewMode, isValidOperationType, loadConfigFromEnv, notifySubscriptionExpired, notifySubscriptionExpiring, parseCreditError, registerConfigProvider, registerNotificationHandler, resetConfig };
496
+ export { ConsoleNotificationHandler, type CreditErrorInfo, type CreditNotificationEvent, PortableReservation as CreditReservation, type CreditSystemConfig, type ICreditConfigProvider, type ICreditNotificationHandler, type OperationCostInfo, PortableReservation, SubscriptionTier as SDKSubscriptionTier, SubscriptionTier, TierConfig, UNLIMITED_BALANCE_SENTINEL, checkAndNotifyLowBalance, clearConfigProvider, clearCooldownState, clearNotificationHandlers, createDummyReservation, generateRequestId, getConfig, getConfigMonthlyLimit, getConfigOperationCost, getConfigProvider, getConfigTierConfig, getDefaultFreeCredits, getDefaultTier, getMonthlyLimit, getOperationCost, getOperationCosts, getOperationCostsWithLabels, getOperationLabel, getOperationLabels, getReservationExpiryMs, getTierConfig, getTotalCredits, getUnlimitedSentinelBalance, getValidOperationTypes, getValidTiers, initializeConfig, isCreditErrorMessage, isFeatureEnabled, isFreeTier, isPreviewMode, isUnlimitedTier, isValidOperationType, isValidTier, loadConfigFromEnv, notifySubscriptionExpired, notifySubscriptionExpiring, parseCreditError, parseTier, registerConfigProvider, registerNotificationHandler, resetConfig, tierSchema };
package/dist/index.js CHANGED
@@ -165,10 +165,13 @@ function clearConfigProvider() {
165
165
 
166
166
  // src/config/index.ts
167
167
  var tierConfigSchema = z.object({
168
- tier: z.enum(["free", "basic", "premium", "unlimited"]),
168
+ tier: z.string().min(1),
169
169
  monthlyCredits: z.number().min(0),
170
170
  priceUsd: z.number().min(0),
171
- features: z.array(z.string())
171
+ features: z.array(z.string()),
172
+ isFree: z.boolean().optional(),
173
+ unlimited: z.boolean().optional(),
174
+ isDefault: z.boolean().optional()
172
175
  });
173
176
  var creditSystemConfigSchema = z.object({
174
177
  /**
@@ -192,7 +195,7 @@ var creditSystemConfigSchema = z.object({
192
195
  * Tier configurations
193
196
  */
194
197
  tierConfigs: z.record(
195
- z.enum(["free", "basic", "premium", "unlimited"]),
198
+ z.string().min(1),
196
199
  tierConfigSchema
197
200
  ),
198
201
  /**
@@ -248,6 +251,8 @@ var DEFAULT_CONFIG = {
248
251
  tier: "free",
249
252
  monthlyCredits: 25,
250
253
  priceUsd: 0,
254
+ isFree: true,
255
+ isDefault: true,
251
256
  features: [
252
257
  "25 credits per month",
253
258
  "Basic story generation",
@@ -281,6 +286,7 @@ var DEFAULT_CONFIG = {
281
286
  tier: "unlimited",
282
287
  monthlyCredits: 0,
283
288
  // 0 = unlimited
289
+ unlimited: true,
284
290
  priceUsd: 49.99,
285
291
  features: [
286
292
  "Unlimited credits",
@@ -408,12 +414,46 @@ function getConfigOperationCost(operationType) {
408
414
  }
409
415
  return cost;
410
416
  }
417
+ function getValidTiers() {
418
+ return Object.keys(getConfig().tierConfigs);
419
+ }
420
+ function isValidTier(tier) {
421
+ return tier in getConfig().tierConfigs;
422
+ }
423
+ function isFreeTier(tier) {
424
+ const c = getConfig().tierConfigs[tier];
425
+ if (!c) return false;
426
+ return c.isFree ?? c.priceUsd === 0;
427
+ }
428
+ function isUnlimitedTier(tier) {
429
+ const c = getConfig().tierConfigs[tier];
430
+ if (!c) return false;
431
+ return c.unlimited ?? c.monthlyCredits === 0;
432
+ }
433
+ function getDefaultTier() {
434
+ const entries = Object.entries(getConfig().tierConfigs);
435
+ const def = entries.find(([, c]) => c.isDefault)?.[0] ?? entries.find(([, c]) => c.isFree ?? c.priceUsd === 0)?.[0];
436
+ return def ?? "free";
437
+ }
438
+ var UNLIMITED_BALANCE_SENTINEL = 999999;
439
+ function getUnlimitedSentinelBalance() {
440
+ return UNLIMITED_BALANCE_SENTINEL;
441
+ }
411
442
  function getConfigTierConfig(tier) {
412
- return getConfig().tierConfigs[tier];
443
+ const cfg = getConfig().tierConfigs[tier];
444
+ if (cfg) return cfg;
445
+ const fallback = getDefaultTier();
446
+ console.warn(
447
+ `[Credits Config] Unknown tier "${tier}". Falling back to "${fallback}". Valid: ${getValidTiers().join(", ")}`
448
+ );
449
+ return getConfig().tierConfigs[fallback];
413
450
  }
414
451
  function getConfigMonthlyLimit(tier) {
415
- const config = getConfig().tierConfigs[tier];
416
- return config.monthlyCredits === 0 ? Infinity : config.monthlyCredits;
452
+ return isUnlimitedTier(tier) ? Infinity : getConfigTierConfig(tier).monthlyCredits;
453
+ }
454
+ var tierSchema = z.string().refine(isValidTier, { message: "Unknown subscription tier" });
455
+ function parseTier(value) {
456
+ return tierSchema.parse(value);
417
457
  }
418
458
  function isFeatureEnabled(feature) {
419
459
  return getConfig().features[feature];
@@ -725,6 +765,9 @@ var InMemoryCreditRepository = class {
725
765
  if (!reservation) {
726
766
  throw new Error(`Reservation ${reservationId} not found`);
727
767
  }
768
+ if (reservation.status === "committed") {
769
+ return;
770
+ }
728
771
  if (reservation.status !== "reserved") {
729
772
  throw new Error(
730
773
  `Cannot commit reservation in ${reservation.status} state`
@@ -985,7 +1028,7 @@ var InMemoryCreditRepository = class {
985
1028
  if (!credits) {
986
1029
  throw new Error(`User ${userId} not found`);
987
1030
  }
988
- if (credits.tier === "free" || !credits.subscriptionExpiresAt) {
1031
+ if (isFreeTier(credits.tier) || !credits.subscriptionExpiresAt) {
989
1032
  return {
990
1033
  wasDowngraded: false,
991
1034
  inGracePeriod: false,
@@ -1012,11 +1055,11 @@ var InMemoryCreditRepository = class {
1012
1055
  credits
1013
1056
  };
1014
1057
  }
1015
- const config = getConfig();
1016
- const freeTierConfig = config.tierConfigs.free;
1017
- credits.tier = "free";
1018
- credits.monthlyLimit = freeTierConfig.monthlyCredits;
1019
- credits.balance = Math.min(credits.balance, freeTierConfig.monthlyCredits);
1058
+ const defaultTier = getDefaultTier();
1059
+ const defaultTierConfig = getConfigTierConfig(defaultTier);
1060
+ credits.tier = defaultTier;
1061
+ credits.monthlyLimit = defaultTierConfig.monthlyCredits;
1062
+ credits.balance = Math.min(credits.balance, defaultTierConfig.monthlyCredits);
1020
1063
  credits.subscriptionExpiresAt = null;
1021
1064
  credits.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1022
1065
  this.users.set(userId, credits);
@@ -1156,7 +1199,7 @@ var CreditsService = class {
1156
1199
  if (!data) {
1157
1200
  return null;
1158
1201
  }
1159
- if (data.tier !== "free" && data.subscriptionExpiresAt) {
1202
+ if (!isFreeTier(data.tier) && data.subscriptionExpiresAt) {
1160
1203
  const expiryResult = await this.repository.checkAndHandleSubscriptionExpiry(
1161
1204
  userId,
1162
1205
  getConfig().subscriptionGracePeriodDays
@@ -1225,7 +1268,7 @@ var CreditsService = class {
1225
1268
  async initializeUserCredits(userId) {
1226
1269
  const credits = await this.repository.initializeUserCredits(
1227
1270
  userId,
1228
- "free",
1271
+ getDefaultTier(),
1229
1272
  getConfig().defaultFreeCredits
1230
1273
  );
1231
1274
  return toClientUserCredits(credits);
@@ -1267,11 +1310,13 @@ var CreditsService = class {
1267
1310
  * @param userId - User ID
1268
1311
  * @param amount - Credits to reserve
1269
1312
  * @param operationType - Operation type for tracking
1313
+ * @param options - Optional settings (e.g. a custom `ttlMs` for long-running async jobs)
1270
1314
  * @returns Reservation object
1271
1315
  * @throws Error if insufficient credits
1272
1316
  */
1273
- async reserveCredits(userId, amount, operationType) {
1274
- const expiresAt = new Date(Date.now() + getConfig().reservationExpiryMs);
1317
+ async reserveCredits(userId, amount, operationType, options) {
1318
+ const ttlMs = options?.ttlMs ?? getConfig().reservationExpiryMs;
1319
+ const expiresAt = new Date(Date.now() + ttlMs);
1275
1320
  return this.repository.reserveCreditsAtomic(userId, amount, operationType, expiresAt);
1276
1321
  }
1277
1322
  /**
@@ -1284,6 +1329,9 @@ var CreditsService = class {
1284
1329
  if (!reservation) {
1285
1330
  throw new Error(`Reservation ${reservationId} not found`);
1286
1331
  }
1332
+ if (reservation.status === "committed") {
1333
+ return;
1334
+ }
1287
1335
  await this.repository.commitReservationAtomic(userId, reservationId);
1288
1336
  const credits = await this.repository.getUserCredits(userId);
1289
1337
  if (credits) {
@@ -1360,12 +1408,15 @@ var CreditsService = class {
1360
1408
  */
1361
1409
  async updateTier(userId, tier, expiresAt) {
1362
1410
  const monthlyLimit = getConfigMonthlyLimit(tier);
1411
+ const unlimited = isUnlimitedTier(tier);
1412
+ const free = isFreeTier(tier);
1363
1413
  await this.repository.updateUserTier(userId, {
1364
1414
  tier,
1365
- monthlyLimit: monthlyLimit === Infinity ? 0 : monthlyLimit,
1415
+ // Stored monthlyLimit uses the 0-means-unlimited convention.
1416
+ monthlyLimit: unlimited ? 0 : monthlyLimit,
1366
1417
  // Reset balance to new tier limit if upgrading
1367
- balance: tier !== "free" ? monthlyLimit === Infinity ? 999999 : monthlyLimit : void 0,
1368
- monthlyUsed: tier !== "free" ? 0 : void 0,
1418
+ balance: !free ? unlimited ? getUnlimitedSentinelBalance() : monthlyLimit : void 0,
1419
+ monthlyUsed: !free ? 0 : void 0,
1369
1420
  subscriptionExpiresAt: expiresAt ? expiresAt.toISOString() : null
1370
1421
  });
1371
1422
  }
@@ -2333,6 +2384,7 @@ export {
2333
2384
  ReservationExpiredError as SDKReservationExpiredError,
2334
2385
  ReservationNotFoundError as SDKReservationNotFoundError,
2335
2386
  ServerError,
2387
+ UNLIMITED_BALANCE_SENTINEL,
2336
2388
  ValidationError,
2337
2389
  calculateAvailableCredits,
2338
2390
  checkAndNotifyLowBalance,
@@ -2361,6 +2413,7 @@ export {
2361
2413
  getConfigProvider,
2362
2414
  getConfigTierConfig,
2363
2415
  getDefaultFreeCredits,
2416
+ getDefaultTier,
2364
2417
  getMonthlyLimit,
2365
2418
  getNextMonthlyReset,
2366
2419
  getOperationCost,
@@ -2371,26 +2424,33 @@ export {
2371
2424
  getReservationExpiryMs,
2372
2425
  getTierConfig,
2373
2426
  getTotalCredits,
2427
+ getUnlimitedSentinelBalance,
2374
2428
  getValidOperationTypes,
2429
+ getValidTiers,
2375
2430
  initializeConfig,
2376
2431
  isCreditError,
2377
2432
  isCreditErrorMessage,
2378
2433
  isFeatureEnabled,
2434
+ isFreeTier,
2379
2435
  isInsufficientCreditsError,
2380
2436
  isPreviewMode2 as isPreviewMode,
2437
+ isUnlimitedTier,
2381
2438
  isValidOperationType,
2439
+ isValidTier,
2382
2440
  loadConfigFromEnv,
2383
2441
  noopDeferred,
2384
2442
  notifySubscriptionExpired,
2385
2443
  notifySubscriptionExpiring,
2386
2444
  parseApiError,
2387
2445
  parseCreditError,
2446
+ parseTier,
2388
2447
  registerConfigProvider,
2389
2448
  registerNotificationHandler,
2390
2449
  releaseReservationWithJournal,
2391
2450
  reserveCreditsForOperation,
2392
2451
  resetConfig,
2393
2452
  synchronousDeferred,
2453
+ tierSchema,
2394
2454
  toClientUserCredits,
2395
2455
  toDate,
2396
2456
  toPortableTimestamp,