@umituz/react-native-subscription 2.14.47 → 2.14.49

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 (32) hide show
  1. package/package.json +3 -3
  2. package/src/domains/paywall/components/PaywallHeader.tsx +1 -0
  3. package/src/domains/paywall/components/PaywallModal.styles.ts +49 -0
  4. package/src/domains/paywall/components/PaywallModal.tsx +2 -37
  5. package/src/domains/wallet/domain/entities/CreditCost.ts +3 -3
  6. package/src/domains/wallet/infrastructure/repositories/TransactionRepository.ts +11 -20
  7. package/src/domains/wallet/presentation/components/BalanceCard.tsx +4 -3
  8. package/src/domains/wallet/presentation/components/TransactionItem.tsx +4 -3
  9. package/src/domains/wallet/presentation/components/TransactionList.tsx +7 -5
  10. package/src/domains/wallet/presentation/hooks/useWallet.ts +6 -4
  11. package/src/domains/wallet/presentation/screens/WalletScreen.tsx +11 -8
  12. package/src/infrastructure/repositories/CreditsRepository.ts +7 -42
  13. package/src/infrastructure/services/CreditsInitializer.ts +1 -52
  14. package/src/presentation/components/feedback/PaywallFeedbackModal.tsx +1 -0
  15. package/src/presentation/components/sections/SubscriptionSection.tsx +4 -3
  16. package/src/presentation/hooks/useCreditChecker.ts +3 -2
  17. package/src/presentation/hooks/useCredits.ts +4 -3
  18. package/src/presentation/hooks/usePremium.ts +4 -3
  19. package/src/presentation/hooks/useSubscriptionDetails.ts +3 -2
  20. package/src/presentation/hooks/useSubscriptionSettingsConfig.ts +4 -3
  21. package/src/presentation/screens/SubscriptionDetailScreen.tsx +3 -2
  22. package/src/presentation/screens/components/UpgradePrompt.tsx +4 -3
  23. package/src/revenuecat/infrastructure/services/CustomerInfoListenerManager.ts +60 -158
  24. package/src/revenuecat/infrastructure/services/OfferingsFetcher.ts +13 -29
  25. package/src/revenuecat/infrastructure/services/PurchaseHandler.ts +64 -88
  26. package/src/revenuecat/infrastructure/services/RestoreHandler.ts +32 -48
  27. package/src/revenuecat/infrastructure/services/RevenueCatInitializer.ts +90 -219
  28. package/src/revenuecat/infrastructure/services/RevenueCatService.ts +121 -126
  29. package/src/revenuecat/infrastructure/utils/InitializationCache.ts +25 -29
  30. package/src/revenuecat/infrastructure/utils/PremiumStatusSyncer.ts +52 -100
  31. package/src/revenuecat/infrastructure/utils/UserIdProvider.ts +17 -25
  32. package/src/revenuecat/presentation/hooks/usePaywallFlow.ts +9 -8
@@ -4,251 +4,122 @@
4
4
  */
5
5
 
6
6
  import Purchases, { LOG_LEVEL } from "react-native-purchases";
7
- import type { InitializeResult } from '../../application/ports/IRevenueCatService';
8
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
9
- import { getErrorMessage } from '../../domain/types/RevenueCatTypes';
10
- import { resolveApiKey } from '../utils/ApiKeyResolver';
7
+ import type { InitializeResult } from "../../application/ports/IRevenueCatService";
8
+ import type { RevenueCatConfig } from "../../domain/value-objects/RevenueCatConfig";
9
+ import { getErrorMessage } from "../../domain/types/RevenueCatTypes";
10
+ import { resolveApiKey } from "../utils/ApiKeyResolver";
11
11
 
12
12
  export interface InitializerDeps {
13
- config: RevenueCatConfig;
14
- isUsingTestStore: () => boolean;
15
- isInitialized: () => boolean;
16
- getCurrentUserId: () => string | null;
17
- setInitialized: (value: boolean) => void;
18
- setCurrentUserId: (userId: string) => void;
13
+ config: RevenueCatConfig;
14
+ isUsingTestStore: () => boolean;
15
+ isInitialized: () => boolean;
16
+ getCurrentUserId: () => string | null;
17
+ setInitialized: (value: boolean) => void;
18
+ setCurrentUserId: (userId: string) => void;
19
19
  }
20
20
 
21
- // Track if Purchases.configure has been called globally
22
21
  let isPurchasesConfigured = false;
23
22
  let isLogHandlerConfigured = false;
