@umituz/react-native-subscription 2.41.7 → 2.41.9

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-subscription",
3
- "version": "2.41.7",
3
+ "version": "2.41.9",
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",
@@ -41,7 +41,8 @@ export async function refundCreditsOperation(
41
41
 
42
42
  const data = docSnap.data();
43
43
  const current = data.credits as number;
44
- const creditLimit = (data.creditLimit as number) ?? Infinity;
44
+ // If creditLimit is null, use the refund amount as the limit to prevent unlimited credits
45
+ const creditLimit = (data.creditLimit as number) ?? (current + amount);
45
46
  const updated = Math.min(current + amount, creditLimit);
46
47
 
47
48
  tx.update(creditsRef, {
@@ -63,11 +63,13 @@ export const useDeductCredit = ({
63
63
  }
64
64
  return false;
65
65
  } catch (error) {
66
- console.error('[useDeductCredit] Unexpected error during credit refund', {
67
- amount,
68
- userId,
69
- error: error instanceof Error ? error.message : String(error),
70
- });
66
+ if (__DEV__) {
67
+ console.error('[useDeductCredit] Unexpected error during credit refund', {
68
+ amount,
69
+ userId,
70
+ error: error instanceof Error ? error.message : String(error),
71
+ });
72
+ }
71
73
  return false;
72
74
  }
73
75
  }, [userId, repository, queryClient]);
@@ -2,7 +2,7 @@ import { useQuery, useQueryClient } from "@umituz/react-native-design-system/tan
2
2
  import { useCallback, useMemo, useEffect } from "react";
3
3
  import { useAuthStore, selectUserId } from "@umituz/react-native-auth";
4
4
  import { subscriptionEventBus, SUBSCRIPTION_EVENTS } from "../../../shared/infrastructure/SubscriptionEventBus";
5
- import { NO_CACHE_QUERY_CONFIG } from "../../../shared/infrastructure/react-query/queryConfig";
5
+ import { SHORT_CACHE_CONFIG } from "../../../shared/infrastructure/react-query/queryConfig";
6
6
  import { usePreviousUserCleanup } from "../../../shared/infrastructure/react-query/hooks/usePreviousUserCleanup";
7
7
  import {
8
8
  getCreditsRepository,
@@ -13,6 +13,7 @@ import { calculateSafePercentage, canAffordAmount } from "../utils/creditValidat
13
13
  import { isAuthenticated } from "../../subscription/utils/authGuards";
14
14
  import { creditsQueryKeys } from "./creditsQueryKeys";
15
15
  import type { UseCreditsResult, CreditsLoadStatus } from "./useCredits.types";
16
+ import type { UserCredits } from "../core/Credits";
16
17
 
17
18
  const deriveLoadStatus = (
18
19
  queryStatus: "pending" | "error" | "success",
@@ -32,7 +33,7 @@ export const useCredits = (): UseCreditsResult => {
32
33
  const hasUser = isAuthenticated(userId);
33
34
  const queryEnabled = hasUser && isConfigured;
34
35
 
35
- const { data, status, error, refetch } = useQuery({
36
+ const { data, status, error, refetch } = useQuery<UserCredits | null, Error>({
36
37
  queryKey: creditsQueryKeys.user(userId),
37
38
  queryFn: async () => {
38
39
  if (!hasUser || !isConfigured) return null;
@@ -47,7 +48,7 @@ export const useCredits = (): UseCreditsResult => {
47
48
  return result.data ?? null;
48
49
  },
49
50
  enabled: queryEnabled,
50
- ...NO_CACHE_QUERY_CONFIG,
51
+ ...SHORT_CACHE_CONFIG,
51
52
  });
52
53
 
53
54
  const queryClient = useQueryClient();
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useCallback, useRef } from "react";
2
2
  import { usePremium } from "../../subscription/presentation/usePremium";
3
- import { useSubscriptionFlow } from "../../subscription/presentation/useSubscriptionFlow";
3
+ import { useSubscriptionFlowStore } from "../../subscription/presentation/useSubscriptionFlow";
4
4
  import { usePaywallVisibility } from "../../subscription/presentation/usePaywallVisibility";
5
5
  import { PaywallTranslations, PaywallLegalUrls, SubscriptionFeature } from "../entities/types";
6
6
 
@@ -36,34 +36,39 @@ export function usePaywallOrchestrator({
36
36
  bestValueIdentifier = "yearly",
37
37
  creditsLabel,
38
38
  }: PaywallOrchestratorOptions) {
39
- const {
40
- isPremium,
41
- packages,
42
- purchasePackage,
43
- restorePurchase
39
+ const {
40
+ isPremium,
41
+ packages,
42
+ purchasePackage,
43
+ restorePurchase
44
44
  } = usePremium();
45
-
46
- const {
47
- state,
48
- markPaywallShown,
49
- closePostOnboardingPaywall,
50
- setShowFeedback
51
- } = useSubscriptionFlow();
52
-
45
+
46
+ // Selectors for stable references and fine-grained updates
47
+ const isOnboardingComplete = useSubscriptionFlowStore((state) => state.isOnboardingComplete);
48
+ const showPostOnboardingPaywall = useSubscriptionFlowStore((state) => state.showPostOnboardingPaywall);
49
+ const paywallShown = useSubscriptionFlowStore((state) => state.paywallShown);
50
+ const isAuthModalOpen = useSubscriptionFlowStore((state) => state.isAuthModalOpen);
51
+ const showFeedback = useSubscriptionFlowStore((state) => state.showFeedback);
52
+ const markPaywallShown = useSubscriptionFlowStore((state) => state.markPaywallShown);
53
+ const closePostOnboardingPaywall = useSubscriptionFlowStore((state) => state.closePostOnboardingPaywall);
54
+ const setShowFeedback = useSubscriptionFlowStore((state) => state.setShowFeedback);
55
+
53
56
  const { showPaywall, closePaywall } = usePaywallVisibility();
54
57
  const purchasedRef = useRef(false);
58
+ const hasNavigatedRef = useRef(false);
55
59
 
56
60
  const handleClose = useCallback(async () => {
57
61
  await closePostOnboardingPaywall();
58
62
  closePaywall();
59
-
63
+
60
64
  // Trigger feedback if user declined and isn't premium
61
65
  if (!isPremium && !purchasedRef.current) {
62
66
  setTimeout(() => setShowFeedback(true), 300);
63
67
  }
64
-
68
+
65
69
  purchasedRef.current = false;
66
-
70
+ hasNavigatedRef.current = false;
71
+
67
72
  if (navigation.canGoBack()) {
68
73
  navigation.goBack();
69
74
  }
@@ -73,9 +78,9 @@ export function usePaywallOrchestrator({
73
78
  purchasedRef.current = true;
74
79
  await markPaywallShown();
75
80
  await closePostOnboardingPaywall();
76
-
81
+
77
82
  onPurchaseSuccess?.();
78
-
83
+
79
84
  if (navigation.canGoBack()) {
80
85
  navigation.goBack();
81
86
  }
@@ -84,16 +89,24 @@ export function usePaywallOrchestrator({
84
89
  useEffect(() => {
85
90
  if (!isNavReady || !isLocalizationReady) return;
86
91
 
87
- const shouldShowPostOnboarding =
88
- state.isOnboardingComplete &&
89
- state.showPostOnboardingPaywall &&
90
- !state.paywallShown &&
91
- !state.isAuthModalOpen &&
92
+ const shouldShowPostOnboarding =
93
+ isOnboardingComplete &&
94
+ showPostOnboardingPaywall &&
95
+ !paywallShown &&
96
+ !isAuthModalOpen &&
92
97
  !isPremium;
93
98
 
94
- const shouldShowManual = showPaywall && !isPremium && !state.isAuthModalOpen;
99
+ const shouldShowManual = showPaywall && !isPremium && !isAuthModalOpen;
95
100
 
96
101
  if (shouldShowPostOnboarding || shouldShowManual) {
102
+ // Guard against double navigation in same render cycle
103
+ if (hasNavigatedRef.current) return;
104
+ hasNavigatedRef.current = true;
105
+
106
+ if (__DEV__) console.log('[usePaywallOrchestrator] 🚀 Navigating to Paywall', {
107
+ source: shouldShowPostOnboarding ? "onboarding" : "manual"
108
+ });
109
+
97
110
  navigation.navigate("PaywallScreen", {
98
111
  onClose: handleClose,
99
112
  translations,
@@ -117,14 +130,17 @@ export function usePaywallOrchestrator({
117
130
  if (showPaywall) {
118
131
  closePaywall();
119
132
  }
133
+ } else {
134
+ // Reset navigation flag if conditions no longer met
135
+ hasNavigatedRef.current = false;
120
136
  }
121
137
  }, [
122
138
  isNavReady,
123
139
  isLocalizationReady,
124
- state.isOnboardingComplete,
125
- state.showPostOnboardingPaywall,
126
- state.paywallShown,
127
- state.isAuthModalOpen,
140
+ isOnboardingComplete,
141
+ showPostOnboardingPaywall,
142
+ paywallShown,
143
+ isAuthModalOpen,
128
144
  isPremium,
129
145
  showPaywall,
130
146
  navigation,
@@ -144,12 +160,21 @@ export function usePaywallOrchestrator({
144
160
  onAuthRequired
145
161
  ]);
146
162
 
147
- return {
148
- isPremium,
149
- packages,
150
- flowState: state,
163
+ const completeOnboarding = useSubscriptionFlowStore((state) => state.completeOnboarding);
164
+
165
+ return {
166
+ isPremium,
167
+ packages,
168
+ flowState: {
169
+ isOnboardingComplete,
170
+ showPostOnboardingPaywall,
171
+ paywallShown,
172
+ isAuthModalOpen,
173
+ showFeedback
174
+ },
151
175
  markPaywallShown,
152
176
  closePostOnboardingPaywall,
177
+ completeOnboarding,
153
178
  setShowFeedback
154
179
  };
155
180
  }
@@ -85,20 +85,28 @@ export async function processCustomerInfo(
85
85
  );
86
86
 
87
87
  if (renewalResult.isRenewal) {
88
+ if (!renewalResult.productId || !renewalResult.newExpirationDate) {
89
+ console.error('[CustomerInfoHandler] Invalid renewal state: missing productId or expirationDate');
90
+ return renewalState;
91
+ }
88
92
  await handleRenewal(
89
93
  userId,
90
- renewalResult.productId!,
91
- renewalResult.newExpirationDate!,
94
+ renewalResult.productId,
95
+ renewalResult.newExpirationDate,
92
96
  customerInfo,
93
97
  config.onRenewalDetected
94
98
  );
95
99
  }
96
100
 
97
101
  if (renewalResult.isPlanChange) {
102
+ if (!renewalResult.productId || !renewalResult.previousProductId) {
103
+ console.error('[CustomerInfoHandler] Invalid plan change state: missing productId(s)');
104
+ return renewalState;
105
+ }
98
106
  await handlePlanChange(
99
107
  userId,
100
- renewalResult.productId!,
101
- renewalResult.previousProductId!,
108
+ renewalResult.productId,
109
+ renewalResult.previousProductId,
102
110
  renewalResult.isUpgrade,
103
111
  customerInfo,
104
112
  config.onPlanChanged
@@ -49,10 +49,12 @@ export async function syncPremiumStatus(
49
49
  }
50
50
  return { success: true };
51
51
  } catch (error) {
52
- console.error('[PremiumStatusSyncer] Premium status callback failed:', {
53
- userId,
54
- error: error instanceof Error ? error.message : String(error)
55
- });
52
+ if (__DEV__) {
53
+ console.error('[PremiumStatusSyncer] Premium status callback failed:', {
54
+ userId,
55
+ error: error instanceof Error ? error.message : String(error)
56
+ });
57
+ }
56
58
 
57
59
  return {
58
60
  success: false,
@@ -85,6 +87,8 @@ export async function notifyRestoreCompleted(
85
87
  try {
86
88
  await config.onRestoreCompleted({ userId, isPremium, customerInfo });
87
89
  } catch (error) {
88
- console.error('[PremiumStatusSyncer] Restore callback failed:', error instanceof Error ? error.message : String(error));
90
+ if (__DEV__) {
91
+ console.error('[PremiumStatusSyncer] Restore callback failed:', error instanceof Error ? error.message : String(error));
92
+ }
89
93
  }
90
94
  }
@@ -104,7 +104,8 @@ const ManagedSubscriptionFlowInner = React.memo<ManagedSubscriptionFlowProps>(({
104
104
 
105
105
  const {
106
106
  flowState,
107
- setShowFeedback
107
+ setShowFeedback,
108
+ completeOnboarding
108
109
  } = usePaywallOrchestrator({
109
110
  navigation,
110
111
  isNavReady,
@@ -165,7 +166,7 @@ const ManagedSubscriptionFlowInner = React.memo<ManagedSubscriptionFlowProps>(({
165
166
  return (
166
167
  <OnboardingScreen
167
168
  slides={onboarding.slides}
168
- onComplete={flowState.completeOnboarding}
169
+ onComplete={completeOnboarding}
169
170
  showSkipButton={onboarding.showSkipButton ?? true}
170
171
  showBackButton={onboarding.showBackButton ?? true}
171
172
  showProgressBar={onboarding.showProgressBar ?? true}
@@ -105,6 +105,7 @@ export const useSubscriptionFlowStore = createStore<SubscriptionFlowState, Subsc
105
105
  status: SubscriptionFlowStatus.INITIALIZING,
106
106
  syncStatus: SyncStatus.IDLE,
107
107
  syncError: null,
108
+ isInitialized: false, // Reset isInitialized to allow fresh initialization
108
109
  isOnboardingComplete: false,
109
110
  showPostOnboardingPaywall: false,
110
111
  showFeedback: false,
@@ -114,22 +115,3 @@ export const useSubscriptionFlowStore = createStore<SubscriptionFlowState, Subsc
114
115
  },
115
116
  }),
116
117
  });
117
-
118
- /**
119
- * Hook for backward compatibility and easier consumption.
120
- * Provides a unified object structure matching the previous implementation.
121
- */
122
- export function useSubscriptionFlow(_userId?: string) {
123
- const store = useSubscriptionFlowStore();
124
-
125
- return {
126
- state: store,
127
- completeOnboarding: store.completeOnboarding,
128
- closePostOnboardingPaywall: store.closePostOnboardingPaywall,
129
- closeFeedback: store.closeFeedback,
130
- setAuthModalOpen: store.setAuthModalOpen,
131
- markPaywallShown: store.markPaywallShown,
132
- setShowFeedback: store.setShowFeedback,
133
- resetFlow: store.resetFlow,
134
- };
135
- }
@@ -6,7 +6,7 @@ import { initializationState } from "../infrastructure/state/initializationState
6
6
  import { subscriptionEventBus, SUBSCRIPTION_EVENTS } from "../../../shared/infrastructure/SubscriptionEventBus";
7
7
  import { SubscriptionStatusResult } from "./useSubscriptionStatus.types";
8
8
  import { isAuthenticated } from "../utils/authGuards";
9
- import { NO_CACHE_QUERY_CONFIG } from "../../../shared/infrastructure/react-query/queryConfig";
9
+ import { SHORT_CACHE_CONFIG } from "../../../shared/infrastructure/react-query/queryConfig";
10
10
  import { usePreviousUserCleanup } from "../../../shared/infrastructure/react-query/hooks/usePreviousUserCleanup";
11
11
 
12
12
  export const subscriptionStatusQueryKeys = {
@@ -43,7 +43,7 @@ export const useSubscriptionStatus = (): SubscriptionStatusResult => {
43
43
  return SubscriptionManager.checkPremiumStatus();
44
44
  },
45
45
  enabled: queryEnabled,
46
- ...NO_CACHE_QUERY_CONFIG,
46
+ ...SHORT_CACHE_CONFIG,
47
47
  });
48
48
 
49
49
  usePreviousUserCleanup(userId, queryClient, subscriptionStatusQueryKeys.user);
@@ -1,7 +1,7 @@
1
1
  import { useQuery } from "@umituz/react-native-design-system/tanstack";
2
2
  import { useMemo } from "react";
3
3
  import { useAuthStore, selectUserId } from "@umituz/react-native-auth";
4
- import { NO_CACHE_QUERY_CONFIG } from "../../../../shared/infrastructure/react-query/queryConfig";
4
+ import { MEDIUM_CACHE_CONFIG } from "../../../../shared/infrastructure/react-query/queryConfig";
5
5
  import type {
6
6
  CreditLog,
7
7
  TransactionRepositoryConfig,
@@ -56,7 +56,7 @@ export function useTransactionHistory({
56
56
  return result.data ?? [];
57
57
  },
58
58
  enabled: hasUser,
59
- ...NO_CACHE_QUERY_CONFIG,
59
+ ...MEDIUM_CACHE_CONFIG,
60
60
  });
61
61
 
62
62
  const transactions = data ?? [];
package/src/index.ts CHANGED
@@ -1,5 +1,23 @@
1
1
  // Domain Layer - Constants & Types
2
- export * from "./domains/subscription/core/SubscriptionConstants";
2
+ export {
3
+ USER_TIER,
4
+ SUBSCRIPTION_STATUS,
5
+ PERIOD_TYPE,
6
+ PACKAGE_TYPE,
7
+ PLATFORM,
8
+ PURCHASE_SOURCE,
9
+ PURCHASE_TYPE,
10
+ ANONYMOUS_CACHE_KEY,
11
+ } from "./domains/subscription/core/SubscriptionConstants";
12
+ export type {
13
+ UserTierType,
14
+ SubscriptionStatusType,
15
+ PeriodType,
16
+ PackageType,
17
+ Platform,
18
+ PurchaseSource,
19
+ PurchaseType,
20
+ } from "./domains/subscription/core/SubscriptionConstants";
3
21
  export type { SubscriptionMetadata } from "./domains/subscription/core/types/SubscriptionMetadata";
4
22
  export type { PremiumStatus } from "./domains/subscription/core/types/PremiumStatus";
5
23
  export type { CreditInfo } from "./domains/subscription/core/types/CreditInfo";
@@ -45,20 +63,33 @@ export { useDeductCredit } from "./domains/credits/presentation/deduct-credit/us
45
63
  export { useFeatureGate } from "./domains/subscription/presentation/useFeatureGate";
46
64
  export { usePaywallVisibility, paywallControl } from "./domains/subscription/presentation/usePaywallVisibility";
47
65
  export { usePremium } from "./domains/subscription/presentation/usePremium";
48
- export { useSubscriptionFlow, useSubscriptionFlowStore } from "./domains/subscription/presentation/useSubscriptionFlow";
66
+ export { useSubscriptionFlowStore } from "./domains/subscription/presentation/useSubscriptionFlow";
49
67
  export type { SubscriptionFlowState, SubscriptionFlowActions, SubscriptionFlowStore } from "./domains/subscription/presentation/useSubscriptionFlow";
50
68
  export { useSubscriptionStatus } from "./domains/subscription/presentation/useSubscriptionStatus";
51
- export * from "./domains/subscription/presentation/useSubscriptionStatus.types";
52
- export * from "./presentation/hooks/feedback/usePaywallFeedback";
53
- export * from "./presentation/hooks/feedback/useFeedbackSubmit";
69
+ export type { SubscriptionStatusResult } from "./domains/subscription/presentation/useSubscriptionStatus.types";
70
+ export { usePaywallFeedback } from "./presentation/hooks/feedback/usePaywallFeedback";
71
+ export {
72
+ usePaywallFeedbackSubmit,
73
+ useSettingsFeedbackSubmit,
74
+ } from "./presentation/hooks/feedback/useFeedbackSubmit";
75
+ export type {
76
+ UsePaywallFeedbackSubmitOptions,
77
+ SettingsFeedbackData,
78
+ UseSettingsFeedbackSubmitOptions,
79
+ } from "./presentation/hooks/feedback/useFeedbackSubmit";
54
80
 
55
81
  // Presentation Layer - Components
56
- export * from "./domains/subscription/presentation/components/details/PremiumDetailsCard";
82
+ export { PremiumDetailsCard } from "./domains/subscription/presentation/components/details/PremiumDetailsCard";
83
+ export type {
84
+ PremiumDetailsTranslations,
85
+ PremiumDetailsCardProps,
86
+ } from "./domains/subscription/presentation/components/details/PremiumDetailsCardTypes";
57
87
  export { PremiumStatusBadge } from "./domains/subscription/presentation/components/details/PremiumStatusBadge";
58
88
  export type { PremiumStatusBadgeProps } from "./domains/subscription/presentation/components/details/PremiumStatusBadge.types";
59
- export * from "./domains/subscription/presentation/components/sections/SubscriptionSection";
60
- export * from "./domains/subscription/presentation/components/feedback/PaywallFeedbackScreen";
61
- export * from "./domains/subscription/presentation/screens/SubscriptionDetailScreen";
89
+ export { SubscriptionSection } from "./domains/subscription/presentation/components/sections/SubscriptionSection";
90
+ export type { SubscriptionSectionProps } from "./domains/subscription/presentation/components/sections/SubscriptionSection.types";
91
+ export { PaywallFeedbackScreen } from "./domains/subscription/presentation/components/feedback/PaywallFeedbackScreen";
92
+ export type { PaywallFeedbackScreenProps } from "./domains/subscription/presentation/components/feedback/PaywallFeedbackScreen.types";
62
93
  export type {
63
94
  SubscriptionDetailConfig,
64
95
  SubscriptionDetailTranslations,
@@ -79,11 +110,47 @@ export type {
79
110
  } from "./domains/credits/core/Credits";
80
111
 
81
112
  // Utils
82
- export * from "./utils/creditMapper";
83
- export * from "./utils/packageTypeDetector";
84
- export * from "./utils/priceUtils";
85
- export * from "./utils/types";
86
- export * from "./utils/dateUtils";
113
+ export {
114
+ getCreditAllocation,
115
+ createCreditAmountsFromPackages,
116
+ } from "./utils/creditMapper";
117
+ export {
118
+ isCreditPackage,
119
+ detectPackageType,
120
+ } from "./utils/packageTypeDetector";
121
+ export type { SubscriptionPackageType } from "./utils/packageTypeDetector";
122
+ export {
123
+ formatPrice,
124
+ getBillingPeriodSuffix,
125
+ formatPriceWithPeriod,
126
+ } from "./utils/priceUtils";
127
+ export type { UserTierInfo, PremiumStatusFetcher } from "./utils/types";
128
+ export type { DateLike } from "./utils/dateUtils.core";
129
+ export {
130
+ isNow,
131
+ isPast,
132
+ isFuture,
133
+ isValidDate,
134
+ toSafeDate,
135
+ formatISO,
136
+ now,
137
+ } from "./utils/dateUtils.core";
138
+ export {
139
+ daysBetween,
140
+ daysUntil,
141
+ isSameDay,
142
+ isToday,
143
+ } from "./utils/dateUtils.compare";
144
+ export {
145
+ formatRelative,
146
+ formatShort,
147
+ formatLong,
148
+ } from "./utils/dateUtils.format";
149
+ export {
150
+ addDays,
151
+ addMonths,
152
+ addYears,
153
+ } from "./utils/dateUtils.math";
87
154
  export { getAppVersion, validatePlatform } from "./utils/appUtils";
88
155
  export { toDate, toISOString, toTimestamp, getCurrentISOString } from "./shared/utils/dateConverter";
89
156
 
@@ -1,7 +1,41 @@
1
- export const NO_CACHE_QUERY_CONFIG = {
2
- gcTime: 0,
3
- staleTime: 0,
4
- refetchOnMount: "always" as const,
5
- refetchOnWindowFocus: "always" as const,
6
- refetchOnReconnect: "always" as const,
1
+ /**
2
+ * Query cache configurations for optimal performance
3
+ * Uses event-based invalidation via subscriptionEventBus for real-time updates
4
+ */
5
+
6
+ /**
7
+ * Short-lived cache for frequently changing data (credits, subscription status)
8
+ * Events automatically invalidate the cache, so we can safely cache for 60s
9
+ */
10
+ export const SHORT_CACHE_CONFIG = {
11
+ gcTime: 1000 * 60, // 1 minute - keep in memory for 1 minute
12
+ staleTime: 1000 * 30, // 30 seconds - consider stale after 30s
13
+ refetchOnMount: false, // Don't refetch on mount if cache exists
14
+ refetchOnWindowFocus: false, // Don't refetch on app focus
15
+ refetchOnReconnect: true, // Refetch on reconnect only
7
16
  };
17
+
18
+ /**
19
+ * Medium cache for relatively stable data (packages, transaction history)
20
+ */
21
+ export const MEDIUM_CACHE_CONFIG = {
22
+ gcTime: 1000 * 60 * 5, // 5 minutes
23
+ staleTime: 1000 * 60 * 2, // 2 minutes
24
+ refetchOnMount: false,
25
+ refetchOnWindowFocus: false,
26
+ refetchOnReconnect: true,
27
+ };
28
+
29
+ /**
30
+ * Long cache for rarely changing data (config, metadata)
31
+ */
32
+ export const LONG_CACHE_CONFIG = {
33
+ gcTime: 1000 * 60 * 30, // 30 minutes
34
+ staleTime: 1000 * 60 * 10, // 10 minutes
35
+ refetchOnMount: false,
36
+ refetchOnWindowFocus: false,
37
+ refetchOnReconnect: true,
38
+ };
39
+
40
+ /** @deprecated Use SHORT_CACHE_CONFIG instead */
41
+ export const NO_CACHE_QUERY_CONFIG = SHORT_CACHE_CONFIG;