@umituz/react-native-subscription 2.26.13 → 2.26.15

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/paywall/components/PaywallModal.tsx +36 -13
  3. package/src/domains/paywall/components/PlanCard.tsx +16 -3
  4. package/src/domains/paywall/entities/types.ts +4 -0
  5. package/src/domains/paywall/hooks/usePaywallTranslations.ts +8 -0
  6. package/src/presentation/hooks/index.ts +0 -15
  7. package/src/presentation/hooks/useFeatureGate.ts +41 -116
  8. package/src/revenuecat/domain/types/RevenueCatTypes.ts +32 -0
  9. package/src/revenuecat/index.ts +1 -0
  10. package/src/revenuecat/presentation/hooks/useRevenueCatTrialEligibility.ts +179 -0
  11. package/src/presentation/hooks/useAuthAwarePurchase.md +0 -92
  12. package/src/presentation/hooks/useAuthAwarePurchase.ts +0 -138
  13. package/src/presentation/hooks/useAuthGate.md +0 -89
  14. package/src/presentation/hooks/useAuthGate.ts +0 -65
  15. package/src/presentation/hooks/useCreditChecker.md +0 -102
  16. package/src/presentation/hooks/useCreditChecker.ts +0 -41
  17. package/src/presentation/hooks/useCreditsGate.md +0 -94
  18. package/src/presentation/hooks/useCreditsGate.ts +0 -81
  19. package/src/presentation/hooks/useDevTestCallbacks.md +0 -91
  20. package/src/presentation/hooks/useDevTestCallbacks.ts +0 -142
  21. package/src/presentation/hooks/useInitializeCredits.md +0 -92
  22. package/src/presentation/hooks/useInitializeCredits.ts +0 -57
  23. package/src/presentation/hooks/usePremiumGate.md +0 -88
  24. package/src/presentation/hooks/usePremiumGate.ts +0 -116
  25. package/src/presentation/hooks/usePremiumWithCredits.md +0 -92
  26. package/src/presentation/hooks/usePremiumWithCredits.ts +0 -48
  27. package/src/presentation/hooks/useSubscription.md +0 -94
  28. package/src/presentation/hooks/useSubscription.ts +0 -119
  29. package/src/presentation/hooks/useSubscriptionDetails.md +0 -93
  30. package/src/presentation/hooks/useSubscriptionDetails.ts +0 -85
  31. package/src/presentation/hooks/useSubscriptionGate.md +0 -84
  32. package/src/presentation/hooks/useSubscriptionGate.ts +0 -67
  33. package/src/presentation/hooks/useSubscriptionStatus.md +0 -94
  34. package/src/presentation/hooks/useSubscriptionStatus.ts +0 -64
  35. package/src/presentation/hooks/useTrialEligibility.ts +0 -66
  36. package/src/presentation/hooks/useUserTier.md +0 -91
  37. package/src/presentation/hooks/useUserTier.ts +0 -78
  38. package/src/presentation/hooks/useUserTierWithRepository.md +0 -92
  39. package/src/presentation/hooks/useUserTierWithRepository.ts +0 -151
