@umituz/react-native-subscription 2.37.38 → 2.37.40

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 (141) hide show
  1. package/package.json +1 -1
  2. package/src/domains/credits/application/CreditLimitCalculator.ts +1 -9
  3. package/src/domains/credits/application/CreditsInitializer.ts +5 -20
  4. package/src/domains/credits/application/DeductCreditsCommand.ts +13 -6
  5. package/src/domains/credits/application/RefundCreditsCommand.ts +1 -5
  6. package/src/domains/credits/application/credit-strategies/CreditAllocationOrchestrator.ts +1 -9
  7. package/src/domains/credits/application/credit-strategies/ICreditStrategy.ts +1 -5
  8. package/src/domains/credits/application/credit-strategies/TrialCreditStrategy.ts +1 -5
  9. package/src/domains/credits/application/creditDocumentHelpers.ts +2 -9
  10. package/src/domains/credits/application/creditOperationUtils.ts +1 -43
  11. package/src/domains/credits/core/Credits.ts +0 -23
  12. package/src/domains/credits/core/CreditsConstants.ts +0 -11
  13. package/src/domains/credits/core/CreditsMapper.ts +0 -6
  14. package/src/domains/credits/core/UserCreditsDocument.ts +0 -12
  15. package/src/domains/credits/infrastructure/CreditsRepository.ts +6 -1
  16. package/src/domains/credits/infrastructure/CreditsRepositoryManager.ts +0 -21
  17. package/src/domains/credits/infrastructure/operations/CreditsWriter.ts +52 -1
  18. package/src/domains/credits/presentation/deduct-credit/useDeductCredit.ts +2 -2
  19. package/src/domains/credits/presentation/useCredits.ts +10 -9
  20. package/src/domains/paywall/components/PaywallContainer.types.ts +0 -28
  21. package/src/domains/paywall/components/PaywallModal.styles.ts +0 -4
  22. package/src/domains/paywall/entities/types.ts +0 -5
  23. package/src/domains/paywall/hooks/usePaywallActions.ts +1 -15
  24. package/src/domains/revenuecat/core/errors/RevenueCatError.ts +0 -6
  25. package/src/domains/revenuecat/core/errors/RevenueCatErrorHandler.ts +0 -24
  26. package/src/domains/revenuecat/core/errors/RevenueCatErrorMessages.ts +0 -18
  27. package/src/domains/revenuecat/core/errors/index.ts +0 -4
  28. package/src/domains/revenuecat/core/types/RevenueCatConfig.ts +3 -7
  29. package/src/domains/revenuecat/core/types/RevenueCatData.ts +4 -9
  30. package/src/domains/revenuecat/core/types/RevenueCatTypes.ts +5 -65
  31. package/src/domains/revenuecat/core/types/index.ts +0 -4
  32. package/src/domains/revenuecat/infrastructure/services/UserSwitchMutex.ts +1 -24
  33. package/src/domains/subscription/application/SubscriptionAuthListener.ts +5 -21
  34. package/src/domains/subscription/application/SubscriptionInitializerTypes.ts +1 -5
  35. package/src/domains/subscription/application/SubscriptionSyncProcessor.ts +0 -4
  36. package/src/domains/subscription/application/SubscriptionSyncService.ts +4 -8
  37. package/src/domains/subscription/application/SubscriptionSyncUtils.ts +1 -1
  38. package/src/domains/subscription/application/initializer/BackgroundInitializer.ts +15 -2
  39. package/src/domains/subscription/application/initializer/ServiceConfigurator.ts +9 -2
  40. package/src/domains/subscription/application/statusChangeHandlers.ts +14 -27
  41. package/src/domains/subscription/application/syncIdGenerators.ts +0 -4
  42. package/src/domains/subscription/constants/thresholds.ts +0 -9
  43. package/src/domains/subscription/core/SubscriptionConstants.ts +0 -4
  44. package/src/domains/subscription/core/SubscriptionStatus.ts +11 -21
  45. package/src/domains/subscription/core/SubscriptionStatusHandlers.ts +4 -7
  46. package/src/domains/subscription/infrastructure/handlers/PurchaseStatusResolver.ts +1 -1
  47. package/src/domains/subscription/infrastructure/hooks/subscriptionQueryKeys.ts +0 -13
  48. package/src/domains/subscription/infrastructure/hooks/usePurchasePackage.ts +0 -18
  49. package/src/domains/subscription/infrastructure/hooks/useRestorePurchase.ts +3 -17
  50. package/src/domains/subscription/infrastructure/hooks/useRevenueCatTrialEligibility.ts +0 -17
  51. package/src/domains/subscription/infrastructure/hooks/useSubscriptionPackages.ts +0 -19
  52. package/src/domains/subscription/infrastructure/hooks/useSubscriptionQueries.ts +0 -6
  53. package/src/domains/subscription/infrastructure/managers/subscriptionManagerUtils.ts +0 -17
  54. package/src/domains/subscription/infrastructure/state/initializationState.ts +0 -25
  55. package/src/domains/subscription/infrastructure/utils/InitializationCache.ts +0 -21
  56. package/src/domains/subscription/infrastructure/utils/PremiumStatusSyncer.ts +3 -17
  57. package/src/domains/subscription/infrastructure/utils/authPurchaseState.ts +0 -5
  58. package/src/domains/subscription/infrastructure/utils/renewal/PackageTierComparator.ts +1 -0
  59. package/src/domains/subscription/infrastructure/utils/trialEligibilityUtils.ts +0 -18
  60. package/src/domains/subscription/presentation/components/details/PremiumDetailsCard.styles.ts +0 -5
  61. package/src/domains/subscription/presentation/components/details/PremiumDetailsCardTypes.ts +0 -5
  62. package/src/domains/subscription/presentation/components/feedback/paywallFeedbackStyles.ts +0 -5
  63. package/src/domains/subscription/presentation/stores/index.ts +0 -4
  64. package/src/domains/subscription/presentation/stores/purchaseLoadingStore.ts +0 -13
  65. package/src/domains/subscription/presentation/useAuthAwarePurchase.ts +30 -21
  66. package/src/domains/subscription/presentation/usePaywallVisibility.ts +0 -9
  67. package/src/domains/subscription/presentation/useSubscriptionStatus.ts +8 -11
  68. package/src/domains/subscription/utils/authGuards.ts +3 -0
  69. package/src/domains/trial/application/TrialService.ts +0 -9
  70. package/src/domains/trial/core/TrialTypes.ts +0 -8
  71. package/src/domains/wallet/domain/mappers/TransactionMapper.ts +0 -5
  72. package/src/domains/wallet/domain/types/transaction.types.ts +0 -7
  73. package/src/domains/wallet/index.ts +0 -7
  74. package/src/domains/wallet/infrastructure/config/walletConfig.ts +0 -11
  75. package/src/domains/wallet/presentation/hooks/useTransactionHistory.ts +6 -3
  76. package/src/domains/wallet/presentation/hooks/useWallet.ts +0 -7
  77. package/src/domains/wallet/utils/transactionIconMap.ts +0 -10
  78. package/src/global.d.ts +0 -6
  79. package/src/index.ts +1 -4
  80. package/src/init/createSubscriptionInitModule.ts +12 -2
  81. package/src/init/index.ts +1 -5
  82. package/src/presentation/hooks/feedback/useFeedbackSubmit.ts +0 -11
  83. package/src/shared/application/FeedbackService.ts +3 -21
  84. package/src/shared/application/ports/ISubscriptionRepository.ts +0 -4
  85. package/src/shared/infrastructure/SubscriptionEventBus.ts +0 -13
  86. package/src/shared/infrastructure/firestore/collectionUtils.ts +1 -17
  87. package/src/shared/infrastructure/firestore/index.ts +0 -4
  88. package/src/shared/infrastructure/firestore/resultUtils.ts +0 -12
  89. package/src/shared/infrastructure/react-query/hooks/usePreviousUserCleanup.ts +0 -17
  90. package/src/shared/infrastructure/react-query/queryConfig.ts +0 -15
  91. package/src/shared/utils/BaseError.ts +0 -5
  92. package/src/shared/utils/Result.ts +0 -20
  93. package/src/shared/utils/dateConverter.ts +6 -46
  94. package/src/utils/appUtils.ts +0 -16
  95. package/src/utils/creditMapper.ts +0 -7
  96. package/src/utils/dateUtils.compare.ts +0 -24
  97. package/src/utils/dateUtils.core.ts +0 -39
  98. package/src/utils/dateUtils.format.ts +0 -41
  99. package/src/utils/dateUtils.math.ts +0 -41
  100. package/src/utils/dateUtils.ts +0 -5
  101. package/src/utils/packagePeriodUtils.ts +0 -20
  102. package/src/utils/packageTypeDetector.ts +1 -21
  103. package/src/utils/premiumStatusUtils.ts +1 -14
  104. package/src/utils/priceUtils.ts +0 -35
  105. package/src/utils/tierUtils.ts +1 -8
  106. package/src/utils/types.ts +1 -25
  107. package/src/utils/validation.ts +1 -7
  108. package/src/domains/README.md +0 -52
  109. package/src/domains/config/domain/README.md +0 -37
  110. package/src/domains/config/domain/entities/README.md +0 -41
  111. package/src/domains/credits/application/credit-strategies/SyncCreditStrategy.ts +0 -24
  112. package/src/domains/paywall/README.md +0 -101
  113. package/src/domains/paywall/entities/README.md +0 -40
  114. package/src/domains/paywall/hooks/README.md +0 -41
  115. package/src/domains/subscription/application/syncConstants.ts +0 -1
  116. package/src/domains/subscription/infrastructure/README.md +0 -41
  117. package/src/domains/subscription/infrastructure/config/README.md +0 -49
  118. package/src/domains/subscription/infrastructure/handlers/README.md +0 -41
  119. package/src/domains/subscription/infrastructure/hooks/README.md +0 -50
  120. package/src/domains/subscription/infrastructure/managers/README.md +0 -41
  121. package/src/domains/subscription/infrastructure/services/README.md +0 -42
  122. package/src/domains/subscription/infrastructure/utils/README.md +0 -41
  123. package/src/domains/subscription/presentation/components/README.md +0 -155
  124. package/src/domains/subscription/presentation/components/details/CreditRow.md +0 -92
  125. package/src/domains/subscription/presentation/components/details/DetailRow.md +0 -91
  126. package/src/domains/subscription/presentation/components/details/PremiumDetailsCard.md +0 -93
  127. package/src/domains/subscription/presentation/components/details/PremiumStatusBadge.md +0 -91
  128. package/src/domains/subscription/presentation/components/details/README.md +0 -99
  129. package/src/domains/subscription/presentation/components/feedback/PaywallFeedbackModal.md +0 -90
  130. package/src/domains/subscription/presentation/components/feedback/README.md +0 -99
  131. package/src/domains/subscription/presentation/components/paywall/PaywallModal.md +0 -94
  132. package/src/domains/subscription/presentation/components/paywall/README.md +0 -54
  133. package/src/domains/subscription/presentation/components/sections/README.md +0 -99
  134. package/src/domains/subscription/presentation/components/sections/SubscriptionSection.md +0 -94
  135. package/src/domains/subscription/presentation/utils/README.md +0 -31
  136. package/src/domains/wallet/README.md +0 -51
  137. package/src/domains/wallet/domain/README.md +0 -41
  138. package/src/domains/wallet/infrastructure/README.md +0 -41
  139. package/src/domains/wallet/presentation/components/README.md +0 -41
  140. package/src/domains/wallet/presentation/hooks/README.md +0 -41
  141. package/src/shared/application/ports/README.md +0 -48
