@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,449 +2,93 @@
2
2
 
3
3
  Core hook for subscription status management and operations.
4
4
 
5
- ## Import
5
+ ## Location
6
6
 
7
- ```typescript
8
- import { useSubscription } from '@umituz/react-native-subscription';
9
- ```
7
+ **Import Path**: `@umituz/react-native-subscription`
10
8
 
11
- ## Signature
9
+ **File**: `src/presentation/hooks/useSubscription.ts`
12
10
 
13
- ```typescript
14
- function useSubscription(): {
15
- status: SubscriptionStatus | null;
16
- loading: boolean;
17
- error: string | null;
18
- isPremium: boolean;
19
- loadStatus: (userId: string) => Promise<void>;
20
- refreshStatus: (userId: string) => Promise<void>;
21
- activateSubscription: (
22
- userId: string,
23
- productId: string,
24
- expiresAt: string | null,
25
- ) => Promise<void>;
26
- deactivateSubscription: (userId: string) => Promise<void>;
27
- }
28
- ```
11
+ **Type**: Hook
29
12
 
30
- ## Returns
13
+ ## Strategy
31
14
 
32
- | Property | Type | Description |
33
- |----------|------|-------------|
34
- | `status` | `SubscriptionStatus \| null` | Current subscription status object |
35
- | `loading` | `boolean` | Loading state |
36
- | `error` | `string \| null` | Error message if any |
37
- | `isPremium` | `boolean` | Whether user has active subscription |
38
- | `loadStatus` | `(userId) => Promise<void>` | Load subscription status |
39
- | `refreshStatus` | `(userId) => Promise<void>` | Refresh subscription status |
40
- | `activateSubscription` | `(userId, productId, expiresAt) => Promise<void>` | Activate subscription |
41
- | `deactivateSubscription` | `(userId) => Promise<void>` | Deactivate subscription |
15
+ ### Subscription Management Flow
42
16
 
43
- ## Basic Usage
17
+ 1. **Status Retrieval**: Fetch current subscription status from repository
18
+ 2. **State Caching**: Cache status for 5 minutes using TanStack Query
19
+ 3. **Real-time Updates**: Auto-refresh when user auth state changes
20
+ 4. **Manual Operations**: Provide functions for manual activation/deactivation
21
+ 5. **Loading States**: Handle loading and error states properly
22
+ 6. **Refresh Mechanisms**: Support both load and refresh operations
44
23
 
45
- ```typescript
46
- function SubscriptionStatus() {
47
- const { user } = useAuth();
48
- const { status, isPremium, loading, loadStatus } = useSubscription();
24
+ ### Integration Points
49
25
 
50
- useEffect(() => {
51
- if (user?.uid) {
52
- loadStatus(user.uid);
53
- }
54
- }, [user]);
26
+ - **Subscription Repository**: `src/infrastructure/repositories/SubscriptionRepository.ts`
27
+ - **TanStack Query**: For caching and background updates
28
+ - **Auth Context**: Sync with user authentication state
29
+ - **RevenueCat**: For subscription data source
55
30
 
56
- if (loading) return <ActivityIndicator />;
31
+ ## Restrictions
57
32
 
58
- return (
59
- <View>
60
- <Text>Status: {isPremium ? 'Premium' : 'Free'}</Text>
61
- {status && (
62
- <Text>Product: {status.productId}</Text>
63
- )}
64
- </View>
65
- );
66
- }
67
- ```
33
+ ### REQUIRED
68
34
 
69
- ## Advanced Usage
35
+ - **User ID**: MUST provide valid userId for operations
36
+ - **Loading State**: MUST handle loading state in UI
37
+ - **Error Handling**: MUST handle error state
38
+ - **Status Check**: MUST verify isPremium before showing premium features
70
39
 
71
- ### With Auto-Refresh
40
+ ### PROHIBITED
72
41
 
