@umituz/react-native-subscription 2.14.97 โ†’ 2.14.99

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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +461 -0
  3. package/package.json +1 -3
  4. package/src/application/README.md +229 -0
  5. package/src/application/ports/README.md +103 -0
  6. package/src/domain/README.md +402 -0
  7. package/src/domain/constants/README.md +80 -0
  8. package/src/domain/entities/README.md +176 -0
  9. package/src/domain/errors/README.md +307 -0
  10. package/src/domain/value-objects/README.md +186 -0
  11. package/src/domains/README.md +240 -0
  12. package/src/domains/config/README.md +390 -0
  13. package/src/domains/config/domain/README.md +390 -0
  14. package/src/domains/config/domain/entities/README.md +350 -0
  15. package/src/domains/paywall/README.md +371 -0
  16. package/src/domains/paywall/components/PaywallHeader.tsx +8 -11
  17. package/src/domains/paywall/components/README.md +185 -0
  18. package/src/domains/paywall/entities/README.md +199 -0
  19. package/src/domains/paywall/hooks/README.md +129 -0
  20. package/src/domains/wallet/README.md +292 -0
  21. package/src/domains/wallet/domain/README.md +108 -0
  22. package/src/domains/wallet/domain/entities/README.md +122 -0
  23. package/src/domains/wallet/domain/errors/README.md +157 -0
  24. package/src/domains/wallet/infrastructure/README.md +96 -0
  25. package/src/domains/wallet/presentation/components/BalanceCard.tsx +6 -12
  26. package/src/domains/wallet/presentation/components/README.md +231 -0
  27. package/src/domains/wallet/presentation/hooks/README.md +255 -0
  28. package/src/infrastructure/README.md +514 -0
  29. package/src/infrastructure/mappers/README.md +34 -0
  30. package/src/infrastructure/models/README.md +26 -0
  31. package/src/infrastructure/repositories/README.md +385 -0
  32. package/src/infrastructure/services/README.md +374 -0
  33. package/src/presentation/README.md +410 -0
  34. package/src/presentation/components/README.md +183 -0
  35. package/src/presentation/components/details/CreditRow.md +337 -0
  36. package/src/presentation/components/details/DetailRow.md +283 -0
  37. package/src/presentation/components/details/PremiumDetailsCard.md +266 -0
  38. package/src/presentation/components/details/PremiumStatusBadge.md +266 -0
  39. package/src/presentation/components/details/README.md +449 -0
  40. package/src/presentation/components/feedback/PaywallFeedbackModal.md +314 -0
  41. package/src/presentation/components/feedback/README.md +447 -0
  42. package/src/presentation/components/paywall/PaywallModal.md +444 -0
  43. package/src/presentation/components/paywall/README.md +190 -0
  44. package/src/presentation/components/sections/README.md +468 -0
  45. package/src/presentation/components/sections/SubscriptionSection.md +246 -0
  46. package/src/presentation/hooks/README.md +743 -0
  47. package/src/presentation/hooks/useAuthAwarePurchase.md +359 -0
  48. package/src/presentation/hooks/useAuthGate.md +403 -0
  49. package/src/presentation/hooks/useAuthSubscriptionSync.md +398 -0
  50. package/src/presentation/hooks/useCreditChecker.md +407 -0
  51. package/src/presentation/hooks/useCredits.md +342 -0
  52. package/src/presentation/hooks/useCreditsGate.md +346 -0
  53. package/src/presentation/hooks/useDeductCredit.md +176 -0
  54. package/src/presentation/hooks/useDevTestCallbacks.md +422 -0
  55. package/src/presentation/hooks/useFeatureGate.md +157 -0
  56. package/src/presentation/hooks/useInitializeCredits.md +458 -0
  57. package/src/presentation/hooks/usePaywall.md +334 -0
  58. package/src/presentation/hooks/usePaywallOperations.md +486 -0
  59. package/src/presentation/hooks/usePaywallVisibility.md +344 -0
  60. package/src/presentation/hooks/usePremium.md +230 -0
  61. package/src/presentation/hooks/usePremiumGate.md +423 -0
  62. package/src/presentation/hooks/usePremiumWithCredits.md +429 -0
  63. package/src/presentation/hooks/useSubscription.md +450 -0
  64. package/src/presentation/hooks/useSubscriptionDetails.md +438 -0
  65. package/src/presentation/hooks/useSubscriptionGate.md +168 -0
  66. package/src/presentation/hooks/useSubscriptionSettingsConfig.md +374 -0
  67. package/src/presentation/hooks/useSubscriptionStatus.md +424 -0
  68. package/src/presentation/hooks/useUserTier.md +356 -0
  69. package/src/presentation/hooks/useUserTierWithRepository.md +452 -0
  70. package/src/presentation/screens/README.md +194 -0
  71. package/src/presentation/types/README.md +38 -0
  72. package/src/presentation/utils/README.md +52 -0
  73. package/src/revenuecat/README.md +523 -0
  74. package/src/revenuecat/application/README.md +158 -0
  75. package/src/revenuecat/application/ports/README.md +169 -0
  76. package/src/revenuecat/domain/README.md +147 -0
  77. package/src/revenuecat/domain/constants/README.md +183 -0
  78. package/src/revenuecat/domain/entities/README.md +382 -0
  79. package/src/revenuecat/domain/errors/README.md +197 -0
  80. package/src/revenuecat/domain/types/README.md +373 -0
  81. package/src/revenuecat/domain/value-objects/README.md +441 -0
  82. package/src/revenuecat/infrastructure/README.md +50 -0
  83. package/src/revenuecat/infrastructure/config/README.md +40 -0
  84. package/src/revenuecat/infrastructure/handlers/README.md +218 -0
  85. package/src/revenuecat/infrastructure/managers/README.md +49 -0
  86. package/src/revenuecat/infrastructure/services/README.md +325 -0
  87. package/src/revenuecat/infrastructure/utils/README.md +382 -0
  88. package/src/revenuecat/presentation/README.md +184 -0
  89. package/src/revenuecat/presentation/hooks/README.md +56 -0
  90. package/src/utils/README.md +529 -0
