@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,451 +2,91 @@
2
2
 
3
3
  Automatically fetches premium status and provides tier information with repository integration.
4
4
 
5
- ## Import
5
+ ## Location
6
6
 
7
- ```typescript
8
- import { useUserTierWithRepository } from '@umituz/react-native-subscription';
9
- ```
7
+ **Import Path**: `@umituz/react-native-subscription`
10
8
 
11
- ## Signature
9
+ **File**: `src/presentation/hooks/useUserTierWithRepository.ts`
12
10
 
13
- ```typescript
14
- function useUserTierWithRepository(params: {
15
- auth: AuthProvider;
16
- repository: ISubscriptionRepository;
17
- }): {
18
- tier: 'guest' | 'freemium' | 'premium';
19
- isPremium: boolean;
20
- isGuest: boolean;
21
- isAuthenticated: boolean;
22
- userId: string | null;
23
- isLoading: boolean;
24
- error: string | null;
25
- refresh: () => Promise<void>;
26
- }
27
- ```
11
+ **Type**: Hook
28
12
 
29
- ## Parameters
13
+ ## Strategy
30
14
 
31
- | Parameter | Type | Default | Description |
32
- |-----------|------|---------|-------------|
33
- | `auth` | `AuthProvider` | **Required** | Auth provider with user state |
34
- | `repository` | `ISubscriptionRepository` | **Required** | Subscription repository |
15
+ ### Tier Determination with Repository
35
16
 
36
- ## AuthProvider Interface
17
+ 1. **Auth State Check**: Use provided auth provider to check authentication
18
+ 2. **Premium Fetch**: Automatically fetch premium status from repository for authenticated users
19
+ 3. **Tier Assignment**: Assign tier based on auth + subscription (guest/freemium/premium)
20
+ 4. **Abort Control**: Use AbortController to prevent race conditions on rapid user changes
21
+ 5. **Guest Optimization**: Skip repository fetch for guest users (no fetch needed)
22
+ 6. **Real-time Updates**: React to auth state changes
37
23
 
38
- ```typescript
39
- interface AuthProvider {
40
- user: { uid: string } | null;
41
- isGuest: boolean;
42
- isAuthenticated: boolean;
43
- }
44
- ```
24
+ ### Integration Points
45
25
 
46
- ## Returns
26
+ - **Auth Provider**: Custom auth provider with user state
27
+ - **Subscription Repository**: `src/infrastructure/repositories/SubscriptionRepository.ts`
28
+ - **Domain Layer**: `src/domain/entities/README.md`
29
+ - **TanStack Query**: For caching and real-time updates
47
30
 
48
- | Property | Type | Description |
49
- |----------|------|-------------|
50
- | `tier` | `'guest' \| 'freemium' \| 'premium'` | User tier |
51
- | `isPremium` | `boolean` | User has premium access |
52
- | `isGuest` | `boolean` | User is not authenticated |
53
- | `isAuthenticated` | `boolean` | User is authenticated |
54
- | `userId` | `string \| null` | User ID |
55
- | `isLoading` | `boolean` | Premium status is loading |
56
- | `error` | `string \| null` | Error message |
57
- | `refresh` | `() => Promise<void>` | Manually refresh premium status |
31
+ ## Restrictions
58
32
 
59
- ## Basic Usage
33
+ ### REQUIRED
60
34
 
61
- ```typescript
62
- function UserTierDisplay() {
63
- const auth = useAuth(); // Your auth hook
64
- const subscriptionRepository = useSubscriptionRepository();
35
+ - **Auth Provider**: MUST provide valid auth provider object
36
+ - **Repository**: MUST provide subscription repository
37
+ - **Loading State**: MUST handle loading state
38
+ - **Error Handling**: MUST handle error state
65
39
 
66
- const {
67
- tier,
68
- isPremium,
69
- isLoading,
70
- } = useUserTierWithRepository({
71
- auth,
72
- repository: subscriptionRepository,
73
- });
40
+ ### PROHIBITED
74
41
 
75
- if (isLoading) return <ActivityIndicator />;
42
+ - **NEVER** call without valid auth provider
43
+ - **NEVER** call without valid repository
44
+ - **DO NOT** hardcode tier values (use hook return values)
45
+ - **DO NOT** assume instant data availability
76
46
 
77
- return (
78
- <View>
79
- <Text>Tier: {tier.toUpperCase()}</Text>
80
- <Text>Status: {isPremium ? 'Premium' : 'Free'}</Text>
81
- </View>
82
- );
83
- }
84
- ```
47
+ ### CRITICAL SAFETY
85
48
 
