@umituz/react-native-subscription 2.14.99 → 2.14.101

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 (98) hide show
  1. package/README.md +211 -394
  2. package/package.json +3 -3
  3. package/src/application/README.md +46 -225
  4. package/src/application/ports/README.md +42 -97
  5. package/src/domain/README.md +36 -384
  6. package/src/domain/constants/README.md +0 -56
  7. package/src/domain/entities/README.md +43 -169
  8. package/src/domain/entities/SubscriptionStatus.ts +1 -1
  9. package/src/domain/errors/README.md +33 -287
  10. package/src/domain/value-objects/README.md +43 -179
  11. package/src/domains/README.md +50 -238
  12. package/src/domains/README.md.bak +274 -0
  13. package/src/domains/config/README.md +93 -383
  14. package/src/domains/config/domain/README.md +23 -376
  15. package/src/domains/config/domain/entities/README.md +34 -343
  16. package/src/domains/paywall/README.md +99 -369
  17. package/src/domains/paywall/components/README.md +34 -178
  18. package/src/domains/paywall/entities/README.md +34 -193
  19. package/src/domains/paywall/hooks/README.md +34 -122
  20. package/src/domains/wallet/README.md +34 -275
  21. package/src/domains/wallet/README.md.bak +209 -0
  22. package/src/domains/wallet/domain/README.md +34 -101
  23. package/src/domains/wallet/domain/entities/README.md +34 -115
  24. package/src/domains/wallet/domain/errors/README.md +34 -151
  25. package/src/domains/wallet/infrastructure/README.md +34 -89
  26. package/src/domains/wallet/presentation/components/README.md +34 -224
  27. package/src/domains/wallet/presentation/components/TransactionItem.tsx +1 -1
  28. package/src/domains/wallet/presentation/hooks/README.md +34 -248
  29. package/src/infrastructure/README.md +37 -496
  30. package/src/infrastructure/mappers/README.md +0 -13
  31. package/src/infrastructure/repositories/README.md +74 -360
  32. package/src/infrastructure/services/ActivationHandler.ts +1 -1
  33. package/src/infrastructure/services/README.md +95 -370
  34. package/src/infrastructure/services/SubscriptionService.ts +1 -1
  35. package/src/presentation/README.md +123 -408
  36. package/src/presentation/README.md.bak +172 -0
  37. package/src/presentation/components/README.md +151 -179
  38. package/src/presentation/components/README.md.bak +217 -0
  39. package/src/presentation/components/details/CreditRow.md +65 -310
  40. package/src/presentation/components/details/DetailRow.md +63 -255
  41. package/src/presentation/components/details/PremiumDetailsCard.md +65 -238
  42. package/src/presentation/components/details/PremiumStatusBadge.md +64 -239
  43. package/src/presentation/components/details/README.md +97 -447
  44. package/src/presentation/components/feedback/PaywallFeedbackModal.md +63 -287
  45. package/src/presentation/components/feedback/README.md +97 -445
  46. package/src/presentation/components/paywall/PaywallModal.md +66 -416
  47. package/src/presentation/components/paywall/README.md +50 -186
  48. package/src/presentation/components/sections/README.md +97 -466
  49. package/src/presentation/components/sections/SubscriptionSection.md +92 -244
  50. package/src/presentation/hooks/README.md +154 -741
  51. package/src/presentation/hooks/useAuthAwarePurchase.md +58 -325
  52. package/src/presentation/hooks/useAuthGate.md +61 -375
  53. package/src/presentation/hooks/useAuthSubscriptionSync.md +66 -370
  54. package/src/presentation/hooks/useCreditChecker.md +73 -378
  55. package/src/presentation/hooks/useCredits.md +74 -313
  56. package/src/presentation/hooks/useCredits.md.bak +231 -0
  57. package/src/presentation/hooks/useCreditsGate.md +66 -318
  58. package/src/presentation/hooks/useDeductCredit.md +0 -76
  59. package/src/presentation/hooks/useDeductCredit.ts +1 -1
  60. package/src/presentation/hooks/useDevTestCallbacks.md +63 -394
  61. package/src/presentation/hooks/useFeatureGate.md +105 -150
  62. package/src/presentation/hooks/useFeatureGate.md.bak +284 -0
  63. package/src/presentation/hooks/useInitializeCredits.md +64 -430
  64. package/src/presentation/hooks/usePaywall.md +61 -306
  65. package/src/presentation/hooks/usePaywallOperations.md +64 -458
  66. package/src/presentation/hooks/usePaywallVisibility.md +67 -316
  67. package/src/presentation/hooks/usePremium.md +84 -226
  68. package/src/presentation/hooks/usePremiumGate.md +60 -395
  69. package/src/presentation/hooks/usePremiumWithCredits.md +64 -401
  70. package/src/presentation/hooks/useSubscription.md +66 -422
  71. package/src/presentation/hooks/useSubscriptionDetails.md +65 -410
  72. package/src/presentation/hooks/useSubscriptionGate.md +80 -164
  73. package/src/presentation/hooks/useSubscriptionSettingsConfig.md +66 -346
  74. package/src/presentation/hooks/useSubscriptionStatus.md +66 -396
  75. package/src/presentation/hooks/useUserTier.md +63 -328
  76. package/src/presentation/hooks/useUserTierWithRepository.md +64 -424
  77. package/src/presentation/screens/README.md +48 -190
  78. package/src/presentation/types/README.md +0 -16
  79. package/src/presentation/utils/README.md +0 -21
  80. package/src/presentation/utils/subscriptionDateUtils.ts +1 -1
  81. package/src/revenuecat/README.md +99 -518
  82. package/src/revenuecat/application/README.md +35 -150
  83. package/src/revenuecat/application/ports/README.md +34 -162
  84. package/src/revenuecat/domain/README.md +42 -141
  85. package/src/revenuecat/domain/constants/README.md +34 -176
  86. package/src/revenuecat/domain/entities/README.md +34 -374
  87. package/src/revenuecat/domain/errors/README.md +47 -191
  88. package/src/revenuecat/domain/types/README.md +34 -366
  89. package/src/revenuecat/domain/value-objects/README.md +34 -434
  90. package/src/revenuecat/infrastructure/README.md +34 -43
  91. package/src/revenuecat/infrastructure/config/README.md +32 -23
  92. package/src/revenuecat/infrastructure/handlers/README.md +34 -211
  93. package/src/revenuecat/infrastructure/managers/README.md +34 -42
  94. package/src/revenuecat/infrastructure/services/README.md +35 -318
  95. package/src/revenuecat/infrastructure/utils/README.md +34 -375
  96. package/src/revenuecat/presentation/README.md +34 -176
  97. package/src/revenuecat/presentation/hooks/README.md +29 -35
  98. package/src/utils/README.md +38 -525
