@umituz/react-native-subscription 2.37.12 → 2.37.14

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 (133) hide show
  1. package/package.json +1 -1
  2. package/src/domains/credits/application/PurchaseMetadataGenerator.ts +1 -1
  3. package/src/domains/credits/application/credit-strategies/CreditAllocationOrchestrator.ts +1 -1
  4. package/src/domains/credits/application/creditDocumentHelpers.ts +0 -14
  5. package/src/domains/credits/presentation/deduct-credit/index.ts +0 -1
  6. package/src/domains/credits/presentation/useCredits.ts +1 -6
  7. package/src/domains/credits/utils/creditValidation.ts +3 -3
  8. package/src/domains/paywall/components/PaywallFeatures.tsx +1 -1
  9. package/src/domains/paywall/hooks/usePaywallActions.ts +1 -1
  10. package/src/domains/revenuecat/core/errors/RevenueCatError.ts +1 -14
  11. package/src/domains/revenuecat/core/errors/RevenueCatErrorHandler.ts +1 -1
  12. package/src/domains/revenuecat/core/types/RevenueCatTypes.ts +3 -3
  13. package/src/domains/revenuecat/infrastructure/services/ConfigurationStateManager.ts +1 -1
  14. package/src/domains/revenuecat/infrastructure/services/RevenueCatInitializer.ts +0 -2
  15. package/src/domains/revenuecat/infrastructure/services/UserSwitchMutex.ts +9 -0
  16. package/src/domains/subscription/application/initializer/index.ts +1 -1
  17. package/src/domains/subscription/core/SubscriptionStatus.ts +4 -10
  18. package/src/domains/subscription/core/SubscriptionStatusHandlers.ts +1 -1
  19. package/src/domains/subscription/infrastructure/handlers/PackageHandler.ts +0 -2
  20. package/src/domains/subscription/infrastructure/hooks/usePurchasePackage.ts +1 -1
  21. package/src/domains/subscription/infrastructure/hooks/useRevenueCatTrialEligibility.ts +1 -2
  22. package/src/domains/subscription/infrastructure/hooks/useSubscriptionQueries.ts +0 -4
  23. package/src/domains/subscription/infrastructure/services/OfferingsFetcher.ts +1 -1
  24. package/src/domains/subscription/infrastructure/services/RestoreHandler.ts +1 -1
  25. package/src/domains/subscription/infrastructure/services/RevenueCatService.ts +1 -2
  26. package/src/domains/subscription/infrastructure/services/revenueCatServiceInstance.ts +0 -4
  27. package/src/domains/subscription/infrastructure/utils/renewal/index.ts +1 -1
  28. package/src/domains/subscription/presentation/components/details/CreditRow.tsx +1 -1
  29. package/src/domains/subscription/presentation/components/details/DetailRow.tsx +1 -1
  30. package/src/domains/subscription/presentation/components/feedback/FeedbackOption.tsx +0 -2
  31. package/src/domains/subscription/presentation/components/feedback/FeedbackTextInput.tsx +1 -1
  32. package/src/domains/subscription/presentation/featureGateRefs.ts +1 -1
  33. package/src/domains/subscription/presentation/screens/components/CreditsList.tsx +2 -2
  34. package/src/domains/subscription/presentation/screens/components/SubscriptionHeader.tsx +0 -2
  35. package/src/domains/subscription/presentation/stores/index.ts +0 -5
  36. package/src/domains/subscription/presentation/stores/purchaseLoadingStore.ts +3 -7
  37. package/src/domains/subscription/presentation/useAuthAwarePurchase.ts +2 -8
  38. package/src/domains/subscription/presentation/useFeatureGate.ts +0 -2
  39. package/src/domains/subscription/presentation/usePaywallVisibility.ts +1 -1
  40. package/src/domains/subscription/utils/authGuards.ts +0 -23
  41. package/src/domains/subscription/utils/syncStatus.ts +1 -1
  42. package/src/domains/wallet/index.ts +0 -112
  43. package/src/domains/wallet/infrastructure/config/walletConfig.ts +1 -23
  44. package/src/domains/wallet/infrastructure/repositories/transaction/CollectionBuilder.ts +1 -1
  45. package/src/domains/wallet/infrastructure/repositories/transaction/index.ts +0 -9
  46. package/src/domains/wallet/presentation/components/BalanceCard.tsx +1 -1
  47. package/src/domains/wallet/presentation/components/TransactionItem.tsx +0 -2
  48. package/src/domains/wallet/presentation/components/TransactionList.tsx +3 -2
  49. package/src/domains/wallet/presentation/hooks/useTransactionHistory.ts +2 -2
  50. package/src/domains/wallet/presentation/hooks/useWallet.ts +2 -2
  51. package/src/shared/application/FeedbackService.ts +2 -2
  52. package/src/shared/infrastructure/SubscriptionEventBus.ts +1 -1
  53. package/src/shared/infrastructure/firestore/collectionUtils.ts +0 -7
  54. package/src/shared/infrastructure/firestore/resultUtils.ts +3 -39
  55. package/src/shared/presentation/layouts/ScreenLayout.tsx +1 -1
  56. package/src/shared/utils/numberUtils.core.ts +0 -27
  57. package/src/shared/utils/numberUtils.ts +1 -9
  58. package/src/shared/utils/validators.ts +0 -58
  59. package/src/domains/config/domain/entities/Plan.ts +0 -44
  60. package/src/domains/config/domain/index.ts +0 -2
  61. package/src/domains/config/domain/value-objects/Config.ts +0 -49
  62. package/src/domains/config/index.ts +0 -6
  63. package/src/domains/config/utils/planSelectors.ts +0 -56
  64. package/src/domains/paywall/components/FeatureItem.tsx +0 -50
  65. package/src/domains/paywall/components/FeatureList.tsx +0 -34
  66. package/src/domains/paywall/components/PaywallHeader.tsx +0 -112
  67. package/src/domains/paywall/hooks/usePaywallTranslations.ts +0 -78
  68. package/src/domains/paywall/hooks/useSubscriptionModal.ts +0 -45
  69. package/src/domains/paywall/index.ts +0 -13
  70. package/src/domains/revenuecat/core/constants/RevenueCatConstants.ts +0 -201
  71. package/src/domains/revenuecat/core/constants/index.ts +0 -5
  72. package/src/domains/revenuecat/core/customerInfoHelpers.ts +0 -21
  73. package/src/domains/revenuecat/core/index.ts +0 -7
  74. package/src/domains/revenuecat/index.ts +0 -7
  75. package/src/domains/revenuecat/infrastructure/index.ts +0 -5
  76. package/src/domains/revenuecat/infrastructure/services/index.ts +0 -7
  77. package/src/domains/subscription/infrastructure/hooks/customer-info/index.ts +0 -2
  78. package/src/domains/subscription/infrastructure/hooks/customer-info/types.ts +0 -9
  79. package/src/domains/subscription/infrastructure/hooks/customer-info/useCustomerInfo.ts +0 -52
  80. package/src/domains/subscription/infrastructure/hooks/useInitializeSubscription.ts +0 -30
  81. package/src/domains/subscription/infrastructure/hooks/usePaywallFlow.ts +0 -78
  82. package/src/domains/subscription/infrastructure/hooks/useRevenueCat.ts +0 -119
  83. package/src/domains/subscription/presentation/components/feedback/FeedbackConstants.ts +0 -6
  84. package/src/domains/subscription/presentation/screens/components/SubscriptionActions.tsx +0 -56
  85. package/src/domains/subscription/utils/dateFormatters.ts +0 -28
  86. package/src/domains/wallet/domain/entities/CreditCost.ts +0 -45
  87. package/src/domains/wallet/domain/entities/README.md +0 -41
  88. package/src/domains/wallet/domain/errors/README.md +0 -40
  89. package/src/domains/wallet/domain/errors/WalletError.ts +0 -17
  90. package/src/domains/wallet/domain/errors/WalletError.types.ts +0 -30
  91. package/src/domains/wallet/domain/errors/WalletErrorClasses.ts +0 -82
  92. package/src/domains/wallet/domain/errors/WalletErrorFactory.ts +0 -24
  93. package/src/domains/wallet/domain/errors/WalletErrorMessages.ts +0 -17
  94. package/src/domains/wallet/domain/types/credit-cost.types.ts +0 -86
  95. package/src/domains/wallet/domain/types/index.ts +0 -33
  96. package/src/domains/wallet/domain/types/wallet.types.ts +0 -50
  97. package/src/domains/wallet/infrastructure/services/product-metadata/CacheManager.ts +0 -30
  98. package/src/domains/wallet/infrastructure/services/product-metadata/FirebaseFetcher.ts +0 -17
  99. package/src/domains/wallet/infrastructure/services/product-metadata/ProductMetadataService.ts +0 -57
  100. package/src/domains/wallet/infrastructure/services/product-metadata/ServiceManager.ts +0 -29
  101. package/src/domains/wallet/infrastructure/services/product-metadata/index.ts +0 -7
  102. package/src/domains/wallet/presentation/hooks/index.ts +0 -8
  103. package/src/domains/wallet/presentation/hooks/useProductMetadata.ts +0 -72
  104. package/src/domains/wallet/utils/index.ts +0 -1
  105. package/src/shared/application/ActivationHandler.ts +0 -108
  106. package/src/shared/application/ports/ISubscriptionService.ts +0 -27
  107. package/src/shared/infrastructure/index.ts +0 -6
  108. package/src/shared/infrastructure/react-query/queryInvalidation.ts +0 -46
  109. package/src/shared/presentation/hooks/index.ts +0 -6
  110. package/src/shared/presentation/hooks/useAsyncState.ts +0 -72
  111. package/src/shared/presentation/hooks/useServiceCall.ts +0 -77
  112. package/src/shared/types/ReactTypes.ts +0 -80
  113. package/src/shared/utils/InsufficientCreditsError.ts +0 -32
  114. package/src/shared/utils/Logger.ts +0 -81
  115. package/src/shared/utils/SubscriptionConfig.ts +0 -15
  116. package/src/shared/utils/SubscriptionError.ts +0 -47
  117. package/src/shared/utils/appValidators.ts +0 -38
  118. package/src/shared/utils/arrayUtils.core.ts +0 -81
  119. package/src/shared/utils/arrayUtils.query.ts +0 -118
  120. package/src/shared/utils/arrayUtils.transforms.ts +0 -116
  121. package/src/shared/utils/arrayUtils.ts +0 -19
  122. package/src/shared/utils/errorUtils.ts +0 -32
  123. package/src/shared/utils/index.ts +0 -14
  124. package/src/shared/utils/numberUtils.aggregate.ts +0 -35
  125. package/src/shared/utils/numberUtils.format.ts +0 -42
  126. package/src/shared/utils/numberUtils.math.ts +0 -48
  127. package/src/shared/utils/queryKeyFactory.ts +0 -9
  128. package/src/shared/utils/stringUtils.case.ts +0 -64
  129. package/src/shared/utils/stringUtils.check.ts +0 -65
  130. package/src/shared/utils/stringUtils.format.ts +0 -84
  131. package/src/shared/utils/stringUtils.generate.ts +0 -47
  132. package/src/shared/utils/stringUtils.modify.ts +0 -67
  133. package/src/shared/utils/stringUtils.ts +0 -10