@@ -0,0 +1,176 @@
1
+ # useDeductCredit Hook
2
+
3
+ Hook for deducting credits from user balance with optimistic updates.
4
+
5
+ ## Location
6
+
7
+ **Import Path**: `@umituz/react-native-subscription`
8
+
9
+ **File**: `src/presentation/hooks/useDeductCredit.ts`
10
+
11
+ ## Strategy
12
+
13
+ ### Credit Deduction Flow
14
+
15
+ 1. **Pre-deduction Validation**
16
+ - Verify user is authenticated (userId must be defined)
17
+ - Check if sufficient credits exist
18
+ - Validate deduction amount is positive
19
+
20
+ 2. **Optimistic Update**
21
+ - Immediately update UI with new balance
22
+ - Store previous state for potential rollback
23
+ - Update TanStack Query cache
24
+
25
+ 3. **Server Synchronization**
26
+ - Send deduction request to backend
27
+ - Handle success/failure responses
28
+ - Rollback on failure
29
+
30
+ 4. **Post-deduction Handling**
31
+ - Trigger `onCreditsExhausted` callback if balance reaches zero
32
+ - Return success/failure boolean
33
+ - Reset loading state
34
+
35
+ ### Integration Points
36
+
37
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
38
+ - **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
39
+ - **TanStack Query**: For cache management and optimistic updates
40
+
41
+ ## Restrictions
42
+
43
+ ### REQUIRED
44
+
45
+ - **User Authentication**: `userId` parameter MUST be provided and cannot be undefined
46
+ - **Positive Amount**: Credit cost MUST be greater than zero
47
+ - **Callback Implementation**: `onCreditsExhausted` callback SHOULD be implemented to handle zero balance scenarios
48
+
49
+ ### PROHIBITED
50
+
51
+ - **NEVER** call `deductCredit` or `deductCredits` without checking `isDeducting` state first
52
+ - **NEVER** allow multiple simultaneous deduction calls for the same user
53
+ - **NEVER** deduce credits when balance is insufficient (should check with `useCreditChecker` first)
54
+ - **DO NOT** use this hook for guest users (userId undefined)
55
+
56
+ ### CRITICAL SAFETY
57
+
58
+ - **ALWAYS** check return value before proceeding with feature execution
59
+ - **ALWAYS** handle the case where deduction returns `false`
60
+ - **NEVER** assume deduction succeeded without checking return value
61
+ - **MUST** implement error boundaries when using this hook
62
+
63
+ ## Rules
64
+
65
+ ### Initialization
66
+
67
+ ```typescript
68
+ // CORRECT
69
+ const { deductCredit, isDeducting } = useDeductCredit({
70
+ userId: user?.uid,
71
+ onCreditsExhausted: () => showPaywall(),
72
+ });
73
+
74
+ // INCORRECT - Missing callback
75
+ const { deductCredit } = useDeductCredit({
76
+ userId: user?.uid,
77
+ });
78
+
79
+ // INCORRECT - userId undefined
80
+ const { deductCredit } = useDeductCredit({
81
+ userId: undefined,
82
+ });
83
+ ```
84
+
85
+ ### Deduction Execution
86
+
87
+ ```typescript
88
+ // CORRECT - Check return value
89
+ const success = await deductCredit(5);
90
+ if (success) {
91
+ executeFeature();
92
+ }
93
+
94
+ // INCORRECT - No return value check
95
+ await deductCredit(5);
96
+ executeFeature(); // May execute even if deduction failed
97
+
98
+ // INCORRECT - Multiple simultaneous calls
99
+ Promise.all([
100
+ deductCredit(5),
101
+ deductCredit(3), // Race condition!
102
+ ]);
103
+ ```
104
+
105
+ ### Loading States
106
+
107
+ ```typescript
108
+ // CORRECT - Respect loading state
109
+ <Button onPress={handleDeduct} disabled={isDeducting}>
110
+ {isDeducting ? 'Deducting...' : 'Use Feature'}
111
+ </Button>
112
+
113
+ // INCORRECT - Ignore loading state
114
+ <Button onPress={handleDeduct}>
115
+ Use Feature
116
+ </Button>
117
+ ```
118
+
119
+ ### Credit Exhaustion Handling
120
+
121
+ ```typescript
122
+ // CORRECT - Implement callback
123
+ const { deductCredit } = useDeductCredit({
124
+ userId: user?.uid,
125
+ onCreditsExhausted: () => {
126
+ navigation.navigate('CreditPackages');
127
+ },
128
+ });
129
+
130
+ // MINIMUM - Show alert
131
+ const { deductCredit } = useDeductCredit({
132
+ userId: user?.uid,
133
+ onCreditsExhausted: () => {
134
+ Alert.alert('No Credits', 'Please purchase more credits');
135
+ },
136
+ });
137
+ ```
138
+
139
+ ## AI Agent Guidelines
140
+
141
+ ### When Implementing Features
142
+
143
+ 1. **Always** check if user has sufficient credits BEFORE allowing action
144
+ 2. **Always** show the credit cost to user before deducting
145
+ 3. **Always** disable buttons while `isDeducting` is true
146
+ 4. **Always** handle the case where deduction returns false
147
+ 5. **Never** allow zero or negative credit costs
148
+
149
+ ### Integration Checklist
150
+
151
+ - [ ] Import from correct path: `@umituz/react-native-subscription`
152
+ - [ ] Provide valid `userId` from authentication context
153
+ - [ ] Implement `onCreditsExhausted` callback
154
+ - [ ] Check `isDeducting` before calling deduct functions
155
+ - [ ] Validate return value before proceeding
156
+ - [ ] Show credit cost to user before action
157
+ - [ ] Handle error cases gracefully
158
+ - [ ] Test with insufficient credits
159
+ - [ ] Test with zero balance
160
+
161
+ ### Common Patterns to Implement
162
+
163
+ 1. **Pre-check**: Use `useCreditChecker` before showing feature button
164
+ 2. **Confirmation Dialog**: Ask user before expensive operations (>5 credits)
165
+ 3. **Success Feedback**: Show success message after deduction
166
+ 4. **Failure Handling**: Show appropriate error message on failure
167
+ 5. **Purchase Flow**: Navigate to purchase screen on exhaustion
168
+
169
+ ## Related Documentation
170
+
171
+ - **useCredits**: Access current credit balance
172
+ - **useCreditChecker**: Check credit availability before operations
173
+ - **useInitializeCredits**: Initialize credits after purchase
174
+ - **useFeatureGate**: Unified feature gating with credits
175
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
176
+ - **Wallet Domain**: `src/domains/wallet/README.md`
@@ -0,0 +1,422 @@
1
+ # useDevTestCallbacks Hook
2
+
3
+ **Development-only** hook for testing subscription renewal and credit operations.
4
+
5
+ ## Import
6
+
7
+ ```typescript
8
+ import { useDevTestCallbacks } from '@umituz/react-native-subscription';
9
+ ```
10
+
11
+ ## Signature
12
+
13
+ ```typescript
14
+ function useDevTestCallbacks(): {
15
+ onTestRenewal: () => void;
16
+ onCheckCredits: () => void;
17
+ onTestDuplicate: () => void;
18
+ } | undefined
19
+ ```
20
+
21
+ ## Returns
22
+
23
+ Returns `undefined` in production. In development, returns:
24
+
25
+ | Property | Type | Description |
26
+ |----------|------|-------------|
27
+ | `onTestRenewal` | `() => void` | Simulate subscription renewal |
28
+ | `onCheckCredits` | `() => void` | Show current credits in alert |
29
+ | `onTestDuplicate` | `() => void` | Test duplicate renewal protection |
30
+
31
+ ## Important Notes
32
+
33
+ โš ๏ธ **Development Only**
34
+ - This hook only works in `__DEV__` mode
35
+ - Returns `undefined` in production builds
36
+ - Use for testing and development purposes only
37
+
38
+ ## Basic Usage
39
+
40
+ ```typescript
41
+ function DevTestSection() {
42
+ const devCallbacks = useDevTestCallbacks();
43
+
44
+ // Don't render in production
45
+ if (!devCallbacks) return null;
46
+
47
+ const { onTestRenewal, onCheckCredits, onTestDuplicate } = devCallbacks;
48
+
49
+ return (
50
+ <View style={styles.devSection}>
51
+ <Text style={styles.title}>Developer Tools</Text>
52
+
53
+ <Button onPress={onTestRenewal} title="Test Renewal" />
54
+ <Button onPress={onCheckCredits} title="Check Credits" />
55
+ <Button onPress={onTestDuplicate} title="Test Duplicate Protection" />
56
+ </View>
57
+ );
58
+ }
59
+ ```
60
+
61
+ ## Advanced Usage
62
+
63
+ ### Complete Dev Test Panel
64
+
65
+ ```typescript
66
+ function DevTestPanel() {
67
+ const devCallbacks = useDevTestCallbacks();
68
+
69
+ if (!__DEV__ || !devCallbacks) return null;
70
+
71
+ const { onTestRenewal, onCheckCredits, onTestDuplicate } = devCallbacks;
72
+
73
+ return (
74
+ <ScrollView style={styles.devPanel}>
75
+ <Text style={styles.header}>Developer Test Panel</Text>
76
+
77
+ <View style={styles.section}>
78
+ <Text style={styles.sectionTitle}>Renewal Testing</Text>
79
+
80
+ <TouchableOpacity
81
+ style={styles.button}
82
+ onPress={onTestRenewal}
83
+ >
84
+ <Text>Test Renewal (Add Credits)</Text>
85
+ </TouchableOpacity>
86
+
87
+ <Text style={styles.help}>
88
+ Simulates a subscription renewal and adds credits using ACCUMULATE mode
89
+ </Text>
90
+ </View>
91
+
92
+ <View style={styles.section}>
93
+ <Text style={styles.sectionTitle}>Credits Inspection</Text>
94
+
95
+ <TouchableOpacity
96
+ style={styles.button}
97
+ onPress={onCheckCredits}
98
+ >
99
+ <Text>Check Current Credits</Text>
100
+ </TouchableOpacity>
101
+
102
+ <Text style={styles.help}>
103
+ Display current credit balance and purchase date
104
+ </Text>
105
+ </View>
106
+
107
+ <View style={styles.section}>
108
+ <Text style={styles.sectionTitle}>Duplicate Protection</Text>
109
+
110
+ <TouchableOpacity
111
+ style={styles.button}
112
+ onPress={onTestDuplicate}
113
+ >
114
+ <Text>Test Duplicate Protection</Text>
115
+ </TouchableOpacity>
116
+
117
+ <Text style={styles.help}>
118
+ Tests that duplicate renewals with the same ID are prevented
119
+ </Text>
120
+ </View>
121
+ </ScrollView>
122
+ );
123
+ }
124
+ ```
125
+
126
+ ### With Settings Screen Integration
127
+
128
+ ```typescript
129
+ function SettingsScreen() {
130
+ const devCallbacks = useDevTestCallbacks();
131
+
132
+ return (
133
+ <ScrollView>
134
+ <Section title="Account">
135
+ <SettingsItem label="Email" value={user?.email} />
136
+ <SettingsItem label="Subscription" value={isPremium ? 'Premium' : 'Free'} />
137
+ </Section>
138
+
139
+ {/* Only show in development */}
140
+ {__DEV__ && devCallbacks && (
141
+ <Section title="Developer Tools">
142
+ <SettingsItem
143
+ label="Test Renewal"
144
+ onPress={devCallbacks.onTestRenewal}
145
+ />
146
+ <SettingsItem
147
+ label="Check Credits"
148
+ onPress={devCallbacks.onCheckCredits}
149
+ />
150
+ <SettingsItem
151
+ label="Test Duplicate Protection"
152
+ onPress={devCallbacks.onTestDuplicate}
153
+ />
154
+ </Section>
155
+ )}
156
+ </ScrollView>
157
+ );
158
+ }
159
+ ```
160
+
161
+ ### With Debug Menu
162
+
163
+ ```typescript
164
+ function DebugMenu() {
165
+ const devCallbacks = useDevTestCallbacks();
166
+
167
+ if (!__DEV__) return null;
168
+
169
+ return (
170
+ <Menu>
171
+ {devCallbacks && (
172
+ <>
173
+ <MenuItem onPress={devCallbacks.onTestRenewal}>
174
+ Test Renewal
175
+ </MenuItem>
176
+ <MenuItem onPress={devCallbacks.onCheckCredits}>
177
+ Check Credits
178
+ </MenuItem>
179
+ <MenuItem onPress={devCallbacks.onTestDuplicate}>
180
+ Test Duplicate Protection
181
+ </MenuItem>
182
+ </>
183
+ )}
184
+ </Menu>
185
+ );
186
+ }
187
+ ```
188
+
189
+ ## Test Functions
190
+
191
+ ### onTestRenewal
192
+
193
+ Simulates a subscription renewal event:
194
+
195
+ ```typescript
196
+ const onTestRenewal = () => {
197
+ // Simulates renewal with:
198
+ // - renewalId: `dev_renewal_${Date.now()}`
199
+ // - productId: 'test_yearly_subscription'
200
+ // - Mode: ACCUMULATE (adds to existing credits)
201
+
202
+ // Shows alert with:
203
+ // - New credit balance
204
+ // - Confirmation of ACCUMULATE mode
205
+ };
206
+ ```
207
+
208
+ **Example output:**
209
+ ```
210
+ โœ… Test Renewal Success
211
+ Credits Updated!
212
+
213
+ New Balance: 1200
214
+
215
+ (ACCUMULATE mode - credits added to existing)
216
+ ```
217
+
218
+ ### onCheckCredits
219
+
220
+ Displays current credit information:
221
+
222
+ ```typescript
223
+ const onCheckCredits = () => {
224
+ // Shows alert with:
225
+ // - Current credit balance
226
+ // - Purchase date (or "N/A")
227
+ };
228
+ ```
229
+
230
+ **Example output:**
231
+ ```
232
+ ๐Ÿ“Š Current Credits
233
+ Credits: 100
234
+
235
+ Purchased: January 15, 2024
236
+ ```
237
+
238
+ ### onTestDuplicate
239
+
240
+ Tests duplicate renewal protection:
241
+
242
+ ```typescript
243
+ const onTestDuplicate = () => {
244
+ // Performs two initialization calls with same renewalId:
245
+ // - First call: Adds credits
246
+ // - Second call: Should be skipped
247
+
248
+ // Shows alert with:
249
+ // - First call result
250
+ // - Second call result (should indicate protection worked)
251
+ };
252
+ ```
253
+
254
+ **Example output:**
255
+ ```
256
+ Duplicate Test
257
+ First call: โœ… Added credits
258
+
259
+ Second call: โœ… Skipped (protection works!)
260
+ ```
261
+
262
+ ## Development Logging
263
+
264
+ The hook logs detailed information in development:
265
+
266
+ ```typescript
267
+ // Test renewal
268
+ ๐Ÿงช [Dev Test] Simulating auto-renewal...
269
+ {
270
+ userId: 'user-123',
271
+ renewalId: 'dev_renewal_1705311234567'
272
+ }
273
+ โœ… [Dev Test] Renewal completed:
274
+ {
275
+ success: true,
276
+ credits: 1100
277
+ }
278
+
279
+ // Check credits
280
+ ๐Ÿ“Š Current Credits
281
+ Credits: 100
282
+ Purchased: January 15, 2024
283
+
284
+ // Test duplicate
285
+ ๐Ÿงช [Dev Test] Testing duplicate protection...
286
+ First call: { credits: 100, ... }
287
+ Second call: { credits: 100, ... }
288
+ ```
289
+
290
+ ## Examples
291
+
292
+ ### Comprehensive Dev Dashboard
293
+
294
+ ```typescript
295
+ function DevDashboard() {
296
+ const devCallbacks = useDevTestCallbacks();
297
+
298
+ if (!__DEV__ || !devCallbacks) return null;
299
+
300
+ const { user } = useAuth();
301
+ const { credits } = useCredits();
302
+
303
+ return (
304
+ <View style={styles.dashboard}>
305
+ <View style={styles.header}>
306
+ <Text style={styles.title}>Development Dashboard</Text>
307
+ <Text style={styles.subtitle}>
308
+ User: {user?.uid || 'Not logged in'}
309
+ </Text>
310
+ <Text style={styles.subtitle}>
311
+ Credits: {credits?.credits || 0}
312
+ </Text>
313
+ </View>
314
+
315
+ <View style={styles.actions}>
316
+ <TouchableOpacity
317
+ style={styles.actionButton}
318
+ onPress={devCallbacks.onTestRenewal}
319
+ >
320
+ <Icon name="refresh" size={20} />
321
+ <Text>Simulate Renewal</Text>
322
+ </TouchableOpacity>
323
+
324
+ <TouchableOpacity
325
+ style={styles.actionButton}
326
+ onPress={devCallbacks.onCheckCredits}
327
+ >
328
+ <Icon name="search" size={20} />
329
+ <Text>Inspect Credits</Text>
330
+ </TouchableOpacity>
331
+
332
+ <TouchableOpacity
333
+ style={styles.actionButton}
334
+ onPress={devCallbacks.onTestDuplicate}
335
+ >
336
+ <Icon name="shield" size={20} />
337
+ <Text>Test Duplicate Protection</Text>
338
+ </TouchableOpacity>
339
+ </View>
340
+
341
+ <View style={styles.info}>
342
+ <Text style={styles.infoTitle}>Test Mode Active</Text>
343
+ <Text style={styles.infoText}>
344
+ All operations use test data and won't affect production
345
+ </Text>
346
+ </View>
347
+ </View>
348
+ );
349
+ }
350
+ ```
351
+
352
+ ### With Flow Testing
353
+
354
+ ```typescript
355
+ function RenewalFlowTest() {
356
+ const devCallbacks = useDevTestCallbacks();
357
+
358
+ if (!__DEV__ || !devCallbacks) return null;
359
+
360
+ const testRenewalFlow = async () => {
361
+ // 1. Check initial credits
362
+ devCallbacks.onCheckCredits();
363
+
364
+ // 2. Simulate renewal
365
+ await new Promise(resolve => setTimeout(resolve, 1000));
366
+ devCallbacks.onTestRenewal();
367
+
368
+ // 3. Verify credits increased
369
+ await new Promise(resolve => setTimeout(resolve, 1000));
370
+ devCallbacks.onCheckCredits();
371
+
372
+ // 4. Test duplicate protection
373
+ await new Promise(resolve => setTimeout(resolve, 1000));
374
+ devCallbacks.onTestDuplicate();
375
+ };
376
+
377
+ return (
378
+ <Button
379
+ onPress={testRenewalFlow}
380
+ title="Run Complete Renewal Flow Test"
381
+ />
382
+ );
383
+ }
384
+ ```
385
+
386
+ ## Best Practices
387
+
388
+ 1. **Development only** - Never use in production code
389
+ 2. **Guard with `__DEV__`** - Always check if in development mode
390
+ 3. **Clear UI** - Make dev tools visually distinct
391
+ 4. **Test thoroughly** - Use for testing renewal flows
392
+ 5. **Document behavior** - Leave clear comments for other developers
393
+ 6. **Remove before release** - Ensure dev UI doesn't ship
394
+ 7. **Test edge cases** - Duplicate handling, error cases
395
+
396
+ ## Production Safety
397
+
398
+ The hook is production-safe:
399
+
400
+ ```typescript
401
+ export const useDevTestCallbacks = (): DevTestActions | undefined => {
402
+ // ... implementation
403
+
404
+ if (!__DEV__) {
405
+ return undefined; // โœ… Returns undefined in production
406
+ }
407
+
408
+ return { onTestRenewal, onCheckCredits, onTestDuplicate };
409
+ };
410
+ ```
411
+
412
+ ## Related Hooks
413
+
414
+ - **useCredits** - For accessing credits balance
415
+ - **useInitializeCredits** - For credit initialization
416
+ - **usePremiumWithCredits** - For premium + credits integration
417
+
418
+ ## See Also
419
+
420
+ - [Credits README](../../../domains/wallet/README.md)
421
+ - [Renewal Testing Guide](../../../docs/RENEWAL_TESTING.md)
422
+ - [Development Tools](../../../docs/DEV_TOOLS.md)