86
- ## Advanced Usage
49
+ - **ALWAYS** check loading state before using tier values
50
+ - **NEVER** trust client-side tier for security enforcement
51
+ - **MUST** provide valid auth provider structure
52
+ - **ALWAYS** handle tier transitions gracefully
87
53
 
88
- ### With Custom Auth Provider
54
+ ## AI Agent Guidelines
89
55
 
90
- ```typescript
91
- function WithCustomAuth() {
92
- const authManager = useCustomAuthManager();
56
+ ### When Implementing Tier Determination
93
57
 
94
- const authProvider = {
95
- user: authManager.user ? { uid: authManager.user.id } : null,
96
- isGuest: !authManager.user,
97
- isAuthenticated: !!authManager.user,
98
- };
58
+ 1. **Always** provide valid auth provider with user, isGuest, isAuthenticated
59
+ 2. **Always** provide valid subscription repository
60
+ 3. **Always** handle loading state
61
+ 4. **Always** handle error state
62
+ 5. **Never** use for security decisions without server validation
99
63
 
100
- const { tier, isPremium } = useUserTierWithRepository({
101
- auth: authProvider,
102
- repository: subscriptionRepository,
103
- });
64
+ ### Integration Checklist
104
65
 
105
- return (
106
- <View>
107
- <Badge text={tier} />
108
- {isPremium && <PremiumBadge />}
109
- </View>
110
- );
111
- }
112
- ```
66
+ - [ ] Import from correct path: `@umituz/react-native-subscription`
67
+ - [ ] Provide valid auth provider object
68
+ - [ ] Provide valid subscription repository
69
+ - [ ] Handle loading state
70
+ - [ ] Handle error state
71
+ - [ ] Use refresh() when needed
72
+ - [ ] Test with guest user
73
+ - [ ] Test with freemium user
74
+ - [ ] Test with premium user
75
+ - [ ] Test user switching scenarios
113
76
 
114
- ### With Firebase Auth
77
+ ### Common Patterns
115
78
 
