@umituz/react-native-subscription 2.14.99 → 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 -394
  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 +50 -238
  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 +23 -376
  14. package/src/domains/config/domain/entities/README.md +34 -343
  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 +0 -76
  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 +35 -150
  77. package/src/revenuecat/application/ports/README.md +34 -162
  78. package/src/revenuecat/domain/README.md +42 -141
  79. package/src/revenuecat/domain/constants/README.md +34 -176
  80. package/src/revenuecat/domain/entities/README.md +34 -374
  81. package/src/revenuecat/domain/errors/README.md +47 -191
  82. package/src/revenuecat/domain/types/README.md +34 -366
  83. package/src/revenuecat/domain/value-objects/README.md +34 -434
  84. package/src/revenuecat/infrastructure/README.md +34 -43
  85. package/src/revenuecat/infrastructure/config/README.md +32 -23
  86. package/src/revenuecat/infrastructure/handlers/README.md +34 -211
  87. package/src/revenuecat/infrastructure/managers/README.md +34 -42
  88. package/src/revenuecat/infrastructure/services/README.md +35 -318
  89. package/src/revenuecat/infrastructure/utils/README.md +34 -375
  90. package/src/revenuecat/presentation/README.md +34 -176
  91. package/src/revenuecat/presentation/hooks/README.md +29 -35
  92. package/src/utils/README.md +38 -525
@@ -1,382 +1,41 @@
1
1
  # RevenueCat Infrastructure Utils
2
2
 
3
+ ## Location
3
4
  Utility functions for RevenueCat operations.
4
5
 