@@ -1,50 +0,0 @@
1
- /**
2
- * Feature Item
3
- * Single feature row with icon
4
- */
5
-
6
- import React from "react";
7
- import { View, StyleSheet } from "react-native";
8
- import { AtomicText, AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
9
-
10
- interface FeatureItemProps {
11
- icon: string;
12
- text: string;
13
- }
14
-
15
- export const FeatureItem: React.FC<FeatureItemProps> = React.memo(({ icon, text }) => {
16
- const tokens = useAppDesignTokens();
17
-
18
- return (
19
- <View style={styles.container}>
20
- <View style={[styles.iconContainer, { backgroundColor: tokens.colors.primaryLight }]}>
21
- <AtomicIcon
22
- name={icon || "checkmark-circle"}
23
- customSize={16}
24
- customColor={tokens.colors.primary}
25
- />
26
- </View>
27
- <AtomicText type="bodyMedium" style={{ color: tokens.colors.textPrimary, flex: 1 }}>
28
- {text}
29
- </AtomicText>
30
- </View>
31
- );
32
- });
33
-
34
- FeatureItem.displayName = "FeatureItem";
35
-
36
- const styles = StyleSheet.create({
37
- container: {
38
- flexDirection: "row",
39
- alignItems: "center",
40
- marginBottom: 12,
41
- },
42
- iconContainer: {
43
- width: 28,
44
- height: 28,
45
- borderRadius: 14,
46
- justifyContent: "center",
47
- alignItems: "center",
48
- marginRight: 12,
49
- },
50
- });
@@ -1,34 +0,0 @@
1
- /**
2
- * Feature List
3
- * List of premium features
4
- */
5
-
6
- import React from "react";
7
- import { View, StyleSheet } from "react-native";
8
- import { FeatureItem } from "./FeatureItem";
9
- import type { SubscriptionFeature } from '../entities/types';
10
-
11
- interface FeatureListProps {
12
- features: SubscriptionFeature[];
13
- }
14
-
15
- export const FeatureList: React.FC<FeatureListProps> = React.memo(({ features }) => {
16
- if (features.length === 0) return null;
17
-
18
- return (
19
- <View style={styles.container}>
20
- {features.map((feature, index) => (
21
- <FeatureItem key={`${feature.icon}-${index}`} icon={feature.icon} text={feature.text} />
22
- ))}
23
- </View>
24
- );
25
- });
26
-
27
- FeatureList.displayName = "FeatureList";
28
-
29
- const styles = StyleSheet.create({
30
- container: {
31
- paddingHorizontal: 24,
32
- marginBottom: 20,
33
- },
34
- });
@@ -1,112 +0,0 @@
1
- /**
2
- * Paywall Header
3
- * Header with background, close button, title and subtitle
4
- */
5
-
6
- import React from "react";
7
- import { View, StyleSheet, TouchableOpacity } from "react-native";
8
-
9
- import {
10
- AtomicText,
11
- AtomicIcon,
12
- useDesignSystemTheme,
13
- useAppDesignTokens,
14
- } from "@umituz/react-native-design-system";
15
-
16
- interface PaywallHeaderProps {
17
- title: string;
18
- subtitle?: string;
19
- onClose: () => void;
20
- }
21
-
22
- export const PaywallHeader: React.FC<PaywallHeaderProps> = React.memo(
23
- ({ title, subtitle, onClose }) => {
24
- const tokens = useAppDesignTokens();
25
- const { themeMode } = useDesignSystemTheme();
26
- const isDark = themeMode === "dark";
27
-
28
- const backgroundColor = isDark
29
- ? tokens.colors.surface
30
- : tokens.colors.primary;
31
-
32
- return (
33
- <View
34
- style={[styles.container, { backgroundColor }]}
35
- >
36
- <TouchableOpacity
37
- onPress={onClose}
38
- style={[styles.closeButton, { backgroundColor: tokens.colors.onPrimary }]}
39
- hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
40
- >
41
- <AtomicIcon
42
- name="close-outline"
43
- size="md"
44
- customColor={isDark ? tokens.colors.textPrimary : tokens.colors.primary}
45
- />
46
- </TouchableOpacity>
47
-
48
- <View style={styles.content}>
49
- <AtomicText
50
- type="headlineLarge"
51
- style={[styles.title, { color: tokens.colors.onPrimary }]}
52
- >
53
- {title}
54
- </AtomicText>
55
- {subtitle && (
56
- <AtomicText
57
- type="bodyLarge"
58
- style={[styles.subtitle, { color: tokens.colors.onPrimary }]}
59
- >
60
- {subtitle}
61
- </AtomicText>
62
- )}
63
- </View>
64
-
65
- <View style={[styles.wave, { backgroundColor: tokens.colors.background }]} />
66
- </View>
67
- );
68
- }
69
- );
70
-
71
- PaywallHeader.displayName = "PaywallHeader";
72
-
73
- const styles = StyleSheet.create({
74
- container: {
75
- paddingTop: 56,
76
- paddingBottom: 36,
77
- paddingHorizontal: 24,
78
- position: "relative",
79
- },
80
- closeButton: {
81
- position: "absolute",
82
- top: 48,
83
- right: 20,
84
- width: 36,
85
- height: 36,
86
- borderRadius: 18,
87
- justifyContent: "center",
88
- alignItems: "center",
89
- zIndex: 10,
90
- },
91
- content: {
92
- alignItems: "center",
93
- },
94
- title: {
95
- fontWeight: "700",
96
- textAlign: "center",
97
- marginBottom: 8,
98
- },
99
- subtitle: {
100
- textAlign: "center",
101
- opacity: 0.9,
102
- },
103
- wave: {
104
- position: "absolute",
105
- bottom: -1,
106
- left: 0,
107
- right: 0,
108
- height: 24,
109
- borderTopLeftRadius: 24,
110
- borderTopRightRadius: 24,
111
- },
112
- });
@@ -1,78 +0,0 @@
1
- import { useMemo } from "react";
2
- import type { PaywallTranslations, PaywallLegalUrls } from "../entities/types";
3
-
4
- type TranslationFunction = (key: string) => string;
5
-
6
- interface PaywallTranslationKeys {
7
- title: string;
8
- subtitle: string;
9
- loadingText: string;
10
- emptyText: string;
11
- purchaseButtonText: string;
12
- restoreButtonText: string;
13
- processingText: string;
14
- privacyText: string;
15
- termsOfServiceText: string;
16
- }
17
-
18
- interface UsePaywallTranslationsParams {
19
- t: TranslationFunction;
20
- keys?: Partial<PaywallTranslationKeys>;
21
- legalUrls: PaywallLegalUrls;
22
- creditsLabel?: string;
23
- }
24
-
25
- interface UsePaywallTranslationsResult {
26
- translations: PaywallTranslations;
27
- legalUrls: PaywallLegalUrls;
28
- creditsLabel: string;
29
- }
30
-
31
- const DEFAULT_KEYS: PaywallTranslationKeys = {
32
- title: "premium.title",
33
- subtitle: "premium.subtitle",
34
- loadingText: "paywall.loading",
35
- emptyText: "paywall.empty",
36
- purchaseButtonText: "paywall.subscribe",
37
- restoreButtonText: "paywall.restore",
38
- processingText: "paywall.processing",
39
- privacyText: "auth.privacyPolicy",
40
- termsOfServiceText: "auth.termsOfService",
41
- };
42
-
43
- export const usePaywallTranslations = ({
44
- t,
45
- keys,
46
- legalUrls,
47
- creditsLabel,
48
- }: UsePaywallTranslationsParams): UsePaywallTranslationsResult => {
49
- const mergedKeys = useMemo(
50
- () => ({ ...DEFAULT_KEYS, ...keys }),
51
- [keys],
52
- );
53
-
54
- const translations: PaywallTranslations = useMemo(
55
- () => ({
56
- title: t(mergedKeys.title),
57
- subtitle: t(mergedKeys.subtitle),
58
- loadingText: t(mergedKeys.loadingText),
59
- emptyText: t(mergedKeys.emptyText),
60
- purchaseButtonText: t(mergedKeys.purchaseButtonText),
61
- restoreButtonText: t(mergedKeys.restoreButtonText),
62
- processingText: t(mergedKeys.processingText),
63
- privacyText: t(mergedKeys.privacyText),
64
- termsOfServiceText: t(mergedKeys.termsOfServiceText),
65
- }),
66
- [t, mergedKeys],
67
- );
68
-
69
- const finalCreditsLabel = creditsLabel ?? t("paywall.credits");
70
-
71
- return {
72
- translations,
73
- legalUrls,
74
- creditsLabel: finalCreditsLabel,
75
- };
76
- };
77
-
78
- export type { UsePaywallTranslationsParams, UsePaywallTranslationsResult };
@@ -1,45 +0,0 @@
1
- import { useState, useCallback } from "react";
2
- import type { PurchasesPackage } from "react-native-purchases";
3
-
4
- interface UseSubscriptionModalProps {
5
- onPurchase: (pkg: PurchasesPackage) => Promise<boolean>;
6
- onRestore: () => Promise<boolean>;
7
- onClose: () => void;
8
- }
9
-
10
- export const useSubscriptionModal = ({
11
- onPurchase,
12
- onRestore,
13
- onClose,
14
- }: UseSubscriptionModalProps) => {
15
- const [selectedPkg, setSelectedPkg] = useState<PurchasesPackage | null>(null);
16
- const [isProcessing, setIsProcessing] = useState(false);
17
-
18
- const handlePurchase = useCallback(async () => {
19
- if (!selectedPkg || isProcessing) return;
20
- setIsProcessing(true);
21
- try {
22
- if (await onPurchase(selectedPkg)) onClose();
23
- } finally {
24
- setIsProcessing(false);
25
- }
26
- }, [selectedPkg, onPurchase, onClose, isProcessing]);
27
-
28
- const handleRestore = useCallback(async () => {
29
- if (isProcessing) return;
30
- setIsProcessing(true);
31
- try {
32
- if (await onRestore()) onClose();
33
- } finally {
34
- setIsProcessing(false);
35
- }
36
- }, [onRestore, onClose, isProcessing]);
37
-
38
- return {
39
- selectedPkg,
40
- setSelectedPkg,
41
- isProcessing,
42
- handlePurchase,
43
- handleRestore,
44
- };
45
- };
@@ -1,13 +0,0 @@
1
- /**
2
- * Paywall Domain
3
- * Complete paywall solution for subscription and credits
4
- */
5
-
6
- // Entities
7
- export * from "./entities/types";
8
-
9
- // Hooks
10
- export * from "./hooks/useSubscriptionModal";
11
- export * from "./hooks/usePaywallActions";
12
- export * from "./hooks/usePaywallTranslations";
13
-
@@ -1,201 +0,0 @@
1
- /**
2
- * RevenueCat Constants
3
- * Error codes, messages, and logging constants
4
- */
5
-
6
- import Purchases from "react-native-purchases";
7
-
8
- export const REVENUECAT_LOG_PREFIX = "[RevenueCat]";
9
-
10
- /**
11
- * RevenueCat Error Code Type
12
- * Re-export for type safety
13
- */
14
- export type PurchasesErrorCode = typeof Purchases.PURCHASES_ERROR_CODE[keyof typeof Purchases.PURCHASES_ERROR_CODE];
15
-
16
- /**
17
- * Error Message Configuration
18
- */
19
- export interface ErrorMessage {
20
- title: string;
21
- message: string;
22
- shouldShowAlert?: boolean;
23
- }
24
-
25
- /**
26
- * Error Code to Enum Mapping
27
- * Maps both string keys and numeric codes to Purchases error enum values
28
- */
29
- const ERROR_CODE_MAP = new Map<string, PurchasesErrorCode>([
30
- ["PURCHASE_CANCELLED_ERROR", Purchases.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR],
31
- ["PURCHASE_NOT_ALLOWED_ERROR", Purchases.PURCHASES_ERROR_CODE.PURCHASE_NOT_ALLOWED_ERROR],
32
- ["PURCHASE_INVALID_ERROR", Purchases.PURCHASES_ERROR_CODE.PURCHASE_INVALID_ERROR],
33
- ["PRODUCT_ALREADY_PURCHASED_ERROR", Purchases.PURCHASES_ERROR_CODE.PRODUCT_ALREADY_PURCHASED_ERROR],
34
- ["PRODUCT_NOT_AVAILABLE_FOR_PURCHASE_ERROR", Purchases.PURCHASES_ERROR_CODE.PRODUCT_NOT_AVAILABLE_FOR_PURCHASE_ERROR],
35
- ["NETWORK_ERROR", Purchases.PURCHASES_ERROR_CODE.NETWORK_ERROR],
36
- ["UNKNOWN_ERROR", Purchases.PURCHASES_ERROR_CODE.UNKNOWN_ERROR],
37
- ["RECEIPT_ALREADY_IN_USE_ERROR", Purchases.PURCHASES_ERROR_CODE.RECEIPT_ALREADY_IN_USE_ERROR],
38
- ["INVALID_CREDENTIALS_ERROR", Purchases.PURCHASES_ERROR_CODE.INVALID_CREDENTIALS_ERROR],
39
- ["UNEXPECTED_BACKEND_RESPONSE_ERROR", Purchases.PURCHASES_ERROR_CODE.UNEXPECTED_BACKEND_RESPONSE_ERROR],
40
- ["CONFIGURATION_ERROR", Purchases.PURCHASES_ERROR_CODE.CONFIGURATION_ERROR],
41
- ["STORE_PROBLEM_ERROR", Purchases.PURCHASES_ERROR_CODE.STORE_PROBLEM_ERROR],
42
- ["PAYMENT_PENDING_ERROR", Purchases.PURCHASES_ERROR_CODE.PAYMENT_PENDING_ERROR],
43
- // Numeric codes as fallback
44
- ["1", Purchases.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR],
45
- ["2", Purchases.PURCHASES_ERROR_CODE.STORE_PROBLEM_ERROR],
46
- ["3", Purchases.PURCHASES_ERROR_CODE.PURCHASE_NOT_ALLOWED_ERROR],
47
- ["4", Purchases.PURCHASES_ERROR_CODE.PURCHASE_INVALID_ERROR],
48
- ["5", Purchases.PURCHASES_ERROR_CODE.PRODUCT_NOT_AVAILABLE_FOR_PURCHASE_ERROR],
49
- ["6", Purchases.PURCHASES_ERROR_CODE.PRODUCT_ALREADY_PURCHASED_ERROR],
50
- ["7", Purchases.PURCHASES_ERROR_CODE.NETWORK_ERROR],
51
- ["8", Purchases.PURCHASES_ERROR_CODE.RECEIPT_ALREADY_IN_USE_ERROR],
52
- ["9", Purchases.PURCHASES_ERROR_CODE.INVALID_CREDENTIALS_ERROR],
53
- ["10", Purchases.PURCHASES_ERROR_CODE.UNEXPECTED_BACKEND_RESPONSE_ERROR],
54
- ["16", Purchases.PURCHASES_ERROR_CODE.CONFIGURATION_ERROR],
55
- ["20", Purchases.PURCHASES_ERROR_CODE.PAYMENT_PENDING_ERROR],
56
- ["0", Purchases.PURCHASES_ERROR_CODE.UNKNOWN_ERROR],
57
- ]);
58
-
59
- /**
60
- * User-friendly error messages mapped by error code enum
61
- * Strategy Pattern: Each error code has its own message configuration
62
- */
63
- const ERROR_MESSAGES_MAP = new Map<PurchasesErrorCode, ErrorMessage>([
64
- [
65
- Purchases.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR,
66
- {
67
- title: "Purchase Cancelled",
68
- message: "The purchase was cancelled.",
69
- shouldShowAlert: false, // Don't show alert for user cancellation
70
- },
71
- ],
72
- [
73
- Purchases.PURCHASES_ERROR_CODE.PURCHASE_NOT_ALLOWED_ERROR,
74
- {
75
- title: "Purchase Not Allowed",
76
- message: "In-app purchases are disabled on this device.",
77
- shouldShowAlert: true,
78
- },
79
- ],
80
- [
81
- Purchases.PURCHASES_ERROR_CODE.PURCHASE_INVALID_ERROR,
82
- {
83
- title: "Invalid Purchase",
84
- message: "The purchase is invalid. Please contact support.",
85
- shouldShowAlert: true,
86
- },
87
- ],
88
- [
89
- Purchases.PURCHASES_ERROR_CODE.PRODUCT_ALREADY_PURCHASED_ERROR,
90
- {
91
- title: "Already Purchased",
92
- message: "You already own this subscription. Restoring your purchase...",
93
- shouldShowAlert: true,
94
- },
95
- ],
96
- [
97
- Purchases.PURCHASES_ERROR_CODE.PRODUCT_NOT_AVAILABLE_FOR_PURCHASE_ERROR,
98
- {
99
- title: "Product Unavailable",
100
- message: "This product is not available for purchase at this time.",
101
- shouldShowAlert: true,
102
- },
103
- ],
104
- [
105
- Purchases.PURCHASES_ERROR_CODE.NETWORK_ERROR,
106
- {
107
- title: "Network Error",
108
- message: "Please check your internet connection and try again.",
109
- shouldShowAlert: true,
110
- },
111
- ],
112
- [
113
- Purchases.PURCHASES_ERROR_CODE.UNKNOWN_ERROR,
114
- {
115
- title: "Unknown Error",
116
- message: "An unexpected error occurred. Please try again.",
117
- shouldShowAlert: true,
118
- },
119
- ],
120
- [
121
- Purchases.PURCHASES_ERROR_CODE.RECEIPT_ALREADY_IN_USE_ERROR,
122
- {
123
- title: "Receipt Already Used",
124
- message: "This receipt is already associated with another account.",
125
- shouldShowAlert: true,
126
- },
127
- ],
128
- [
129
- Purchases.PURCHASES_ERROR_CODE.INVALID_CREDENTIALS_ERROR,
130
- {
131
- title: "Configuration Error",
132
- message: "The app is not configured correctly. Please contact support.",
133
- shouldShowAlert: true,
134
- },
135
- ],
136
- [
137
- Purchases.PURCHASES_ERROR_CODE.UNEXPECTED_BACKEND_RESPONSE_ERROR,
138
- {
139
- title: "Server Error",
140
- message: "The server returned an unexpected response. Please try again later.",
141
- shouldShowAlert: true,
142
- },
143
- ],
144
- [
145
- Purchases.PURCHASES_ERROR_CODE.CONFIGURATION_ERROR,
146
- {
147
- title: "Configuration Error",
148
- message: "RevenueCat is not configured correctly. Please contact support.",
149
- shouldShowAlert: true,
150
- },
151
- ],
152
- [
153
- Purchases.PURCHASES_ERROR_CODE.STORE_PROBLEM_ERROR,
154
- {
155
- title: "Store Error",
156
- message: "There was a problem with the app store. Please try again.",
157
- shouldShowAlert: true,
158
- },
159
- ],
160
- [
161
- Purchases.PURCHASES_ERROR_CODE.PAYMENT_PENDING_ERROR,
162
- {
163
- title: "Payment Pending",
164
- message: "Your payment is still being processed. Please check back later.",
165
- shouldShowAlert: true,
166
- },
167
- ],
168
- ]);
169
-
170
- /**
171
- * Default error message for unknown errors
172
- */
173
- const DEFAULT_ERROR_MESSAGE: ErrorMessage = {
174
- title: "Error",
175
- message: "An error occurred. Please try again.",
176
- shouldShowAlert: true,
177
- };
178
-
179
- /**
180
- * Get error message configuration for a given error code
181
- * Uses Strategy Pattern with Map lookup - O(1) complexity
182
- *
183
- * @param errorCode - Error code string from RevenueCat error
184
- * @returns ErrorMessage configuration
185
- */
186
- export function getErrorMessageForCode(errorCode: string | null | undefined): ErrorMessage {
187
- if (!errorCode) {
188
- return DEFAULT_ERROR_MESSAGE;
189
- }
190
-
191
- // Try to map string code to enum value
192
- const enumCode = ERROR_CODE_MAP.get(errorCode);
193
- if (enumCode) {
194
- const message = ERROR_MESSAGES_MAP.get(enumCode);
195
- if (message) {
196
- return message;
197
- }
198
- }
199
-
200
- return DEFAULT_ERROR_MESSAGE;
201
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * RevenueCat Domain - Constants
3
- */
4
-
5
- export { REVENUECAT_LOG_PREFIX } from "./RevenueCatConstants";
@@ -1,21 +0,0 @@
1
- /**
2
- * Customer Info Helper Functions
3
- * Utilities for extracting data from RevenueCat CustomerInfo objects
4
- */
5
-
6
- import type { CustomerInfo } from "react-native-purchases";
7
-
8
- /**
9
- * Extracts active entitlement IDs from CustomerInfo
10
- * Useful for logging and debugging
11
- *
12
- * @param customerInfo - RevenueCat CustomerInfo object
13
- * @returns Array of active entitlement IDs
14
- *
15
- * @example
16
- * const activeIds = getActiveEntitlementIds(customerInfo);
17
- * console.log("Active entitlements:", activeIds); // ["premium", "pro_features"]
18
- */
19
- export function getActiveEntitlementIds(customerInfo: CustomerInfo): string[] {
20
- return Object.keys(customerInfo.entitlements.active);
21
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * RevenueCat Domain - Core Layer
3
- */
4
-
5
- export * from "./errors";
6
- export * from "./types";
7
- export * from "./constants";
@@ -1,7 +0,0 @@
1
- /**
2
- * RevenueCat Domain
3
- * Bounded Context for RevenueCat SDK Integration
4
- */
5
-
6
- export * from "./core";
7
- export * from "./infrastructure";
@@ -1,5 +0,0 @@
1
- /**
2
- * RevenueCat Domain - Infrastructure Layer
3
- */
4
-
5
- export * from "./services";
@@ -1,7 +0,0 @@
1
- /**
2
- * RevenueCat Domain - Infrastructure Services
3
- * Pure RevenueCat SDK Integration
4
- */
5
-
6
- export * from "./RevenueCatInitializer";
7
- export * from "./RevenueCatInitializer.types";
@@ -1,2 +0,0 @@
1
- export { useCustomerInfo } from "./useCustomerInfo";
2
- export type { UseCustomerInfoResult } from "./types";
@@ -1,9 +0,0 @@
1
- import type { CustomerInfo } from "react-native-purchases";
2
-
3
- export interface UseCustomerInfoResult {
4
- customerInfo: CustomerInfo | null;
5
- loading: boolean;
6
- error: string | null;
7
- refetch: () => Promise<void>;
8
- isFetching: boolean;
9
- }
@@ -1,52 +0,0 @@
1
- /**
2
- * Customer Info Hook
3
- * Fetches customer info without registering a listener
4
- * CustomerInfoListenerManager handles all listener logic
5
- */
6
-
7
- import { useQuery, useQueryClient } from "@umituz/react-native-design-system";
8
- import { useEffect, useRef } from "react";
9
- import Purchases from "react-native-purchases";
10
- import type { UseCustomerInfoResult } from "./types";
11
- import { SUBSCRIPTION_QUERY_KEYS } from "../subscriptionQueryKeys";
12
-
13
- export function useCustomerInfo(): UseCustomerInfoResult {
14
- const queryClient = useQueryClient();
15
- const mountedRef = useRef(true);
16
-
17
- useEffect(() => {
18
- mountedRef.current = true;
19
- return () => {
20
- mountedRef.current = false;
21
- };
22
- }, []);
23
-
24
- const query = useQuery({
25
- queryKey: SUBSCRIPTION_QUERY_KEYS.customerInfo,
26
- queryFn: async () => {
27
- const info = await Purchases.getCustomerInfo();
28
- return info;
29
- },
30
- staleTime: 30 * 1000, // 30 seconds
31
- gcTime: 5 * 60 * 1000, // 5 minutes
32
- refetchOnMount: true,
33
- refetchOnWindowFocus: false,
34
- retry: 2,
35
- });
36
-
37
- // Expose refetch as a method
38
- const refetch = async () => {
39
- if (!mountedRef.current) return;
40
- await queryClient.invalidateQueries({
41
- queryKey: SUBSCRIPTION_QUERY_KEYS.customerInfo,
42
- });
43
- };
44
-
45
- return {
46
- customerInfo: query.data ?? null,
47
- loading: query.isLoading,
48
- error: query.error?.message ?? null,
49
- refetch,
50
- isFetching: query.isFetching,
51
- };
52
- }