@umituz/react-native-subscription 2.14.97 → 2.14.99

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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +461 -0
  3. package/package.json +1 -3
  4. package/src/application/README.md +229 -0
  5. package/src/application/ports/README.md +103 -0
  6. package/src/domain/README.md +402 -0
  7. package/src/domain/constants/README.md +80 -0
  8. package/src/domain/entities/README.md +176 -0
  9. package/src/domain/errors/README.md +307 -0
  10. package/src/domain/value-objects/README.md +186 -0
  11. package/src/domains/README.md +240 -0
  12. package/src/domains/config/README.md +390 -0
  13. package/src/domains/config/domain/README.md +390 -0
  14. package/src/domains/config/domain/entities/README.md +350 -0
  15. package/src/domains/paywall/README.md +371 -0
  16. package/src/domains/paywall/components/PaywallHeader.tsx +8 -11
  17. package/src/domains/paywall/components/README.md +185 -0
  18. package/src/domains/paywall/entities/README.md +199 -0
  19. package/src/domains/paywall/hooks/README.md +129 -0
  20. package/src/domains/wallet/README.md +292 -0
  21. package/src/domains/wallet/domain/README.md +108 -0
  22. package/src/domains/wallet/domain/entities/README.md +122 -0
  23. package/src/domains/wallet/domain/errors/README.md +157 -0
  24. package/src/domains/wallet/infrastructure/README.md +96 -0
  25. package/src/domains/wallet/presentation/components/BalanceCard.tsx +6 -12
  26. package/src/domains/wallet/presentation/components/README.md +231 -0
  27. package/src/domains/wallet/presentation/hooks/README.md +255 -0
  28. package/src/infrastructure/README.md +514 -0
  29. package/src/infrastructure/mappers/README.md +34 -0
  30. package/src/infrastructure/models/README.md +26 -0
  31. package/src/infrastructure/repositories/README.md +385 -0
  32. package/src/infrastructure/services/README.md +374 -0
  33. package/src/presentation/README.md +410 -0
  34. package/src/presentation/components/README.md +183 -0
  35. package/src/presentation/components/details/CreditRow.md +337 -0
  36. package/src/presentation/components/details/DetailRow.md +283 -0
  37. package/src/presentation/components/details/PremiumDetailsCard.md +266 -0
  38. package/src/presentation/components/details/PremiumStatusBadge.md +266 -0
  39. package/src/presentation/components/details/README.md +449 -0
  40. package/src/presentation/components/feedback/PaywallFeedbackModal.md +314 -0
  41. package/src/presentation/components/feedback/README.md +447 -0
  42. package/src/presentation/components/paywall/PaywallModal.md +444 -0
  43. package/src/presentation/components/paywall/README.md +190 -0
  44. package/src/presentation/components/sections/README.md +468 -0
  45. package/src/presentation/components/sections/SubscriptionSection.md +246 -0
  46. package/src/presentation/hooks/README.md +743 -0
  47. package/src/presentation/hooks/useAuthAwarePurchase.md +359 -0
  48. package/src/presentation/hooks/useAuthGate.md +403 -0
  49. package/src/presentation/hooks/useAuthSubscriptionSync.md +398 -0
  50. package/src/presentation/hooks/useCreditChecker.md +407 -0
  51. package/src/presentation/hooks/useCredits.md +342 -0
  52. package/src/presentation/hooks/useCreditsGate.md +346 -0
  53. package/src/presentation/hooks/useDeductCredit.md +176 -0
  54. package/src/presentation/hooks/useDevTestCallbacks.md +422 -0
  55. package/src/presentation/hooks/useFeatureGate.md +157 -0
  56. package/src/presentation/hooks/useInitializeCredits.md +458 -0
  57. package/src/presentation/hooks/usePaywall.md +334 -0
  58. package/src/presentation/hooks/usePaywallOperations.md +486 -0
  59. package/src/presentation/hooks/usePaywallVisibility.md +344 -0
  60. package/src/presentation/hooks/usePremium.md +230 -0
  61. package/src/presentation/hooks/usePremiumGate.md +423 -0
  62. package/src/presentation/hooks/usePremiumWithCredits.md +429 -0
  63. package/src/presentation/hooks/useSubscription.md +450 -0
  64. package/src/presentation/hooks/useSubscriptionDetails.md +438 -0
  65. package/src/presentation/hooks/useSubscriptionGate.md +168 -0
  66. package/src/presentation/hooks/useSubscriptionSettingsConfig.md +374 -0
  67. package/src/presentation/hooks/useSubscriptionStatus.md +424 -0
  68. package/src/presentation/hooks/useUserTier.md +356 -0
  69. package/src/presentation/hooks/useUserTierWithRepository.md +452 -0
  70. package/src/presentation/screens/README.md +194 -0
  71. package/src/presentation/types/README.md +38 -0
  72. package/src/presentation/utils/README.md +52 -0
  73. package/src/revenuecat/README.md +523 -0
  74. package/src/revenuecat/application/README.md +158 -0
  75. package/src/revenuecat/application/ports/README.md +169 -0
  76. package/src/revenuecat/domain/README.md +147 -0
  77. package/src/revenuecat/domain/constants/README.md +183 -0
  78. package/src/revenuecat/domain/entities/README.md +382 -0
  79. package/src/revenuecat/domain/errors/README.md +197 -0
  80. package/src/revenuecat/domain/types/README.md +373 -0
  81. package/src/revenuecat/domain/value-objects/README.md +441 -0
  82. package/src/revenuecat/infrastructure/README.md +50 -0
  83. package/src/revenuecat/infrastructure/config/README.md +40 -0
  84. package/src/revenuecat/infrastructure/handlers/README.md +218 -0
  85. package/src/revenuecat/infrastructure/managers/README.md +49 -0
  86. package/src/revenuecat/infrastructure/services/README.md +325 -0
  87. package/src/revenuecat/infrastructure/utils/README.md +382 -0
  88. package/src/revenuecat/presentation/README.md +184 -0
  89. package/src/revenuecat/presentation/hooks/README.md +56 -0
  90. package/src/utils/README.md +529 -0