5
- ## Overview
6
-
7
- This directory contains utility functions for common RevenueCat operations including error mapping, data transformation, and validation.
8
-
9
- ## Utilities
10
-
11
- ### Error Mapping
12
-
13
- Convert RevenueCat SDK errors to domain errors.
14
-
15
- ```typescript
16
- function mapRevenueCatError(error: PurchasesError): DomainError {
17
- switch (error.code) {
18
- case 'PURCHASE_CANCELLED':
19
- return {
20
- code: 'PURCHASE_CANCELLED',
21
- message: 'Purchase was cancelled',
22
- userMessage: 'You cancelled the purchase',
23
- };
24
-
25
- case 'NETWORK_ERROR':
26
- return {
27
- code: 'NETWORK_ERROR',
28
- message: 'Network error occurred',
29
- userMessage: 'Please check your internet connection',
30
- };
31
-
32
- case 'INVALID_CREDENTIALS_ERROR':
33
- return {
34
- code: 'CONFIGURATION_ERROR',
35
- message: 'Invalid RevenueCat credentials',
36
- userMessage: 'Configuration error. Please contact support.',
37
- };
38
-
39
- case 'PRODUCT_NOT_AVAILABLE_FOR_PURCHASE':
40
- return {
41
- code: 'PRODUCT_NOT_AVAILABLE',
42
- message: 'Product not available',
43
- userMessage: 'This product is currently unavailable',
44
- };
45
-
46
- default:
47
- return {
48
- code: 'UNKNOWN_ERROR',
49
- message: error.message || 'Unknown error',
50
- userMessage: 'An error occurred. Please try again.',
51
- };
52
- }
53
- }
54
- ```
55
-
56
- ### Entitlement Extraction
57
-
58
- Extract entitlement information from customer info.
59
-
60
- ```typescript
61
- function extractEntitlementInfo(
62
- customerInfo: CustomerInfo,
63
- entitlementId: string
64
- ): EntitlementInfo | null {
65
- const entitlement = customerInfo.entitlements[entitlementId];
66
-
67
- if (!entitlement) {
68
- return null;
69
- }
70
-
71
- return {
72
- identifier: entitlementId,
73
- isActive: entitlement.isActive,
74
- willRenew: entitlement.willRenew,
75
- periodType: entitlement.periodType,
76
- productId: entitlement.productId,
77
- latestPurchaseDate: entitlement.latestPurchaseDate,
78
- originalPurchaseDate: entitlement.originalPurchaseDate,
79
- expirationDate: entitlement.expirationDate,
80
- renewAt: entitlement.renewAt,
81
- isSandbox: entitlement.isSandbox,
82
- billingIssueDetectedAt: entitlement.billingIssueDetectedAt,
83
- unsubscribeDetectedAt: entitlement.unsubscribeDetectedAt,
84
- store: entitlement.store,
85
- };
86
- }
87
- ```
88
-
89
- ### Package Filtering
90
-
91
- Filter packages by type or criteria.
92
-
93
- ```typescript
94
- function filterPackagesByType(
95
- offering: Offering,
96
- packageType: PackageType
97
- ): Package[] {
98
- return offering.availablePackages.filter(
99
- pkg => pkg.packageType === packageType
100
- );
101
- }
102
-
103
- function getSubscriptionPackages(offering: Offering): Package[] {
104
- return offering.availablePackages.filter(pkg =>
105
- ['monthly', 'annual', 'weekly'].includes(pkg.packageType)
106
- );
107
- }
108
-
109
- function getLifetimePackages(offering: Offering): Package[] {
110
- return offering.availablePackages.filter(pkg =>
111
- pkg.packageType === 'lifetime'
112
- );
113
- }
114
-
115
- function getSinglePurchasePackages(offering: Offering): Package[] {
116
- return offering.availablePackages.filter(pkg =>
117
- pkg.packageType === 'single_purchase'
118
- );
119
- }
120
- ```
121
-
122
- ### Price Formatting
123
-
124
- Format prices for display.
125
-
126
- ```typescript
127
- function formatPrice(
128
- price: Price,
129
- locale?: string
130
- ): string {
131
- return new Intl.NumberFormat(locale, {
132
- style: 'currency',
133
- currency: price.currencyCode,
134
- }).format(price.amount);
135
- }
136
-
137
- function formatPricePerMonth(
138
- package: Package,
139
- locale?: string
140
- ): string {
141
- const { price, product } = package;
142
-
143
- if (product.subscriptionPeriod) {
144
- const { value, unit } = product.subscriptionPeriod;
145
-
146
- // Calculate monthly equivalent
147
- let months = 1;
148
- if (unit === 'week') months = value / 4;
149
- if (unit === 'month') months = value;
150
- if (unit === 'year') months = value * 12;
151
-
152
- const monthlyPrice = price.amount / months;
153
- return formatPrice(
154
- { amount: monthlyPrice, currencyCode: price.currencyCode },
155
- locale
156
- );
157
- }
158
-
159
- return formatPrice(price, locale);
160
- }
161
- ```
162
-
163
- ### Period Formatting
164
-
165
- Format subscription periods.
166
-
167
- ```typescript
168
- function formatPeriod(
169
- period: SubscriptionPeriod,
170
- locale = 'en-US'
171
- ): string {
172
- const formatter = new Intl.RelativeTimeFormat(locale, {
173
- numeric: 'always',
174
- });
175
- return formatter.format(period.value, period.unit);
176
- }
177
-
178
- function getPeriodInMonths(period: SubscriptionPeriod): number {
179
- switch (period.unit) {
180
- case 'day': return period.value / 30;
181
- case 'week': return period.value / 4;
182
- case 'month': return period.value;
183
- case 'year': return period.value * 12;
184
- }
185
- }
186
-
187
- function getPeriodInDays(period: SubscriptionPeriod): number {
188
- switch (period.unit) {
189
- case 'day': return period.value;
190
- case 'week': return period.value * 7;
191
- case 'month': return period.value * 30;
192
- case 'year': return period.value * 365;
193
- }
194
- }
195
- ```
196
-
197
- ### Subscription Status
198
-
199
- Determine subscription status from entitlement.
200
-
201
- ```typescript
202
- function getSubscriptionStatus(
203
- entitlement: EntitlementInfo | null
204
- ): SubscriptionStatus {
205
- if (!entitlement || !entitlement.isActive) {
206
- return 'expired';
207
- }
208
-
209
- if (entitlement.billingIssueDetectedAt) {
210
- return 'in_billing_retry';
211
- }
212
-
213
- if (entitlement.unsubscribeDetectedAt && !entitlement.willRenew) {
214
- return 'cancelled';
215
- }
216
-
217
- return 'active';
218
- }
219
-
220
- function getSubscriptionStatusType(
221
- entitlement: EntitlementInfo | null
222
- ): 'active' | 'expired' | 'canceled' | 'none' {
223
- if (!entitlement) {
224
- return 'none';
225
- }
226
-
227
- if (!entitlement.isActive) {
228
- return 'expired';
229
- }
230
-
231
- if (entitlement.unsubscribeDetectedAt && !entitlement.willRenew) {
232
- return 'canceled';
233
- }
234
-
235
- return 'active';
236
- }
237
- ```
238
-
239
- ### Validation
240
-
241
- Validate RevenueCat data.
242
-
243
- ```typescript
244
- function isValidEntitlementId(id: string): boolean {
245
- const validIds = ['premium', 'pro', 'lifetime'];
246
- return validIds.includes(id);
247
- }
248
-
249
- function isValidOffering(offering: Offering | null): boolean {
250
- return (
251
- offering !== null &&
252
- offering.availablePackages.length > 0
253
- );
254
- }
255
-
256
- function isValidPackage(pkg: Package | null): boolean {
257
- return (
258
- pkg !== null &&
259
- !!pkg.identifier &&
260
- !!pkg.product &&
261
- !!pkg.price
262
- );
263
- }
264
- ```
265
-
266
- ### Debug Helpers
267
-
268
- Helper functions for debugging.
269
-
270
- ```typescript
271
- function logCustomerInfo(info: CustomerInfo): void {
272
- if (__DEV__) {
273
- console.log('[RevenueCat] Customer Info:', {
274
- userId: info.originalAppUserId,
275
- activeSubscriptions: info.activeSubscriptions,
276
- allPurchasedProductIds: info.allPurchasedProductIds,
277
- entitlements: Object.keys(info.entitlements),
278
- });
279
- }
280
- }
281
-
282
- function logPurchaseResult(result: PurchaseResult): void {
283
- if (__DEV__) {
284
- console.log('[RevenueCat] Purchase Result:', {
285
- transactionId: result.transaction?.transactionIdentifier,
286
- productId: result.transaction?.productIdentifier,
287
- hasPremium: !!result.customerInfo.entitlements.premium?.isActive,
288
- });
289
- }
290
- }
291
-
292
- function logError(error: PurchasesError): void {
293
- if (__DEV__) {
294
- console.error('[RevenueCat] Error:', {
295
- code: error.code,
296
- message: error.message,
297
- readableMessage: error.readableErrorMessage,
298
- });
299
- }
300
- }
301
- ```
302
-
303
- ## Usage Examples
304
-
305
- ### Using Error Mapping
306
-
307
- ```typescript
308
- import { mapRevenueCatError } from './utils';
309
-
310
- try {
311
- const result = await purchasePackage(pkg);
312
- } catch (error) {
313
- const domainError = mapRevenueCatError(error);
314
-
315
- // Show user-friendly message
316
- Alert.alert('Error', domainError.userMessage);
317
-
318
- // Log technical details
319
- console.error(domainError.message);
320
- }
321
- ```
322
-
323
- ### Extracting Entitlement Info
324
-
325
- ```typescript
326
- import { extractEntitlementInfo } from './utils';
327
-
328
- const customerInfo = await getCustomerInfo();
329
- const premium = extractEntitlementInfo(customerInfo, 'premium');
330
-
331
- if (premium?.isActive) {
332
- console.log('Premium active until', premium.expirationDate);
333
- }
334
- ```
335
-
336
- ### Filtering Packages
337
-
338
- ```typescript
339
- import { filterPackagesByType, getSubscriptionPackages } from './utils';
340
-
341
- const offering = await getOfferings();
342
- const monthlyPackages = filterPackagesByType(offering.current, 'monthly');
343
- const allSubscriptions = getSubscriptionPackages(offering.current);
344
- ```
345
-
346
- ### Formatting Prices
347
-
348
- ```typescript
349
- import { formatPrice, formatPricePerMonth } from './utils';
350
-
351
- // Standard price
352
- const priceString = formatPrice(pkg.price, 'en-US'); // '$9.99'
353
- const priceStringTR = formatPrice(pkg.price, 'tr-TR'); // '9,99 $'
354
-
355
- // Per month (for annual)
356
- const perMonth = formatPricePerMonth(annualPackage, 'en-US'); // '$8.33/mo'
357
- ```
358
-
359
- ### Getting Subscription Status
360
-
361
- ```typescript
362
- import { getSubscriptionStatus, getSubscriptionStatusType } from './utils';
363
-
364
- const entitlement = customerInfo.entitlements.premium;
365
- const status = getSubscriptionStatus(entitlement); // 'active'
366
- const statusType = getSubscriptionStatusType(entitlement); // 'active'
367
- ```
368
-
369
- ## Best Practices
370
-
371
- 1. **Error Handling**: Always use error mapping for user-facing messages
372
- 2. **Type Safety**: Ensure types are validated before use
373
- 3. **Locale**: Respect user locale for formatting
374
- 4. **Null Checks**: Always check for null/undefined values
375
- 5. **Logging**: Use debug helpers in development
376
- 6. **Validation**: Validate data before processing
377
-
378
- ## Related
379
-
6
+ ## Strategy
7
+ This directory contains utility functions for common RevenueCat operations including error mapping, data transformation, validation, and formatting with proper type safety.
8
+
9
+ ## Restrictions
10
+
11
+ ### REQUIRED
12
+ - Must use error mapping for user-facing messages
13
+ - Must ensure types are validated before use
14
+ - Must respect user locale for formatting
15
+ - Must check for null/undefined values
16
+
17
+ ### PROHIBITED
18
+ - DO NOT show SDK errors directly to users
19
+ - DO NOT use data without type validation
20
+ - DO NOT ignore locale settings
21
+ - DO NOT skip null checks
22
+
23
+ ### CRITICAL SAFETY
24
+ - All errors MUST be mapped to domain errors
25
+ - All types MUST be validated before use
26
+ - Locale MUST be respected for formatting
27
+ - Null checks MUST be performed consistently
28
+
29
+ ## AI Agent Guidelines
30
+ 1. Always map SDK errors to domain errors for user-facing messages
31
+ 2. Ensure type safety by validating types before use
32
+ 3. Respect user locale when formatting prices and periods
33
+ 4. Always check for null/undefined values before processing
34
+ 5. Use debug helpers in development for troubleshooting
35
+ 6. Validate all data before processing
36
+ 7. Test utility functions with edge cases
37
+
38
+ ## Related Documentation
380
39
  - [RevenueCat Infrastructure](../README.md)
