@umituz/react-native-subscription 2.12.29 → 2.12.31

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 (23) hide show
  1. package/package.json +1 -1
  2. package/src/domains/paywall/components/CreditCard.tsx +2 -2
  3. package/src/domains/paywall/components/FeatureList.tsx +1 -1
  4. package/src/domains/paywall/components/PaywallModal.tsx +1 -1
  5. package/src/domains/paywall/components/PaywallTabBar.tsx +1 -1
  6. package/src/domains/paywall/components/PlanCard.tsx +1 -1
  7. package/src/presentation/components/details/PremiumStatusBadge.tsx +1 -1
  8. package/src/revenuecat/infrastructure/handlers/PackageHandler.ts +2 -2
  9. package/src/revenuecat/infrastructure/managers/SubscriptionManager.ts +7 -7
  10. package/src/revenuecat/infrastructure/services/CustomerInfoListenerManager.ts +2 -2
  11. package/src/revenuecat/infrastructure/services/PurchaseHandler.ts +5 -5
  12. package/src/revenuecat/infrastructure/services/RestoreHandler.ts +5 -5
  13. package/src/revenuecat/infrastructure/services/RevenueCatInitializer.ts +59 -4
  14. package/src/revenuecat/infrastructure/services/RevenueCatService.ts +3 -3
  15. package/src/revenuecat/infrastructure/services/ServiceStateManager.ts +2 -2
  16. package/src/revenuecat/infrastructure/utils/ApiKeyResolver.ts +21 -1
  17. package/src/revenuecat/infrastructure/utils/ExpirationDateCalculator.ts +1 -1
  18. package/src/revenuecat/infrastructure/utils/PremiumStatusSyncer.ts +2 -2
  19. package/src/revenuecat/presentation/hooks/useInitializeSubscription.ts +1 -1
  20. package/src/revenuecat/presentation/hooks/usePurchasePackage.ts +1 -1
  21. package/src/revenuecat/presentation/hooks/useRestorePurchase.ts +1 -1
  22. package/src/revenuecat/presentation/hooks/useRevenueCat.ts +2 -2
  23. package/src/revenuecat/presentation/hooks/useSubscriptionPackages.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-subscription",
3
- "version": "2.12.29",
3
+ "version": "2.12.31",
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",
@@ -6,9 +6,9 @@
6
6
  import React from "react";
7
7
  import { View, TouchableOpacity, StyleSheet } from "react-native";
8
8
  import { AtomicText, AtomicIcon, AtomicBadge, useAppDesignTokens } from "@umituz/react-native-design-system";
9
- import type { CreditsPackage } from '../entities";
9
+ import type { CreditsPackage } from '../entities';
10
10
 
11
- import { formatPrice } from '../../../utils/priceUtils";
11
+ import { formatPrice } from '../../../utils/priceUtils';
12
12
 