@@ -1,92 +0,0 @@
1
- # useAuthAwarePurchase Hook
2
-
3
- Security-focused purchase hook that requires authentication before any transaction.
4
-
5
- ## Location
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **File**: `src/presentation/hooks/useAuthAwarePurchase.ts`
10
-
11
- **Type**: Hook
12
-
13
- ## Strategy
14
-
15
- ### Auth-Gated Purchase Flow
16
-
17
- 1. **Auth Provider Validation**: Verify auth provider is configured at app startup
18
- 2. **Authentication Check**: Block purchases for unauthenticated users
19
- 3. **Auth Flow Trigger**: Show auth modal when guest attempts purchase
20
- 4. **Purchase Blocking**: Prevent all transactions without valid authentication
21
- 5. **Post-Auth Purchase**: Allow purchase after user completes authentication
22
- 6. **Security Enforcement**: Server-side validation required for final verification
23
-
24
- ### Integration Points
25
-
26
- - **Auth Provider Configuration**: Must be configured once at app initialization
27
- - **Auth Context**: User authentication state
28
- - **Paywall Domain**: For subscription upgrade flow
29
- - **Auth UI**: For sign-in/sign-up flows
30
- - **RevenueCat**: For purchase transactions
31
-
32
- ## Restrictions
33
-
34
- ### REQUIRED
35
-
36
- - **Auth Provider Configuration**: MUST call `configureAuthProvider()` once at app startup
37
- - **isAuthenticated Function**: MUST provide function to check auth status
38
- - **showAuthModal Function**: MUST provide function to show auth UI
39
- - **Error Handling**: MUST handle purchase failures appropriately
40
-
41
- ### PROHIBITED
42
-
43
- - **NEVER** use without configuring auth provider first
44
- - **NEVER** bypass auth checks for convenience
45
- - **NEVER** allow anonymous/guest purchases
46
- - **DO NOT** call handlePurchase/handleRestore without auth provider setup
47
-
48
- ### CRITICAL SAFETY
49
-
50
- - **ALWAYS** configure auth provider at app initialization
51
- - **NEVER** allow purchases for anonymous users
52
- - **MUST** implement proper auth flow with pending purchase preservation
53
- - **ALWAYS** verify auth status in production
54
-
55
- ## AI Agent Guidelines
56
-
57
- ### When Implementing Auth-Gated Purchases
58
-
59
- 1. **Always** configure auth provider at app startup
60
- 2. **Always** implement isAuthenticated function
61
- 3. **Always** implement showAuthModal function
62
- 4. **Never** bypass auth checks
63
- 5. **Always** test purchase flow with authenticated and unauthenticated users
64
-
65
- ### Integration Checklist
66
-
67
- - [ ] Import from correct path: `@umituz/react-native-subscription`
68
- - [ ] Call `configureAuthProvider()` once at app startup
69
- - [ ] Provide `isAuthenticated()` function
70
- - [ ] Provide `showAuthModal()` function
71
- - [ ] Test purchase flow with authenticated user
72
- - [ ] Test purchase flow with unauthenticated user
73
- - [ ] Verify auth modal appears for guests
74
- - [ ] Verify purchase proceeds after authentication
75
- - [ ] Check development logs for auth verification
76
- - [ ] Verify purchases are blocked without auth provider
77
-
78
- ### Common Patterns
79
-
80
- 1. **App-Level Config**: Configure once in root App component
81
- 2. **Pending Purchase**: Store package for post-auth completion
82
- 3. **Auth Integration**: Use with Firebase, Auth0, or custom auth
83
- 4. **Error Handling**: Handle auth failures and purchase failures
84
- 5. **Development Testing**: Use dev logs to verify auth checks
85
-
86
- ## Related Documentation
87
-
88
- - **usePremium**: For purchase and restore operations
89
- - **usePaywallOperations**: For complete paywall purchase handling
90
- - **useAuthGate**: For authentication gating
91
- - **useAuthSubscriptionSync**: For syncing auth with subscription
92
- - **Security Best Practices**: `src/docs/SECURITY.md`
@@ -1,138 +0,0 @@
1
- /**
2
- * Auth-Aware Purchase Hook
3
- * Handles purchase flow with authentication requirement
4
- */
5
-
6
- import { useCallback } from "react";
7
- import type { PurchasesPackage } from "react-native-purchases";
8
- import { usePremium } from "./usePremium";
9
- import type { PurchaseSource } from "../../domain/entities/Credits";
10
-
11
- declare const __DEV__: boolean;
12
-
13
- export interface PurchaseAuthProvider {
14
- isAuthenticated: () => boolean;
15
- showAuthModal: () => void;
16
- }
17
-
18
- let globalAuthProvider: PurchaseAuthProvider | null = null;
19
- let savedPackage: PurchasesPackage | null = null;
20
- let savedSource: PurchaseSource | null = null;
21
-
22
- export const configureAuthProvider = (provider: PurchaseAuthProvider): void => {
23
- globalAuthProvider = provider;
24
- };
25
-
26
- export const getSavedPurchase = (): { pkg: PurchasesPackage; source: PurchaseSource } | null => {
27
- if (savedPackage && savedSource) {
28
- return { pkg: savedPackage, source: savedSource };
29
- }
30
- return null;
31
- };
32
-
33
- export const clearSavedPurchase = (): void => {
34
- savedPackage = null;
35
- savedSource = null;
36
- };
37
-
38
- export interface UseAuthAwarePurchaseParams {
39
- source?: PurchaseSource;
40
- userId?: string;
41
- }
42
-
43
- export interface UseAuthAwarePurchaseResult {
44
- handlePurchase: (pkg: PurchasesPackage, source?: PurchaseSource) => Promise<boolean>;
45
- handleRestore: () => Promise<boolean>;
46
- executeSavedPurchase: () => Promise<boolean>;
47
- }
48
-
49
- export const useAuthAwarePurchase = (
50
- params?: UseAuthAwarePurchaseParams
51
- ): UseAuthAwarePurchaseResult => {
52
- const { purchasePackage, restorePurchase } = usePremium(params?.userId);
53
-
54
- const handlePurchase = useCallback(
55
- async (pkg: PurchasesPackage, source?: PurchaseSource): Promise<boolean> => {
56
- if (__DEV__) {
57
- console.log("[useAuthAwarePurchase] handlePurchase called:", {
58
- productId: pkg.product.identifier,
59
- hasAuthProvider: !!globalAuthProvider,
60
- });
61
- }
62
-
63
- if (!globalAuthProvider) {
64
- if (__DEV__) {
65
- console.error("[useAuthAwarePurchase] Auth provider not configured");
66
- }
67
- return false;
68
- }
69
-
70
- const isAuth = globalAuthProvider.isAuthenticated();
71
- if (__DEV__) {
72
- console.log("[useAuthAwarePurchase] Auth check:", { isAuthenticated: isAuth });
73
- }
74
-
75
- if (!isAuth) {
76
- if (__DEV__) {
77
- console.log("[useAuthAwarePurchase] Not authenticated, saving and showing auth");
78
- }
79
- savedPackage = pkg;
80
- savedSource = source || params?.source || "settings";
81
- globalAuthProvider.showAuthModal();
82
- return false;
83
- }
84
-
85
- if (__DEV__) {
86
- console.log("[useAuthAwarePurchase] Calling purchasePackage");
87
- }
88
- const result = await purchasePackage(pkg);
89
- if (__DEV__) {
90
- console.log("[useAuthAwarePurchase] purchasePackage returned:", result);
91
- }
92
- return result;
93
- },
94
- [purchasePackage, params?.source]
95
- );
96
-
97
- const handleRestore = useCallback(async (): Promise<boolean> => {
98
- if (!globalAuthProvider) {
99
- if (__DEV__) {
100
- console.error("[useAuthAwarePurchase] Auth provider not configured");
101
- }
102
- return false;
103
- }
104
-
105
- if (!globalAuthProvider.isAuthenticated()) {
106
- if (__DEV__) {
107
- console.log("[useAuthAwarePurchase] Not authenticated for restore");
108
- }
109
- globalAuthProvider.showAuthModal();
110
- return false;
111
- }
112
-
113
- return restorePurchase();
114
- }, [restorePurchase]);
115
-
116
- const executeSavedPurchase = useCallback(async (): Promise<boolean> => {
117
- const saved = getSavedPurchase();
118
- if (!saved) {
119
- if (__DEV__) {
120
- console.log("[useAuthAwarePurchase] No saved purchase to execute");
121
- }
122
- return false;
123
- }
124
-
125
- if (__DEV__) {
126
- console.log("[useAuthAwarePurchase] Executing saved purchase:", saved.pkg.product.identifier);
127
- }
128
-
129
- clearSavedPurchase();
130
- return purchasePackage(saved.pkg);
131
- }, [purchasePackage]);
132
-
133
- return {
134
- handlePurchase,
135
- handleRestore,
136
- executeSavedPurchase,
137
- };
138
- };
@@ -1,89 +0,0 @@
1
- # useAuthGate Hook
2
-
3
- Hook for combining authentication and subscription gating.
4
-
5
- ## Location
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **File**: `src/presentation/hooks/useAuthGate.ts`
10
-
11
- **Type**: Hook
12
-
13
- ## Strategy
14
-
15
- ### Auth Gate Flow
16
-
17
- 1. **Authentication Check**: Verify if user is authenticated
18
- 2. **Subscription Check**: Verify if user has required subscription
19
- 3. **Authorization Evaluation**: Combine auth + subscription status
20
- 4. **Gate Actions**: Provide functions to gate features
21
- 5. **Sign In Flow**: Trigger authentication when required
22
- 6. **Upgrade Flow**: Trigger subscription when required
23
-
24
- ### Integration Points
25
-
26
- - **Auth Context**: User authentication state
27
- - **Subscription Repository**: `src/infrastructure/repositories/SubscriptionRepository.ts`
28
- - **Paywall Domain**: For subscription upgrade flow
29
- - **Auth UI**: For sign-in/sign-up flows
30
-
31
- ## Restrictions
32
-
33
- ### REQUIRED
34
-
35
- - **Loading State**: MUST handle loading state
36
- - **Authorization Check**: MUST verify isAuthorized before showing protected content
37
- - **Callback Implementation**: MUST implement onAuthRequired/onSubscriptionRequired callbacks
38
-
39
- ### PROHIBITED
40
-
41
- - **NEVER** show protected content without checking isAuthorized
42
- - **NEVER** use for security decisions without server validation
43
- - **DO NOT** assume user is authenticated or subscribed
44
-
45
- ### CRITICAL SAFETY
46
-
47
- - **ALWAYS** check isAuthorized before showing protected features
48
- - **NEVER** trust client-side state for security
49
- - **MUST** implement proper auth flow
50
- - **ALWAYS** handle all states (loading, authorized, unauthorized)
51
-
52
- ## AI Agent Guidelines
53
-
54
- ### When Implementing Auth Gates
55
-
56
- 1. **Always** check loading state first
57
- 2. **Always** verify isAuthorized before showing content
58
- 3. **Always** provide sign-in option for unauthenticated users
59
- 4. **Always** provide upgrade option for non-subscribed users
60
- 5. **Never** bypass auth checks for convenience
61
-
62
- ### Integration Checklist
63
-
64
- - [ ] Import from correct path: `@umituz/react-native-subscription`
65
- - [ ] Configure requireAuth and requireSubscription
66
- - [ ] Handle loading state
67
- - [ ] Check isAuthorized before showing content
68
- - [ ] Implement sign-in callback
69
- - [ ] Implement subscription upgrade callback
70
- - [ ] Test with unauthenticated user
71
- - [ ] Test with authenticated non-subscribed user
72
- - [ ] Test with authenticated subscribed user
73
- - [ ] Test loading states
74
-
75
- ### Common Patterns
76
-
77
- 1. **Auth Only**: Require authentication only
78
- 2. **Subscription Only**: Require subscription only (auth handled internally)
79
- 3. **Both**: Require both auth and subscription
80
- 4. **Conditional Gates**: Different requirements per feature
81
- 5. **Nested Gates**: Layer multiple gate conditions
82
-
83
- ## Related Documentation
84
-
85
- - **useAuth**: Authentication state
86
- - **usePremiumGate**: Premium-only gating
87
- - **useSubscriptionGate**: Subscription-only gating
88
- - **useFeatureGate**: Unified feature gating
89
- - **Auth Domain**: `src/domains/config/README.md`
@@ -1,65 +0,0 @@
1
- /**
2
- * useAuthGate Hook
3
- *
4
- * Single responsibility: Authentication gating
5
- * Checks if user is authenticated before allowing actions.
6
- *
7
- * @example
8
- * ```typescript
9
- * const { requireAuth, isAuthenticated } = useAuthGate({
10
- * isAuthenticated: !!user && !user.isAnonymous,
11
- * onAuthRequired: (callback) => showAuthModal(callback),
12
- * });
13
- *
14
- * const handleAction = () => {
15
- * requireAuth(() => doSomething());
16
- * };
17
- * ```
18
- */
19
-
20
- import { useCallback } from "react";
21
-
22
- declare const __DEV__: boolean;
23
-
24
- export interface UseAuthGateParams {
25
- /** Whether user is authenticated (not guest/anonymous) */
26
- isAuthenticated: boolean;
27
- /** Callback when auth is required - receives pending action callback */
28
- onAuthRequired: (pendingCallback: () => void | Promise<void>) => void;
29
- }
30
-
31
- export interface UseAuthGateResult {
32
- /** Whether user is authenticated */
33
- isAuthenticated: boolean;
34
- /** Gate action behind auth - executes if authenticated, else shows auth modal */
35
- requireAuth: (action: () => void | Promise<void>) => boolean;
36
- }
37
-
38
- export function useAuthGate(params: UseAuthGateParams): UseAuthGateResult {
39
- const { isAuthenticated, onAuthRequired } = params;
40
-
41
- const requireAuth = useCallback(
42
- (action: () => void | Promise<void>): boolean => {
43
- if (!isAuthenticated) {
44
- if (__DEV__) {
45
-
46
- console.log("[useAuthGate] Not authenticated, showing auth modal");
47
- }
48
- onAuthRequired(action);
49
- return false;
50
- }
51
-
52
- if (__DEV__) {
53
-
54
- console.log("[useAuthGate] Authenticated, proceeding");
55
- }
56
- return true;
57
- },
58
- [isAuthenticated, onAuthRequired]
59
- );
60
-
61
- return {
62
- isAuthenticated,
63
- requireAuth,
64
- };
65
- }
@@ -1,102 +0,0 @@
1
- # useCreditChecker Hook
2
-
3
- Simple hook for checking if user has sufficient credits before operations.
4
-
5
- ## Location
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **File**: `src/presentation/hooks/useCreditChecker.ts`
10
-
11
- **Type**: Hook
12
-
13
- ## Strategy
14
-
15
- ### Credit Validation Flow
16
-
17
- 1. **Initial Check**
18
- - Compare current balance against required amount
19
- - Return boolean result immediately
20
- - No network calls required (uses cached balance)
21
-
22
- 2. **Real-time Updates**
23
- - Automatically re-checks when credits change
24
- - Updates result via `useCredits` hook
25
- - Triggers re-renders on balance changes
26
-
27
- 3. **Manual Refresh**
28
- - Optionally trigger manual credit check
29
- - Useful before expensive operations
30
- - Validates current state before action
31
-
32
- ### Integration Points
33
-
34
- - **useCredits**: For fetching current credit balance
35
- - **useDeductCredit**: For deducting credits after check
36
- - **Credit Checking UI**: Pre-action validation displays
37
- - **Purchase Flows**: Redirect to credit packages
38
-
39
- ## Restrictions
40
-
41
- ### REQUIRED
42
-
43
- - **Required Amount**: MUST specify positive credit cost
44
- - **Balance Check**: MUST verify `hasEnoughCredits` before action
45
- - **User Feedback**: MUST show credit cost to user
46
-
47
- ### PROHIBITED
48
-
49
- - **NEVER** assume credits are sufficient without checking
50
- - **NEVER** use for security decisions (server-side validation required)
51
- - **DO NOT** deduct credits with this hook (use `useDeductCredit`)
52
- - **NEVER** hardcode credit costs (should be configurable)
53
-
54
- ### CRITICAL SAFETY
55
-
56
- - **ALWAYS** check return value before proceeding with action
57
- - **ALWAYS** show credit cost to user before execution
58
- - **NEVER** trust client-side check for security (server must validate)
59
- - **MUST** handle case where credits become insufficient between check and action
60
-
61
- ## AI Agent Guidelines
62
-
63
- ### When Implementing Credit Checks
64
-
65
- 1. **Always** specify positive credit cost
66
- 2. **Always** check `hasEnoughCredits` before action
67
- 3. **Always** show credit cost to user in UI
68
- 4. **Always** provide upgrade path when insufficient
69
- 5. **Never** use for security decisions (server validation required)
70
-
71
- ### Integration Checklist
72
-
73
- - [ ] Import from correct path: `@umituz/react-native-subscription`
74
- - [ ] Specify positive credit cost
75
- - [ ] Check `hasEnoughCredits` before action
76
- - [ ] Display credit cost to user
77
- - [ ] Show upgrade/purchase option when insufficient
78
- - [ ] Validate credit cost is positive number
79
- - [ ] Test with sufficient credits
80
- - [ ] Test with insufficient credits
81
- - [ ] Test with zero credits
82
- - [ ] Test credit changes between check and action
83
-
84
- ### Common Patterns to Implement
85
-
86
- 1. **Pre-action Validation**: Check before showing button
87
- 2. **Cost Display**: Always show credit cost to user
88
- 3. **Upgrade Prompts**: Link to credit packages when low
89
- 4. **Manual Refresh**: Check again before expensive operations
90
- 5. **Credit Deduction**: Use with `useDeductCredit` for complete flow
91
- 6. **Visual Feedback**: Disable buttons when insufficient
92
- 7. **Warning Messages**: Alert user before high-cost operations
93
- 8. **Balance Display**: Show current balance alongside cost
94
-
95
- ## Related Documentation
96
-
97
- - **useCredits**: Access current credit balance
98
- - **useDeductCredit**: Deduct credits after check passes
99
- - **useCreditsGate**: Complete credit gating with deduction
100
- - **useFeatureGate**: Unified feature gating with credits
101
- - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
102
- - **Wallet Domain**: `src/domains/wallet/README.md`
@@ -1,41 +0,0 @@
1
- /**
2
- * useCreditChecker Hook
3
- *
4
- * Provides credit checking utilities using module-level repository.
5
- */
6
-
7
- import { useMemo } from "react";
8
- import { getCreditsRepository } from "../../infrastructure/repositories/CreditsRepositoryProvider";
9
- import {
10
- createCreditChecker,
11
- type CreditCheckResult,
12
- } from "../../utils/creditChecker";
13
-
14
- export interface UseCreditCheckerParams {
15
- onCreditDeducted?: (userId: string, cost: number) => void;
16
- }
17
-
18
- export interface UseCreditCheckerResult {
19
- checkCreditsAvailable: (
20
- userId: string | undefined,
21
- cost?: number
22
- ) => Promise<CreditCheckResult>;
23
- deductCreditsAfterSuccess: (
24
- userId: string | undefined,
25
- cost?: number
26
- ) => Promise<void>;
27
- }
28
-
29
- export const useCreditChecker = (
30
- params?: UseCreditCheckerParams
31
- ): UseCreditCheckerResult => {
32
- const repository = getCreditsRepository();
33
- const onCreditDeducted = params?.onCreditDeducted;
34
-
35
- const checker = useMemo(
36
- () => createCreditChecker({ repository, onCreditDeducted }),
37
- [repository, onCreditDeducted]
38
- );
39
-
40
- return checker;
41
- };
@@ -1,94 +0,0 @@
1
- # useCreditsGate Hook
2
-
3
- Hook for gating features behind credit requirements.
4
-
5
- ## Location
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **File**: `src/presentation/hooks/useCreditsGate.ts`
10
-
11
- **Type**: Hook
12
-
13
- ## Strategy
14
-
15
- ### Credit Gating Flow
16
-
17
- 1. **Credit Check**: Verify user has sufficient credits for feature
18
- 2. **Balance Display**: Show current credit balance to user
19
- 3. **Feature Access Control**: Enable/disable features based on credit availability
20
- 4. **Consumption**: Deduct credits when feature is used
21
- 5. **Purchase Prompt**: Guide users to purchase when insufficient
22
- 6. **Transaction Tracking**: Record all credit transactions
23
-
24
- ### Integration Points
25
-
26
- - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
27
- - **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
28
- - **TanStack Query**: For optimistic updates and caching
29
- - **Paywall Domain**: For purchase flow integration
30
-
31
- ## Restrictions
32
-
33
- ### REQUIRED
34
-
35
- - **Credit Cost**: MUST specify credit cost for feature
36
- - **Feature ID**: MUST provide unique feature identifier
37
- - **Balance Check**: MUST verify hasCredits before allowing action
38
- - **Error Handling**: MUST handle consumption failures
39
-
40
- ### PROHIBITED
41
-
42
- - **NEVER** allow feature access when hasCredits is false
43
- - **NEVER** consume credits without checking balance first
44
- - **NEVER** assume credits will be sufficient (always check)
45
- - **DO NOT** use for security decisions without server validation
46
-
47
- ### CRITICAL SAFETY
48
-
49
- - **ALWAYS** check return value from consumeCredit
50
- - **NEVER** allow negative credit balance
51
- - **MUST** handle insufficient credits gracefully
52
- - **ALWAYS** show credit cost to user before action
53
-
54
- ## AI Agent Guidelines
55
-
56
- ### When Implementing Credit Gates
57
-
58
- 1. **Always** display credit cost to user before action
59
- 2. **Always** check hasCredits before enabling buttons
60
- 3. **Always** handle consumeCredit result
61
- 4. **Never** allow action when credits are insufficient
62
- 5. **Always** provide purchase path for credits
63
-
64
- ### Integration Checklist
65
-
66
- - [ ] Import from correct path: `@umituz/react-native-subscription`
67
- - [ ] Specify credit cost in config
68
- - [ ] Provide unique feature ID
69
- - [ ] Check hasCredits before enabling feature
70
- - [ ] Handle consumeCredit result
71
- - [ ] Show credit cost in UI
72
- - [ ] Display current balance
73
- - [ ] Implement purchase prompt for insufficient credits
74
- - [ ] Test with zero balance
75
- - [ ] Test with insufficient credits
76
- - [ ] Test with sufficient credits
77
-
78
- ### Common Patterns
79
-
80
- 1. **Pre-check**: Verify balance before showing feature
81
- 2. **Confirmation**: Ask user before expensive operations
82
- 3. **Success Feedback**: Show message after successful consumption
83
- 4. **Failure Handling**: Display appropriate error on failure
84
- 5. **Purchase Flow**: Navigate to purchase screen on exhaustion
85
-
86
- ## Related Documentation
87
-
88
- - **useCredits**: Access current credit balance
89
- - **useDeductCredit**: Manual credit deduction with optimistic updates
90
- - **useCreditChecker**: Simple credit validation
91
- - **usePremiumWithCredits**: Hybrid premium/credits access
92
- - **useFeatureGate**: Unified feature gating
93
- - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
94
- - **Wallet Domain**: `src/domains/wallet/README.md`
@@ -1,81 +0,0 @@
1
- /**
2
- * useCreditsGate Hook
3
- *
4
- * Single responsibility: Credits gating
5
- * Checks if user has enough credits before allowing actions.
6
- *
7
- * @example
8
- * ```typescript
9
- * const { requireCredits, hasCredits } = useCreditsGate({
10
- * hasCredits: canAfford(cost),
11
- * creditBalance: credits,
12
- * requiredCredits: cost,
13
- * onCreditsRequired: (required) => showPaywall(required),
14
- * });
15
- *
16
- * const handleGenerate = () => {
17
- * requireCredits(() => generate());
18
- * };
19
- * ```
20
- */
21
-
22
- import { useCallback } from "react";
23
-
24
- export interface UseCreditsGateParams {
25
- /** Whether user has enough credits for the action */
26
- hasCredits: boolean;
27
- /** Current credit balance */
28
- creditBalance: number;
29
- /** Credits required for this action (optional, for display) */
30
- requiredCredits?: number;
31
- /** Callback when credits are required - receives required amount */
32
- onCreditsRequired: (requiredCredits?: number) => void;
33
- }
34
-
35
- export interface UseCreditsGateResult {
36
- /** Whether user has enough credits */
37
- hasCredits: boolean;
38
- /** Current credit balance */
39
- creditBalance: number;
40
- /** Gate action behind credits - executes if has credits, else shows paywall */
41
- requireCredits: (action: () => void | Promise<void>) => boolean;
42
- }
43
-
44
- declare const __DEV__: boolean;
45
-
46
- export function useCreditsGate(
47
- params: UseCreditsGateParams
48
- ): UseCreditsGateResult {
49
- const { hasCredits, creditBalance, requiredCredits, onCreditsRequired } =
50
- params;
51
-
52
- const requireCredits = useCallback(
53
- (_action: () => void | Promise<void>): boolean => {
54
- if (typeof __DEV__ !== "undefined" && __DEV__) {
55
- console.log("[useCreditsGate] requireCredits called", {
56
- hasCredits,
57
- creditBalance,
58
- requiredCredits,
59
- });
60
- }
61
- if (!hasCredits) {
62
- if (typeof __DEV__ !== "undefined" && __DEV__) {
63
- console.log("[useCreditsGate] No credits, showing paywall");
64
- }
65
- onCreditsRequired(requiredCredits);
66
- return false;
67
- }
68
- if (typeof __DEV__ !== "undefined" && __DEV__) {
69
- console.log("[useCreditsGate] Has credits, allowing action");
70
- }
71
- return true;
72
- },
73
- [hasCredits, creditBalance, requiredCredits, onCreditsRequired]
74
- );
75
-
76
- return {
77
- hasCredits,
78
- creditBalance,
79
- requireCredits,
80
- };
81
- }