24
23
 
25
- /**
26
- * Configures custom log handler to filter StoreKit 2 internal errors
27
- * These errors occur on simulator when no prior purchases exist
28
- */
29
24
  function configureLogHandler(): void {
30
- if (isLogHandlerConfigured) return;
31
-
32
- Purchases.setLogHandler((logLevel, message) => {
33
- // Filter out StoreKit 2 AppTransaction errors (normal on simulator)
34
- const isAppTransactionError =
35
- message.includes("Purchase was cancelled") ||
36
- message.includes("AppTransaction") ||
37
- message.includes("Couldn't find previous transactions");
38
-
39
- if (isAppTransactionError) {
40
- // Downgrade to debug level - only show in __DEV__
41
- if (__DEV__) {
42
- console.debug("[RevenueCat] (filtered)", message);
43
- }
44
- return;
45
- }
25
+ if (isLogHandlerConfigured) return;
46
26
 
47
- // Normal logging for other messages
48
- switch (logLevel) {
49
- case LOG_LEVEL.VERBOSE:
50
- case LOG_LEVEL.DEBUG:
51
- if (__DEV__) console.debug("[RevenueCat]", message);
52
- break;
53
- case LOG_LEVEL.INFO:
54
- if (__DEV__) console.info("[RevenueCat]", message);
55
- break;
56
- case LOG_LEVEL.WARN:
57
- if (__DEV__) console.warn("[RevenueCat]", message);
58
- break;
59
- case LOG_LEVEL.ERROR:
60
- console.error("[RevenueCat]", message);
61
- break;
62
- }
63
- });
27
+ Purchases.setLogHandler((logLevel, message) => {
28
+ const isAppTransactionError =
29
+ message.includes("Purchase was cancelled") ||
30
+ message.includes("AppTransaction") ||
31
+ message.includes("Couldn't find previous transactions");
64
32
 
65
- isLogHandlerConfigured = true;
66
- }
33
+ if (isAppTransactionError) {
34
+ return;
35
+ }
67
36
 
68
- export async function initializeSDK(
69
- deps: InitializerDeps,
70
- userId: string,
71
- apiKey?: string
72
- ): Promise<InitializeResult> {
73
- if (__DEV__) {
74
- console.log('[DEBUG RevenueCatInitializer] initializeSDK called', {
75
- userId,
76
- hasApiKey: !!apiKey,
77
- isAlreadyConfigured: isPurchasesConfigured,
78
- isInitialized: deps.isInitialized(),
79
- currentUserId: deps.getCurrentUserId(),
37
+ switch (logLevel) {
38
+ case LOG_LEVEL.ERROR:
39
+ break;
40
+ default:
41
+ break;
42
+ }
80
43
  });
81
- }
82
44
 
83
- userId,
84
- hasApiKey: !!apiKey,
85
- isAlreadyConfigured: isPurchasesConfigured,
86
- });
87
-
88
- // Case 1: Already initialized with the same user ID
89
- if (deps.isInitialized() && deps.getCurrentUserId() === userId) {
45
+ isLogHandlerConfigured = true;
46
+ }
90
47
 
91
- try {
92
- const [customerInfo, offerings] = await Promise.all([
93
- Purchases.getCustomerInfo(),
94
- Purchases.getOfferings(),
95
- ]);
96
- const entitlementId = deps.config.entitlementIdentifier;
97
- const hasPremium = !!customerInfo.entitlements.active[entitlementId];
98
- return { success: true, offering: offerings.current, hasPremium };
99
- } catch (error) {
100
- error instanceof Error ? error : new Error(String(error)),
101
- {
102
- packageName: "subscription",
103
- operation: "get_current_state",
104
- userId,
48
+ export async function initializeSDK(
49
+ deps: InitializerDeps,
50
+ userId: string,
51
+ apiKey?: string
52
+ ): Promise<InitializeResult> {
53
+ // Case 1: Already initialized with the same user ID
54
+ if (deps.isInitialized() && deps.getCurrentUserId() === userId) {
55
+ try {
56
+ const [customerInfo, offerings] = await Promise.all([
57
+ Purchases.getCustomerInfo(),
58
+ Purchases.getOfferings(),
59
+ ]);
60
+ const entitlementId = deps.config.entitlementIdentifier;
61
+ const hasPremium = !!customerInfo.entitlements.active[entitlementId];
62
+ return { success: true, offering: offerings.current, hasPremium };
63
+ } catch {
64
+ return { success: false, offering: null, hasPremium: false };
105
65
  }
106
- );
107
- return { success: false, offering: null, hasPremium: false };
108
66
  }
109
- }
110
67
 
111
- // Case 2: Already configured but different user or re-initializing
112
- if (isPurchasesConfigured) {
113
- try {
114
- // Check if we're already logged in with this user ID
115
- const currentAppUserId = await Purchases.getAppUserID();
116
-
117
- if (__DEV__) {
118
- console.log('[DEBUG RevenueCatInitializer] Current app user ID check', {
119
- currentAppUserId,
120
- requestedUserId: userId,
121
- needsLogin: currentAppUserId !== userId,
122
- });
123
- }
124
-
125
- // Only call logIn if the user ID is different
126
- let customerInfo;
127
- if (currentAppUserId !== userId) {
128
- if (__DEV__) {
129
- console.log('[DEBUG RevenueCatInitializer] User ID changed, calling logIn');
130
- }
131
- const result = await Purchases.logIn(userId);
132
- customerInfo = result.customerInfo;
133
- } else {
134
- if (__DEV__) {
135
- console.log('[DEBUG RevenueCatInitializer] Already logged in with same user ID, skipping logIn');
68
+ // Case 2: Already configured but different user or re-initializing
69
+ if (isPurchasesConfigured) {
70
+ try {
71
+ const currentAppUserId = await Purchases.getAppUserID();
72
+
73
+ let customerInfo;
74
+ if (currentAppUserId !== userId) {
75
+ const result = await Purchases.logIn(userId);
76
+ customerInfo = result.customerInfo;
77
+ } else {
78
+ customerInfo = await Purchases.getCustomerInfo();
79
+ }
80
+
81
+ deps.setInitialized(true);
82
+ deps.setCurrentUserId(userId);
83
+
84
+ const offerings = await Purchases.getOfferings();
85
+ const entitlementId = deps.config.entitlementIdentifier;
86
+ const hasPremium = !!customerInfo.entitlements.active[entitlementId];
87
+
88
+ return { success: true, offering: offerings.current, hasPremium };
89
+ } catch {
90
+ return { success: false, offering: null, hasPremium: false };
136
91
  }
137
- customerInfo = await Purchases.getCustomerInfo();
138
- }
139
-
140
- deps.setInitialized(true);
141
- deps.setCurrentUserId(userId);
142
-
143
- const offerings = await Purchases.getOfferings();
144
- const entitlementId = deps.config.entitlementIdentifier;
145
- const hasPremium = !!customerInfo.entitlements.active[entitlementId];
146
-
147
- return { success: true, offering: offerings.current, hasPremium };
148
- } catch {
149
- // If logIn fails, we don't necessarily want to re-configure if it's already configured
150
- // But we can return failure
151
- return { success: false, offering: null, hasPremium: false };
152
92
  }
153
- }
154
-
155
- // Case 3: First time configuration
156
- const key = apiKey || resolveApiKey(deps.config);
157
- if (__DEV__) {
158
- console.log('[DEBUG RevenueCatInitializer] Resolved API key', {
159
- hasKey: !!key,
160
- keyPrefix: key ? key.substring(0, 10) + '...' : 'null',
161
- isTestStore: deps.isUsingTestStore(),
162
- configApiKey: deps.config.apiKey ? deps.config.apiKey.substring(0, 10) + '...' : 'null',
163
- configTestStoreKey: deps.config.testStoreKey ? deps.config.testStoreKey.substring(0, 10) + '...' : 'null',
164
- });
165
- }
166
93
 
167
- if (!key) {
168
- if (__DEV__) {
169
- console.log('[DEBUG RevenueCatInitializer] ERROR: No API key available!');
170
- }
171
- const error = new Error("No RevenueCat API key available");
172
- packageName: "subscription",
173
- operation: "sdk_init_no_key",
174
- userId,
175
- });
176
- return { success: false, offering: null, hasPremium: false };
177
- }
178
-
179
- try {
180
- // Configure log handler before SDK initialization
181
- configureLogHandler();
182
-
183
- if (__DEV__) {
184
- console.log('[DEBUG RevenueCatInitializer] Calling Purchases.configure', {
185
- apiKey: key.substring(0, 10) + '...',
186
- appUserID: userId,
187
- });
188
- }
189
- await Purchases.configure({
190
- apiKey: key,
191
- appUserID: userId,
192
- });
193
- isPurchasesConfigured = true;
194
- deps.setInitialized(true);
195
- deps.setCurrentUserId(userId);
94
+ // Case 3: First time configuration
95
+ const key = apiKey || resolveApiKey(deps.config);
196
96
 
197
- if (__DEV__) {
198
- console.log('[DEBUG RevenueCatInitializer] Purchases.configure succeeded, fetching data...');
97
+ if (!key) {
98
+ return { success: false, offering: null, hasPremium: false };
199
99
  }
200
100
 
201
- const [customerInfo, offerings] = await Promise.all([
202
- Purchases.getCustomerInfo(),
203
- Purchases.getOfferings(),
204
- ]);
205
-
206
- const packagesCount = offerings.current?.availablePackages?.length ?? 0;
207
-
208
- if (__DEV__) {
209
- console.log('[DEBUG RevenueCatInitializer] Data fetched', {
210
- hasCurrent: !!offerings.current,
211
- currentIdentifier: offerings.current?.identifier,
212
- packagesCount,
213
- allOfferingsCount: Object.keys(offerings.all).length,
214
- allOfferingIds: Object.keys(offerings.all),
215
- packages: offerings.current?.availablePackages?.map(p => ({
216
- identifier: p.identifier,
217
- packageType: p.packageType,
218
- })),
219
- });
220
- }
101
+ try {
102
+ configureLogHandler();
221
103
 
222
- userId,
223
- hasCurrent: !!offerings.current,
224
- packagesCount,
225
- allOfferingsCount: Object.keys(offerings.all).length,
226
- });
104
+ await Purchases.configure({
105
+ apiKey: key,
106
+ appUserID: userId,
107
+ });
108
+ isPurchasesConfigured = true;
109
+ deps.setInitialized(true);
110
+ deps.setCurrentUserId(userId);
227
111
 
228
- const entitlementId = deps.config.entitlementIdentifier;
229
- const hasPremium = !!customerInfo.entitlements.active[entitlementId];
112
+ const [customerInfo, offerings] = await Promise.all([
113
+ Purchases.getCustomerInfo(),
114
+ Purchases.getOfferings(),
115
+ ]);
230
116
 
231
- return { success: true, offering: offerings.current, hasPremium };
232
- } catch (error) {
233
- const errorMessage = getErrorMessage(error, "RevenueCat init failed");
117
+ const entitlementId = deps.config.entitlementIdentifier;
118
+ const hasPremium = !!customerInfo.entitlements.active[entitlementId];
234
119
 
235
- if (__DEV__) {
236
- console.log('[DEBUG RevenueCatInitializer] ERROR during initialization', {
237
- error,
238
- errorMessage,
239
- errorType: error instanceof Error ? error.constructor.name : typeof error,
240
- });
120
+ return { success: true, offering: offerings.current, hasPremium };
121
+ } catch (error) {
122
+ getErrorMessage(error, "RevenueCat init failed");
123
+ return { success: false, offering: null, hasPremium: false };
241
124
  }
242
-
243
- error instanceof Error ? error : new Error(errorMessage),
244
- {
245
- packageName: "subscription",
246
- operation: "sdk_init",
247
- userId,
248
- errorMessage,
249
- }
250
- );
251
-
252
- return { success: false, offering: null, hasPremium: false };
253
- }
254
125
  }