@@ -0,0 +1,382 @@
1
+ # RevenueCat Infrastructure Utils
2
+
3
+ Utility functions for RevenueCat operations.
4
+
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
+
380
+ - [RevenueCat Infrastructure](../README.md)
381
+ - [RevenueCat Domain Types](../../domain/types/README.md)
382
+ - [RevenueCat Errors](../../domain/errors/README.md)
@@ -0,0 +1,184 @@
1
+ # RevenueCat Presentation
2
+
3
+ Presentation layer for RevenueCat integration.
4
+
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
+
181
+ - [RevenueCat Integration](../README.md)
182
+ - [RevenueCat Application](../application/README.md)
183
+ - [RevenueCat Infrastructure](../infrastructure/README.md)
184
+ - [RevenueCat Domain](../domain/README.md)
@@ -0,0 +1,56 @@
1
+ # RevenueCat Presentation Hooks
2
+
3
+ React hooks for accessing RevenueCat data and operations.
4
+
5
+ ## Overview
6
+
7
+ This directory contains React hooks that expose RevenueCat functionality to the presentation layer.
8
+
9
+ ## Contents
10
+
11
+ - **useCustomerInfo.ts** - Hook for accessing RevenueCat customer info
12
+ - **useSubscriptionPackages.ts** - Hook for accessing subscription packages/offering
13
+
14
+ ## Key Hooks
15
+
16
+ ### useCustomerInfo
17
+
18
+ Access RevenueCat customer information including entitlements.
19
+
20
+ ```typescript
21
+ function useCustomerInfo() {
22
+ const { customerInfo, isLoading } = useCustomerInfo();
23
+
24
+ return (
25
+ <View>
26
+ <Text>Entitlements: {Object.keys(customerInfo.entitlements.active).join(', ')}</Text>
27
+ </View>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ### useSubscriptionPackages
33
+
34
+ Access available subscription packages from current offering.
35
+
36
+ ```typescript
37
+ function PackageList() {
38
+ const { packages, isLoading } = useSubscriptionPackages();
39
+
40
+ if (isLoading) return <Loading />;
41
+
42
+ return (
43
+ <View>
44
+ {packages.map(pkg => (
45
+ <PackageCard key={pkg.identifier} package={pkg} />
46
+ ))}
47
+ </View>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ## Related
53
+
54
+ - [Main Hooks](../../../presentation/hooks/README.md)
55
+ - [Domain](../../domain/README.md)
56
+ - [Services](../infrastructure/services/README.md)