73
- ```typescript
74
- function SubscriptionWithRefresh() {
75
- const { user } = useAuth();
76
- const { status, isPremium, loading, refreshStatus } = useSubscription();
42
+ - **NEVER** assume instant data availability (always check loading state)
43
+ - **NEVER** use for security decisions without server validation
44
+ - **DO NOT** call loadStatus/refreshStatus without userId
45
+ - **DO NOT** activate/deactivate subscriptions without proper validation
77
46
 
78
- useEffect(() => {
79
- if (user?.uid) {
80
- refreshStatus(user.uid);
81
- }
82
- }, [user]);
47
+ ### CRITICAL SAFETY
83
48
 
84
- // Refresh when app comes to foreground
85
- useFocusEffect(
86
- useCallback(() => {
87
- if (user?.uid) {
88
- refreshStatus(user.uid);
89
- }
90
- }, [user])
91
- );
49
+ - **ALWAYS** check loading state before accessing status
50
+ - **NEVER** trust client-side state for security enforcement
51
+ - **MUST** validate userId before all operations
52
+ - **ALWAYS** handle errors gracefully
92
53
 
93
- // Refresh every 5 minutes
94
- useEffect(() => {
95
- const interval = setInterval(() => {
96
- if (user?.uid) {
97
- refreshStatus(user.uid);
98
- }
99
- }, 5 * 60 * 1000);
54
+ ## AI Agent Guidelines
100
55
 
101
- return () => clearInterval(interval);
102
- }, [user]);
56
+ ### When Implementing Subscription Features
103
57
 
104
- if (loading) return <LoadingScreen />;
58
+ 1. **Always** check loading state before rendering subscription data
59
+ 2. **Always** handle error state
60
+ 3. **Always** verify isPremium before showing premium features
61
+ 4. **Always** validate userId before operations
62
+ 5. **Never** use for security decisions without server validation
105
63
 
106
- return (
107
- <View>
108
- <Text>{isPremium ? 'Premium' : 'Free'} User</Text>
109
- </View>
110
- );
111
- }
112
- ```
64
+ ### Integration Checklist
113
65
 
114
- ### With Manual Activation
66
+ - [ ] Import from correct path: `@umituz/react-native-subscription`
67
+ - [ ] Handle loading state
68
+ - [ ] Handle error state
69
+ - [ ] Check isPremium before rendering premium content
70
+ - [ ] Validate userId before operations
71
+ - [ ] Implement refresh mechanism
72
+ - [ ] Test with premium user
73
+ - [ ] Test with free user
74
+ - [ ] Test with guest user
75
+ - [ ] Test offline scenario
115
76
 