@@ -2,175 +2,49 @@
2
2
 
3
3
  Core domain entities for subscription management.
4
4
 
5
- ## Purpose
6
-
7
- Domain entities represent the core business concepts and rules of the subscription system. They are framework-agnostic and contain only business logic.
8
-
9
- ## Entities
10
-
11
- ### SubscriptionStatus
12
-
13
- Represents the subscription state of a user.
14
-
15
- ```typescript
16
- interface SubscriptionStatus {
17
- type: SubscriptionStatusType;
18
- isActive: boolean;
19
- isPremium: boolean;
20
- expirationDate: string | null;
21
- willRenew: boolean;
22
- productId?: string;
23
- }
24
-
25
- type SubscriptionStatusType =
26
- | 'unknown'
27
- | 'guest'
28
- | 'free'
29
- | 'premium';
30
- ```
31
-
32
- **Usage:**
33
- ```typescript
34
- import { SubscriptionStatus } from '@umituz/react-native-subscription/domain';
35
-
36
- const status = SubscriptionStatus.create({
37
- type: 'premium',
38
- isActive: true,
39
- isPremium: true,
40
- expirationDate: '2025-12-31',
41
- willRenew: true,
42
- });
43
- ```
44
-
45
- ## Design Principles
46
-
47
- ### 1. Self-Validation
48
-
49
- Entities validate themselves on creation:
50
-
51
- ```typescript
52
- class SubscriptionStatus {
53
- private constructor(data: SubscriptionStatusData) {
54
- this.validate(data);
55
- // ...
56
- }
57
-
58
- private validate(data: SubscriptionStatusData): void {
59
- if (data.isPremium && !data.isActive) {
60
- throw new ValidationError('Premium users must be active');
61
- }
62
- }
63
- }
64
- ```
65
-
66
- ### 2. Immutable State
67
-
68
- Entities cannot be modified after creation:
69
-
70
- ```typescript
71
- const status = SubscriptionStatus.create({...});
72
- // status.isActive = false; // Error: Cannot assign to read-only property
73
- ```
74
-
75
- ### 3. Business Rules
76
-
77
- Business logic is encapsulated in entities:
78
-
79
- ```typescript
80
- class SubscriptionStatus {
81
- isExpired(): boolean {
82
- if (!this.expirationDate) return false;
83
- return new Date(this.expirationDate) < new Date();
84
- }
85
-
86
- requiresRenewal(): boolean {
87
- return this.isPremium && this.expirationDate && this.willRenew;
88
- }
89
- }
90
- ```
91
-
92
- ## Creating Entities
93
-
94
- ### Factory Method
95
-
96
- ```typescript
97
- const status = SubscriptionStatus.create({
98
- type: 'premium',
99
- isActive: true,
100
- isPremium: true,
101
- expirationDate: null,
102
- willRenew: false,
103
- });
104
- ```
105
-
106
- ### Validation
107
-
108
- ```typescript
109
- try {
110
- const status = SubscriptionStatus.create({
111
- type: 'premium',
112
- isActive: false, // Invalid!
113
- isPremium: true,
114
- });
115
- } catch (error) {
116
- console.error('Validation failed:', error.message);
117
- }
118
- ```
119
-
120
- ## Domain Services
121
-
122
- Business operations that don't naturally fit in entities:
123
-
124
- ```typescript
125
- class SubscriptionDomainService {
126
- canUpgrade(currentStatus: SubscriptionStatus): boolean {
127
- return !currentStatus.isPremium;
128
- }
129
-
130
- calculateDaysUntilExpiry(status: SubscriptionStatus): number | null {
131
- if (!status.expirationDate) return null;
132
- const diff = new Date(status.expirationDate).getTime() - Date.now();
133
- return Math.ceil(diff / (1000 * 60 * 60 * 24));
134
- }
135
- }
136
- ```
137
-
138
- ## Best Practices
139
-
140
- 1. **Keep entities pure** - No framework dependencies
141
- 2. **Validate invariants** - Ensure valid state
142
- 3. **Use value objects** - For complex attributes
143
- 4. **Encapsulate logic** - Keep business rules inside entities
144
- 5. **Make immutable** - Prevent direct state modification
145
-
146
- ## Testing
147
-
148
- ```typescript
149
- describe('SubscriptionStatus', () => {
150
- it('should create valid premium status', () => {
151
- const status = SubscriptionStatus.create({
152
- type: 'premium',
153
- isActive: true,
154
- isPremium: true,
155
- });
156
-
157
- expect(status.isPremium).toBe(true);
158
- });
159
-
160
- it('should reject invalid premium status', () => {
161
- expect(() => {
162
- SubscriptionStatus.create({
163
- type: 'premium',
164
- isActive: false,
165
- isPremium: true,
166
- });
167
- }).toThrow();
168
- });
169
- });
170
- ```
171
-
172
- ## Related
5
+ ## Location
6
+
7
+ `src/domain/entities/`
8
+
9
+ ## Strategy
10
+
11
+ Domain entities represent the core business concepts and rules of the subscription system. They are framework-agnostic and contain only business logic, ensuring pure domain modeling.
12
+
13
+ ## Restrictions
14
+
15
+ ### REQUIRED
16
+
17
+ - MUST validate themselves on creation
18
+ - MUST remain immutable after creation
19
+ - MUST encapsulate business logic internally
20
+ - MUST use value objects for complex attributes
21
+ - MUST be framework-agnostic
22
+
23
+ ### PROHIBITED
24
+
25
+ - MUST NOT have framework dependencies
26
+ - MUST NOT expose internal state directly
27
+ - MUST NOT allow direct state modification
28
+ - MUST NOT contain infrastructure concerns
29
+
30
+ ### CRITICAL
31
+
32
+ - Always validate invariants to ensure valid state
33
+ - Prevent direct state modification through immutability
34
+ - Keep business rules encapsulated within entities
35
+ - Maintain purity - no external dependencies
36
+
37
+ ## AI Agent Guidelines
38
+
39
+ When working with domain entities:
40
+ 1. Keep entities pure - no framework dependencies
41
+ 2. Validate invariants - ensure valid state
42
+ 3. Use value objects - for complex attributes
43
+ 4. Encapsulate logic - keep business rules inside entities
44
+ 5. Make immutable - prevent direct state modification
45
+
46
+ ## Related Documentation
173
47
 
