@umituz/react-native-subscription 2.27.92 → 2.27.94

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 (39) hide show
  1. package/package.json +1 -1
  2. package/src/domains/credits/application/CreditsInitializer.ts +99 -40
  3. package/src/domains/credits/application/DeductCreditsCommand.ts +31 -13
  4. package/src/domains/credits/application/PurchaseMetadataGenerator.ts +17 -23
  5. package/src/domains/credits/core/Credits.ts +39 -39
  6. package/src/domains/credits/core/CreditsMapper.ts +11 -10
  7. package/src/domains/credits/core/UserCreditsDocument.ts +33 -33
  8. package/src/domains/credits/infrastructure/CreditsRepository.ts +46 -59
  9. package/src/domains/paywall/components/PaywallModal.tsx +1 -1
  10. package/src/domains/subscription/application/SubscriptionInitializer.ts +59 -18
  11. package/src/domains/subscription/application/SubscriptionInitializerTypes.ts +20 -20
  12. package/src/domains/subscription/infrastructure/handlers/PackageHandler.ts +46 -27
  13. package/src/domains/subscription/infrastructure/managers/SubscriptionManager.ts +106 -42
  14. package/src/domains/subscription/infrastructure/services/RestoreHandler.ts +4 -2
  15. package/src/domains/subscription/infrastructure/services/RevenueCatInitializer.ts +1 -2
  16. package/src/domains/subscription/infrastructure/utils/RenewalDetector.ts +1 -1
  17. package/src/domains/subscription/presentation/components/details/PremiumStatusBadge.tsx +6 -4
  18. package/src/domains/subscription/presentation/components/feedback/PaywallFeedbackModal.tsx +1 -1
  19. package/src/domains/subscription/presentation/types/SubscriptionDetailTypes.ts +4 -2
  20. package/src/domains/subscription/presentation/types/SubscriptionSettingsTypes.ts +1 -1
  21. package/src/domains/subscription/presentation/usePremiumGate.ts +1 -1
  22. package/src/domains/subscription/presentation/useSavedPurchaseAutoExecution.ts +1 -1
  23. package/src/domains/subscription/presentation/useSubscriptionSettingsConfig.ts +4 -3
  24. package/src/domains/subscription/presentation/useSubscriptionSettingsConfig.utils.ts +1 -1
  25. package/src/domains/trial/application/TrialEligibilityService.ts +1 -1
  26. package/src/domains/trial/infrastructure/DeviceTrialRepository.ts +2 -2
  27. package/src/shared/application/ports/IRevenueCatService.ts +2 -0
  28. package/src/shared/infrastructure/SubscriptionEventBus.ts +5 -2
  29. package/src/presentation/README.md +0 -125
  30. package/src/presentation/hooks/README.md +0 -156
  31. package/src/presentation/hooks/useAuthSubscriptionSync.md +0 -94
  32. package/src/presentation/hooks/useCredits.md +0 -103
  33. package/src/presentation/hooks/useDeductCredit.md +0 -100
  34. package/src/presentation/hooks/useFeatureGate.md +0 -112
  35. package/src/presentation/hooks/usePaywall.md +0 -89
  36. package/src/presentation/hooks/usePaywallOperations.md +0 -92
  37. package/src/presentation/hooks/usePaywallVisibility.md +0 -95
  38. package/src/presentation/hooks/usePremium.md +0 -88
  39. package/src/presentation/hooks/useSubscriptionSettingsConfig.md +0 -94
@@ -6,10 +6,12 @@
6
6
  import React, { useMemo } from "react";
7
7
  import { View, StyleSheet } from "react-native";
8
8
  import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-system";
9
- import {
10
- SUBSCRIPTION_STATUS,
11
- type SubscriptionStatusType
12
- } from "../../../domains/subscription/core/SubscriptionConstants";
9
+ import {
10
+ SUBSCRIPTION_STATUS,
11
+ type SubscriptionStatusType
12
+ } from "../../../core/SubscriptionConstants";
13
+
14
+ export type { SubscriptionStatusType };
13
15
 