@@ -4,15 +4,19 @@
4
4
  */
5
5
 
6
6
  import Purchases from "react-native-purchases";
7
- import type { PurchasesOffering, PurchasesPackage, CustomerInfo } from "react-native-purchases";
8
7
  import type {
9
- IRevenueCatService,
10
- InitializeResult,
11
- PurchaseResult,
12
- RestoreResult,
13
- } from '../../application/ports/IRevenueCatService';
14
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
15
- import { resolveApiKey } from '../utils/ApiKeyResolver';
8
+ PurchasesOffering,
9
+ PurchasesPackage,
10
+ CustomerInfo,
11
+ } from "react-native-purchases";
12
+ import type {
13
+ IRevenueCatService,
14
+ InitializeResult,
15
+ PurchaseResult,
16
+ RestoreResult,
17
+ } from "../../application/ports/IRevenueCatService";
18
+ import type { RevenueCatConfig } from "../../domain/value-objects/RevenueCatConfig";
19
+ import { resolveApiKey } from "../utils/ApiKeyResolver";
16
20
  import { initializeSDK } from "./RevenueCatInitializer";
17
21
  import { fetchOfferings } from "./OfferingsFetcher";
18
22
  import { handlePurchase } from "./PurchaseHandler";
@@ -21,146 +25,137 @@ import { CustomerInfoListenerManager } from "./CustomerInfoListenerManager";
21
25
  import { ServiceStateManager } from "./ServiceStateManager";
