@umituz/react-native-subscription 2.14.41 → 2.14.43
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.
- package/package.json +1 -3
- package/src/revenuecat/infrastructure/handlers/PackageHandler.ts +0 -11
- package/src/revenuecat/infrastructure/managers/SubscriptionManager.ts +0 -9
- package/src/revenuecat/infrastructure/services/CustomerInfoListenerManager.ts +0 -7
- package/src/revenuecat/infrastructure/services/OfferingsFetcher.ts +0 -8
- package/src/revenuecat/infrastructure/services/PurchaseHandler.ts +0 -8
- package/src/revenuecat/infrastructure/services/RestoreHandler.ts +0 -8
- package/src/revenuecat/infrastructure/services/RevenueCatInitializer.ts +0 -8
- package/src/revenuecat/infrastructure/services/RevenueCatService.ts +0 -12
- package/src/revenuecat/infrastructure/utils/InitializationCache.ts +0 -2
- package/src/revenuecat/infrastructure/utils/PremiumStatusSyncer.ts +0 -12
- package/src/revenuecat/infrastructure/utils/UserIdProvider.ts +0 -6
- package/src/revenuecat/presentation/hooks/useCustomerInfo.ts +0 -5
- package/src/revenuecat/presentation/hooks/useInitializeSubscription.ts +0 -6
- package/src/revenuecat/presentation/hooks/usePurchasePackage.ts +0 -7
- package/src/revenuecat/presentation/hooks/useRestorePurchase.ts +0 -7
- package/src/revenuecat/presentation/hooks/useSubscriptionPackages.ts +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.43",
|
|
4
4
|
"description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
"@umituz/react-native-firebase": "latest",
|
|
38
38
|
"@umituz/react-native-legal": "latest",
|
|
39
39
|
"@umituz/react-native-localization": "latest",
|
|
40
|
-
"@umituz/react-native-sentry": "latest",
|
|
41
40
|
"expo-constants": ">=16.0.0",
|
|
42
41
|
"expo-image": ">=2.0.0",
|
|
43
42
|
"expo-linear-gradient": ">=14.0.0",
|
|
@@ -58,7 +57,6 @@
|
|
|
58
57
|
"@umituz/react-native-firebase": "*",
|
|
59
58
|
"@umituz/react-native-legal": "*",
|
|
60
59
|
"@umituz/react-native-localization": "*",
|
|
61
|
-
"@umituz/react-native-sentry": "*",
|
|
62
60
|
"eslint": "^9.39.2",
|
|
63
61
|
"eslint-plugin-react": "^7.37.5",
|
|
64
62
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
@@ -7,10 +7,6 @@ import type { PurchasesPackage, CustomerInfo } from "react-native-purchases";
|
|
|
7
7
|
import type { IRevenueCatService } from "../../application/ports/IRevenueCatService";
|
|
8
8
|
import { getPremiumEntitlement } from "../../domain/types/RevenueCatTypes";
|
|
9
9
|
import {
|
|
10
|
-
trackPackageError,
|
|
11
|
-
addPackageBreadcrumb,
|
|
12
|
-
trackPackageWarning,
|
|
13
|
-
} from "@umituz/react-native-sentry";
|
|
14
10
|
|
|
15
11
|
export interface PremiumStatus {
|
|
16
12
|
isPremium: boolean;
|
|
@@ -34,7 +30,6 @@ export class PackageHandler {
|
|
|
34
30
|
|
|
35
31
|
async fetchPackages(): Promise<PurchasesPackage[]> {
|
|
36
32
|
if (!this.service?.isInitialized()) {
|
|
37
|
-
trackPackageWarning("subscription", "Fetch packages called but not initialized", {});
|
|
38
33
|
return [];
|
|
39
34
|
}
|
|
40
35
|
|
|
@@ -54,7 +49,6 @@ export class PackageHandler {
|
|
|
54
49
|
});
|
|
55
50
|
}
|
|
56
51
|
|
|
57
|
-
addPackageBreadcrumb("subscription", "Packages fetched", {
|
|
58
52
|
identifier: offering?.identifier,
|
|
59
53
|
count: offering?.availablePackages?.length ?? 0,
|
|
60
54
|
});
|
|
@@ -64,7 +58,6 @@ export class PackageHandler {
|
|
|
64
58
|
if (__DEV__) {
|
|
65
59
|
console.error('[DEBUG PackageHandler] fetchOfferings failed:', error);
|
|
66
60
|
}
|
|
67
|
-
trackPackageError(error instanceof Error ? error : new Error(String(error)), {
|
|
68
61
|
packageName: "subscription",
|
|
69
62
|
operation: "fetch_packages",
|
|
70
63
|
});
|
|
@@ -74,7 +67,6 @@ export class PackageHandler {
|
|
|
74
67
|
|
|
75
68
|
async purchase(pkg: PurchasesPackage, userId: string): Promise<boolean> {
|
|
76
69
|
if (!this.service?.isInitialized()) {
|
|
77
|
-
trackPackageWarning("subscription", "Purchase attempted but not initialized", {
|
|
78
70
|
productId: pkg.product.identifier,
|
|
79
71
|
});
|
|
80
72
|
return false;
|
|
@@ -84,7 +76,6 @@ export class PackageHandler {
|
|
|
84
76
|
const result = await this.service.purchasePackage(pkg, userId);
|
|
85
77
|
return result.success;
|
|
86
78
|
} catch (error) {
|
|
87
|
-
trackPackageError(error instanceof Error ? error : new Error(String(error)), {
|
|
88
79
|
packageName: "subscription",
|
|
89
80
|
operation: "purchase",
|
|
90
81
|
userId,
|
|
@@ -96,7 +87,6 @@ export class PackageHandler {
|
|
|
96
87
|
|
|
97
88
|
async restore(userId: string): Promise<RestoreResultInfo> {
|
|
98
89
|
if (!this.service?.isInitialized()) {
|
|
99
|
-
trackPackageWarning("subscription", "Restore attempted but not initialized", {});
|
|
100
90
|
return { success: false, productId: null };
|
|
101
91
|
}
|
|
102
92
|
|
|
@@ -117,7 +107,6 @@ export class PackageHandler {
|
|
|
117
107
|
|
|
118
108
|
return { success: result.success, productId };
|
|
119
109
|
} catch (error) {
|
|
120
|
-
trackPackageError(error instanceof Error ? error : new Error(String(error)), {
|
|
121
110
|
packageName: "subscription",
|
|
122
111
|
operation: "restore",
|
|
123
112
|
userId,
|
|
@@ -13,10 +13,6 @@ import { InitializationCache } from "../utils/InitializationCache";
|
|
|
13
13
|
import { PackageHandler } from "../handlers/PackageHandler";
|
|
14
14
|
import type { PremiumStatus, RestoreResultInfo } from "../handlers/PackageHandler";
|
|
15
15
|
import {
|
|
16
|
-
trackPackageError,
|
|
17
|
-
addPackageBreadcrumb,
|
|
18
|
-
trackPackageWarning,
|
|
19
|
-
} from "@umituz/react-native-sentry";
|
|
20
16
|
|
|
21
17
|
export interface SubscriptionManagerConfig {
|
|
22
18
|
config: RevenueCatConfig;
|
|
@@ -39,7 +35,6 @@ class SubscriptionManagerImpl {
|
|
|
39
35
|
this.userIdProvider.configure(config.getAnonymousUserId);
|
|
40
36
|
}
|
|
41
37
|
|
|
42
|
-
addPackageBreadcrumb("subscription", "Manager configured", {
|
|
43
38
|
entitlementId: config.config.entitlementIdentifier,
|
|
44
39
|
});
|
|
45
40
|
}
|
|
@@ -47,7 +42,6 @@ class SubscriptionManagerImpl {
|
|
|
47
42
|
private ensureConfigured(): void {
|
|
48
43
|
if (!this.managerConfig || !this.packageHandler) {
|
|
49
44
|
const error = new Error("SubscriptionManager not configured");
|
|
50
|
-
trackPackageError(error, {
|
|
51
45
|
packageName: "subscription",
|
|
52
46
|
operation: "ensure_configured",
|
|
53
47
|
});
|
|
@@ -63,7 +57,6 @@ class SubscriptionManagerImpl {
|
|
|
63
57
|
this.serviceInstance = getRevenueCatService();
|
|
64
58
|
|
|
65
59
|
if (!this.serviceInstance) {
|
|
66
|
-
trackPackageWarning("subscription", "Service instance not created", { userId });
|
|
67
60
|
return false;
|
|
68
61
|
}
|
|
69
62
|
|
|
@@ -73,7 +66,6 @@ class SubscriptionManagerImpl {
|
|
|
73
66
|
const result = await this.serviceInstance.initialize(userId);
|
|
74
67
|
return result.success;
|
|
75
68
|
} catch (error) {
|
|
76
|
-
trackPackageError(error instanceof Error ? error : new Error(String(error)), {
|
|
77
69
|
packageName: "subscription",
|
|
78
70
|
operation: "initialize",
|
|
79
71
|
userId,
|
|
@@ -174,7 +166,6 @@ class SubscriptionManagerImpl {
|
|
|
174
166
|
this.initCache.reset();
|
|
175
167
|
this.userIdProvider.reset();
|
|
176
168
|
this.serviceInstance = null;
|
|
177
|
-
addPackageBreadcrumb("subscription", "Manager reset completed", {});
|
|
178
169
|
}
|
|
179
170
|
}
|
|
180
171
|
|
|
@@ -9,7 +9,6 @@ import Purchases, {
|
|
|
9
9
|
} from "react-native-purchases";
|
|
10
10
|
import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
|
|
11
11
|
import { syncPremiumStatus } from '../utils/PremiumStatusSyncer';
|
|
12
|
-
import { addPackageBreadcrumb } from "@umituz/react-native-sentry";
|
|
13
12
|
|
|
14
13
|
export class CustomerInfoListenerManager {
|
|
15
14
|
private listener: CustomerInfoUpdateListener | null = null;
|
|
@@ -38,7 +37,6 @@ export class CustomerInfoListenerManager {
|
|
|
38
37
|
});
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
addPackageBreadcrumb("subscription", "Setting up customer info listener", {
|
|
42
40
|
userId: this.currentUserId,
|
|
43
41
|
});
|
|
44
42
|
|
|
@@ -69,7 +67,6 @@ export class CustomerInfoListenerManager {
|
|
|
69
67
|
});
|
|
70
68
|
}
|
|
71
69
|
|
|
72
|
-
addPackageBreadcrumb("subscription", "Customer info updated", {
|
|
73
70
|
userId: this.currentUserId,
|
|
74
71
|
hasPremium,
|
|
75
72
|
entitlementIdentifier: this.entitlementIdentifier,
|
|
@@ -93,7 +90,6 @@ export class CustomerInfoListenerManager {
|
|
|
93
90
|
});
|
|
94
91
|
}
|
|
95
92
|
|
|
96
|
-
addPackageBreadcrumb(
|
|
97
93
|
"subscription",
|
|
98
94
|
"Processing credit renewal",
|
|
99
95
|
{
|
|
@@ -117,7 +113,6 @@ export class CustomerInfoListenerManager {
|
|
|
117
113
|
});
|
|
118
114
|
}
|
|
119
115
|
|
|
120
|
-
addPackageBreadcrumb(
|
|
121
116
|
"subscription",
|
|
122
117
|
"Credit renewal completed",
|
|
123
118
|
{
|
|
@@ -139,7 +134,6 @@ export class CustomerInfoListenerManager {
|
|
|
139
134
|
});
|
|
140
135
|
}
|
|
141
136
|
|
|
142
|
-
addPackageBreadcrumb(
|
|
143
137
|
"subscription",
|
|
144
138
|
"Credit renewal failed",
|
|
145
139
|
{
|
|
@@ -174,7 +168,6 @@ export class CustomerInfoListenerManager {
|
|
|
174
168
|
|
|
175
169
|
removeListener(): void {
|
|
176
170
|
if (this.listener) {
|
|
177
|
-
addPackageBreadcrumb("subscription", "Removing customer info listener", {});
|
|
178
171
|
Purchases.removeCustomerInfoUpdateListener(this.listener);
|
|
179
172
|
this.listener = null;
|
|
180
173
|
}
|
|
@@ -5,10 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import Purchases, { type PurchasesOffering } from "react-native-purchases";
|
|
7
7
|
import {
|
|
8
|
-
trackPackageError,
|
|
9
|
-
addPackageBreadcrumb,
|
|
10
|
-
trackPackageWarning,
|
|
11
|
-
} from "@umituz/react-native-sentry";
|
|
12
8
|
|
|
13
9
|
export interface OfferingsFetcherDeps {
|
|
14
10
|
isInitialized: () => boolean;
|
|
@@ -18,12 +14,10 @@ export interface OfferingsFetcherDeps {
|
|
|
18
14
|
export async function fetchOfferings(
|
|
19
15
|
deps: OfferingsFetcherDeps
|
|
20
16
|
): Promise<PurchasesOffering | null> {
|
|
21
|
-
addPackageBreadcrumb("subscription", "Fetch offerings started", {
|
|
22
17
|
isInitialized: deps.isInitialized(),
|
|
23
18
|
});
|
|
24
19
|
|
|
25
20
|
if (!deps.isInitialized()) {
|
|
26
|
-
trackPackageWarning("subscription", "Fetch offerings called before initialization", {});
|
|
27
21
|
return null;
|
|
28
22
|
}
|
|
29
23
|
|
|
@@ -32,14 +26,12 @@ export async function fetchOfferings(
|
|
|
32
26
|
|
|
33
27
|
const packagesCount = offerings.current?.availablePackages?.length ?? 0;
|
|
34
28
|
|
|
35
|
-
addPackageBreadcrumb("subscription", "Fetch offerings success", {
|
|
36
29
|
hasCurrent: !!offerings.current,
|
|
37
30
|
packagesCount,
|
|
38
31
|
});
|
|
39
32
|
|
|
40
33
|
return offerings.current;
|
|
41
34
|
} catch (error) {
|
|
42
|
-
trackPackageError(
|
|
43
35
|
error instanceof Error ? error : new Error(String(error)),
|
|
44
36
|
{
|
|
45
37
|
packageName: "subscription",
|
|
@@ -19,9 +19,6 @@ import {
|
|
|
19
19
|
notifyPurchaseCompleted,
|
|
20
20
|
} from '../utils/PremiumStatusSyncer';
|
|
21
21
|
import {
|
|
22
|
-
trackPackageError,
|
|
23
|
-
addPackageBreadcrumb,
|
|
24
|
-
} from "@umituz/react-native-sentry";
|
|
25
22
|
|
|
26
23
|
export interface PurchaseHandlerDeps {
|
|
27
24
|
config: RevenueCatConfig;
|
|
@@ -46,14 +43,12 @@ export async function handlePurchase(
|
|
|
46
43
|
pkg: PurchasesPackage,
|
|
47
44
|
userId: string
|
|
48
45
|
): Promise<PurchaseResult> {
|
|
49
|
-
addPackageBreadcrumb("subscription", "Purchase started", {
|
|
50
46
|
productId: pkg.product.identifier,
|
|
51
47
|
userId,
|
|
52
48
|
});
|
|
53
49
|
|
|
54
50
|
if (!deps.isInitialized()) {
|
|
55
51
|
const error = new RevenueCatInitializationError();
|
|
56
|
-
trackPackageError(error, {
|
|
57
52
|
packageName: "subscription",
|
|
58
53
|
operation: "purchase",
|
|
59
54
|
userId,
|
|
@@ -97,7 +92,6 @@ export async function handlePurchase(
|
|
|
97
92
|
"Purchase completed but premium entitlement not active",
|
|
98
93
|
pkg.product.identifier
|
|
99
94
|
);
|
|
100
|
-
trackPackageError(entitlementError, {
|
|
101
95
|
packageName: "subscription",
|
|
102
96
|
operation: "purchase",
|
|
103
97
|
userId,
|
|
@@ -107,7 +101,6 @@ export async function handlePurchase(
|
|
|
107
101
|
throw entitlementError;
|
|
108
102
|
} catch (error) {
|
|
109
103
|
if (isUserCancelledError(error)) {
|
|
110
|
-
addPackageBreadcrumb("subscription", "Purchase cancelled by user", {
|
|
111
104
|
productId: pkg.product.identifier,
|
|
112
105
|
userId,
|
|
113
106
|
});
|
|
@@ -115,7 +108,6 @@ export async function handlePurchase(
|
|
|
115
108
|
}
|
|
116
109
|
const errorMessage = getErrorMessage(error, "Purchase failed");
|
|
117
110
|
const purchaseError = new RevenueCatPurchaseError(errorMessage, pkg.product.identifier);
|
|
118
|
-
trackPackageError(purchaseError, {
|
|
119
111
|
packageName: "subscription",
|
|
120
112
|
operation: "purchase",
|
|
121
113
|
userId,
|
|
@@ -16,9 +16,6 @@ import {
|
|
|
16
16
|
notifyRestoreCompleted,
|
|
17
17
|
} from '../utils/PremiumStatusSyncer';
|
|
18
18
|
import {
|
|
19
|
-
trackPackageError,
|
|
20
|
-
addPackageBreadcrumb,
|
|
21
|
-
} from "@umituz/react-native-sentry";
|
|
22
19
|
|
|
23
20
|
export interface RestoreHandlerDeps {
|
|
24
21
|
config: RevenueCatConfig;
|
|
@@ -33,11 +30,9 @@ export async function handleRestore(
|
|
|
33
30
|
deps: RestoreHandlerDeps,
|
|
34
31
|
userId: string
|
|
35
32
|
): Promise<RestoreResult> {
|
|
36
|
-
addPackageBreadcrumb("subscription", "Restore started", { userId });
|
|
37
33
|
|
|
38
34
|
if (!deps.isInitialized()) {
|
|
39
35
|
const error = new RevenueCatInitializationError();
|
|
40
|
-
trackPackageError(error, {
|
|
41
36
|
packageName: "subscription",
|
|
42
37
|
operation: "restore",
|
|
43
38
|
userId,
|
|
@@ -52,12 +47,10 @@ export async function handleRestore(
|
|
|
52
47
|
|
|
53
48
|
if (isPremium) {
|
|
54
49
|
await syncPremiumStatus(deps.config, userId, customerInfo);
|
|
55
|
-
addPackageBreadcrumb("subscription", "Restore successful - premium active", {
|
|
56
50
|
userId,
|
|
57
51
|
entitlementId: entitlementIdentifier,
|
|
58
52
|
});
|
|
59
53
|
} else {
|
|
60
|
-
addPackageBreadcrumb("subscription", "Restore completed - no premium found", {
|
|
61
54
|
userId,
|
|
62
55
|
});
|
|
63
56
|
}
|
|
@@ -68,7 +61,6 @@ export async function handleRestore(
|
|
|
68
61
|
} catch (error) {
|
|
69
62
|
const errorMessage = getErrorMessage(error, "Restore failed");
|
|
70
63
|
const restoreError = new RevenueCatRestoreError(errorMessage);
|
|
71
|
-
trackPackageError(restoreError, {
|
|
72
64
|
packageName: "subscription",
|
|
73
65
|
operation: "restore",
|
|
74
66
|
userId,
|
|
@@ -9,9 +9,6 @@ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConf
|
|
|
9
9
|
import { getErrorMessage } from '../../domain/types/RevenueCatTypes';
|
|
10
10
|
import { resolveApiKey } from '../utils/ApiKeyResolver';
|
|
11
11
|
import {
|
|
12
|
-
trackPackageError,
|
|
13
|
-
addPackageBreadcrumb,
|
|
14
|
-
} from "@umituz/react-native-sentry";
|
|
15
12
|
|
|
16
13
|
export interface InitializerDeps {
|
|
17
14
|
config: RevenueCatConfig;
|
|
@@ -84,7 +81,6 @@ export async function initializeSDK(
|
|
|
84
81
|
});
|
|
85
82
|
}
|
|
86
83
|
|
|
87
|
-
addPackageBreadcrumb("subscription", "SDK initialization started", {
|
|
88
84
|
userId,
|
|
89
85
|
hasApiKey: !!apiKey,
|
|
90
86
|
isAlreadyConfigured: isPurchasesConfigured,
|
|
@@ -102,7 +98,6 @@ export async function initializeSDK(
|
|
|
102
98
|
const hasPremium = !!customerInfo.entitlements.active[entitlementId];
|
|
103
99
|
return { success: true, offering: offerings.current, hasPremium };
|
|
104
100
|
} catch (error) {
|
|
105
|
-
trackPackageError(
|
|
106
101
|
error instanceof Error ? error : new Error(String(error)),
|
|
107
102
|
{
|
|
108
103
|
packageName: "subscription",
|
|
@@ -175,7 +170,6 @@ export async function initializeSDK(
|
|
|
175
170
|
console.log('[DEBUG RevenueCatInitializer] ERROR: No API key available!');
|
|
176
171
|
}
|
|
177
172
|
const error = new Error("No RevenueCat API key available");
|
|
178
|
-
trackPackageError(error, {
|
|
179
173
|
packageName: "subscription",
|
|
180
174
|
operation: "sdk_init_no_key",
|
|
181
175
|
userId,
|
|
@@ -226,7 +220,6 @@ export async function initializeSDK(
|
|
|
226
220
|
});
|
|
227
221
|
}
|
|
228
222
|
|
|
229
|
-
addPackageBreadcrumb("subscription", "Offerings fetched", {
|
|
230
223
|
userId,
|
|
231
224
|
hasCurrent: !!offerings.current,
|
|
232
225
|
packagesCount,
|
|
@@ -248,7 +241,6 @@ export async function initializeSDK(
|
|
|
248
241
|
});
|
|
249
242
|
}
|
|
250
243
|
|
|
251
|
-
trackPackageError(
|
|
252
244
|
error instanceof Error ? error : new Error(errorMessage),
|
|
253
245
|
{
|
|
254
246
|
packageName: "subscription",
|
|
@@ -20,10 +20,6 @@ import { handleRestore } from "./RestoreHandler";
|
|
|
20
20
|
import { CustomerInfoListenerManager } from "./CustomerInfoListenerManager";
|
|
21
21
|
import { ServiceStateManager } from "./ServiceStateManager";
|
|
22
22
|
import {
|
|
23
|
-
trackPackageError,
|
|
24
|
-
addPackageBreadcrumb,
|
|
25
|
-
trackPackageWarning,
|
|
26
|
-
} from "@umituz/react-native-sentry";
|
|
27
23
|
|
|
28
24
|
export class RevenueCatService implements IRevenueCatService {
|
|
29
25
|
private stateManager: ServiceStateManager;
|
|
@@ -54,11 +50,9 @@ export class RevenueCatService implements IRevenueCatService {
|
|
|
54
50
|
|
|
55
51
|
async initialize(userId: string, apiKey?: string): Promise<InitializeResult> {
|
|
56
52
|
if (this.isInitialized() && this.getCurrentUserId() === userId) {
|
|
57
|
-
addPackageBreadcrumb("subscription", "Already initialized", { userId });
|
|
58
53
|
return { success: true, offering: (await this.fetchOfferings()), hasPremium: false };
|
|
59
54
|
}
|
|
60
55
|
|
|
61
|
-
addPackageBreadcrumb("subscription", "Initialization started", { userId });
|
|
62
56
|
|
|
63
57
|
try {
|
|
64
58
|
const result = await initializeSDK(
|
|
@@ -77,9 +71,7 @@ export class RevenueCatService implements IRevenueCatService {
|
|
|
77
71
|
if (result.success) {
|
|
78
72
|
this.listenerManager.setUserId(userId);
|
|
79
73
|
this.listenerManager.setupListener(this.stateManager.getConfig());
|
|
80
|
-
addPackageBreadcrumb("subscription", "Initialization successful", { userId });
|
|
81
74
|
} else {
|
|
82
|
-
trackPackageWarning("subscription", "Initialization failed", {
|
|
83
75
|
userId,
|
|
84
76
|
hasOffering: !!result.offering,
|
|
85
77
|
});
|
|
@@ -87,7 +79,6 @@ export class RevenueCatService implements IRevenueCatService {
|
|
|
87
79
|
|
|
88
80
|
return result;
|
|
89
81
|
} catch (error) {
|
|
90
|
-
trackPackageError(error instanceof Error ? error : new Error(String(error)), {
|
|
91
82
|
packageName: "subscription",
|
|
92
83
|
operation: "initialize",
|
|
93
84
|
userId,
|
|
@@ -141,7 +132,6 @@ export class RevenueCatService implements IRevenueCatService {
|
|
|
141
132
|
return;
|
|
142
133
|
}
|
|
143
134
|
|
|
144
|
-
addPackageBreadcrumb("subscription", "Reset started", {
|
|
145
135
|
userId: this.getCurrentUserId(),
|
|
146
136
|
});
|
|
147
137
|
|
|
@@ -150,9 +140,7 @@ export class RevenueCatService implements IRevenueCatService {
|
|
|
150
140
|
try {
|
|
151
141
|
await Purchases.logOut();
|
|
152
142
|
this.stateManager.setInitialized(false);
|
|
153
|
-
addPackageBreadcrumb("subscription", "Reset successful", {});
|
|
154
143
|
} catch (error) {
|
|
155
|
-
trackPackageWarning("subscription", "Reset failed (non-critical)", {
|
|
156
144
|
error: error instanceof Error ? error.message : String(error),
|
|
157
145
|
});
|
|
158
146
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Manages promise caching and user state for initialization
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { addPackageBreadcrumb } from "@umituz/react-native-sentry";
|
|
7
6
|
|
|
8
7
|
export class InitializationCache {
|
|
9
8
|
private initPromise: Promise<boolean> | null = null;
|
|
@@ -15,7 +14,6 @@ export class InitializationCache {
|
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
if (this.currentUserId !== userId) {
|
|
18
|
-
addPackageBreadcrumb("subscription", "User changed, reinitialize needed", {
|
|
19
17
|
oldUserId: this.currentUserId,
|
|
20
18
|
newUserId: userId,
|
|
21
19
|
});
|
|
@@ -8,9 +8,6 @@ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConf
|
|
|
8
8
|
import { getPremiumEntitlement } from '../../domain/types/RevenueCatTypes';
|
|
9
9
|
import { getExpirationDate } from "./ExpirationDateCalculator";
|
|
10
10
|
import {
|
|
11
|
-
trackPackageError,
|
|
12
|
-
addPackageBreadcrumb,
|
|
13
|
-
} from "@umituz/react-native-sentry";
|
|
14
11
|
|
|
15
12
|
export async function syncPremiumStatus(
|
|
16
13
|
config: RevenueCatConfig,
|
|
@@ -29,7 +26,6 @@ export async function syncPremiumStatus(
|
|
|
29
26
|
|
|
30
27
|
const isPremium = !!premiumEntitlement;
|
|
31
28
|
|
|
32
|
-
addPackageBreadcrumb("subscription", "Syncing premium status", {
|
|
33
29
|
userId,
|
|
34
30
|
isPremium,
|
|
35
31
|
productId: premiumEntitlement?.productIdentifier,
|
|
@@ -49,12 +45,10 @@ export async function syncPremiumStatus(
|
|
|
49
45
|
await config.onPremiumStatusChanged(userId, false);
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
addPackageBreadcrumb("subscription", "Premium status synced successfully", {
|
|
53
48
|
userId,
|
|
54
49
|
isPremium,
|
|
55
50
|
});
|
|
56
51
|
} catch (error) {
|
|
57
|
-
trackPackageError(
|
|
58
52
|
error instanceof Error ? error : new Error(String(error)),
|
|
59
53
|
{
|
|
60
54
|
packageName: "subscription",
|
|
@@ -76,7 +70,6 @@ export async function notifyPurchaseCompleted(
|
|
|
76
70
|
return;
|
|
77
71
|
}
|
|
78
72
|
|
|
79
|
-
addPackageBreadcrumb("subscription", "Notifying purchase completed", {
|
|
80
73
|
userId,
|
|
81
74
|
productId,
|
|
82
75
|
});
|
|
@@ -84,12 +77,10 @@ export async function notifyPurchaseCompleted(
|
|
|
84
77
|
try {
|
|
85
78
|
await config.onPurchaseCompleted(userId, productId, customerInfo);
|
|
86
79
|
|
|
87
|
-
addPackageBreadcrumb("subscription", "Purchase callback completed", {
|
|
88
80
|
userId,
|
|
89
81
|
productId,
|
|
90
82
|
});
|
|
91
83
|
} catch (error) {
|
|
92
|
-
trackPackageError(
|
|
93
84
|
error instanceof Error ? error : new Error(String(error)),
|
|
94
85
|
{
|
|
95
86
|
packageName: "subscription",
|
|
@@ -111,7 +102,6 @@ export async function notifyRestoreCompleted(
|
|
|
111
102
|
return;
|
|
112
103
|
}
|
|
113
104
|
|
|
114
|
-
addPackageBreadcrumb("subscription", "Notifying restore completed", {
|
|
115
105
|
userId,
|
|
116
106
|
isPremium,
|
|
117
107
|
});
|
|
@@ -119,12 +109,10 @@ export async function notifyRestoreCompleted(
|
|
|
119
109
|
try {
|
|
120
110
|
await config.onRestoreCompleted(userId, isPremium, customerInfo);
|
|
121
111
|
|
|
122
|
-
addPackageBreadcrumb("subscription", "Restore callback completed", {
|
|
123
112
|
userId,
|
|
124
113
|
isPremium,
|
|
125
114
|
});
|
|
126
115
|
} catch (error) {
|
|
127
|
-
trackPackageError(
|
|
128
116
|
error instanceof Error ? error : new Error(String(error)),
|
|
129
117
|
{
|
|
130
118
|
packageName: "subscription",
|
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
trackPackageError,
|
|
8
|
-
addPackageBreadcrumb,
|
|
9
|
-
} from "@umituz/react-native-sentry";
|
|
10
7
|
|
|
11
8
|
export class UserIdProvider {
|
|
12
9
|
private cachedAnonUserId: string | null = null;
|
|
@@ -14,7 +11,6 @@ export class UserIdProvider {
|
|
|
14
11
|
|
|
15
12
|
configure(getAnonymousUserId: () => Promise<string>): void {
|
|
16
13
|
this.getAnonymousUserIdFn = getAnonymousUserId;
|
|
17
|
-
addPackageBreadcrumb("subscription", "UserIdProvider configured", {});
|
|
18
14
|
}
|
|
19
15
|
|
|
20
16
|
async getOrCreateAnonymousUserId(): Promise<string> {
|
|
@@ -24,7 +20,6 @@ export class UserIdProvider {
|
|
|
24
20
|
|
|
25
21
|
if (!this.getAnonymousUserIdFn) {
|
|
26
22
|
const error = new Error("Anonymous user ID provider not configured");
|
|
27
|
-
trackPackageError(error, {
|
|
28
23
|
packageName: "subscription",
|
|
29
24
|
operation: "get_anon_user_id",
|
|
30
25
|
});
|
|
@@ -32,7 +27,6 @@ export class UserIdProvider {
|
|
|
32
27
|
}
|
|
33
28
|
|
|
34
29
|
this.cachedAnonUserId = await this.getAnonymousUserIdFn();
|
|
35
|
-
addPackageBreadcrumb("subscription", "Anonymous user ID created", {
|
|
36
30
|
userId: this.cachedAnonUserId,
|
|
37
31
|
});
|
|
38
32
|
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
import { useEffect, useState, useCallback } from "react";
|
|
18
18
|
import Purchases, { type CustomerInfo } from "react-native-purchases";
|
|
19
|
-
import { addPackageBreadcrumb, trackPackageError } from "@umituz/react-native-sentry";
|
|
20
19
|
|
|
21
20
|
export interface UseCustomerInfoResult {
|
|
22
21
|
/** Current CustomerInfo from RevenueCat SDK */
|
|
@@ -67,7 +66,6 @@ export function useCustomerInfo(): UseCustomerInfoResult {
|
|
|
67
66
|
setIsFetching(true);
|
|
68
67
|
setError(null);
|
|
69
68
|
|
|
70
|
-
addPackageBreadcrumb("subscription", "Fetching CustomerInfo", {});
|
|
71
69
|
|
|
72
70
|
// SDK returns cached data instantly if available
|
|
73
71
|
// Network fetch happens in background automatically
|
|
@@ -75,7 +73,6 @@ export function useCustomerInfo(): UseCustomerInfoResult {
|
|
|
75
73
|
|
|
76
74
|
setCustomerInfo(info);
|
|
77
75
|
|
|
78
|
-
addPackageBreadcrumb("subscription", "CustomerInfo fetched", {
|
|
79
76
|
hasActiveEntitlements: Object.keys(info.entitlements.active).length > 0,
|
|
80
77
|
latestExpiration: info.latestExpirationDate || "none",
|
|
81
78
|
});
|
|
@@ -84,7 +81,6 @@ export function useCustomerInfo(): UseCustomerInfoResult {
|
|
|
84
81
|
err instanceof Error ? err.message : "Failed to fetch customer info";
|
|
85
82
|
setError(errorMessage);
|
|
86
83
|
|
|
87
|
-
trackPackageError(
|
|
88
84
|
err instanceof Error ? err : new Error(String(err)),
|
|
89
85
|
{
|
|
90
86
|
packageName: "subscription",
|
|
@@ -103,7 +99,6 @@ export function useCustomerInfo(): UseCustomerInfoResult {
|
|
|
103
99
|
|
|
104
100
|
// Listen for real-time updates (renewals, purchases, restore)
|
|
105
101
|
const listener = (info: CustomerInfo) => {
|
|
106
|
-
addPackageBreadcrumb("subscription", "CustomerInfo updated via listener", {
|
|
107
102
|
hasActiveEntitlements: Object.keys(info.entitlements.active).length > 0,
|
|
108
103
|
});
|
|
109
104
|
|
|
@@ -6,9 +6,6 @@
|
|
|
6
6
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
7
7
|
import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager';
|
|
8
8
|
import {
|
|
9
|
-
trackPackageError,
|
|
10
|
-
addPackageBreadcrumb,
|
|
11
|
-
} from "@umituz/react-native-sentry";
|
|
12
9
|
import { SUBSCRIPTION_QUERY_KEYS } from "./subscriptionQueryKeys";
|
|
13
10
|
|
|
14
11
|
/**
|
|
@@ -23,7 +20,6 @@ export const useInitializeSubscription = (userId: string | undefined) => {
|
|
|
23
20
|
throw new Error("User not authenticated");
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
addPackageBreadcrumb("subscription", "Initialize mutation started", {
|
|
27
23
|
userId,
|
|
28
24
|
});
|
|
29
25
|
|
|
@@ -35,7 +31,6 @@ export const useInitializeSubscription = (userId: string | undefined) => {
|
|
|
35
31
|
queryKey: SUBSCRIPTION_QUERY_KEYS.packages,
|
|
36
32
|
});
|
|
37
33
|
|
|
38
|
-
addPackageBreadcrumb(
|
|
39
34
|
"subscription",
|
|
40
35
|
"Initialize mutation success - packages invalidated",
|
|
41
36
|
{ userId }
|
|
@@ -43,7 +38,6 @@ export const useInitializeSubscription = (userId: string | undefined) => {
|
|
|
43
38
|
}
|
|
44
39
|
},
|
|
45
40
|
onError: (error) => {
|
|
46
|
-
trackPackageError(
|
|
47
41
|
error instanceof Error ? error : new Error(String(error)),
|
|
48
42
|
{
|
|
49
43
|
packageName: "subscription",
|
|
@@ -8,9 +8,6 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
|
8
8
|
import type { PurchasesPackage } from "react-native-purchases";
|
|
9
9
|
import { SubscriptionManager } from "../../infrastructure/managers/SubscriptionManager";
|
|
10
10
|
import {
|
|
11
|
-
trackPackageError,
|
|
12
|
-
addPackageBreadcrumb,
|
|
13
|
-
} from "@umituz/react-native-sentry";
|
|
14
11
|
import { SUBSCRIPTION_QUERY_KEYS } from "./subscriptionQueryKeys";
|
|
15
12
|
import { creditsQueryKeys } from "../../../presentation/hooks/useCredits";
|
|
16
13
|
|
|
@@ -34,7 +31,6 @@ export const usePurchasePackage = (userId: string | undefined) => {
|
|
|
34
31
|
|
|
35
32
|
const productId = pkg.product.identifier;
|
|
36
33
|
|
|
37
|
-
addPackageBreadcrumb("subscription", "Purchase started", {
|
|
38
34
|
packageId: pkg.identifier,
|
|
39
35
|
productId,
|
|
40
36
|
userId,
|
|
@@ -43,14 +39,12 @@ export const usePurchasePackage = (userId: string | undefined) => {
|
|
|
43
39
|
const success = await SubscriptionManager.purchasePackage(pkg);
|
|
44
40
|
|
|
45
41
|
if (success) {
|
|
46
|
-
addPackageBreadcrumb("subscription", "Purchase success", {
|
|
47
42
|
packageId: pkg.identifier,
|
|
48
43
|
productId,
|
|
49
44
|
userId,
|
|
50
45
|
});
|
|
51
46
|
// Credits will be initialized by CustomerInfoListener
|
|
52
47
|
} else {
|
|
53
|
-
addPackageBreadcrumb("subscription", "Purchase cancelled", {
|
|
54
48
|
packageId: pkg.identifier,
|
|
55
49
|
userId,
|
|
56
50
|
});
|
|
@@ -71,7 +65,6 @@ export const usePurchasePackage = (userId: string | undefined) => {
|
|
|
71
65
|
}
|
|
72
66
|
},
|
|
73
67
|
onError: (error) => {
|
|
74
|
-
trackPackageError(
|
|
75
68
|
error instanceof Error ? error : new Error(String(error)),
|
|
76
69
|
{
|
|
77
70
|
packageName: "subscription",
|
|
@@ -7,9 +7,6 @@
|
|
|
7
7
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
8
8
|
import { SubscriptionManager } from "../../infrastructure/managers/SubscriptionManager";
|
|
9
9
|
import {
|
|
10
|
-
trackPackageError,
|
|
11
|
-
addPackageBreadcrumb,
|
|
12
|
-
} from "@umituz/react-native-sentry";
|
|
13
10
|
import { SUBSCRIPTION_QUERY_KEYS } from "./subscriptionQueryKeys";
|
|
14
11
|
import { creditsQueryKeys } from "../../../presentation/hooks/useCredits";
|
|
15
12
|
|
|
@@ -31,20 +28,17 @@ export const useRestorePurchase = (userId: string | undefined) => {
|
|
|
31
28
|
throw new Error("User not authenticated");
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
addPackageBreadcrumb("subscription", "Restore started", {
|
|
35
31
|
userId,
|
|
36
32
|
});
|
|
37
33
|
|
|
38
34
|
const result = await SubscriptionManager.restore();
|
|
39
35
|
|
|
40
36
|
if (result.success) {
|
|
41
|
-
addPackageBreadcrumb("subscription", "Restore success", {
|
|
42
37
|
userId,
|
|
43
38
|
productId: result.productId,
|
|
44
39
|
});
|
|
45
40
|
// Credits will be initialized by CustomerInfoListener
|
|
46
41
|
} else {
|
|
47
|
-
addPackageBreadcrumb("subscription", "Restore failed - no premium found", {
|
|
48
42
|
userId,
|
|
49
43
|
});
|
|
50
44
|
}
|
|
@@ -64,7 +58,6 @@ export const useRestorePurchase = (userId: string | undefined) => {
|
|
|
64
58
|
}
|
|
65
59
|
},
|
|
66
60
|
onError: (error) => {
|
|
67
|
-
trackPackageError(
|
|
68
61
|
error instanceof Error ? error : new Error(String(error)),
|
|
69
62
|
{
|
|
70
63
|
packageName: "subscription",
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import { useQuery } from "@tanstack/react-query";
|
|
7
7
|
import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager';
|
|
8
|
-
import { addPackageBreadcrumb } from "@umituz/react-native-sentry";
|
|
9
8
|
import {
|
|
10
9
|
SUBSCRIPTION_QUERY_KEYS,
|
|
11
10
|
STALE_TIME,
|
|
@@ -33,7 +32,6 @@ export const useSubscriptionPackages = (userId: string | undefined) => {
|
|
|
33
32
|
console.log('[DEBUG useSubscriptionPackages] QueryFn executing...', { userId: userId || 'ANONYMOUS' });
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
addPackageBreadcrumb("subscription", "Fetch packages query started", {
|
|
37
35
|
userId: userId ?? "ANONYMOUS",
|
|
38
36
|
});
|
|
39
37
|
|
|
@@ -85,7 +83,6 @@ export const useSubscriptionPackages = (userId: string | undefined) => {
|
|
|
85
83
|
});
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
addPackageBreadcrumb("subscription", "Fetch packages query success", {
|
|
89
86
|
userId: userId ?? "ANONYMOUS",
|
|
90
87
|
count: packages.length,
|
|
91
88
|
});
|