174
48
  - [Value Objects](../value-objects/README.md)
175
49
  - [Domain Errors](../errors/README.md)
176
- - [Domain Layer](../../README.md)
50
+ - [Domain Layer](../README.md)
@@ -1,4 +1,4 @@
1
- import { timezoneService } from "@umituz/react-native-timezone";
1
+ import { timezoneService } from "@umituz/react-native-design-system";
2
2
 
3
3
  export const SUBSCRIPTION_STATUS = {
4
4
  ACTIVE: 'active',
@@ -2,306 +2,52 @@
2
2
 
3
3
  Domain-specific error types for subscription system.
4
4
 
5
- ## Purpose
5
+ ## Location
6
6
 
7
- Domain errors provide typed, contextual error handling for business logic failures. They make error handling explicit and type-safe.
7
+ `src/domain/errors/`
8
8
 
9
- ## Error Hierarchy
9
+ ## Strategy
10
10
 
11
- ```
12
- Error (JavaScript)
13
- └── SubscriptionError (Domain base)
14
- ├── SubscriptionValidationError
15
- ├── SubscriptionRepositoryError
16
- ├── SubscriptionOperationError
17
- └── InsufficientCreditsError
18
- ```
11
+ Domain errors provide typed, contextual error handling for business logic failures. They make error handling explicit and type-safe, enabling precise error management.
19
12
 
20
- ## Error Types
13
+ ## Restrictions
21
14
 
22
- ### SubscriptionError
15
+ ### REQUIRED
23
16
 
24
- Base error for all subscription-related errors.
17
+ - MUST use specific error types (not generic Error)
18
+ - MUST include contextual information
19
+ - MUST document all error codes
20
+ - MUST handle errors gracefully with user-friendly messages
21
+ - MUST log errors for debugging
22
+ - MUST use type guards for type-safe error handling
25
23
 
26
- ```typescript
27
- class SubscriptionError extends Error {
28
- constructor(
29
- message: string,
30
- public readonly code: string,
31
- public readonly context?: Record<string, any>
32
- ) {
33
- super(message);
34
- this.name = 'SubscriptionError';
35
- }
36
- }
37
- ```
24
+ ### PROHIBITED
38
25
 
39
- ### SubscriptionValidationError
26
+ - MUST NOT swallow errors without handling
27
+ - MUST NOT use generic Error class
28
+ - MUST NOT expose sensitive information in error messages
29
+ - MUST NOT ignore error conditions
40
30
 
41
- Thrown when validation fails.
31
+ ### CRITICAL
42
32
 
43
- ```typescript
44
- throw new SubscriptionValidationError('Invalid user ID');
45
- ```
33
+ - Always handle or rethrow errors
34
+ - Include relevant context in error objects
35
+ - Use type guards to enable type-safe error handling
36
+ - Show user-friendly messages while logging technical details
46
37
 
47
- ### SubscriptionRepositoryError
38
+ ## AI Agent Guidelines
48
39
 
49
- Thrown when repository operations fail.
40
+ When working with domain errors:
41
+ 1. Use specific error types - don't use generic Error
42
+ 2. Include context - add relevant data to errors
43
+ 3. Document error codes - list all possible errors
44
+ 4. Handle gracefully - show user-friendly messages
45
+ 5. Log errors - track for debugging
46
+ 6. Don't swallow errors - always handle or rethrow
47
+ 7. Use type guards - enable type-safe error handling
50
48
 
51
- ```typescript
52
- throw new SubscriptionRepositoryError('Database connection failed');
53
- ```
54
-
55
- ### InsufficientCreditsError
56
-
57
- Thrown when user doesn't have enough credits.
58
-
59
- ```typescript
60
- throw new InsufficientCreditsError(
61
- 'Not enough credits',
62
- {
63
- required: 10,
64
- available: 5,
65
- featureId: 'export',
66
- }
67
- );
68
- ```
69
-
70
- ## Usage
71
-
72
- ### Throwing Errors
73
-
74
- ```typescript
75
- function deductCredits(amount: number) {
76
- if (amount <= 0) {
77
- throw new SubscriptionValidationError(
78
- 'Amount must be positive',
79
- 'INVALID_AMOUNT',
80
- { amount }
81
- );
82
- }
83
-
84
- if (currentBalance < amount) {
85
- throw new InsufficientCreditsError(
86
- 'Insufficient credits',
87
- {
88
- required: amount,
89
- available: currentBalance,
90
- }
91
- );
92
- }
93
- }
94
- ```
95
-
96
- ### Catching Errors
97
-
98
- ```typescript
99
- try {
100
- await purchasePackage(packageToPurchase);
101
- } catch (error) {
102
- if (error instanceof InsufficientCreditsError) {
103
- console.log(`Need ${error.context.required} credits`);
104
- showPaywall();
105
- } else if (error instanceof SubscriptionValidationError) {
106
- console.error('Validation error:', error.message);
107
- } else if (error instanceof SubscriptionError) {
108
- console.error('Subscription error:', error.code, error.message);
109
- } else {
110
- console.error('Unexpected error:', error);
111
- }
112
- }
113
- ```
114
-
115
- ### Type Guards
116
-
117
- ```typescript
118
- function isSubscriptionError(error: unknown): error is SubscriptionError {
119
- return error instanceof SubscriptionError;
120
- }
121
-
122
- function isInsufficientCreditsError(error: unknown): error is InsufficientCreditsError {
123
- return error instanceof InsufficientCreditsError;
124
- }
125
- ```
126
-
127
- ## Error Codes
128
-
129
- | Code | Description |
130
- |------|-------------|
131
- | `INVALID_USER_ID` | User ID is invalid or missing |
132
- | `INVALID_PRODUCT_ID` | Product ID is not recognized |
133
- | `INVALID_AMOUNT` | Amount is invalid (e.g., negative) |
134
- | `INSUFFICIENT_CREDITS` | User doesn't have enough credits |
135
- | `SUBSCRIPTION_EXPIRED` | Subscription has expired |
136
- | `SUBSCRIPTION_NOT_FOUND` | Subscription doesn't exist |
137
- | `REPOSITORY_ERROR` | Database/repository error |
138
- | `NETWORK_ERROR` | Network connectivity issue |
139
- | `PURCHASE_CANCELLED` | User cancelled purchase |
140
- | `PURCHASE_FAILED` | Purchase operation failed |
141
-
142
- ## Error Context
143
-
144
- Errors can include contextual information:
145
-
146
- ```typescript
147
- interface InsufficientCreditsContext {
148
- required: number;
149
- available: number;
150
- featureId?: string;
151
- currency?: string;
152
- }
153
-
154
- throw new InsufficientCreditsError(
155
- 'Insufficient credits',
156
- {
157
- required: 10,
158
- available: 5,
159
- featureId: 'export',
160
- currency: 'credits',
161
- }
162
- );
163
- ```
164
-
165
- ## Custom Errors
166
-
167
- Create your own domain errors:
168
-
169
- ```typescript
170
- class FeatureAccessError extends SubscriptionError {
171
- constructor(
172
- featureId: string,
173
- public readonly requiredTier: UserTier,
174
- public readonly currentTier: UserTier
175
- ) {
176
- super(
177
- `Feature "${featureId}" requires ${requiredTier} tier`,
178
- 'FEATURE_ACCESS_DENIED',
179
- { featureId, requiredTier, currentTier }
180
- );
181
- this.name = 'FeatureAccessError';
182
- }
183
- }
184
-
185
- // Usage
186
- if (!canAccessFeature('advanced_analytics')) {
187
- throw new FeatureAccessError(
188
- 'advanced_analytics',
189
- 'premium',
190
- userTier
191
- );
192
- }
193
- ```
194
-
195
- ## Error Handling Patterns
196
-
197
- ### 1. Try-Catch with Type Guards
198
-
199
- ```typescript
200
- try {
201
- await executeOperation();
202
- } catch (error) {
203
- if (error instanceof InsufficientCreditsError) {
204
- handleInsufficientCredits(error);
205
- } else if (error instanceof SubscriptionError) {
206
- handleSubscriptionError(error);
207
- } else {
208
- handleUnexpectedError(error);
209
- }
210
- }
211
- ```
212
-
213
- ### 2. Result Type
214
-
215
- ```typescript
216
- type Result<T, E extends Error = Error> =
217
- | { success: true; data: T }
218
- | { success: false; error: E };
219
-
220
- async function deductCredits(
221
- amount: number
222
- ): Promise<Result<number, InsufficientCreditsError>> {
223
- if (currentBalance < amount) {
224
- return {
225
- success: false,
226
- error: new InsufficientCreditsError('...', {...}),
227
- };
228
- }
229
-
230
- return { success: true, data: newBalance };
231
- }
232
-
233
- // Usage
234
- const result = await deductCredits(10);
235
- if (result.success) {
236
- console.log('New balance:', result.data);
237
- } else {
238
- console.error('Error:', result.error.message);
239
- }
240
- ```
241
-
242
- ### 3. Error Boundary
243
-
244
- ```typescript
245
- class SubscriptionErrorBoundary extends React.Component {
246
- state = { hasError: false, error: null };
247
-
248
- static getDerivedStateFromError(error: Error) {
249
- return { hasError: true, error };
250
- }
251
-
252
- componentDidCatch(error: Error, errorInfo: any) {
253
- if (error instanceof SubscriptionError) {
254
- analytics().logEvent('subscription_error', {
255
- code: error.code,
256
- message: error.message,
257
- });
258
- }
259
- }
260
-
261
- render() {
262
- if (this.state.hasError) {
263
- return <ErrorFallback error={this.state.error} />;
264
- }
265
-
266
- return this.props.children;
267
- }
268
- }
269
- ```
270
-
271
- ## Best Practices
272
-
273
- 1. **Use specific error types** - Don't use generic Error
274
- 2. **Include context** - Add relevant data to errors
275
- 3. **Document error codes** - List all possible errors
276
- 4. **Handle gracefully** - Show user-friendly messages
277
- 5. **Log errors** - Track for debugging
278
- 6. **Don't swallow errors** - Always handle or rethrow
279
- 7. **Use type guards** - Enable type-safe error handling
280
-
281
- ## Testing
282
-
283
- ```typescript
284
- describe('InsufficientCreditsError', () => {
285
- it('should create error with context', () => {
286
- const error = new InsufficientCreditsError('Not enough credits', {
287
- required: 10,
288
- available: 5,
289
- });
290
-
291
- expect(error.context.required).toBe(10);
292
- expect(error.context.available).toBe(5);
293
- });
294
-
295
- it('should be instance of SubscriptionError', () => {
296
- const error = new InsufficientCreditsError('...', {...});
297
-
298
- expect(error).toBeInstanceOf(SubscriptionError);
299
- });
300
- });
301
- ```
302
-
303
- ## Related
49
+ ## Related Documentation
304
50
 
305
51
  - [Domain Entities](../entities/README.md)
306
52
  - [Value Objects](../value-objects/README.md)
307
- - [Domain Layer](../../README.md)
53
+ - [Domain Layer](../README.md)