@umituz/react-native-subscription 2.14.98 → 2.14.100

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 (92) hide show
  1. package/README.md +211 -395
  2. package/package.json +1 -1
  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/errors/README.md +33 -287
  9. package/src/domain/value-objects/README.md +43 -179
  10. package/src/domains/README.md +52 -0
  11. package/src/domains/README.md.bak +274 -0
  12. package/src/domains/config/README.md +93 -383
  13. package/src/domains/config/domain/README.md +37 -0
  14. package/src/domains/config/domain/entities/README.md +41 -0
  15. package/src/domains/paywall/README.md +99 -369
  16. package/src/domains/paywall/components/README.md +34 -178
  17. package/src/domains/paywall/entities/README.md +34 -193
  18. package/src/domains/paywall/hooks/README.md +34 -122
  19. package/src/domains/wallet/README.md +34 -275
  20. package/src/domains/wallet/README.md.bak +209 -0
  21. package/src/domains/wallet/domain/README.md +34 -101
  22. package/src/domains/wallet/domain/entities/README.md +34 -115
  23. package/src/domains/wallet/domain/errors/README.md +34 -151
  24. package/src/domains/wallet/infrastructure/README.md +34 -89
  25. package/src/domains/wallet/presentation/components/README.md +34 -224
  26. package/src/domains/wallet/presentation/hooks/README.md +34 -248
  27. package/src/infrastructure/README.md +37 -496
  28. package/src/infrastructure/mappers/README.md +0 -13
  29. package/src/infrastructure/repositories/README.md +74 -360
  30. package/src/infrastructure/services/README.md +95 -370
  31. package/src/presentation/README.md +123 -408
  32. package/src/presentation/README.md.bak +172 -0
  33. package/src/presentation/components/README.md +151 -179
  34. package/src/presentation/components/README.md.bak +217 -0
  35. package/src/presentation/components/details/CreditRow.md +65 -310
  36. package/src/presentation/components/details/DetailRow.md +63 -255
  37. package/src/presentation/components/details/PremiumDetailsCard.md +65 -238
  38. package/src/presentation/components/details/PremiumStatusBadge.md +64 -239
  39. package/src/presentation/components/details/README.md +97 -447
  40. package/src/presentation/components/feedback/PaywallFeedbackModal.md +63 -287
  41. package/src/presentation/components/feedback/README.md +97 -445
  42. package/src/presentation/components/paywall/PaywallModal.md +66 -416
  43. package/src/presentation/components/paywall/README.md +50 -186
  44. package/src/presentation/components/sections/README.md +97 -466
  45. package/src/presentation/components/sections/SubscriptionSection.md +92 -244
  46. package/src/presentation/hooks/README.md +154 -741
  47. package/src/presentation/hooks/useAuthAwarePurchase.md +58 -325
  48. package/src/presentation/hooks/useAuthGate.md +61 -375
  49. package/src/presentation/hooks/useAuthSubscriptionSync.md +66 -370
  50. package/src/presentation/hooks/useCreditChecker.md +73 -378
  51. package/src/presentation/hooks/useCredits.md +74 -313
  52. package/src/presentation/hooks/useCredits.md.bak +231 -0
  53. package/src/presentation/hooks/useCreditsGate.md +66 -318
  54. package/src/presentation/hooks/useDeductCredit.md +96 -156
  55. package/src/presentation/hooks/useDevTestCallbacks.md +63 -394
  56. package/src/presentation/hooks/useFeatureGate.md +105 -150
  57. package/src/presentation/hooks/useFeatureGate.md.bak +284 -0
  58. package/src/presentation/hooks/useInitializeCredits.md +64 -430
  59. package/src/presentation/hooks/usePaywall.md +61 -306
  60. package/src/presentation/hooks/usePaywallOperations.md +64 -458
  61. package/src/presentation/hooks/usePaywallVisibility.md +67 -316
  62. package/src/presentation/hooks/usePremium.md +84 -226
  63. package/src/presentation/hooks/usePremiumGate.md +60 -395
  64. package/src/presentation/hooks/usePremiumWithCredits.md +64 -401
  65. package/src/presentation/hooks/useSubscription.md +66 -422
  66. package/src/presentation/hooks/useSubscriptionDetails.md +65 -410
  67. package/src/presentation/hooks/useSubscriptionGate.md +80 -164
  68. package/src/presentation/hooks/useSubscriptionSettingsConfig.md +66 -346
  69. package/src/presentation/hooks/useSubscriptionStatus.md +66 -396
  70. package/src/presentation/hooks/useUserTier.md +63 -328
  71. package/src/presentation/hooks/useUserTierWithRepository.md +64 -424
  72. package/src/presentation/screens/README.md +48 -190
  73. package/src/presentation/types/README.md +0 -16
  74. package/src/presentation/utils/README.md +0 -21
  75. package/src/revenuecat/README.md +99 -518
  76. package/src/revenuecat/application/README.md +43 -0
  77. package/src/revenuecat/application/ports/README.md +41 -0
  78. package/src/revenuecat/domain/README.md +42 -141
  79. package/src/revenuecat/domain/constants/README.md +41 -0
  80. package/src/revenuecat/domain/entities/README.md +42 -0
  81. package/src/revenuecat/domain/errors/README.md +47 -191
  82. package/src/revenuecat/domain/types/README.md +41 -0
  83. package/src/revenuecat/domain/value-objects/README.md +41 -0
  84. package/src/revenuecat/infrastructure/README.md +41 -0
  85. package/src/revenuecat/infrastructure/config/README.md +32 -23
  86. package/src/revenuecat/infrastructure/handlers/README.md +41 -0
  87. package/src/revenuecat/infrastructure/managers/README.md +34 -42
  88. package/src/revenuecat/infrastructure/services/README.md +42 -0
  89. package/src/revenuecat/infrastructure/utils/README.md +41 -0
  90. package/src/revenuecat/presentation/README.md +42 -0
  91. package/src/revenuecat/presentation/hooks/README.md +29 -35
  92. package/src/utils/README.md +38 -525