116
- ```typescript
117
- function WithFirebaseAuth() {
118
- const { user } = useFirebaseAuth();
79
+ 1. **Auth Provider Setup**: Use with Firebase, custom auth, or auth library
80
+ 2. **Tier-Based UI**: Show different features based on tier
81
+ 3. **Navigation Guards**: Redirect based on tier requirements
82
+ 4. **Tier Monitoring**: Track tier changes for analytics
83
+ 5. **Manual Refresh**: Call refresh() after subscription changes
119
84
 
120
- const authProvider = useMemo(() => ({
121
- user: user ? { uid: user.uid } : null,
122
- isGuest: !user,
123
- isAuthenticated: !!user,
124
- }), [user]);
85
+ ## Related Documentation
125
86
 
126
- const { tier, isPremium, isLoading } = useUserTierWithRepository({
127
- auth: authProvider,
128
- repository: subscriptionRepository,
129
- });
130
-
131
- if (isLoading) return <LoadingScreen />;
132
-
133
- return <TierBadge tier={tier} />;
134
- }
135
- ```
136
-
137
- ### With Error Handling
138
-
139
- ```typescript
140
- function TierWithErrorHandling() {
141
- const auth = useAuth();
142
-
143
- const {
144
- tier,
145
- error,
146
- isLoading,
147
- refresh,
148
- } = useUserTierWithRepository({
149
- auth,
150
- repository: subscriptionRepository,
151
- });
152
-
153
- useEffect(() => {
154
- if (error) {
155
- console.error('Failed to fetch tier:', error);
156
- // Optionally show error to user
157
- }
158
- }, [error]);
159
-
160
- if (isLoading) return <LoadingScreen />;
161
-
162
- if (error) {
163
- return (
164
- <View>
165
- <Text>Failed to load subscription status</Text>
166
- <Button onPress={refresh} title="Retry" />
167
- </View>
168
- );
169
- }
170
-
171
- return <TierDisplay tier={tier} />;
172
- }
173
- ```
174
-
175
- ### With Manual Refresh
176
-
177
- ```typescript
178
- function TierWithRefresh() {
179
- const auth = useAuth();
180
-
181
- const {
182
- tier,
183
- isLoading,
184
- refresh,
185
- } = useUserTierWithRepository({
186
- auth,
187
- repository: subscriptionRepository,
188
- });
189
-
190
- const handleRefresh = async () => {
191
- await refresh();
192
- Alert.alert('Success', 'Subscription status refreshed');
193
- };
194
-
195
- return (
196
- <View>
197
- <Text>Tier: {tier}</Text>
198
-
199
- <Button
200
- onPress={handleRefresh}
201
- disabled={isLoading}
202
- title="Refresh Status"
203
- />
204
- </View>
205
- );
206
- }
207
- ```
208
-
209
- ### With Loading State
210
-
211
- ```typescript
212
- function TierWithLoading() {
213
- const auth = useAuth();
214
-
215
- const {
216
- tier,
217
- isPremium,
218
- isLoading,
219
- } = useUserTierWithRepository({
220
- auth,
221
- repository: subscriptionRepository,
222
- });
223
-
224
- return (
225
- <View>
226
- <Text>Tier: {tier}</Text>
227
- <Text>Premium: {isPremium ? 'Yes' : 'No'}</Text>
228
-
229
- {isLoading && (
230
- <View style={styles.loadingContainer}>
231
- <ActivityIndicator size="small" />
232
- <Text>Checking subscription...</Text>
233
- </View>
234
- )}
235
- </View>
236
- );
237
- }
238
- ```
239
-
240
- ## Examples
241
-
242
- ### Complete User Profile
243
-
244
- ```typescript
245
- function UserProfile() {
246
- const auth = useAuth();
247
-
248
- const {
249
- tier,
250
- isPremium,
251
- userId,
252
- isLoading,
253
- error,
254
- } = useUserTierWithRepository({
255
- auth,
256
- repository: subscriptionRepository,
257
- });
258
-
259
- if (isLoading) return <LoadingScreen />;
260
-
261
- return (
262
- <ScrollView>
263
- <UserHeader userId={userId} />
264
-
265
- <View style={styles.section}>
266
- <Text style={styles.label}>Account Status</Text>
267
- <TierBadge tier={tier} />
268
- </View>
269
-
270
- {isPremium && (
271
- <View style={styles.section}>
272
- <Text style={styles.label}>Premium Benefits</Text>
273
- <BenefitList />
274
- </View>
275
- )}
276
-
277
- {!isPremium && tier !== 'guest' && (
278
- <View style={styles.section}>
279
- <Button
280
- onPress={() => navigation.navigate('Paywall')}
281
- title="Upgrade to Premium"
282
- />
283
- </View>
284
- )}
285
-
286
- {error && (
287
- <ErrorBanner
288
- message="Failed to load subscription status"
289
- onRetry={() => refresh()}
290
- />
291
- )}
292
- </ScrollView>
293
- );
294
- }
295
- ```
296
-
297
- ### Navigation Guard
298
-
299
- ```typescript
300
- function ProtectedScreen() {
301
- const auth = useAuth();
302
- const navigation = useNavigation();
303
-
304
- const {
305
- tier,
306
- isLoading,
307
- } = useUserTierWithRepository({
308
- auth,
309
- repository: subscriptionRepository,
310
- });
311
-
312
- useEffect(() => {
313
- if (!isLoading && tier !== 'premium') {
314
- navigation.replace('Paywall', {
315
- returnTo: 'ProtectedScreen',
316
- });
317
- }
318
- }, [tier, isLoading]);
319
-
320
- if (isLoading) return <LoadingScreen />;
321
- if (tier !== 'premium') return null;
322
-
323
- return <ProtectedContent />;
324
- }
325
- ```
326
-
327
- ### Conditional Features
328
-
329
- ```typescript
330
- function TierBasedFeatures() {
331
- const auth = useAuth();
332
-
333
- const { tier } = useUserTierWithRepository({
334
- auth,
335
- repository: subscriptionRepository,
336
- });
337
-
338
- return (
339
- <View>
340
- {/* Available to everyone */}
341
- <BasicFeature />
342
-
343
- {/* Available to freemium and premium */}
344
- {(tier === 'freemium' || tier === 'premium') && (
345
- <AuthenticatedFeature />
346
- )}
347
-
348
- {/* Premium only */}
349
- {tier === 'premium' && (
350
- <PremiumFeature />
351
- )}
352
- </View>
353
- );
354
- }
355
- ```
356
-
357
- ### With Analytics
358
-
359
- ```typescript
360
- function TierTracker() {
361
- const auth = useAuth();
362
-
363
- const { tier } = useUserTierWithRepository({
364
- auth,
365
- repository: subscriptionRepository,
366
- });
367
-
368
- const previousTier = useRef(tier);
369
-
370
- useEffect(() => {
371
- if (previousTier.current !== tier) {
372
- analytics.track('tier_changed', {
373
- from: previousTier.current,
374
- to: tier,
375
- timestamp: Date.now(),
376
- });
377
- previousTier.current = tier;
378
- }
379
- }, [tier]);
380
-
381
- return <YourComponent />;
382
- }
383
- ```
384
-
385
- ## How It Works
386
-
387
- ### Automatic Fetching
388
-
389
- ```typescript
390
- // Mount with authenticated user
391
- auth.user = { uid: 'user-123' }
392
- auth.isAuthenticated = true
393
- → Fetch premium status from repository ✅
394
-
395
- // Status returned
396
- tier = 'premium'
397
- isPremium = true
398
- isLoading = false ✅
399
-
400
- // User logs out
401
- auth.user = null
402
- auth.isAuthenticated = false
403
- → No fetch (guest users can't be premium) ✅
404
- tier = 'guest'
405
- isPremium = false ✅
406
- ```
407
-
408
- ### Guest Users
409
-
410
- ```typescript
411
- auth.user = null
412
- auth.isGuest = true
413
- auth.isAuthenticated = false
414
-
415
- // Hook doesn't fetch for guests
416
- tier = 'guest'
417
- isPremium = false
418
- isLoading = false (no fetch needed) ✅
419
- ```
420
-
421
- ### Abort Handling
422
-
423
- The hook uses AbortController for race condition prevention:
424
-
425
- ```typescript
426
- // User changes quickly: A → B → A
427
- // Only the last user's status is set
428
- // Intermediate fetches are aborted ✅
429
- ```
430
-
431
- ## Best Practices
432
-
433
- 1. **Provide valid auth** - Ensure auth provider has correct state
434
- 2. **Handle loading** - Show loading during initial fetch
435
- 3. **Handle errors** - Display error messages and retry option
436
- 4. **Use refresh** - Call refresh when needed (e.g., after purchase)
437
- 5. **Check tier** - Use tier for feature gating
438
- 6. **Test transitions** - Verify guest → freemium → premium flows
439
- 7. **Cache appropriately** - Repository should handle caching
440
-
441
- ## Related Hooks
442
-
443
- - **useUserTier** - Tier logic without repository
444
- - **usePremium** - Premium status checking
445
- - **useAuthGate** - Authentication gating
446
- - **useSubscription** - Subscription details
447
-
448
- ## See Also
449
-
450
- - [User Tier Guide](../../../docs/USER_TIER.md)
451
- - [Repository Pattern](../../infrastructure/repositories/README.md)
452
- - [Tier Utilities](../../utils/tierUtils.md)
87
+ - **useUserTier**: Tier logic without repository
88
+ - **usePremium**: Premium status checking
89
+ - **useAuthGate**: Authentication gating
90
+ - **useSubscription**: Subscription details
91
+ - **Repository Pattern**: `src/infrastructure/repositories/README.md`
92
+ - **User Tier Utils**: `src/utils/README.md`