116
- ```typescript
117
- function SubscriptionManager() {
118
- const { user } = useAuth();
119
- const {
120
- status,
121
- activateSubscription,
122
- deactivateSubscription,
123
- loading,
124
- } = useSubscription();
77
+ ### Common Patterns
125
78
 
126
- const handleActivate = async () => {
127
- if (!user?.uid) return;
79
+ 1. **Status Display**: Show current subscription status
80
+ 2. **Conditional Rendering**: Show/hide features based on isPremium
81
+ 3. **Manual Refresh**: Provide refresh button for users
82
+ 4. **Auto-refresh**: Refresh on screen focus or app foreground
83
+ 5. **Status Polling**: Periodic refresh for real-time updates
84
+ 6. **Purchase Completion**: Refresh after successful purchase
85
+ 7. **Error Recovery**: Provide retry mechanism on failure
128
86
 
129
- try {
130
- await activateSubscription(
131
- user.uid,
132
- 'premium_monthly',
133
- new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString()
134
- );
135
- Alert.alert('Success', 'Subscription activated');
136
- } catch (error) {
137
- Alert.alert('Error', 'Failed to activate subscription');
138
- }
139
- };
87
+ ## Related Documentation
140
88
 
141
- const handleDeactivate = async () => {
142
- if (!user?.uid) return;
143
-
144
- try {
145
- await deactivateSubscription(user.uid);
146
- Alert.alert('Success', 'Subscription deactivated');
147
- } catch (error) {
148
- Alert.alert('Error', 'Failed to deactivate subscription');
149
- }
150
- };
151
-
152
- return (
153
- <View>
154
- <Text>Status: {status?.type || 'None'}</Text>
155
-
156
- <Button
157
- onPress={handleActivate}
158
- disabled={loading}
159
- title="Activate Subscription"
160
- />
161
-
162
- <Button
163
- onPress={handleDeactivate}
164
- disabled={loading || !status}
165
- title="Deactivate Subscription"
166
- />
167
- </View>
168
- );
169
- }
170
- ```
171
-
172
- ### With Error Handling
173
-
174
- ```typescript
175
- function RobustSubscription() {
176
- const { user } = useAuth();
177
- const { status, error, loading, loadStatus } = useSubscription();
178
-
179
- useEffect(() => {
180
- if (user?.uid) {
181
- loadStatus(user.uid).catch((err) => {
182
- console.error('Failed to load subscription:', err);
183
- });
184
- }
185
- }, [user]);
186
-
187
- useEffect(() => {
188
- if (error) {
189
- Alert.alert(
190
- 'Subscription Error',
191
- error,
192
- [{ text: 'Retry', onPress: () => user && loadStatus(user.uid) }]
193
- );
194
- }
195
- }, [error]);
196
-
197
- if (loading) return <LoadingScreen />;
198
-
199
- return (
200
- <View>
201
- {error ? (
202
- <ErrorBanner message={error} />
203
- ) : (
204
- <SubscriptionDisplay status={status} />
205
- )}
206
- </View>
207
- );
208
- }
209
- ```
210
-
211
- ### With Status Polling
212
-
213
- ```typescript
214
- function PollingSubscription() {
215
- const { user } = useAuth();
216
- const { status, refreshStatus, loading } = useSubscription();
217
-
218
- const [isPolling, setIsPolling] = useState(false);
219
-
220
- useEffect(() => {
221
- if (!user?.uid) return;
222
-
223
- // Initial load
224
- refreshStatus(user.uid);
225
-
226
- // Poll for status updates
227
- const interval = setInterval(async () => {
228
- if (!isPolling) {
229
- setIsPolling(true);
230
- try {
231
- await refreshStatus(user.uid);
232
- } finally {
233
- setIsPolling(false);
234
- }
235
- }
236
- }, 30000); // Every 30 seconds
237
-
238
- return () => clearInterval(interval);
239
- }, [user]);
240
-
241
- return (
242
- <View>
243
- <Text>Status: {status?.type || 'Loading...'}</Text>
244
- {loading && <ActivityIndicator size="small" />}
245
- </View>
246
- );
247
- }
248
- ```
249
-
250
- ## Examples
251
-
252
- ### Complete Subscription Dashboard
253
-
254
- ```typescript
255
- function SubscriptionDashboard() {
256
- const { user } = useAuth();
257
- const {
258
- status,
259
- isPremium,
260
- loading,
261
- error,
262
- refreshStatus,
263
- } = useSubscription();
264
-
265
- useEffect(() => {
266
- if (user?.uid) {
267
- refreshStatus(user.uid);
268
- }
269
- }, [user]);
270
-
271
- useFocusEffect(
272
- useCallback(() => {
273
- if (user?.uid) {
274
- refreshStatus(user.uid);
275
- }
276
- }, [user])
277
- );
278
-
279
- if (loading) {
280
- return <LoadingScreen />;
281
- }
282
-
283
- return (
284
- <ScrollView>
285
- {error && <ErrorBanner message={error} />}
286
-
287
- <SubscriptionCard
288
- status={status}
289
- isPremium={isPremium}
290
- />
291
-
292
- {status && (
293
- <>
294
- <DetailRow
295
- label="Product ID"
296
- value={status.productId}
297
- />
298
- <DetailRow
299
- label="Status"
300
- value={status.isActive ? 'Active' : 'Inactive'}
301
- />
302
- {status.expirationDate && (
303
- <DetailRow
304
- label="Expires"
305
- value={new Date(status.expirationDate).toLocaleDateString()}
306
- />
307
- )}
308
- </>
309
- )}
310
-
311
- <Button
312
- onPress={() => user && refreshStatus(user.uid)}
313
- title="Refresh Status"
314
- />
315
- </ScrollView>
316
- );
317
- }
318
- ```
319
-
320
- ### Subscription State Machine
321
-
322
- ```typescript
323
- function SubscriptionStateMachine() {
324
- const { user } = useAuth();
325
- const { status, loading, isPremium } = useSubscription();
326
-
327
- useEffect(() => {
328
- if (user?.uid) {
329
- loadStatus(user.uid);
330
- }
331
- }, [user]);
332
-
333
- const getState = () => {
334
- if (loading) return 'loading';
335
- if (!status) return 'none';
336
- if (!status.isActive) return 'expired';
337
- if (isPremium) return 'active';
338
- return 'inactive';
339
- };
340
-
341
- const state = getState();
342
-
343
- switch (state) {
344
- case 'loading':
345
- return <LoadingScreen />;
346
- case 'none':
347
- return <EmptyState message="No subscription found" />;
348
- case 'expired':
349
- return <ExpiredState onRenew={() => navigation.navigate('Paywall')} />;
350
- case 'active':
351
- return <PremiumContent />;
352
- default:
353
- return <FreeContent />;
354
- }
355
- }
356
- ```
357
-
358
- ### With Analytics Tracking
359
-
360
- ```typescript
361
- function TrackedSubscription() {
362
- const { user } = useAuth();
363
- const { status, isPremium, loading, loadStatus } = useSubscription();
364
-
365
- const previousStatus = useRef(status);
366
-
367
- useEffect(() => {
368
- if (user?.uid) {
369
- loadStatus(user.uid);
370
- }
371
- }, [user]);
372
-
373
- useEffect(() => {
374
- // Track subscription status changes
375
- if (previousStatus.current?.isActive !== status?.isActive) {
376
- analytics.track('subscription_status_changed', {
377
- from: previousStatus.current?.isActive,
378
- to: status?.isActive,
379
- userId: user?.uid,
380
- });
381
- }
382
-
383
- if (previousStatus.current?.type !== status?.type) {
384
- analytics.track('subscription_type_changed', {
385
- from: previousStatus.current?.type,
386
- to: status?.type,
387
- userId: user?.uid,
388
- });
389
- }
390
-
391
- previousStatus.current = status;
392
- }, [status]);
393
-
394
- if (loading) return <LoadingScreen />;
395
-
396
- return (
397
- <View>
398
- <Text>Status: {isPremium ? 'Premium' : 'Free'}</Text>
399
- </View>
400
- );
401
- }
402
- ```
403
-
404
- ## Best Practices
405
-
406
- 1. **Validate user ID** - Always check userId before operations
407
- 2. **Handle loading** - Show loading states appropriately
408
- 3. **Handle errors** - Display user-friendly error messages
409
- 4. **Refresh on focus** - Update when screen regains focus
410
- 5. **Auto-load** - Load status when user changes
411
- 6. **Track changes** - Monitor status transitions
412
- 7. **Cache wisely** - Don't over-refresh
413
-
414
- ## Common Patterns
415
-
416
- ### Basic Load
417
-
418
- ```typescript
419
- const { status, loadStatus } = useSubscription();
420
- useEffect(() => {
421
- if (user?.uid) loadStatus(user.uid);
422
- }, [user]);
423
- ```
424
-
425
- ### With Refresh
426
-
427
- ```typescript
428
- const { status, refreshStatus } = useSubscription();
429
- const handleRefresh = () => user && refreshStatus(user.uid);
430
- ```
431
-
432
- ### Manual Activation
433
-
434
- ```typescript
435
- const { activateSubscription } = useSubscription();
436
- await activateSubscription(userId, productId, expiresAt);
437
- ```
438
-
439
- ## Related Hooks
440
-
441
- - **usePremium** - Simplified premium checking
442
- - **useSubscriptionStatus** - Detailed subscription status
443
- - **useSubscriptionDetails** - Package and pricing info
444
- - **useUserTier** - Tier information
445
-
446
- ## See Also
447
-
448
- - [Subscription Entity](../../domain/entities/SubscriptionStatus.md)
449
- - [Subscription Service](../../infrastructure/services/SubscriptionService.md)
450
- - [Status Utilities](../../utils/subscriptionUtils.md)
89
+ - **usePremium**: Simplified premium checking
90
+ - **useSubscriptionStatus**: Detailed subscription status
91
+ - **useSubscriptionDetails**: Package and pricing info
92
+ - **useUserTier**: Tier information
93
+ - **Subscription Repository**: `src/infrastructure/repositories/README.md`
94
+ - **Domain Layer**: `src/domain/README.md`