@@ -2,457 +2,91 @@
2
2
 
3
3
  TanStack Query mutation hook for initializing credits after purchase.
4
4
 
5
- ## Import
5
+ ## Location
6
6
 
7
- ```typescript
8
- import { useInitializeCredits } from '@umituz/react-native-subscription';
9
- ```
7
+ **Import Path**: `@umituz/react-native-subscription`
10
8
 
11
- ## Signature
9
+ **File**: `src/presentation/hooks/useInitializeCredits.ts`
12
10
 
13
- ```typescript
14
- function useInitializeCredits(params: {
15
- userId: string | undefined;
16
- }): {
17
- initializeCredits: (options?: {
18
- purchaseId?: string;
19
- productId?: string;
20
- }) => Promise<boolean>;
21
- isInitializing: boolean;
22
- }
23
- ```
11
+ **Type**: Hook
24
12
 
25
- ## Parameters
13
+ ## Strategy
26
14
 
27
- | Parameter | Type | Default | Description |
28
- |-----------|------|---------|-------------|
29
- | `userId` | `string \| undefined` | **Required** | User ID for credit initialization |
15
+ ### Credit Initialization Flow
30
16
 
31
- ## Returns
17
+ 1. **User Validation**: Verify user is authenticated before initialization
18
+ 2. **Repository Call**: Call credits repository to initialize credits
19
+ 3. **Duplicate Protection**: Repository prevents duplicate initialization with same purchase ID
20
+ 4. **Loading State**: Track initialization progress with isInitializing flag
21
+ 5. **Error Handling**: Handle and report initialization failures
22
+ 6. **Success Tracking**: Return success boolean for caller to handle
32
23
 
