@umituz/react-native-subscription 2.27.53 → 2.27.54
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 -1
- package/src/domain/entities/Credits.ts +2 -1
- package/src/infrastructure/models/UserCreditsDocument.ts +2 -1
- package/src/infrastructure/repositories/CreditsRepository.ts +11 -8
- package/src/infrastructure/services/SubscriptionInitializer.ts +6 -6
- package/src/infrastructure/services/SubscriptionInitializerTypes.ts +0 -10
- package/src/revenuecat/domain/value-objects/RevenueCatConfig.ts +2 -1
- package/src/revenuecat/infrastructure/services/RevenueCatInitializer.ts +2 -2
- package/src/revenuecat/infrastructure/utils/InitializationCache.ts +0 -22
- package/src/revenuecat/infrastructure/utils/PremiumStatusSyncer.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.27.
|
|
3
|
+
"version": "2.27.54",
|
|
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",
|
|
@@ -42,9 +42,10 @@ export class CreditsRepository extends BaseRepository {
|
|
|
42
42
|
const entity = CreditsMapper.toEntity(d);
|
|
43
43
|
if (__DEV__) console.log("[CreditsRepository] Credits fetched:", { credits: entity.credits, limit: entity.creditLimit });
|
|
44
44
|
return { success: true, data: entity };
|
|
45
|
-
} catch (e:
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
} catch (e: unknown) {
|
|
46
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
47
|
+
if (__DEV__) console.error("[CreditsRepository] Fetch error:", message);
|
|
48
|
+
return { success: false, error: { message, code: "FETCH_ERR" } };
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -80,8 +81,9 @@ export class CreditsRepository extends BaseRepository {
|
|
|
80
81
|
success: true,
|
|
81
82
|
data: CreditsMapper.toEntity({ ...res, purchasedAt: undefined, lastUpdatedAt: undefined })
|
|
82
83
|
};
|
|
83
|
-
} catch (e:
|
|
84
|
-
|
|
84
|
+
} catch (e: unknown) {
|
|
85
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
86
|
+
return { success: false, error: { message, code: "INIT_ERR" } };
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
|
|
@@ -99,9 +101,10 @@ export class CreditsRepository extends BaseRepository {
|
|
|
99
101
|
return updated;
|
|
100
102
|
});
|
|
101
103
|
return { success: true, remainingCredits: remaining };
|
|
102
|
-
} catch (e:
|
|
103
|
-
const
|
|
104
|
-
|
|
104
|
+
} catch (e: unknown) {
|
|
105
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
106
|
+
const code = message === "NO_CREDITS" || message === "CREDITS_EXHAUSTED" ? message : "DEDUCT_ERR";
|
|
107
|
+
return { success: false, error: { message, code } };
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
|
|
@@ -15,6 +15,7 @@ import { SubscriptionManager } from "../../revenuecat/infrastructure/managers/Su
|
|
|
15
15
|
import { configureAuthProvider } from "../../presentation/hooks/useAuthAwarePurchase";
|
|
16
16
|
import type { RevenueCatData } from "../../domain/types/RevenueCatData";
|
|
17
17
|
import type { SubscriptionInitConfig, FirebaseAuthLike } from "./SubscriptionInitializerTypes";
|
|
18
|
+
import type { PurchaseSource } from "../../domain/entities/Credits";
|
|
18
19
|
|
|
19
20
|
export type { FirebaseAuthLike, CreditPackageConfig, SubscriptionInitConfig } from "./SubscriptionInitializerTypes";
|
|
20
21
|
|
|
@@ -63,7 +64,6 @@ export const initializeSubscription = async (config: SubscriptionInitConfig): Pr
|
|
|
63
64
|
apiKey, apiKeyIos, apiKeyAndroid, entitlementId, credits,
|
|
64
65
|
getAnonymousUserId, getFirebaseAuth, showAuthModal,
|
|
65
66
|
onCreditsUpdated, creditPackages,
|
|
66
|
-
// Note: timeoutMs and authStateTimeoutMs are deprecated and ignored
|
|
67
67
|
} = config;
|
|
68
68
|
|
|
69
69
|
const key = Platform.OS === 'ios' ? (apiKeyIos || apiKey || '') : (apiKeyAndroid || apiKey || '');
|
|
@@ -71,11 +71,11 @@ export const initializeSubscription = async (config: SubscriptionInitConfig): Pr
|
|
|
71
71
|
|
|
72
72
|
configureCreditsRepository({ ...credits, creditPackageAmounts: creditPackages?.amounts });
|
|
73
73
|
|
|
74
|
-
const onPurchase = async (userId: string, productId: string, customerInfo: CustomerInfo, source?:
|
|
74
|
+
const onPurchase = async (userId: string, productId: string, customerInfo: CustomerInfo, source?: PurchaseSource) => {
|
|
75
75
|
if (__DEV__) console.log('[SubscriptionInitializer] onPurchase:', { userId, productId, source });
|
|
76
76
|
try {
|
|
77
77
|
const revenueCatData = extractRevenueCatData(customerInfo, entitlementId);
|
|
78
|
-
await getCreditsRepository().initializeCredits(userId, `purchase_${productId}_${Date.now()}`, productId, source
|
|
78
|
+
await getCreditsRepository().initializeCredits(userId, `purchase_${productId}_${Date.now()}`, productId, source, revenueCatData);
|
|
79
79
|
onCreditsUpdated?.(userId);
|
|
80
80
|
} catch (error) {
|
|
81
81
|
if (__DEV__) console.error('[SubscriptionInitializer] Credits init failed:', error);
|
|
@@ -87,7 +87,7 @@ export const initializeSubscription = async (config: SubscriptionInitConfig): Pr
|
|
|
87
87
|
try {
|
|
88
88
|
const revenueCatData = extractRevenueCatData(customerInfo, entitlementId);
|
|
89
89
|
revenueCatData.expirationDate = newExpirationDate || revenueCatData.expirationDate;
|
|
90
|
-
await getCreditsRepository().initializeCredits(userId, `renewal_${productId}_${Date.now()}`, productId, "renewal"
|
|
90
|
+
await getCreditsRepository().initializeCredits(userId, `renewal_${productId}_${Date.now()}`, productId, "renewal", revenueCatData);
|
|
91
91
|
onCreditsUpdated?.(userId);
|
|
92
92
|
} catch (error) {
|
|
93
93
|
if (__DEV__) console.error('[SubscriptionInitializer] Renewal credits init failed:', error);
|
|
@@ -115,7 +115,7 @@ export const initializeSubscription = async (config: SubscriptionInitConfig): Pr
|
|
|
115
115
|
} else {
|
|
116
116
|
if (__DEV__) console.log('[SubscriptionInitializer] Canceled but not expired, preserving until:', expiresAt);
|
|
117
117
|
const revenueCatData: RevenueCatData = { expirationDate: expiresAt, willRenew: false, isPremium: true, periodType };
|
|
118
|
-
await getCreditsRepository().initializeCredits(userId, `status_sync_canceled_${Date.now()}`, productId, "settings"
|
|
118
|
+
await getCreditsRepository().initializeCredits(userId, `status_sync_canceled_${Date.now()}`, productId, "settings", revenueCatData);
|
|
119
119
|
}
|
|
120
120
|
onCreditsUpdated?.(userId);
|
|
121
121
|
return;
|
|
@@ -123,7 +123,7 @@ export const initializeSubscription = async (config: SubscriptionInitConfig): Pr
|
|
|
123
123
|
|
|
124
124
|
// Premium user - initialize credits with subscription data
|
|
125
125
|
const revenueCatData: RevenueCatData = { expirationDate: expiresAt ?? null, willRenew: willRenew ?? false, isPremium, periodType };
|
|
126
|
-
await getCreditsRepository().initializeCredits(userId, `status_sync_${Date.now()}`, productId, "settings"
|
|
126
|
+
await getCreditsRepository().initializeCredits(userId, `status_sync_${Date.now()}`, productId, "settings", revenueCatData);
|
|
127
127
|
if (__DEV__) console.log('[SubscriptionInitializer] Premium status synced to Firestore');
|
|
128
128
|
onCreditsUpdated?.(userId);
|
|
129
129
|
} catch (error) {
|
|
@@ -25,14 +25,4 @@ export interface SubscriptionInitConfig {
|
|
|
25
25
|
showAuthModal: () => void;
|
|
26
26
|
onCreditsUpdated?: (userId: string) => void;
|
|
27
27
|
creditPackages?: CreditPackageConfig;
|
|
28
|
-
/**
|
|
29
|
-
* @deprecated No longer used. Initialization is now non-blocking.
|
|
30
|
-
* RevenueCat best practice: Use listener pattern instead of timeouts.
|
|
31
|
-
*/
|
|
32
|
-
timeoutMs?: number;
|
|
33
|
-
/**
|
|
34
|
-
* @deprecated No longer used. Auth state is read synchronously.
|
|
35
|
-
* Auth state changes are handled reactively via onAuthStateChanged listener.
|
|
36
|
-
*/
|
|
37
|
-
authStateTimeoutMs?: number;
|
|
38
28
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CustomerInfo } from "react-native-purchases";
|
|
2
|
+
import type { PurchaseSource } from "../../../domain/entities/Credits";
|
|
2
3
|
|
|
3
4
|
export interface RevenueCatConfig {
|
|
4
5
|
apiKey?: string;
|
|
@@ -16,7 +17,7 @@ export interface RevenueCatConfig {
|
|
|
16
17
|
userId: string,
|
|
17
18
|
productId: string,
|
|
18
19
|
customerInfo: CustomerInfo,
|
|
19
|
-
source?:
|
|
20
|
+
source?: PurchaseSource
|
|
20
21
|
) => Promise<void> | void;
|
|
21
22
|
onRestoreCompleted?: (
|
|
22
23
|
userId: string,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Purchases, { LOG_LEVEL } from "react-native-purchases";
|
|
1
|
+
import Purchases, { LOG_LEVEL, type CustomerInfo, type PurchasesOfferings } from "react-native-purchases";
|
|
2
2
|
import type { InitializeResult } from "../../application/ports/IRevenueCatService";
|
|
3
3
|
import type { RevenueCatConfig } from "../../domain/value-objects/RevenueCatConfig";
|
|
4
4
|
import { resolveApiKey } from "../utils/ApiKeyResolver";
|
|
@@ -32,7 +32,7 @@ function configureLogHandler(): void {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function buildSuccessResult(deps: InitializerDeps, customerInfo:
|
|
35
|
+
function buildSuccessResult(deps: InitializerDeps, customerInfo: CustomerInfo, offerings: PurchasesOfferings): InitializeResult {
|
|
36
36
|
const hasPremium = !!customerInfo.entitlements.active[deps.config.entitlementIdentifier];
|
|
37
37
|
return { success: true, offering: offerings.current, hasPremium };
|
|
38
38
|
}
|
|
@@ -35,28 +35,6 @@ export class InitializationCache {
|
|
|
35
35
|
return { shouldInit: true, existingPromise: null };
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/**
|
|
39
|
-
* @deprecated Use tryAcquireInitialization instead for atomic operations
|
|
40
|
-
*/
|
|
41
|
-
shouldReinitialize(userId: string): boolean {
|
|
42
|
-
if (!this.initPromise) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (this.currentUserId !== userId) {
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @deprecated Use tryAcquireInitialization instead for atomic operations
|
|
55
|
-
*/
|
|
56
|
-
getExistingPromise(): Promise<boolean> | null {
|
|
57
|
-
return this.initPromise;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
38
|
setPromise(promise: Promise<boolean>, userId: string): void {
|
|
61
39
|
this.initPromise = promise;
|
|
62
40
|
this.promiseUserId = userId;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { CustomerInfo } from "react-native-purchases";
|
|
7
7
|
import type { RevenueCatConfig } from "../../domain/value-objects/RevenueCatConfig";
|
|
8
|
+
import type { PurchaseSource } from "../../../domain/entities/Credits";
|
|
8
9
|
import { getPremiumEntitlement } from "../../domain/types/RevenueCatTypes";
|
|
9
10
|
|
|
10
11
|
declare const __DEV__: boolean;
|
|
@@ -48,7 +49,7 @@ export async function notifyPurchaseCompleted(
|
|
|
48
49
|
userId: string,
|
|
49
50
|
productId: string,
|
|
50
51
|
customerInfo: CustomerInfo,
|
|
51
|
-
source?:
|
|
52
|
+
source?: PurchaseSource
|
|
52
53
|
): Promise<void> {
|
|
53
54
|
if (__DEV__) {
|
|
54
55
|
console.log('[PremiumStatusSyncer] notifyPurchaseCompleted called:', {
|