@@ -1,8 +1,3 @@
1
- /**
2
- * Premium Status Syncer
3
- * Syncs premium status to database via callbacks
4
- */
5
-
6
1
  import type { CustomerInfo } from "react-native-purchases";
7
2
  import type { RevenueCatConfig, PackageType } from "../../../revenuecat/core/types";
8
3
  import type { PurchaseSource } from "../../../subscription/core/SubscriptionConstants";
@@ -70,16 +65,7 @@ export async function notifyPurchaseCompleted(
70
65
  return;
71
66
  }
72
67
 
73
- try {
74
- await config.onPurchaseCompleted(userId, productId, customerInfo, source, packageType);
75
- } catch (error) {
76
- // Silently fail callback notifications to prevent crashing the main flow
77
- console.error('[PremiumStatusSyncer] Purchase completed callback failed:', {
78
- userId,
79
- productId,
80
- error: error instanceof Error ? error.message : String(error)
81
- });
82
- }
68
+ await config.onPurchaseCompleted(userId, productId, customerInfo, source, packageType);
83
69
  }
84
70
 
85
71
  export async function notifyRestoreCompleted(
@@ -94,7 +80,7 @@ export async function notifyRestoreCompleted(
94
80
 
95
81
  try {
96
82
  await config.onRestoreCompleted(userId, isPremium, customerInfo);
97
- } catch (_error) {
98
- // Silently fail callback notifications to prevent crashing the main flow
83
+ } catch (error) {
84
+ console.error('[PremiumStatusSyncer] Restore callback failed:', error instanceof Error ? error.message : String(error));
99
85
  }
100
86
  }
@@ -1,8 +1,3 @@
1
- /**
2
- * Auth Purchase State Manager
3
- * Manages global state for auth-aware purchase operations
4
- */
5
-
6
1
  import type { PurchasesPackage } from "react-native-purchases";
7
2
  import type { PurchaseSource } from "../../core/SubscriptionConstants";
8
3
 
@@ -4,6 +4,7 @@ const PACKAGE_TIER_ORDER: Record<string, number> = {
4
4
  weekly: 1,
5
5
  monthly: 2,
6
6
  yearly: 3,
7
+ lifetime: 4,
7
8
  unknown: 0,
8
9
  };
9
10
 
@@ -1,29 +1,18 @@
1
- /**
2
- * Trial Eligibility Utilities
3
- * Business logic for checking trial eligibility
4
- */
5
-
6
1
  import Purchases, {
7
2
  type IntroEligibility,
8
3
  INTRO_ELIGIBILITY_STATUS,
9
4
  } from "react-native-purchases";
10
5
 
11
- /** Trial eligibility info for a single product */
12
6
  export interface ProductTrialEligibility {
13
7
  productId: string;
14
8
  eligible: boolean;
15
9
  trialDurationDays?: number;
16
10
  }
17
11
 
18
- /** Map of product ID to eligibility */
19
12
  export type TrialEligibilityMap = Record<string, ProductTrialEligibility>;
20
13
 
21
- /** Default trial duration in days */
22
14
  const DEFAULT_TRIAL_DURATION_DAYS = 7;
23
15
 
24
- /**
25
- * Check trial eligibility for product IDs
26
- */
27
16
  export async function checkTrialEligibility(
28
17
  productIds: string[]
29
18
  ): Promise<TrialEligibilityMap> {
@@ -47,10 +36,6 @@ export async function checkTrialEligibility(
47
36
  return result;
48
37
  }
49
38
 
50
- /**
51
- * Create fallback eligibility map (all eligible)
52
- * Used when eligibility check fails
53
- */
54
39
  export function createFallbackEligibilityMap(
55
40
  productIds: string[]
56
41
  ): TrialEligibilityMap {
@@ -67,9 +52,6 @@ export function createFallbackEligibilityMap(
67
52
  return result;
68
53
  }
69
54
 
70
- /**
71
- * Check if any product has eligible trial
72
- */
73
55
  export function hasAnyEligibleTrial(
74
56
  eligibilityMap: TrialEligibilityMap
75
57
  ): boolean {
@@ -1,8 +1,3 @@
1
- /**
2
- * Premium Details Card Styles
3
- * StyleSheet for PremiumDetailsCard component
4
- */
5
-
6
1
  import { StyleSheet } from "react-native";
7
2
 
8
3
  export const styles = StyleSheet.create({
@@ -1,8 +1,3 @@
1
- /**
2
- * Premium Details Card Types
3
- * Type definitions for premium subscription details display
4
- */
5
-
6
1
  import type { SubscriptionStatusType } from "./PremiumStatusBadge";
7
2
 
8
3
  export interface CreditInfo {
@@ -1,8 +1,3 @@
1
- /**
2
- * Paywall Feedback Styles
3
- * Generates styles based on design tokens
4
- */
5
-
6
1
  import { StyleSheet } from "react-native";
7
2
  import type { DesignTokens } from "@umituz/react-native-design-system";
8
3
 
@@ -1,7 +1,3 @@
1
- /**
2
- * Presentation Layer - Stores
3
- */
4
-
5
1
  export {
6
2
  usePurchaseLoadingStore,
7
3
  selectIsPurchasing,
@@ -1,25 +1,13 @@
1
- /**
2
- * Purchase Loading Store
3
- * Global state for tracking purchase loading across the app
4
- * Supports concurrent purchases via Map-based tracking
5
- * Used by both PaywallModal and useSavedPurchaseAutoExecution
6
- */
7
-
8
1
  import { create } from "zustand";
9
2
 
10
3
  interface PurchaseLoadingState {
11
- /** Map of product IDs to purchase sources (supports concurrent purchases) */
12
4
  activePurchases: Map<string, "manual" | "auto-execution">;
13
5
  }
14
6
 
15
7
  interface PurchaseLoadingActions {
16
- /** Start purchase loading state for a product */
17
8
  startPurchase: (productId: string, source: "manual" | "auto-execution") => void;
18
- /** End purchase loading state for a product */
19
9
  endPurchase: (productId: string) => void;
20
- /** Check if any purchase is in progress, or if a specific product is being purchased */
21
10
  isPurchasing: (productId?: string) => boolean;
22
- /** Reset all state */
23
11
  reset: () => void;
24
12
  }
25
13
 
@@ -59,5 +47,4 @@ export const usePurchaseLoadingStore = create<PurchaseLoadingStore>((set, get) =
59
47
  },
60
48
  }));
61
49
 
62
- // Selectors for optimized re-renders
63
50
  export const selectIsPurchasing = (state: PurchaseLoadingStore) => state.activePurchases.size > 0;
@@ -1,9 +1,4 @@
1
- /**
2
- * Auth-Aware Purchase Hook
3
- * Handles purchase flow with authentication requirement
4
- */
5
-
6
- import { useCallback } from "react";
1
+ import { useCallback, useEffect, useRef } from "react";
7
2
  import type { PurchasesPackage } from "react-native-purchases";
8
3
  import { usePremium } from "./usePremium";
9
4
  import type { PurchaseSource } from "../core/SubscriptionConstants";
@@ -35,10 +30,38 @@ export const useAuthAwarePurchase = (
35
30
  params?: UseAuthAwarePurchaseParams
36
31
  ): UseAuthAwarePurchaseResult => {
37
32
  const { purchasePackage, restorePurchase } = usePremium();
33
+ const isExecutingSavedRef = useRef(false);
34
+
35
+ const executeSavedPurchase = useCallback(async (): Promise<boolean> => {
36
+ const saved = authPurchaseStateManager.getSavedPurchase();
37
+ if (!saved) {
38
+ return false;
39
+ }
40
+
41
+ const result = await purchasePackage(saved.pkg);
42
+ if (result) {
43
+ authPurchaseStateManager.clearSavedPurchase();
44
+ }
45
+ return result;
46
+ }, [purchasePackage]);
47
+
48
+ useEffect(() => {
49
+ const authProvider = authPurchaseStateManager.getProvider();
50
+ if (!authProvider) return;
51
+
52
+ const isAuth = authProvider.isAuthenticated();
53
+ const hasSavedPurchase = !!authPurchaseStateManager.getSavedPurchase();
54
+
55
+ if (isAuth && hasSavedPurchase && !isExecutingSavedRef.current) {
56
+ isExecutingSavedRef.current = true;
57
+ executeSavedPurchase().finally(() => {
58
+ isExecutingSavedRef.current = false;
59
+ });
60
+ }
61
+ });
38
62
 
39
63
  const handlePurchase = useCallback(
40
64
  async (pkg: PurchasesPackage, source?: PurchaseSource): Promise<boolean> => {
41
-
42
65
  const authProvider = authPurchaseStateManager.getProvider();
43
66
 
44
67
  if (!authProvider) {
@@ -61,7 +84,6 @@ export const useAuthAwarePurchase = (
61
84
  );
62
85
 
63
86
  const handleRestore = useCallback(async (): Promise<boolean> => {
64
-
65
87
  const authProvider = authPurchaseStateManager.getProvider();
66
88
 
67
89
  if (!authProvider) {
@@ -78,19 +100,6 @@ export const useAuthAwarePurchase = (
78
100
  return result;
79
101
  }, [restorePurchase]);
80
102
 
81
- const executeSavedPurchase = useCallback(async (): Promise<boolean> => {
82
- const saved = authPurchaseStateManager.getSavedPurchase();
83
- if (!saved) {
84
- return false;
85
- }
86
-
87
- const result = await purchasePackage(saved.pkg);
88
- if (result) {
89
- authPurchaseStateManager.clearSavedPurchase();
90
- }
91
- return result;
92
- }, [purchasePackage]);
93
-
94
103
  return {
95
104
  handlePurchase,
96
105
  handleRestore,
@@ -1,9 +1,3 @@
1
- /**
2
- * Paywall Visibility Hook
3
- * Simple global state for paywall visibility using module-level state
4
- * Generic implementation for 100+ apps
5
- */
6
-
7
1
  import { useCallback, useSyncExternalStore } from "react";
8
2
  import type { PurchaseSource } from "../core/SubscriptionConstants";
9
3
 
@@ -29,9 +23,6 @@ const setPaywallState = (visible: boolean, source?: PurchaseSource): void => {
29
23
  listeners.forEach((listener) => listener());
30
24
  };
31
25
 
32
- /**
33
- * Direct paywall control for non-React services (e.g., appInitializer)
34
- */
35
26
  export const paywallControl = {
36
27
  open: (source?: PurchaseSource) => setPaywallState(true, source),
37
28
  close: () => setPaywallState(false, undefined),
@@ -1,11 +1,11 @@
1
1
  import { useQuery, useQueryClient } from "@umituz/react-native-design-system";
2
2
  import { useEffect, useSyncExternalStore } from "react";
3
- import { useAuthStore, selectUserId } from "@umituz/react-native-auth";
3
+ import { useAuthStore, selectUserId, selectIsAnonymous } from "@umituz/react-native-auth";
4
4
  import { SubscriptionManager } from "../infrastructure/managers/SubscriptionManager";
5
5
  import { initializationState } from "../infrastructure/state/initializationState";
6
6
  import { subscriptionEventBus, SUBSCRIPTION_EVENTS } from "../../../shared/infrastructure/SubscriptionEventBus";
7
7
  import { SubscriptionStatusResult } from "./useSubscriptionStatus.types";
8
- import { isAuthenticated } from "../utils/authGuards";
8
+ import { isRegisteredUser } from "../utils/authGuards";
9
9
  import { NO_CACHE_QUERY_CONFIG } from "../../../shared/infrastructure/react-query/queryConfig";
10
10
  import { usePreviousUserCleanup } from "../../../shared/infrastructure/react-query/hooks/usePreviousUserCleanup";
11
11
 
@@ -17,32 +17,30 @@ export const subscriptionStatusQueryKeys = {
17
17
 
18
18
  export const useSubscriptionStatus = (): SubscriptionStatusResult => {
19
19
  const userId = useAuthStore(selectUserId);
20
+ const isAnonymous = useAuthStore(selectIsAnonymous);
20
21
  const queryClient = useQueryClient();
21
22
  const isConfigured = SubscriptionManager.isConfigured();
23
+ const isUserRegistered = isRegisteredUser(userId, isAnonymous);
22
24
 
23
- // Reactive initialization state - triggers re-render when BackgroundInitializer completes
24
25
  const initState = useSyncExternalStore(
25
26
  initializationState.subscribe,
26
27
  initializationState.getSnapshot,
27
28
  initializationState.getSnapshot,
28
29
  );
29
30
 
30
- // Check if initialized for this specific user (reactive)
31
31
  const isInitialized = userId
32
32
  ? initState.initialized && initState.userId === userId
33
33
  : false;
34
34
 
35
- const queryEnabled = isAuthenticated(userId) && isConfigured && isInitialized;
35
+ const queryEnabled = isUserRegistered && isConfigured && isInitialized;
36
36
 
37
37
  const { data, status, error, refetch } = useQuery({
38
38
  queryKey: subscriptionStatusQueryKeys.user(userId),
39
39
  queryFn: async () => {
40
- if (!isAuthenticated(userId)) {
40
+ if (!isUserRegistered) {
41
41
  return null;
42
42
  }
43
43
 
44
- // No side effects - just check premium status
45
- // Initialization is handled by BackgroundInitializer
46
44
  try {
47
45
  const result = await SubscriptionManager.checkPremiumStatus();
48
46
  return result;
@@ -54,11 +52,10 @@ export const useSubscriptionStatus = (): SubscriptionStatusResult => {
54
52
  ...NO_CACHE_QUERY_CONFIG,
55
53
  });
56
54
 
57
- // Clean up previous user's cache on logout/user switch
58
55
  usePreviousUserCleanup(userId, queryClient, subscriptionStatusQueryKeys.user);
59
56
 
60
57
  useEffect(() => {
61
- if (!isAuthenticated(userId)) return undefined;
58
+ if (!isUserRegistered) return undefined;
62
59
 
63
60
  const unsubscribe = subscriptionEventBus.on(
64
61
  SUBSCRIPTION_EVENTS.PREMIUM_STATUS_CHANGED,
@@ -72,7 +69,7 @@ export const useSubscriptionStatus = (): SubscriptionStatusResult => {
72
69
  );
73
70
 
74
71
  return unsubscribe;
75
- }, [userId, queryClient]);
72
+ }, [userId, isUserRegistered, queryClient]);
76
73
 
77
74
  const isLoading = status === "pending";
78
75
 
@@ -4,3 +4,6 @@ export function isAuthenticated(userId: string | null | undefined): userId is st
4
4
  return isDefined(userId) && userId.length > 0;
5
5
  }
6
6
 
7
+ export function isRegisteredUser(userId: string | null | undefined, isAnonymous: boolean): userId is string {
8
+ return isAuthenticated(userId) && !isAnonymous;
9
+ }
@@ -1,7 +1,3 @@
1
- /**
2
- * Trial Service - Facade for device-based trial tracking
3
- */
4
-
5
1
  import { arrayUnion, type FieldValue } from "firebase/firestore";
6
2
  import { serverTimestamp } from "@umituz/react-native-firebase";
7
3
  import { PersistentDeviceIdService } from "@umituz/react-native-design-system";
@@ -10,7 +6,6 @@ import { TrialEligibilityService } from "./TrialEligibilityService";
10
6
  import type { TrialEligibilityResult } from "../core/TrialTypes";
11
7
  export type { TrialEligibilityResult };
12
8
 
13
- // Type for Firestore write operations with FieldValue
14
9
  interface TrialRecordWrite {
15
10
  deviceId?: string;
16
11
  hasUsedTrial?: boolean;
@@ -26,10 +21,6 @@ const repository = new DeviceTrialRepository();
26
21
 
27
22
  export const getDeviceId = () => PersistentDeviceIdService.getDeviceId();
28
23
 
29
- /**
30
- * Ensures a valid device ID is available
31
- * Uses provided deviceId if non-empty, otherwise fetches from PersistentDeviceIdService
32
- */
33
24
  async function ensureDeviceId(deviceId?: string): Promise<string> {
34
25
  return (deviceId && deviceId.length > 0) ? deviceId : await getDeviceId();
35
26
  }
@@ -1,15 +1,8 @@
1
- /**
2
- * Trial Types and Constants
3
- * Device-based trial tracking types
4
- */
5
-
6
- /** Trial constants */
7
1
  export const TRIAL_CONFIG = {
8
2
  DURATION_DAYS: 3,
9
3
  CREDITS: 0,
10
4
  } as const;
11
5
 
12
- /** Device trial record in Firestore */
13
6
  export interface DeviceTrialRecord {
14
7
  deviceId: string;
15
8
  hasUsedTrial: boolean;
@@ -23,7 +16,6 @@ export interface DeviceTrialRecord {
23
16
  updatedAt: Date;
24
17
  }
25
18
 
26
- /** Trial eligibility result */
27
19
  export interface TrialEligibilityResult {
28
20
  eligible: boolean;
29
21
  reason?: "already_used" | "device_not_found" | "error" | "user_already_used";
@@ -1,8 +1,3 @@
1
- /**
2
- * Transaction Mapper
3
- * Maps Firestore data to CreditLog entity
4
- */
5
-
6
1
  import type { QueryDocumentSnapshot, DocumentData } from "firebase/firestore";
7
2
  import type { CreditLog } from "../types/transaction.types";
8
3
 
@@ -1,10 +1,3 @@
1
- /**
2
- * Transaction Types
3
- *
4
- * Types for credit transaction history and logs.
5
- * Generic types for use across hundreds of apps.
6
- */
7
-
8
1
  export type TransactionReason =
9
2
  | "purchase"
10
3
  | "usage"
@@ -1,10 +1,3 @@
1
- /**
2
- * Wallet Domain
3
- *
4
- * Public API for wallet functionality.
5
- */
6
-
7
- // Screens
8
1
  export {
9
2
  WalletScreen,
10
3
  } from "./presentation/screens/WalletScreen";
@@ -1,13 +1,5 @@
1
- /**
2
- * Wallet Configuration
3
- *
4
- * Global configuration for wallet feature.
5
- * Set once at app init, used by WalletScreen automatically.
6
- */
7
-
8
1
  import type { WalletScreenTranslations } from "../../presentation/screens/WalletScreen.types";
9
2
 
10
-
11
3
  interface WalletConfiguration {
12
4
  translations: WalletScreenTranslations;
13
5
  transactionCollection: string;
@@ -41,9 +33,6 @@ const DEFAULT_CONFIG: WalletConfiguration = {
41
33
 
42
34
  let walletConfig: WalletConfiguration = { ...DEFAULT_CONFIG };
43
35
 
44
- /**
45
- * Get current wallet configuration
46
- */
47
36
  export function getWalletConfig(): WalletConfiguration {
48
37
  return walletConfig;
49
38
  }
@@ -1,6 +1,6 @@
1
1
  import { useQuery } from "@umituz/react-native-design-system";
2
2
  import { useMemo } from "react";
3
- import { useAuthStore, selectUserId } from "@umituz/react-native-auth";
3
+ import { useAuthStore, selectUserId, selectIsAnonymous } from "@umituz/react-native-auth";
4
4
  import { NO_CACHE_QUERY_CONFIG } from "../../../../shared/infrastructure/react-query/queryConfig";
5
5
  import type {
6
6
  CreditLog,
@@ -31,16 +31,19 @@ export function useTransactionHistory({
31
31
  limit = 50,
32
32
  }: UseTransactionHistoryParams): UseTransactionHistoryResult {
33
33
  const userId = useAuthStore(selectUserId);
34
+ const isAnonymous = useAuthStore(selectIsAnonymous);
34
35
 
35
36
  const repository = useMemo(
36
37
  () => new TransactionRepository(config),
37
38
  [config]
38
39
  );
39
40
 
41
+ const isUserRegistered = !!userId && !isAnonymous;
42
+
40
43
  const { data, isLoading, error, refetch } = useQuery({
41
44
  queryKey: [...transactionQueryKeys.user(userId ?? ""), limit],
42
45
  queryFn: async () => {
43
- if (!userId) return [];
46
+ if (!userId || isAnonymous) return [];
44
47
 
45
48
  const result = await repository.getTransactions({
46
49
  userId,
@@ -53,7 +56,7 @@ export function useTransactionHistory({
53
56
 
54
57
  return result.data ?? [];
55
58
  },
56
- enabled: !!userId,
59
+ enabled: isUserRegistered,
57
60
  ...NO_CACHE_QUERY_CONFIG,
58
61
  });
59
62
 
@@ -1,10 +1,3 @@
1
- /**
2
- * useWallet Hook
3
- *
4
- * Orchestration hook for wallet functionality.
5
- * Combines balance, transactions, and purchase state.
6
- */
7
-
8
1
  import { useCallback, useMemo } from "react";
9
2
  import { useCredits } from "../../../credits/presentation/useCredits";
10
3
  import {
@@ -1,8 +1,3 @@
1
- /**
2
- * Transaction Icon Mapping Utility
3
- * Maps transaction reasons to their corresponding icons
4
- */
5
-
6
1
  import type { TransactionReason } from "../domain/types/transaction.types";
7
2
 
8
3
  const ICON_MAP: Record<TransactionReason, string> = {
@@ -16,11 +11,6 @@ const ICON_MAP: Record<TransactionReason, string> = {
16
11
  expired: "clock",
17
12
  };
18
13
 
19
- /**
20
- * Get icon name for a transaction reason
21
- * @param reason - Transaction reason type
22
- * @returns Icon name for the transaction
23
- */
24
14
  export function getTransactionIcon(reason: TransactionReason): string {
25
15
  return ICON_MAP[reason] || "circle";
26
16
  }
package/src/global.d.ts CHANGED
@@ -1,11 +1,5 @@
1
- /**
2
- * Global type declarations for React Native environment
3
- */
4
-
5
- /** React Native development flag */
6
1
  declare const __DEV__: boolean;
7
2
 
8
- /** Extend NodeJS namespace for React Native compatibility */
9
3
  declare namespace NodeJS {
10
4
  interface Global {
11
5
  __DEV__: boolean;
package/src/index.ts CHANGED
@@ -1,7 +1,3 @@
1
- /**
2
- * React Native Subscription - Public API
3
- */
4
-
5
1
  // Domain Layer - Constants & Types
6
2
  export * from "./domains/subscription/core/SubscriptionConstants";
7
3
  export {
@@ -112,6 +108,7 @@ export type { PurchaseLoadingOverlayProps } from "./domains/subscription/present
112
108
  // Init Module Factory
113
109
  export {
114
110
  createSubscriptionInitModule,
111
+ cleanupSubscriptionModule,
115
112
  type SubscriptionInitModuleConfig,
116
113
  } from './init';
117
114
 
@@ -7,6 +7,15 @@ export interface SubscriptionInitModuleConfig extends Omit<SubscriptionInitConfi
7
7
  dependsOn?: string[];
8
8
  }
9
9
 
10
+ let subscriptionCleanup: (() => void) | null = null;
11
+
12
+ export function cleanupSubscriptionModule(): void {
13
+ if (subscriptionCleanup) {
14
+ subscriptionCleanup();
15
+ subscriptionCleanup = null;
16
+ }
17
+ }
18
+
10
19
  export function createSubscriptionInitModule(config: SubscriptionInitModuleConfig): InitModule {
11
20
  const { getApiKey, critical = false, dependsOn = ['auth'], ...subscriptionConfig } = config;
12
21
 
@@ -21,9 +30,10 @@ export function createSubscriptionInitModule(config: SubscriptionInitModuleConfi
21
30
  return true;
22
31
  }
23
32
 
24
- await initializeSubscription({ apiKey, ...subscriptionConfig });
33
+ subscriptionCleanup = await initializeSubscription({ apiKey, ...subscriptionConfig });
25
34
  return true;
26
- } catch {
35
+ } catch (error) {
36
+ console.error('[SubscriptionInitModule] Initialization failed:', error instanceof Error ? error.message : String(error));
27
37
  return false;
28
38
  }
29
39
  },
package/src/init/index.ts CHANGED
@@ -1,9 +1,5 @@
1
- /**
2
- * Subscription Init Module
3
- * Provides factory for creating app initialization modules
4
- */
5
-
6
1
  export {
7
2
  createSubscriptionInitModule,
3
+ cleanupSubscriptionModule,
8
4
  type SubscriptionInitModuleConfig,
9
5
  } from './createSubscriptionInitModule';
@@ -1,8 +1,3 @@
1
- /**
2
- * Feedback Submit Hooks
3
- * React hooks for submitting feedback to Firestore
4
- */
5
-
6
1
  import { useCallback } from "react";
7
2
  import { useAuth } from "@umituz/react-native-auth";
8
3
  import {
@@ -16,9 +11,6 @@ export interface UsePaywallFeedbackSubmitOptions {
16
11
  onComplete?: () => void;
17
12
  }
18
13
 
19
- /**
20
- * Hook for submitting paywall decline feedback
21
- */
22
14
  export function usePaywallFeedbackSubmit(
23
15
  options: UsePaywallFeedbackSubmitOptions = {}
24
16
  ) {
@@ -63,9 +55,6 @@ export interface UseSettingsFeedbackSubmitOptions {
63
55
  onError?: (error: Error) => void;
64
56
  }
65
57
 
66
- /**
67
- * Hook for submitting general settings feedback
68
- */
69
58
  export function useSettingsFeedbackSubmit(
70
59
  options: UseSettingsFeedbackSubmitOptions = {}
71
60
  ) {