33
- | Property | Type | Description |
34
- |----------|------|-------------|
35
- | `initializeCredits` | `(options?) => Promise<boolean>` | Initialize credits function |
36
- | `isInitializing` | `boolean` | Mutation is in progress |
24
+ ### Integration Points
37
25
 
38
- ## Options
26
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
27
+ - **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
28
+ - **TanStack Query**: For mutation and optimistic updates
29
+ - **Purchase Flow**: Called after successful subscription purchase
39
30
 
40
- | Property | Type | Default | Description |
41
- |-----------|------|---------|-------------|
42
- | `purchaseId` | `string` | `undefined` | Optional purchase/renewal ID |
43
- | `productId` | `string` | `undefined` | Optional product ID |
31
+ ## Restrictions
44
32
 
45
- ## Basic Usage
33
+ ### REQUIRED
46
34
 
47
- ```typescript
48
- function CreditsInitializer() {
49
- const { user } = useAuth();
35
+ - **User ID**: MUST provide valid userId parameter
36
+ - **Authentication**: User MUST be authenticated
37
+ - **Error Handling**: MUST handle initialization failures
38
+ - **Loading State**: MUST show loading indicator during initialization
50
39
 
51
- const { initializeCredits, isInitializing } = useInitializeCredits({
52
- userId: user?.uid,
53
- });
40
+ ### PROHIBITED
54
41
 
55
- const handleInitialize = async () => {
56
- const success = await initializeCredits();
42
+ - **NEVER** initialize credits without valid userId
43
+ - **NEVER** call for unauthenticated users
44
+ - **DO NOT** assume successful initialization (check return value)
45
+ - **DO NOT** call excessively (repository handles duplicates)
57
46
 
58
- if (success) {
59
- Alert.alert('Success', 'Credits initialized successfully');
60
- } else {
61
- Alert.alert('Error', 'Failed to initialize credits');
62
- }
63
- };
47
+ ### CRITICAL SAFETY
64
48
 
65
- return (
66
- <Button
67
- onPress={handleInitialize}
68
- disabled={isInitializing}
69
- title={isInitializing ? 'Initializing...' : 'Initialize Credits'}
70
- />
71
- );
72
- }
73
- ```
49
+ - **ALWAYS** validate userId before initialization
50
+ - **MUST** handle errors gracefully
51
+ - **ALWAYS** check return value
52
+ - **NEVER** rely on side effects without checking success
74
53
 
75
- ## Advanced Usage
54
+ ## AI Agent Guidelines
76
55
 
77
- ### With Purchase ID
56
+ ### When Implementing Credit Initialization
78
57
 
79
- ```typescript
80
- function PurchaseCompletion() {
81
- const { user } = useAuth();
58
+ 1. **Always** validate userId before calling initializeCredits
59
+ 2. **Always** handle loading state
60
+ 3. **Always** check return value
61
+ 4. **Always** provide purchaseId and productId when available
62
+ 5. **Never** initialize credits for unauthenticated users
82
63
 
83
- const { initializeCredits, isInitializing } = useInitializeCredits({
84
- userId: user?.uid,
85
- });
64
+ ### Integration Checklist
86
65
 
87
- const handlePurchaseComplete = async (transaction: PurchaseTransaction) => {
88
- const success = await initializeCredits({
89
- purchaseId: transaction.transactionId,
90
- productId: transaction.productId,
91
- });
66
+ - [ ] Import from correct path: `@umituz/react-native-subscription`
67
+ - [ ] Validate userId is not undefined
68
+ - [ ] Handle isInitializing state
69
+ - [ ] Check return value from initializeCredits
70
+ - [ ] Provide purchaseId when available
71
+ - [ ] Provide productId when available
72
+ - [ ] Test with premium user (no existing credits)
73
+ - [ ] Test with premium user (existing credits)
74
+ - [ ] Test duplicate protection
75
+ - [ ] Test error scenarios
92
76
 
93
- if (success) {
94
- analytics.track('credits_initialized', {
95
- userId: user?.uid,
96
- purchaseId: transaction.transactionId,
97
- });
98
- }
77
+ ### Common Patterns
99
78
 
100
- return success;
101
- };
79
+ 1. **Post-Purchase Init**: Initialize after successful purchase
80
+ 2. **Auto-Init for Premium**: Automatically initialize for premium users without credits
81
+ 3. **Product-Specific Allocation**: Different products provide different credit amounts
82
+ 4. **Retry Logic**: Implement retry mechanism on failure
83
+ 5. **Admin Init**: Manual initialization for admin users
102
84
 
103
- return <PurchaseFlow onComplete={handlePurchaseComplete} />;
104
- }
105
- ```
85
+ ## Related Documentation
106
86
 