14
16
  export interface PremiumStatusBadgeProps {
15
17
  status: SubscriptionStatusType;
@@ -1,7 +1,7 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { View, TouchableOpacity, TextInput } from "react-native";
3
3
  import { AtomicText, BaseModal, useAppDesignTokens } from "@umituz/react-native-design-system";
4
- import { usePaywallFeedback } from "../../hooks/feedback/usePaywallFeedback";
4
+ import { usePaywallFeedback } from "../../../../../presentation/hooks/feedback/usePaywallFeedback";
5
5
  import { createPaywallFeedbackStyles } from "./paywallFeedbackStyles";
6
6
 
7
7
  const FEEDBACK_OPTION_IDS = [
@@ -3,7 +3,7 @@
3
3
  * Type definitions for subscription detail screen and components
4
4
  */
5
5
 
6
- import type { SubscriptionStatusType } from "../../domains/subscription/core/SubscriptionStatus";
6
+ import type { SubscriptionStatusType } from "../../core/SubscriptionStatus";
7
7
  import type { CreditInfo } from "../components/details/PremiumDetailsCardTypes";
8
8
 
9
9
  export type { SubscriptionStatusType, CreditInfo };
@@ -16,6 +16,8 @@ export interface SubscriptionDetailTranslations {
16
16
  statusExpired: string;
17
17
  statusInactive: string;
18
18
  statusCanceled: string;
19
+ /** Free status label */
20
+ statusFree: string;
19
21
  /** Trial status label (defaults to statusActive if not provided) */
20
22
  statusTrial?: string;
21
23
  /** Trial canceled status label (defaults to statusCanceled if not provided) */
@@ -109,7 +111,7 @@ export interface SubscriptionHeaderProps {
109
111
  | "expiresLabel"
110
112
  | "purchasedLabel"
111
113
  | "lifetimeLabel"
112
- >;
114
+ > & { statusFree: string };
113
115
  }
114
116
 
115
117
  /** Props for credits list component */
@@ -3,7 +3,7 @@
3
3
  * Type definitions for subscription settings configuration
4
4
  */
5
5
 
6
- import type { SubscriptionStatusType } from "../../domains/subscription/core/SubscriptionConstants";
6
+ import type { SubscriptionStatusType } from "../../core/SubscriptionConstants";
7
7
  import type {
8
8
  SubscriptionDetailConfig,
9
9
  UpgradePromptConfig,
@@ -27,7 +27,7 @@
27
27
  * ```
28
28
  */
29
29
 
30
- import { useCallback, useEffect } from "react";
30
+ import { useCallback } from "react";
31
31
  import { useSubscriptionStatus } from "./useSubscriptionStatus";
32
32
  import { paywallControl } from "./usePaywallVisibility";
33
33
 
@@ -12,7 +12,7 @@ import {
12
12
  import { getSavedPurchase, clearSavedPurchase } from "./useAuthAwarePurchase";
13
13
  import { usePremium } from "./usePremium";
14
14
  import { SubscriptionManager } from "../infrastructure/managers/SubscriptionManager";
15
- import { usePurchaseLoadingStore } from "../../../presentation/stores";
15
+ import { usePurchaseLoadingStore } from "./stores";
16
16
 
17
17
  export interface UseSavedPurchaseAutoExecutionParams {
18
18
  onSuccess?: () => void;
@@ -7,21 +7,21 @@ import { useMemo, useCallback } from "react";
7
7
  import { useCredits } from "../../credits/presentation/useCredits";
8
8
  import { usePaywallVisibility } from "./usePaywallVisibility";
9
9
  import { calculateDaysRemaining } from "../core/SubscriptionStatus";
10
- import { formatDate } from "../../../presentation/utils/subscriptionDateUtils";
10
+ import { formatDate } from "./utils/subscriptionDateUtils";
11
11
  import { useCreditsArray, getSubscriptionStatusType } from "./useSubscriptionSettingsConfig.utils";
12
12
  import { getCreditsConfig } from "../../credits/infrastructure/CreditsRepositoryProvider";
13
13
  import type {
14
14
  SubscriptionSettingsConfig,
15
15
  SubscriptionStatusType,
16
16
  UseSubscriptionSettingsConfigParams,
17
- } from "../../../presentation/types/SubscriptionSettingsTypes";
17
+ } from "./types/SubscriptionSettingsTypes";
18
18
 
19
19
  export type {
20
20
  SubscriptionSettingsConfig,
21
21
  SubscriptionSettingsItemConfig,
22
22
  SubscriptionSettingsTranslations,
23
23
  UseSubscriptionSettingsConfigParams,
24
- } from "../../../presentation/types/SubscriptionSettingsTypes";
24
+ } from "./types/SubscriptionSettingsTypes";
25
25
 
26
26
  export const useSubscriptionSettingsConfig = (
27
27
  params: Omit<UseSubscriptionSettingsConfigParams, 'userId'>
@@ -95,6 +95,7 @@ export const useSubscriptionSettingsConfig = (
95
95
  statusExpired: translations.statusExpired,
96
96
  statusInactive: translations.statusInactive,
97
97
  statusCanceled: translations.statusCanceled,
98
+ statusFree: translations.statusInactive,
98
99
  expiresLabel: translations.expiresLabel,
99
100
  purchasedLabel: translations.purchasedLabel,
100
101
  lifetimeLabel: translations.lifetimeLabel,
@@ -6,7 +6,7 @@
6
6
  import { useMemo } from "react";
7
7
  import type { UserCredits } from "../../credits/core/Credits";
8
8
  import { resolveSubscriptionStatus, type PeriodType, type SubscriptionStatusType } from "../core/SubscriptionStatus";
9
- import type { SubscriptionSettingsTranslations } from "../types/SubscriptionSettingsTypes";
9
+ import type { SubscriptionSettingsTranslations } from "./types/SubscriptionSettingsTypes";
10
10
 
11
11
  export interface CreditsInfo {
12
12
  id: string;
@@ -1,4 +1,4 @@
1
- import type { TrialEligibilityResult, DeviceTrialRecord } from "./TrialTypes";
1
+ import type { TrialEligibilityResult, DeviceTrialRecord } from "../core/TrialTypes";
2
2
 
3
3
  export class TrialEligibilityService {
4
4
  static check(
@@ -1,6 +1,6 @@
1
- import { doc, getDoc, setDoc, serverTimestamp, arrayUnion, type Firestore } from "firebase/firestore";
1
+ import { doc, getDoc, setDoc, serverTimestamp, type Firestore } from "firebase/firestore";
2
2
  import { getFirestore } from "@umituz/react-native-firebase";
3
- import type { DeviceTrialRecord } from "./TrialTypes";
3
+ import type { DeviceTrialRecord } from "../core/TrialTypes";
4
4
 
5
5
  const DEVICE_TRIALS_COLLECTION = "device_trials";
6
6
 
@@ -21,6 +21,8 @@ export interface PurchaseResult {
21
21
  export interface RestoreResult {
22
22
  success: boolean;
23
23
  productId: string | null;
24
+ isPremium?: boolean;
25
+ customerInfo?: CustomerInfo;
24
26
  }
25
27
 
26
28
  export interface IRevenueCatService {
@@ -22,10 +22,13 @@ export class SubscriptionEventBus {
22
22
  this.listeners[event] = [];
23
23
  }
24
24
  this.listeners[event].push(callback);
25
-
25
+
26
26
  // Return unsubscribe function
27
27
  return () => {
28
- this.listeners[event] = this.listeners[event].filter(l => l !== callback);
28
+ const listeners = this.listeners[event];
29
+ if (listeners) {
30
+ this.listeners[event] = listeners.filter(l => l !== callback);
31
+ }
29
32
  };
30
33
  }
31
34
 
@@ -1,125 +0,0 @@
1
- # Presentation Layer
2
-
3
- UI/UX layer for the subscription system - React hooks, components, and screens.
4
-
5
- ## Location
6
-
7
- **Directory**: `src/presentation/`
8
-
9
- **Type**: Layer
10
-
11
- ## Strategy
12
-
13
- ### Layer Responsibilities
14
-
15
- The Presentation Layer is responsible for:
16
-
17
- 1. **State Management**
18
- - React hooks for data fetching and mutations
19
- - TanStack Query for server state management
20
- - Local state management for UI state
21
-
22
- 2. **UI Components**
23
- - Reusable subscription components
24
- - Feature gating UI elements
25
- - Credit display components
26
- - Paywall components
27
-
28
- 3. **User Interaction**
29
- - Handle user actions
30
- - Display appropriate feedback
31
- - Guide users through purchase flows
32
- - Show upgrade prompts at right time
33
-
34
- ### Architecture Pattern
35
-
36
- The presentation layer follows a layered architecture where:
37
- - Hooks manage state and data fetching at the top level
38
- - Components consume hooks and render UI
39
- - Screens compose multiple components together
40
- - All layers communicate with the domain layer for business logic
41
-
42
- ### Integration Points
43
-
44
- - **Domain Layer**: Business logic and data access
45
- - **TanStack Query**: Server state management
46
- - **RevenueCat**: Purchase operations
47
- - **Navigation**: Screen routing
48
-
49
- ## Restrictions
50
-
51
- ### REQUIRED
52
-
53
- - **Type Safety**: All components MUST be typed with TypeScript
54
- - **Error Boundaries**: MUST implement error boundaries for all screens
55
- - **Loading States**: MUST show loading indicators during async operations
56
- - **User Feedback**: MUST provide feedback for all user actions
57
-
58
- ### PROHIBITED
59
-
60
- - **NEVER** include business logic in components (use hooks instead)
61
- - **NEVER** make direct API calls from components (use hooks)
62
- - **DO NOT** store sensitive data in component state
63
- - **NEVER** hardcode strings (use localization)
64
-
65
- ### CRITICAL SAFETY
66
-
67
- - **ALWAYS** validate props before rendering
68
- - **ALWAYS** handle loading and error states
69
- - **NEVER** trust client-side state for security decisions
70
- - **MUST** implement proper error boundaries
71
- - **ALWAYS** sanitize user inputs before display
72
-
73
- ## AI Agent Guidelines
74
-
75
- ### When Building Presentation Layer
76
-
77
- 1. **Always** use hooks for data fetching and state management
78
- 2. **Always** handle loading and error states
79
- 3. **Always** provide user feedback for actions
80
- 4. **Always** implement error boundaries
81
- 5. **Never** include business logic in components
82
-
83
- ### Integration Checklist
84
-
85
- - [ ] Use appropriate hooks for data access
86
- - [ ] Handle loading states
87
- - [ ] Handle error states
88
- - [ ] Implement error boundaries
89
- - [ ] Provide user feedback
90
- - [ ] Test with various data states
91
- - [ ] Test error scenarios
92
- - [ ] Ensure type safety
93
- - [ ] Use localization for all strings
94
- - [ ] Test accessibility
95
-
96
- ### Common Patterns
97
-
98
- 1. **Compound Components**: Build complex UIs from simple components
99
- 2. **Render Props**: Share stateful logic between components
100
- 3. **Custom Hooks**: Extract reusable stateful logic
101
- 4. **Error Boundaries**: Prevent crashes from propagating
102
- 5. **Loading Skeletons**: Show placeholder during loading
103
- 6. **Optimistic Updates**: Update UI immediately, rollback on failure
104
- 7. **Graceful Degradation**: Show limited version on error
105
- 8. **Responsive Design**: Support different screen sizes
106
-
107
- ## Related Documentation
108
-
109
- - **Hooks**: `hooks/README.md`
110
- - **Components**: `components/README.md`
111
- - **Screens**: `screens/README.md`
112
- - **Wallet Domain**: `../../domains/wallet/README.md`
113
- - **Paywall Domain**: `../../domains/paywall/README.md`
114
- - **RevenueCat**: `../../revenuecat/README.md`
115
-
116
- ## Directory Structure
117
-
118
- The presentation layer contains:
119
- - **hooks/** - React hooks for state management (usePremium, useSubscription, useCredits, useDeductCredit, useFeatureGate)
120
- - **components/** - UI components organized by functionality
121
- - **details/** - Detail cards, badges
122
- - **feedback/** - Modals, feedback components
123
- - **sections/** - Section components
124
- - **paywall/** - Paywall components
125
- - **screens/** - Full-screen components (SubscriptionDetailScreen)
@@ -1,156 +0,0 @@
1
- # Subscription Hooks
2
-
3
- Collection of React hooks for subscription, premium, and credits management.
4
-
5
- ## Location
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **Directory**: `src/presentation/hooks/`
10
-
11
- **Type**: Hooks Collection
12
-
13
- ## Strategy
14
-
15
- ### Hook Organization
16
-
17
- Hooks are organized by functionality:
18
-
19
- 1. **Subscription Hooks**: Manage subscription status and details
20
- 2. **Premium Hooks**: Check and manage premium access
21
- 3. **Credits Hooks**: Handle credit balance and operations
22
- 4. **Gate Hooks**: Control feature access based on user state
23
- 5. **Auth Hooks**: Authentication-aware purchase flows
24
- 6. **Paywall Hooks**: Paywall display and management
25
-
26
- ### Integration Pattern
27
-
28
- All hooks follow consistent patterns:
29
- - Return loading, error, and data states
30
- - Provide refetch/refresh functions
31
- - Use TanStack Query for caching
32
- - Handle optimistic updates
33
- - Support real-time updates
34
-
35
- ## Hook Categories
36
-
37
- ### Subscription Hooks
38
-
39
- - **useSubscription**: Core subscription status management
40
- - **useSubscriptionStatus**: Detailed subscription status
41
- - **useSubscriptionDetails**: Subscription package and feature details
42
- - **useSubscriptionSettingsConfig**: Settings and configuration
43
-
44
- ### Premium Hooks
45
-
46
- - **usePremium**: Premium status checker
47
- - **usePremiumGate**: Premium feature gating
48
- - **usePremiumWithCredits**: Hybrid premium/credits access
49
-
50
- ### Credits Hooks
51
-
52
- - **useCredits**: Credit balance and transactions
53
- - **useCreditChecker**: Simple credit validation
54
- - **useDeductCredit**: Credit deduction with optimistic updates
55
- - **useInitializeCredits**: Initialize credits after purchase
56
-
57
- ### Gate Hooks
58
-
59
- - **useFeatureGate**: Unified auth, subscription, and credits gating
60
- - **useSubscriptionGate**: Subscription-only gating
61
- - **useCreditsGate**: Credits-only gating
62
- - **usePremiumGate**: Premium-only gating
63
- - **useAuthGate**: Authentication gating
64
-
65
- ### Auth Hooks
66
-
67
- - **useAuthAwarePurchase**: Authentication-aware purchase flow
68
- - **useAuthSubscriptionSync**: Auth and subscription synchronization
69
-
70
- ### Paywall Hooks
71
-
72
- - **usePaywall**: Paywall display management
73
- - **usePaywallOperations**: Paywall show/hide operations
74
- - **usePaywallVisibility**: Paywall visibility rules
75
-
76
- ### User Tier Hooks
77
-
78
- - **useUserTier**: User tier management
79
- - **useUserTierWithRepository**: Repository-based tier management
80
-
81
- ### Development Hooks
82
-
83
- - **useDevTestCallbacks**: Development and testing utilities
84
-
85
- ## Restrictions
86
-
87
- ### REQUIRED
88
-
89
- - **Import Path**: MUST import from `@umituz/react-native-subscription`
90
- - **Loading States**: MUST handle loading state in UI
91
- - **Error Handling**: MUST handle error state
92
- - **User Authentication**: Most hooks require authenticated user
93
-
94
- ### PROHIBITED
95
-
96
- - **NEVER** use hooks outside React components
97
- - **NEVER** ignore loading states
98
- - **NEVER** skip error handling
99
- - **DO NOT** use hook returns for security decisions (server-side validation required)
100
-
101
- ### CRITICAL SAFETY
102
-
103
- - **ALWAYS** handle loading and error states
104
- - **NEVER** trust client-side state for security
105
- - **MUST** implement error boundaries
106
- - **ALWAYS** test with various user states (anonymous, free, premium)
107
-
108
- ## AI Agent Guidelines
109
-
110
- ### When Using Subscription Hooks
111
-
112
- 1. **Always** handle loading and error states
113
- 2. **Always** use appropriate gate hooks for feature access
114
- 3. **Always** provide user feedback for all operations
115
- 4. **Never** trust client-side state for security
116
- 5. **Always** test with different user tiers
117
-
118
- ### Integration Checklist
119
-
120
- - [ ] Import from correct path: `@umituz/react-native-subscription`
121
- - [ ] Choose appropriate hook for use case
122
- - [ ] Handle loading state
123
- - [ ] Handle error state
124
- - [ ] Implement error boundaries
125
- - [ ] Use gate hooks for feature access
126
- - [ ] Test with all user tiers
127
- - [ ] Test offline scenarios
128
- - [ ] Test error scenarios
129
-
130
- ### Common Patterns
131
-
132
- 1. **Feature Gating**: Use `useFeatureGate` for unified access control
133
- 2. **Credit Operations**: Check → Deduct → Execute pattern
134
- 3. **Subscription Display**: Show status, expiration, renewal info
135
- 4. **Premium Features**: Gate content, provide upgrade path
136
- 5. **Paywall Integration**: Automatic display on access denial
137
- 6. **Real-time Updates**: Refresh on focus, background sync
138
-
139
- ## Related Documentation
140
-
141
- - **Subscription Domain**: `src/domains/wallet/README.md`
142
- - **Paywall Domain**: `src/domains/paywall/README.md`
143
- - **Config Domain**: `src/domains/config/README.md`
144
- - **RevenueCat Integration**: `src/revenuecat/README.md`
145
- - **Presentation Components**: `src/presentation/components/README.md`
146
-
147
- ## Individual Hook Documentation
148
-
149
- - [useDeductCredit](./useDeductCredit.md) - Credit deduction with optimistic updates
150
- - [useCredits](./useCredits.md) - Credit balance access
151
- - [useCreditChecker](./useCreditChecker.md) - Simple credit validation
152
- - [useFeatureGate](./useFeatureGate.md) - Unified feature gating
153
- - [useSubscription](./useSubscription.md) - Subscription status management
154
- - [usePremium](./usePremium.md) - Premium status checker
155
- - [useCreditsGate](./useCreditsGate.md) - Credits-based feature gating
156
- - [useInitializeCredits](./useInitializeCredits.md) - Initialize credits after purchase
@@ -1,94 +0,0 @@
1
- # useAuthSubscriptionSync Hook
2
-
3
- Automatically synchronizes subscription state with authentication changes.
4
-
5
- ## Location
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **File**: `src/presentation/hooks/useAuthSubscriptionSync.ts`
10
-
11
- **Type**: Hook
12
-
13
- ## Strategy
14
-
15
- ### Auth-Subscription Synchronization
16
-
17
- 1. **Auth Listener Setup**: Subscribe to auth state changes via provided callback
18
- 2. **User Change Detection**: Detect when userId changes (including sign out)
19
- 3. **Subscription Initialization**: Initialize subscription when user signs in
20
- 4. **One-Time Init**: Only initialize once per user session (skips duplicates)
21
- 5. **User Switching**: Re-initialize when switching between accounts
22
- 6. **Cleanup**: Unsubscribe from auth listener on unmount
23
-
24
- ### Integration Points
25
-
26
- - **Auth Provider**: Any auth system (Firebase, Auth0, custom)
27
- - **RevenueCat**: For subscription initialization with logIn
28
- - **Subscription Service**: Backend subscription sync
29
- - **Credits System**: Optional credits initialization
30
- - **App Root**: Should be placed in root App component
31
-
32
- ## Restrictions
33
-
34
- ### REQUIRED
35
-
36
- - **Auth State Change Callback**: MUST provide onAuthStateChanged function
37
- - **Subscription Init**: MUST provide initializeSubscription function
38
- - **App Root Setup**: SHOULD be placed in root App component
39
- - **Unsubscribe Handling**: Callback MUST return unsubscribe function
40
-
41
- ### PROHIBITED
42
-
43
- - **NEVER** place in individual screen components (use app root)
44
- - **NEVER** call without proper auth callback
45
- - **DO NOT** manually call initializeSubscription (hook handles it)
46
- - **DO NOT** configure multiple times (one-time setup)
47
-
48
- ### CRITICAL SAFETY
49
-
50
- - **ALWAYS** configure at app root level
51
- - **MUST** handle user switching correctly
52
- - **ALWAYS** return unsubscribe function from callback
53
- - **NEVER** rely on manual subscription initialization
54
-
55
- ## AI Agent Guidelines
56
-
57
- ### When Implementing Auth-Subscription Sync
58
-
59
- 1. **Always** place in root App component
60
- 2. **Always** provide onAuthStateChanged that returns unsubscribe
61
- 3. **Always** provide initializeSubscription for user ID
62
- 4. **Always** test user switching scenarios
63
- 5. **Never** place in child components
64
-
65
- ### Integration Checklist
66
-
67
- - [ ] Import from correct path: `@umituz/react-native-subscription`
68
- - [ ] Place in root App component
69
- - [ ] Provide onAuthStateChanged callback
70
- - [ ] Ensure callback returns unsubscribe function
71
- - [ ] Provide initializeSubscription function
72
- - [ ] Test with initial user sign-in
73
- - [ ] Test with user sign-out
74
- - [ ] Test with account switching
75
- - [ ] Verify subscription initializes only once per user
76
- - [ ] Test cleanup on unmount
77
-
78
- ### Common Patterns
79
-
80
- 1. **Firebase + RevenueCat**: Sync Firebase auth with RevenueCat
81
- 2. **Custom Auth + Backend**: Use custom auth with backend sync
82
- 3. **Multi-Service Setup**: Initialize multiple services (RevenueCat, credits, backend)
83
- 4. **Error Handling**: Handle initialization failures gracefully
84
- 5. **Loading State**: Show loading during sync
85
- 6. **Analytics Tracking**: Track auth and subscription events
86
-
87
- ## Related Documentation
88
-
89
- - **useAuth**: For authentication state
90
- - **usePremium**: For subscription status
91
- - **useAuthAwarePurchase**: For auth-gated purchases
92
- - **useUserTier**: For tier determination
93
- - **Auth Integration Guide**: `src/docs/AUTH_INTEGRATION.md`
94
- - **RevenueCat Setup**: `src/docs/REVENUECAT_SETUP.md`
@@ -1,103 +0,0 @@
1
- # useCredits Hook
2
-
3
- Hook for accessing and managing credits balance with real-time updates.
4
-
5
- ## Location
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **File**: `src/presentation/hooks/useCredits.ts`
10
-
11
- **Type**: Hook
12
-
13
- ## Strategy
14
-
15
- ### Data Fetching Flow
16
-
17
- 1. **Initial Load**
18
- - Fetch credits from repository on mount
19
- - Cache results in TanStack Query
20
- - Handle loading/error states
21
-
22
- 2. **Real-time Updates**
23
- - Subscribe to credit changes via repository listener
24
- - Auto-update on balance changes
25
- - Invalidate query on external modifications
26
-
27
- 3. **Cache Management**
28
- - Use TanStack Query for caching
29
- - Background refetch on window focus
30
- - Manual refetch capability
31
-
32
- ### Integration Points
33
-
34
- - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
35
- - **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
36
- - **TanStack Query**: For cache management and background updates
37
- - **useFocusEffect**: For refresh on screen focus
38
-
39
- ## Restrictions
40
-
41
- ### REQUIRED
42
-
43
- - **User Authentication**: User MUST be authenticated to access credits
44
- - **Error Handling**: MUST handle error state in UI
45
- - **Loading State**: MUST show loading indicator while fetching
46
-
47
- ### PROHIBITED
48
-
49
- - **NEVER** assume credits are available without checking loading state
50
- - **NEVER** use this hook for unauthenticated users
51
- - **DO NOT** mutate credits directly - use `useDeductCredit` instead
52
- - **DO NOT** call refetch excessively (causes unnecessary network calls)
53
-
54
- ### CRITICAL SAFETY
55
-
56
- - **ALWAYS** check `isLoading` before displaying credits
57
- - **ALWAYS** handle `error` state to prevent crashes
58
- - **NEVER** use `credits` value for security decisions (validate on backend)
59
- - **MUST** implement error boundaries when displaying balance
60
-
61
- ## AI Agent Guidelines
62
-
63
- ### When Implementing Credit Displays
64
-
65
- 1. **Always** handle loading state explicitly
66
- 2. **Always** handle error state gracefully
67
- 3. **Always** provide manual refresh option
68
- 4. **Always** format balance safely (handle undefined/null)
69
- 5. **Never** use credits for security decisions (server-side validation required)
70
-
71
- ### Integration Checklist
72
-
73
- - [ ] Import from correct path: `@umituz/react-native-subscription`
74
- - [ ] Handle loading state in UI
75
- - [ ] Handle error state in UI
76
- - [ ] Provide refresh mechanism
77
- - [ ] Format balance safely with default values
78
- - [ ] Implement error boundaries
79
- - [ ] Test with no credits (zero balance)
80
- - [ ] Test with loading states
81
- - [ ] Test with error states
82
- - [ ] Test refresh functionality
83
-
84
- ### Common Patterns to Implement
85
-
86
- 1. **Balance Card**: Display credits with currency conversion
87
- 2. **Transaction List**: Show recent credit activity
88
- 3. **Low Credits Warning**: Alert when balance is low
89
- 4. **Refresh Control**: Pull-to-refresh or button
90
- 5. **Real-time Updates**: Use focus effect for auto-refresh
91
- 6. **Purchase Prompt**: Link to credit packages when low
92
- 7. **Skeletal Loading**: Show skeleton during initial load
93
- 8. **Error Recovery**: Retry mechanism for failed fetches
94
-
95
- ## Related Documentation
96
-
97
- - **useDeductCredit**: Deduct credits from balance
98
- - **useCreditChecker**: Check credit availability before operations
99
- - **useInitializeCredits**: Initialize credits after purchase
100
- - **useCreditsGate**: Gate features behind credit requirements
101
- - **useFeatureGate**: Unified feature gating with credits
102
- - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
103
- - **Wallet Domain**: `src/domains/wallet/README.md`