381
40
  - [RevenueCat Domain Types](../../domain/types/README.md)
382
41
  - [RevenueCat Errors](../../domain/errors/README.md)
@@ -1,183 +1,41 @@
1
1
  # RevenueCat Presentation
2
2
 
3
+ ## Location
3
4
  Presentation layer for RevenueCat integration.
4
5
 
5
- ## Overview
6
-
7
- This directory contains React hooks, components, and utilities for integrating RevenueCat functionality into the UI layer.
8
-
9
- ## Components
10
-
11
- This directory may contain:
12
-
13
- ### Hooks
14
-
15
- Custom React hooks for RevenueCat operations.
16
-
17
- **Potential Hooks:**
18
- - `useRevenueCatCustomerInfo` - Fetch and monitor customer info
19
- - `useRevenueCatOfferings` - Fetch available offerings
20
- - `useRevenueCatPurchase` - Handle purchase flow
21
- - `useRevenueCatEntitlement` - Check entitlement status
22
-
23
- **Example:**
24
- ```typescript
25
- function useRevenueCatOfferings() {
26
- const [offerings, setOfferings] = useState<Offerings | null>(null);
27
- const [loading, setLoading] = useState(true);
28
- const [error, setError] = useState<Error | null>(null);
29
-
30
- useEffect(() => {
31
- loadOfferings();
32
- }, []);
33
-
34
- const loadOfferings = async () => {
35
- try {
36
- setLoading(true);
37
- const service = getRevenueCatService();
38
- const result = await service.getOfferings();
39
- setOfferings(result);
40
- } catch (err) {
41
- setError(err as Error);
42
- } finally {
43
- setLoading(false);
44
- }
45
- };
46
-
47
- return { offerings, loading, error, refetch: loadOfferings };
48
- }
49
- ```
50
-
51
- ### Components
52
-
53
- React components for displaying RevenueCat data.
54
-
55
- **Potential Components:**
56
- - `PackageList` - Display available packages
57
- - `PackageCard` - Display individual package
58
- - `EntitlementBadge` - Show entitlement status
59
- - `SubscriptionStatus` - Display subscription status
60
-
61
- **Example:**
62
- ```typescript
63
- function PackageCard({
64
- package,
65
- onPress,
66
- highlight = false,
67
- }: {
68
- package: Package;
69
- onPress: () => void;
70
- highlight?: boolean;
71
- }) {
72
- return (
73
- <TouchableOpacity
74
- onPress={onPress}
75
- style={[styles.card, highlight && styles.highlight]}
76
- >
77
- <Text style={styles.title}>
78
- {package.product.title}
79
- </Text>
80
- <Text style={styles.price}>
81
- {package.localizedPriceString}
82
- </Text>
83
- {package.product.description && (
84
- <Text style={styles.description}>
85
- {package.product.description}
86
- </Text>
87
- )}
88
- </TouchableOpacity>
89
- );
90
- }
91
- ```
92
-
93
- ## Usage Patterns
94
-
95
- ### Displaying Offerings
96
-
97
- ```typescript
98
- import { useRevenueCatOfferings } from './hooks/useRevenueCatOfferings';
99
- import { PackageCard } from './components/PackageCard';
100
-
101
- function PremiumPackages() {
102
- const { offerings, loading, error } = useRevenueCatOfferings();
103
-
104
- if (loading) return <LoadingSpinner />;
105
- if (error) return <Error message={error.message} />;
106
- if (!offerings?.current) return <EmptyState />;
107
-
108
- return (
109
- <ScrollView horizontal>
110
- {offerings.current.availablePackages.map(pkg => (
111
- <PackageCard
112
- key={pkg.identifier}
113
- package={pkg}
114
- onPress={() => handlePurchase(pkg)}
115
- highlight={pkg.packageType === 'annual'}
116
- />
117
- ))}
118
- </ScrollView>
119
- );
120
- }
121
- ```
122
-
123
- ### Checking Entitlements
124
-
125
- ```typescript
126
- import { useRevenueCatCustomerInfo } from './hooks/useRevenueCatCustomerInfo';
127
-
128
- function PremiumContent() {
129
- const { customerInfo, loading } = useRevenueCatCustomerInfo();
130
-
131
- if (loading) return <LoadingSpinner />;
132
-
133
- const hasPremium = customerInfo?.entitlements.premium?.isActive ?? false;
134
-
135
- if (!hasPremium) {
136
- return <UpgradePrompt />;
137
- }
138
-
139
- return <PremiumFeatures />;
140
- }
141
- ```
142
-
143
- ### Purchase Flow
144
-
145
- ```typescript
146
- import { useRevenueCatPurchase } from './hooks/useRevenueCatPurchase';
147
-
148
- function PurchaseButton({ package }: { package: Package }) {
149
- const { purchase, purchasing } = useRevenueCatPurchase();
150
-
151
- const handlePurchase = async () => {
152
- const result = await purchase(package);
153
-
154
- if (result.error) {
155
- Alert.alert('Purchase Failed', result.error.message);
156
- } else {
157
- Alert.alert('Success', 'Purchase completed!');
158
- }
159
- };
160
-
161
- return (
162
- <Button onPress={handlePurchase} disabled={purchasing}>
163
- {purchasing ? 'Purchasing...' : 'Subscribe'}
164
- </Button>
165
- );
166
- }
167
- ```
168
-
169
- ## Best Practices
170
-
171
- 1. **Loading States**: Always show loading states during async operations
172
- 2. **Error Handling**: Handle and display errors appropriately
173
- 3. **Optimistic Updates**: Update UI optimistically where possible
174
- 4. **Caching**: Cache customer info and offerings
175
- 5. **Reactivity**: Re-render on entitlement changes
176
- 6. **User Feedback**: Provide clear feedback during purchases
177
- 7. **Validation**: Validate data before displaying
178
-
179
- ## Related
180
-
6
+ ## Strategy
7
+ This directory contains React hooks, components, and utilities for integrating RevenueCat functionality into the UI layer with proper loading states, error handling, and caching.
8
+
9
+ ## Restrictions
10
+
11
+ ### REQUIRED
12
+ - Must show loading states during async operations
13
+ - Must handle and display errors appropriately
14
+ - Must cache customer info and offerings
15
+ - Must re-render on entitlement changes
16
+
17
+ ### PROHIBITED
18
+ - DO NOT skip loading states
19
+ - DO NOT show technical errors to users
20
+ - DO NOT ignore cache invalidation
21
+ - DO NOT prevent re-renders on state changes
22
+
23
+ ### CRITICAL SAFETY
24
+ - All async operations MUST show loading states
25
+ - All errors MUST be handled and displayed appropriately
26
+ - Data MUST be cached appropriately
27
+ - UI MUST re-render on entitlement changes
28
+
29
+ ## AI Agent Guidelines
30
+ 1. Always show loading states during async operations
31
+ 2. Handle and display errors appropriately to users
32
+ 3. Update UI optimistically where possible
33
+ 4. Cache customer info and offerings appropriately
34
+ 5. Re-render on entitlement changes
35
+ 6. Provide clear feedback during purchases
36
+ 7. Validate data before displaying to users
37
+
38
+ ## Related Documentation
181
39
  - [RevenueCat Integration](../README.md)
182
40
  - [RevenueCat Application](../application/README.md)
183
41
  - [RevenueCat Infrastructure](../infrastructure/README.md)