107
- ### With Auto-Initialize for Premium
108
-
109
- ```typescript
110
- function PremiumUserSetup() {
111
- const { user } = useAuth();
112
- const { isPremium } = usePremium();
113
- const { credits } = useCredits();
114
-
115
- const { initializeCredits, isInitializing } = useInitializeCredits({
116
- userId: user?.uid,
117
- });
118
-
119
- useEffect(() => {
120
- // Auto-initialize credits for premium users who don't have them yet
121
- if (isPremium && !credits && !isInitializing) {
122
- const init = async () => {
123
- const success = await initializeCredits();
124
- if (success) {
125
- console.log('Credits initialized for premium user');
126
- }
127
- };
128
- init();
129
- }
130
- }, [isPremium, credits]);
131
-
132
- return <YourAppContent />;
133
- }
134
- ```
135
-
136
- ### With Product-Specific Allocations
137
-
138
- ```typescript
139
- function ProductBasedAllocation() {
140
- const { user } = useAuth();
141
-
142
- const { initializeCredits } = useInitializeCredits({
143
- userId: user?.uid,
144
- });
145
-
146
- const handlePurchase = async (productId: string) => {
147
- // Different products provide different credit amounts
148
- const productConfig = {
149
- 'premium_monthly': { credits: 100 },
150
- 'premium_yearly': { credits: 1200 },
151
- 'credits_small': { credits: 50 },
152
- 'credits_large': { credits: 500 },
153
- };
154
-
155
- const config = productConfig[productId];
156
- if (!config) {
157
- Alert.alert('Error', 'Unknown product');
158
- return;
159
- }
160
-
161
- const success = await initializeCredits({
162
- purchaseId: `purchase_${Date.now()}`,
163
- productId,
164
- });
165
-
166
- if (success) {
167
- Alert.alert('Success', `You received ${config.credits} credits!`);
168
- }
169
- };
170
-
171
- return <PackageList onSelectPackage={handlePurchase} />;
172
- }
173
- ```
174
-
175
- ### With Error Handling
176
-
177
- ```typescript
178
- function RobustInitialization() {
179
- const { user } = useAuth();
180
-
181
- const {
182
- initializeCredits,
183
- isInitializing,
184
- } = useInitializeCredits({
185
- userId: user?.uid,
186
- });
187
-
188
- const handleInitialize = async () => {
189
- if (!user?.uid) {
190
- Alert.alert('Error', 'User not authenticated');
191
- return;
192
- }
193
-
194
- try {
195
- const success = await initializeCredits({
196
- purchaseId: `init_${Date.now()}`,
197
- productId: 'premium_subscription',
198
- });
199
-
200
- if (success) {
201
- Alert.alert('Success', 'Credits initialized');
202
- } else {
203
- Alert.alert('Failed', 'Could not initialize credits');
204
- }
205
- } catch (error) {
206
- console.error('Initialization error:', error);
207
- Alert.alert(
208
- 'Error',
209
- 'Failed to initialize credits. Please try again.'
210
- );
211
- }
212
- };
213
-
214
- return (
215
- <Button
216
- onPress={handleInitialize}
217
- disabled={isInitializing}
218
- title="Initialize Credits"
219
- />
220
- );
221
- }
222
- ```
223
-
224
- ### With Retry Logic
225
-
226
- ```typescript
227
- function InitializationWithRetry() {
228
- const { user } = useAuth();
229
-
230
- const { initializeCredits, isInitializing } = useInitializeCredits({
231
- userId: user?.uid,
232
- });
233
-
234
- const handleInitializeWithRetry = async (retries = 3) => {
235
- for (let i = 0; i < retries; i++) {
236
- const success = await initializeCredits();
237
-
238
- if (success) {
239
- Alert.alert('Success', 'Credits initialized');
240
- return true;
241
- }
242
-
243
- // Wait before retry
244
- if (i < retries - 1) {
245
- await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
246
- }
247
- }
248
-
249
- Alert.alert('Failed', 'Could not initialize credits after retries');
250
- return false;
251
- };
252
-
253
- return (
254
- <Button
255
- onPress={() => handleInitializeWithRetry()}
256
- disabled={isInitializing}
257
- title="Initialize (with retry)"
258
- />
259
- );
260
- }
261
- ```
262
-
263
- ## Examples
264
-
265
- ### Post-Purchase Flow
266
-
267
- ```typescript
268
- function PostPurchaseFlow() {
269
- const { user } = useAuth();
270
- const navigation = useNavigation();
271
-
272
- const { initializeCredits, isInitializing } = useInitializeCredits({
273
- userId: user?.uid,
274
- });
275
-
276
- useEffect(() => {
277
- const handlePurchase = async (purchase: any) => {
278
- console.log('Purchase completed:', purchase);
279
-
280
- const success = await initializeCredits({
281
- purchaseId: purchase.transactionId,
282
- productId: purchase.productId,
283
- });
284
-
285
- if (success) {
286
- // Navigate to success screen
287
- navigation.replace('PurchaseSuccess', {
288
- credits: purchase.credits,
289
- });
290
- } else {
291
- // Show error
292
- Alert.alert(
293
- 'Setup Required',
294
- 'Could not initialize credits. Please contact support.'
295
- );
296
- }
297
- };
298
-
299
- const subscription = purchasesEmitter.on('purchase_complete', handlePurchase);
300
-
301
- return () => subscription.remove();
302
- }, []);
303
-
304
- if (isInitializing) {
305
- return (
306
- <View>
307
- <ActivityIndicator size="large" />
308
- <Text>Setting up your credits...</Text>
309
- </View>
310
- );
311
- }
312
-
313
- return <YourAppContent />;
314
- }
315
- ```
316
-
317
- ### Subscription Renewal Handler
318
-
319
- ```typescript
320
- function RenewalHandler() {
321
- const { user } = useAuth();
322
-
323
- const { initializeCredits } = useInitializeCredits({
324
- userId: user?.uid,
325
- });
326
-
327
- useEffect(() => {
328
- const handleRenewal = async (renewalInfo: RenewalEvent) => {
329
- console.log('Subscription renewed:', renewalInfo);
330
-
331
- const success = await initializeCredits({
332
- purchaseId: renewalInfo.renewalId,
333
- productId: renewalInfo.productId,
334
- });
335
-
336
- if (success) {
337
- analytics.track('subscription_renewed', {
338
- userId: user?.uid,
339
- renewalId: renewalInfo.renewalId,
340
- });
341
-
342
- // Notify user
343
- showNotification('Credits Added!', 'Your subscription has renewed');
344
- }
345
- };
346
-
347
- const subscription = subscriptionEmitter.on('renewal', handleRenewal);
348
-
349
- return () => subscription.remove();
350
- }, []);
351
-
352
- return null;
353
- }
354
- ```
355
-
356
- ### Manual Admin Initialization
357
-
358
- ```typescript
359
- function AdminCreditInitializer() {
360
- const { user } = useAuth();
361
- const { isAdmin } = useAdmin();
362
-
363
- const { initializeCredits, isInitializing } = useInitializeCredits({
364
- userId: targetUserId, // Admin can initialize for other users
365
- });
366
-
367
- const handleAdminInit = async () => {
368
- if (!isAdmin) {
369
- Alert.alert('Access Denied', 'Admin access required');
370
- return;
371
- }
372
-
373
- Alert.alert(
374
- 'Confirm Initialization',
375
- 'Initialize credits for this user?',
376
- [
377
- { text: 'Cancel', style: 'cancel' },
378
- {
379
- text: 'Initialize',
380
- onPress: async () => {
381
- const success = await initializeCredits({
382
- purchaseId: `admin_init_${Date.now()}`,
383
- productId: 'admin_grant',
384
- });
385
-
386
- Alert.alert(
387
- success ? 'Success' : 'Failed',
388
- success ? 'Credits initialized' : 'Could not initialize credits'
389
- );
390
- },
391
- },
392
- ]
393
- );
394
- };
395
-
396
- if (!isAdmin) return null;
397
-
398
- return (
399
- <Button
400
- onPress={handleAdminInit}
401
- disabled={isInitializing}
402
- title="Initialize Credits (Admin)"
403
- />
404
- );
405
- }
406
- ```
407
-
408
- ## Development Logging
409
-
410
- In development mode, the hook logs useful information:
411
-
412
- ```typescript
413
- // Initialization starts
414
- [useInitializeCredits] Initializing: { userId: 'user-123', purchaseId: 'purchase-456', productId: 'premium_monthly' }
415
-
416
- // Success
417
- [useInitializeCredits] Success: { credits: 100, purchasedAt: '2024-01-15T10:30:00Z' }
418
-
419
- // Error
420
- [useInitializeCredits] Error: Some error message
421
- ```
422
-
423
- ## Best Practices
424
-
425
- 1. **Validate userId** - Always check user is authenticated
426
- 2. **Provide purchase info** - Include purchaseId and productId when possible
427
- 3. **Handle loading** - Show loading state during initialization
428
- 4. **Track success** - Log successful initializations
429
- 5. **Retry on failure** - Implement retry logic for reliability
430
- 6. **Use duplicate protection** - Repository handles duplicate purchase IDs
431
- 7. **Test scenarios** - Test new purchase, renewal, admin init
432
-
433
- ## Duplicate Protection
434
-
435
- The repository prevents duplicate initialization with the same purchase ID:
436
-
437
- ```typescript
438
- // First call
439
- await initializeCredits({ purchaseId: 'renewal_123', productId: 'premium' });
440
- // Returns: success, credits: 100 ✅
441
-
442
- // Second call with same purchaseId
443
- await initializeCredits({ purchaseId: 'renewal_123', productId: 'premium' });
444
- // Returns: success, credits: 100 (same as before, not added again) ✅
445
- ```
446
-
447
- ## Related Hooks
448
-
449
- - **useCredits** - For accessing credits balance
450
- - **useDeductCredit** - For deducting credits
451
- - **usePremiumWithCredits** - For premium + credits integration
452
- - **useDevTestCallbacks** - For testing credit initialization
453
-
454
- ## See Also
455
-
456
- - [Credits Repository](../../infrastructure/repositories/CreditsRepository.md)
457
- - [Credits Entity](../../../domains/wallet/domain/entities/Credits.md)
458
- - [Credits README](../../../domains/wallet/README.md)
87
+ - **useCredits**: For accessing credits balance
88
+ - **useDeductCredit**: For deducting credits
89
+ - **usePremiumWithCredits**: For premium + credits integration
90
+ - **useDevTestCallbacks**: For testing credit initialization
91
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
92
+ - **Wallet Domain**: `src/domains/wallet/README.md`