22
26
 
23
27
  export class RevenueCatService implements IRevenueCatService {
24
- private stateManager: ServiceStateManager;
25
- private listenerManager: CustomerInfoListenerManager;
26
-
27
- constructor(config: RevenueCatConfig) {
28
- this.stateManager = new ServiceStateManager(config);
29
- this.listenerManager = new CustomerInfoListenerManager(
30
- config.entitlementIdentifier
31
- );
32
- }
33
-
34
- getRevenueCatKey(): string | null {
35
- return resolveApiKey(this.stateManager.getConfig());
36
- }
37
-
38
- isInitialized(): boolean {
39
- return this.stateManager.isInitialized();
40
- }
41
-
42
- isUsingTestStore(): boolean {
43
- return this.stateManager.isUsingTestStore();
44
- }
45
-
46
- getCurrentUserId(): string | null {
47
- return this.stateManager.getCurrentUserId();
48
- }
49
-
50
- async initialize(userId: string, apiKey?: string): Promise<InitializeResult> {
51
- if (this.isInitialized() && this.getCurrentUserId() === userId) {
52
- return { success: true, offering: (await this.fetchOfferings()), hasPremium: false };
28
+ private stateManager: ServiceStateManager;
29
+ private listenerManager: CustomerInfoListenerManager;
30
+
31
+ constructor(config: RevenueCatConfig) {
32
+ this.stateManager = new ServiceStateManager(config);
33
+ this.listenerManager = new CustomerInfoListenerManager(
34
+ config.entitlementIdentifier
35
+ );
36
+ }
37
+
38
+ getRevenueCatKey(): string | null {
39
+ return resolveApiKey(this.stateManager.getConfig());
40
+ }
41
+
42
+ isInitialized(): boolean {
43
+ return this.stateManager.isInitialized();
44
+ }
45
+
46
+ isUsingTestStore(): boolean {
47
+ return this.stateManager.isUsingTestStore();
53
48
  }
54
49
 
50
+ getCurrentUserId(): string | null {
51
+ return this.stateManager.getCurrentUserId();
52
+ }
53
+
54
+ async initialize(userId: string, apiKey?: string): Promise<InitializeResult> {
55
+ if (this.isInitialized() && this.getCurrentUserId() === userId) {
56
+ return {
57
+ success: true,
58
+ offering: await this.fetchOfferings(),
59
+ hasPremium: false,
60
+ };
61
+ }
62
+
63
+ try {
64
+ const result = await initializeSDK(
65
+ {
66
+ config: this.stateManager.getConfig(),
67
+ isUsingTestStore: () => this.isUsingTestStore(),
68
+ isInitialized: () => this.isInitialized(),
69
+ getCurrentUserId: () => this.stateManager.getCurrentUserId(),
70
+ setInitialized: (value) => this.stateManager.setInitialized(value),
71
+ setCurrentUserId: (id) => this.stateManager.setCurrentUserId(id),
72
+ },
73
+ userId,
74
+ apiKey
75
+ );
76
+
77
+ if (result.success) {
78
+ this.listenerManager.setUserId(userId);
79
+ this.listenerManager.setupListener(this.stateManager.getConfig());
80
+ }
81
+
82
+ return result;
83
+ } catch (error) {
84
+ throw error;
85
+ }
86
+ }
55
87
 
56
- try {
57
- const result = await initializeSDK(
58
- {
59
- config: this.stateManager.getConfig(),
60
- isUsingTestStore: () => this.isUsingTestStore(),
61
- isInitialized: () => this.isInitialized(),
62
- getCurrentUserId: () => this.stateManager.getCurrentUserId(),
63
- setInitialized: (value) => this.stateManager.setInitialized(value),
64
- setCurrentUserId: (id) => this.stateManager.setCurrentUserId(id),
65
- },
66
- userId,
67
- apiKey
68
- );
69
-
70
- if (result.success) {
71
- this.listenerManager.setUserId(userId);
72
- this.listenerManager.setupListener(this.stateManager.getConfig());
73
- } else {
74
- userId,
75
- hasOffering: !!result.offering,
88
+ async fetchOfferings(): Promise<PurchasesOffering | null> {
89
+ return fetchOfferings({
90
+ isInitialized: () => this.isInitialized(),
91
+ isUsingTestStore: () => this.isUsingTestStore(),
76
92
  });
77
- }
78
-
79
- return result;
80
- } catch (error) {
81
- packageName: "subscription",
82
- operation: "initialize",
83
- userId,
84
- });
85
- throw error;
86
93
  }
87
- }
88
-
89
- async fetchOfferings(): Promise<PurchasesOffering | null> {
90
- return fetchOfferings({
91
- isInitialized: () => this.isInitialized(),
92
- isUsingTestStore: () => this.isUsingTestStore(),
93
- });
94
- }
95
-
96
- async purchasePackage(
97
- pkg: PurchasesPackage,
98
- userId: string
99
- ): Promise<PurchaseResult> {
100
- return handlePurchase(
101
- {
102
- config: this.stateManager.getConfig(),
103
- isInitialized: () => this.isInitialized(),
104
- isUsingTestStore: () => this.isUsingTestStore(),
105
- },
106
- pkg,
107
- userId
108
- );
109
- }
110
-
111
- async restorePurchases(userId: string): Promise<RestoreResult> {
112
- return handleRestore(
113
- {
114
- config: this.stateManager.getConfig(),
115
- isInitialized: () => this.isInitialized(),
116
- isUsingTestStore: () => this.isUsingTestStore(),
117
- },
118
- userId
119
- );
120
- }
121
-
122
- async getCustomerInfo(): Promise<CustomerInfo | null> {
123
- if (!this.isInitialized()) {
124
- return null;
94
+
95
+ async purchasePackage(
96
+ pkg: PurchasesPackage,
97
+ userId: string
98
+ ): Promise<PurchaseResult> {
99
+ return handlePurchase(
100
+ {
101
+ config: this.stateManager.getConfig(),
102
+ isInitialized: () => this.isInitialized(),
103
+ isUsingTestStore: () => this.isUsingTestStore(),
104
+ },
105
+ pkg,
106
+ userId
107
+ );
125
108
  }
126
- return Purchases.getCustomerInfo();
127
- }
128
109
 
129
- async reset(): Promise<void> {
130
- if (!this.isInitialized()) {
131
- return;
110
+ async restorePurchases(userId: string): Promise<RestoreResult> {
111
+ return handleRestore(
112
+ {
113
+ config: this.stateManager.getConfig(),
114
+ isInitialized: () => this.isInitialized(),
115
+ isUsingTestStore: () => this.isUsingTestStore(),
116
+ },
117
+ userId
118
+ );
132
119
  }
133
120
 
134
- userId: this.getCurrentUserId(),
135
- });
121
+ async getCustomerInfo(): Promise<CustomerInfo | null> {
122
+ if (!this.isInitialized()) {
123
+ return null;
124
+ }
125
+ return Purchases.getCustomerInfo();
126
+ }
127
+
128
+ async reset(): Promise<void> {
129
+ if (!this.isInitialized()) {
130
+ return;
131
+ }
136
132
 
137
- this.listenerManager.destroy();
133
+ this.listenerManager.destroy();
138
134
 
139
- try {
140
- await Purchases.logOut();
141
- this.stateManager.setInitialized(false);
142
- } catch (error) {
143
- error: error instanceof Error ? error.message : String(error),
144
- });
135
+ try {
136
+ await Purchases.logOut();
137
+ this.stateManager.setInitialized(false);
138
+ } catch {
139
+ // Silent error handling
140
+ }
145
141
  }
146
- }
147
142
  }
148
143
 
149
144
  let revenueCatServiceInstance: RevenueCatService | null = null;
150
145
 
151
146
  export function initializeRevenueCatService(
152
- config: RevenueCatConfig
147
+ config: RevenueCatConfig
153
148
  ): RevenueCatService {
154
- if (!revenueCatServiceInstance) {
155
- revenueCatServiceInstance = new RevenueCatService(config);
156
- }
157
- return revenueCatServiceInstance;
149
+ if (!revenueCatServiceInstance) {
150
+ revenueCatServiceInstance = new RevenueCatService(config);
151
+ }
152
+ return revenueCatServiceInstance;
158
153
  }
159
154
 
160
155
  export function getRevenueCatService(): RevenueCatService | null {
161
- return revenueCatServiceInstance;
156
+ return revenueCatServiceInstance;
162
157
  }
163
158
 
164
159
  export function resetRevenueCatService(): void {
165
- revenueCatServiceInstance = null;
160
+ revenueCatServiceInstance = null;
166
161
  }