13
13
  interface CreditCardProps {
14
14
  pkg: CreditsPackage;
@@ -6,7 +6,7 @@
6
6
  import React from "react";
7
7
  import { View, StyleSheet } from "react-native";
8
8
  import { FeatureItem } from "./FeatureItem";
9
- import type { SubscriptionFeature } from '../entities";
9
+ import type { SubscriptionFeature } from '../entities';
10
10
 
11
11
  interface FeatureListProps {
12
12
  features: SubscriptionFeature[];
@@ -9,7 +9,7 @@ import { BaseModal, useAppDesignTokens, AtomicText, AtomicIcon } from "@umituz/r
9
9
  import type { PurchasesPackage } from "react-native-purchases";
10
10
  import { PlanCard } from "./PlanCard";
11
11
  import { CreditCard } from "./CreditCard";
12
- import type { PaywallMode, CreditsPackage, SubscriptionFeature, PaywallTranslations, PaywallLegalUrls } from '../entities";
12
+ import type { PaywallMode, CreditsPackage, SubscriptionFeature, PaywallTranslations, PaywallLegalUrls } from '../entities';
13
13
 
14
14
  export interface PaywallModalProps {
15
15
  visible: boolean;
@@ -6,7 +6,7 @@
6
6
  import React from "react";
7
7
  import { View, TouchableOpacity, StyleSheet, Animated } from "react-native";
8
8
  import { AtomicText, useAppDesignTokens } from "@umituz/react-native-design-system";
9
- import type { PaywallTabType } from '../entities";
9
+ import type { PaywallTabType } from '../entities';
10
10
 
11
11
  interface PaywallTabBarProps {
12
12
  activeTab: PaywallTabType;
@@ -8,7 +8,7 @@ import { View, TouchableOpacity, StyleSheet } from "react-native";
8
8
  import { AtomicText, AtomicIcon, AtomicBadge, useAppDesignTokens } from "@umituz/react-native-design-system";
9
9
  import type { PurchasesPackage } from "react-native-purchases";
10
10
 
11
- import { formatPrice } from '../../../utils/priceUtils";
11
+ import { formatPrice } from '../../../utils/priceUtils';
12
12
 
13
13
  interface PlanCardProps {
14
14
  pkg: PurchasesPackage;
@@ -6,7 +6,7 @@
6
6
  import React from "react";
7
7
  import { View, StyleSheet } from "react-native";
8
8
  import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-system";
9
- import { SubscriptionStatusType } from '../../../domain/entities/SubscriptionStatus";
9
+ import { SubscriptionStatusType } from '../../../domain/entities/SubscriptionStatus';
10
10
  export type { SubscriptionStatusType };
11
11
 
12
12
  export interface PremiumStatusBadgeProps {
@@ -4,8 +4,8 @@
4
4
  */
5
5
 
6
6
  import type { PurchasesPackage } from "react-native-purchases";
7
- import type { IRevenueCatService } from '../../application/ports/IRevenueCatService";
8
- import { getPremiumEntitlement } from '../../domain/types/RevenueCatTypes";
7
+ import type { IRevenueCatService } from '../../application/ports/IRevenueCatService';
8
+ import { getPremiumEntitlement } from '../../domain/types/RevenueCatTypes';
9
9
  import {
10
10
  trackPackageError,
11
11
  addPackageBreadcrumb,
@@ -5,13 +5,13 @@
5
5
  */
6
6
 
7
7
  import type { PurchasesPackage } from "react-native-purchases";
8
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
9
- import type { IRevenueCatService } from '../../application/ports/IRevenueCatService";
10
- import { initializeRevenueCatService, getRevenueCatService } from '../services/RevenueCatService";
11
- import { UserIdProvider } from '../utils/UserIdProvider";
12
- import { InitializationCache } from '../utils/InitializationCache";
13
- import { PackageHandler } from '../handlers/PackageHandler";
14
- import type { PremiumStatus } from '../handlers/PackageHandler";
8
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
9
+ import type { IRevenueCatService } from '../../application/ports/IRevenueCatService';
10
+ import { initializeRevenueCatService, getRevenueCatService } from '../services/RevenueCatService';
11
+ import { UserIdProvider } from '../utils/UserIdProvider';
12
+ import { InitializationCache } from '../utils/InitializationCache';
13
+ import { PackageHandler } from '../handlers/PackageHandler';
14
+ import type { PremiumStatus } from '../handlers/PackageHandler';
15
15
  import {
16
16
  trackPackageError,
17
17
  addPackageBreadcrumb,
@@ -7,8 +7,8 @@ import Purchases, {
7
7
  type CustomerInfo,
8
8
  type CustomerInfoUpdateListener,
9
9
  } from "react-native-purchases";
10
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
11
- import { syncPremiumStatus } from '../utils/PremiumStatusSyncer";
10
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
11
+ import { syncPremiumStatus } from '../utils/PremiumStatusSyncer';
12
12
  import { addPackageBreadcrumb } from "@umituz/react-native-sentry";
13
13
 
14
14
  export class CustomerInfoListenerManager {
@@ -4,20 +4,20 @@
4
4
  */
5
5
 
6
6
  import Purchases, { type PurchasesPackage } from "react-native-purchases";
7
- import type { PurchaseResult } from '../../application/ports/IRevenueCatService";
7
+ import type { PurchaseResult } from '../../application/ports/IRevenueCatService';
8
8
  import {
9
9
  RevenueCatPurchaseError,
10
10
  RevenueCatInitializationError,
11
- } from '../../domain/errors/RevenueCatError";
12
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
11
+ } from '../../domain/errors/RevenueCatError';
12
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
13
13
  import {
14
14
  isUserCancelledError,
15
15
  getErrorMessage,
16
- } from '../../domain/types/RevenueCatTypes";
16
+ } from '../../domain/types/RevenueCatTypes';
17
17
  import {
18
18
  syncPremiumStatus,
19
19
  notifyPurchaseCompleted,
20
- } from '../utils/PremiumStatusSyncer";
20
+ } from '../utils/PremiumStatusSyncer';
21
21
  import {
22
22
  trackPackageError,
23
23
  addPackageBreadcrumb,
@@ -4,17 +4,17 @@
4
4
  */
5
5
 
6
6
  import Purchases from "react-native-purchases";
7
- import type { RestoreResult } from '../../application/ports/IRevenueCatService";
7
+ import type { RestoreResult } from '../../application/ports/IRevenueCatService';
8
8
  import {
9
9
  RevenueCatRestoreError,
10
10
  RevenueCatInitializationError,
11
- } from '../../domain/errors/RevenueCatError";
12
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
13
- import { getErrorMessage } from '../../domain/types/RevenueCatTypes";
11
+ } from '../../domain/errors/RevenueCatError';
12
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
13
+ import { getErrorMessage } from '../../domain/types/RevenueCatTypes';
14
14
  import {
15
15
  syncPremiumStatus,
16
16
  notifyRestoreCompleted,
17
- } from '../utils/PremiumStatusSyncer";
17
+ } from '../utils/PremiumStatusSyncer';
18
18
  import {
19
19
  trackPackageError,
20
20
  addPackageBreadcrumb,
@@ -4,10 +4,10 @@
4
4
  */
5
5
 
6
6
  import Purchases 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
  import {
12
12
  trackPackageError,
13
13
  addPackageBreadcrumb,
@@ -30,6 +30,16 @@ export async function initializeSDK(
30
30
  userId: string,
31
31
  apiKey?: string
32
32
  ): Promise<InitializeResult> {
33
+ if (__DEV__) {
34
+ console.log('[DEBUG RevenueCatInitializer] initializeSDK called', {
35
+ userId,
36
+ hasApiKey: !!apiKey,
37
+ isAlreadyConfigured: isPurchasesConfigured,
38
+ isInitialized: deps.isInitialized(),
39
+ currentUserId: deps.getCurrentUserId(),
40
+ });
41
+ }
42
+
33
43
  addPackageBreadcrumb("subscription", "SDK initialization started", {
34
44
  userId,
35
45
  hasApiKey: !!apiKey,
@@ -82,7 +92,20 @@ export async function initializeSDK(
82
92
 
83
93
  // Case 3: First time configuration
84
94
  const key = apiKey || resolveApiKey(deps.config);
95
+ if (__DEV__) {
96
+ console.log('[DEBUG RevenueCatInitializer] Resolved API key', {
97
+ hasKey: !!key,
98
+ keyPrefix: key ? key.substring(0, 10) + '...' : 'null',
99
+ isTestStore: deps.isUsingTestStore(),
100
+ configApiKey: deps.config.apiKey ? deps.config.apiKey.substring(0, 10) + '...' : 'null',
101
+ configTestStoreKey: deps.config.testStoreKey ? deps.config.testStoreKey.substring(0, 10) + '...' : 'null',
102
+ });
103
+ }
104
+
85
105
  if (!key) {
106
+ if (__DEV__) {
107
+ console.log('[DEBUG RevenueCatInitializer] ERROR: No API key available!');
108
+ }
86
109
  const error = new Error("No RevenueCat API key available");
87
110
  trackPackageError(error, {
88
111
  packageName: "subscription",
@@ -93,11 +116,21 @@ export async function initializeSDK(
93
116
  }
94
117
 
95
118
  try {
119
+ if (__DEV__) {
120
+ console.log('[DEBUG RevenueCatInitializer] Calling Purchases.configure', {
121
+ apiKey: key.substring(0, 10) + '...',
122
+ appUserID: userId,
123
+ });
124
+ }
96
125
  await Purchases.configure({ apiKey: key, appUserID: userId });
97
126
  isPurchasesConfigured = true;
98
127
  deps.setInitialized(true);
99
128
  deps.setCurrentUserId(userId);
100
129
 
130
+ if (__DEV__) {
131
+ console.log('[DEBUG RevenueCatInitializer] Purchases.configure succeeded, fetching data...');
132
+ }
133
+
101
134
  const [customerInfo, offerings] = await Promise.all([
102
135
  Purchases.getCustomerInfo(),
103
136
  Purchases.getOfferings(),
@@ -105,6 +138,20 @@ export async function initializeSDK(
105
138
 
106
139
  const packagesCount = offerings.current?.availablePackages?.length ?? 0;
107
140
 
141
+ if (__DEV__) {
142
+ console.log('[DEBUG RevenueCatInitializer] Data fetched', {
143
+ hasCurrent: !!offerings.current,
144
+ currentIdentifier: offerings.current?.identifier,
145
+ packagesCount,
146
+ allOfferingsCount: Object.keys(offerings.all).length,
147
+ allOfferingIds: Object.keys(offerings.all),
148
+ packages: offerings.current?.availablePackages?.map(p => ({
149
+ identifier: p.identifier,
150
+ packageType: p.packageType,
151
+ })),
152
+ });
153
+ }
154
+
108
155
  addPackageBreadcrumb("subscription", "Offerings fetched", {
109
156
  userId,
110
157
  hasCurrent: !!offerings.current,
@@ -119,6 +166,14 @@ export async function initializeSDK(
119
166
  } catch (error) {
120
167
  const errorMessage = getErrorMessage(error, "RevenueCat init failed");
121
168
 
169
+ if (__DEV__) {
170
+ console.log('[DEBUG RevenueCatInitializer] ERROR during initialization', {
171
+ error,
172
+ errorMessage,
173
+ errorType: error instanceof Error ? error.constructor.name : typeof error,
174
+ });
175
+ }
176
+
122
177
  trackPackageError(
123
178
  error instanceof Error ? error : new Error(errorMessage),
124
179
  {
@@ -10,9 +10,9 @@ import type {
10
10
  InitializeResult,
11
11
  PurchaseResult,
12
12
  RestoreResult,
13
- } from '../../application/ports/IRevenueCatService";
14
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
15
- import { resolveApiKey } from '../utils/ApiKeyResolver";
13
+ } from '../../application/ports/IRevenueCatService';
14
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
15
+ import { resolveApiKey } from '../utils/ApiKeyResolver';
16
16
  import { initializeSDK } from "./RevenueCatInitializer";
17
17
  import { fetchOfferings } from "./OfferingsFetcher";
18
18
  import { handlePurchase } from "./PurchaseHandler";
@@ -3,8 +3,8 @@
3
3
  * Manages RevenueCat service state
4
4
  */
5
5
 
6
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
7
- import { isExpoGo, isDevelopment } from '../utils/ExpoGoDetector";
6
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
7
+ import { isExpoGo, isDevelopment } from '../utils/ExpoGoDetector';
8
8
 
9
9
  export class ServiceStateManager {
10
10
  private isInitializedFlag: boolean = false;
@@ -4,7 +4,7 @@
4
4
  * NOTE: Main app is responsible for resolving platform-specific keys
5
5
  */
6
6
 
7
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
7
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
8
8
  import { isTestStoreEnvironment } from "./ExpoGoDetector";
9
9
 
10
10
  /**
@@ -31,15 +31,35 @@ export function shouldUseTestStore(config: RevenueCatConfig): boolean {
31
31
  export function resolveApiKey(config: RevenueCatConfig): string | null {
32
32
  const useTestStore = shouldUseTestStore(config);
33
33
 
34
+ if (__DEV__) {
35
+ console.log('[DEBUG ApiKeyResolver] resolveApiKey called', {
36
+ useTestStore,
37
+ hasTestStoreKey: !!config.testStoreKey,
38
+ hasApiKey: !!config.apiKey,
39
+ testStoreKeyPrefix: config.testStoreKey ? config.testStoreKey.substring(0, 10) + '...' : 'null',
40
+ apiKeyPrefix: config.apiKey ? config.apiKey.substring(0, 10) + '...' : 'null',
41
+ });
42
+ }
43
+
34
44
  if (useTestStore) {
45
+ if (__DEV__) {
46
+ console.log('[DEBUG ApiKeyResolver] Using Test Store key');
47
+ }
35
48
  return config.testStoreKey ?? null;
36
49
  }
37
50
 
38
51
  const key = config.apiKey;
39
52
 
40
53
  if (!key || key === "" || key.includes("YOUR_")) {
54
+ if (__DEV__) {
55
+ console.log('[DEBUG ApiKeyResolver] No valid production API key');
56
+ }
41
57
  return null;
42
58
  }
43
59
 
60
+ if (__DEV__) {
61
+ console.log('[DEBUG ApiKeyResolver] Using production API key');
62
+ }
63
+
44
64
  return key;
45
65
  }
@@ -3,7 +3,7 @@
3
3
  * Handles RevenueCat expiration date extraction
4
4
  */
5
5
 
6
- import type { RevenueCatEntitlement } from '../../domain/types/RevenueCatTypes";
6
+ import type { RevenueCatEntitlement } from '../../domain/types/RevenueCatTypes';
7
7
 
8
8
  export function getExpirationDate(
9
9
  entitlement: RevenueCatEntitlement | null
@@ -4,8 +4,8 @@
4
4
  */
5
5
 
6
6
  import type { CustomerInfo } from "react-native-purchases";
7
- import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig";
8
- import { getPremiumEntitlement } from '../../domain/types/RevenueCatTypes";
7
+ import type { RevenueCatConfig } from '../../domain/value-objects/RevenueCatConfig';
8
+ import { getPremiumEntitlement } from '../../domain/types/RevenueCatTypes';
9
9
  import { getExpirationDate } from "./ExpirationDateCalculator";
10
10
  import {
11
11
  trackPackageError,
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { useMutation, useQueryClient } from "@tanstack/react-query";
7
- import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager";
7
+ import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager';
8
8
  import {
9
9
  trackPackageError,
10
10
  addPackageBreadcrumb,
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { useMutation, useQueryClient } from "@tanstack/react-query";
7
7
  import type { PurchasesPackage } from "react-native-purchases";
8
- import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager";
8
+ import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager';
9
9
  import {
10
10
  trackPackageError,
11
11
  addPackageBreadcrumb,
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { useMutation, useQueryClient } from "@tanstack/react-query";
7
- import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager";
7
+ import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager';
8
8
  import {
9
9
  trackPackageError,
10
10
  addPackageBreadcrumb,
@@ -5,8 +5,8 @@
5
5
 
6
6
  import { useState, useCallback } from "react";
7
7
  import type { PurchasesOffering, PurchasesPackage } from "react-native-purchases";
8
- import { getRevenueCatService } from '../../infrastructure/services/RevenueCatService";
9
- import type { PurchaseResult, RestoreResult } from '../../application/ports/IRevenueCatService";
8
+ import { getRevenueCatService } from '../../infrastructure/services/RevenueCatService';
9
+ import type { PurchaseResult, RestoreResult } from '../../application/ports/IRevenueCatService';
10
10
 
11
11
  export interface UseRevenueCatResult {
12
12
  /** Current offering */
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { useQuery } from "@tanstack/react-query";
7
- import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager";
7
+ import { SubscriptionManager } from '../../infrastructure/managers/SubscriptionManager';
8
8
  import { addPackageBreadcrumb } from "@umituz/react-native-sentry";
9
9
  import {
10
10
  SUBSCRIPTION_QUERY_KEYS,