@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,514 @@
1
+ # Infrastructure Layer
2
+
3
+ Abonelik sisteminin dış dünya ile iletişimini sağlayan implementations ve repositories içeren katman.
4
+
5
+ ## Sorumluluklar
6
+
7
+ - **Repositories**: Veri erişim implementasyonları
8
+ - **Services**: Dış servis entegrasyonları (Firebase, RevenueCat, vb.)
9
+ - **Managers**: Karmaşık operasyon yöneticileri
10
+ - **Handlers**: Özel durum ve event yöneticileri
11
+
12
+ ## Yapı
13
+
14
+ ```
15
+ infrastructure/
16
+ ├── repositories/
17
+ │ └── CreditsRepositoryProvider.ts # Kredi repository konfigürasyonu
18
+ ├── services/
19
+ │ ├── SubscriptionService.ts # Abonelik servisi implementasyonu
20
+ │ └── SubscriptionInitializer.ts # Abonelik başlatıcı
21
+ └── [other implementations]
22
+ ```
23
+
24
+ ## Repositories
25
+
26
+ ### CreditsRepositoryProvider
27
+
28
+ Kredi repository'sini konfigüre etmek ve yönetmek için:
29
+
30
+ ```typescript
31
+ import {
32
+ configureCreditsRepository,
33
+ getCreditsRepository,
34
+ getCreditsConfig,
35
+ resetCreditsRepository,
36
+ isCreditsRepositoryConfigured,
37
+ type CreditsConfig,
38
+ } from '@umituz/react-native-subscription';
39
+
40
+ // Repository konfigürasyonu
41
+ const config: CreditsConfig = {
42
+ initialCredits: 100,
43
+
44
+ creditPackages: [
45
+ {
46
+ id: 'credits_small',
47
+ productId: 'com.app.credits.small',
48
+ amount: 100,
49
+ price: 0.99,
50
+ currency: 'USD',
51
+ },
52
+ {
53
+ id: 'credits_medium',
54
+ productId: 'com.app.credits.medium',
55
+ amount: 500,
56
+ price: 3.99,
57
+ currency: 'USD',
58
+ },
59
+ ],
60
+
61
+ creditCosts: {
62
+ ai_generation: 1,
63
+ ai_analysis: 2,
64
+ premium_feature: 5,
65
+ },
66
+
67
+ expiration: {
68
+ enabled: true,
69
+ daysUntilExpiration: 365,
70
+ },
71
+ };
72
+
73
+ // Repository'i konfigüre et
74
+ configureCreditsRepository({
75
+ firebase: firebaseInstance,
76
+ storage: storageInstance,
77
+ config,
78
+ });
79
+
80
+ // Repository'e eriş
81
+ const repository = getCreditsRepository();
82
+ const creditsConfig = getCreditsConfig();
83
+
84
+ // Konfigürasyon kontrolü
85
+ if (isCreditsRepositoryConfigured()) {
86
+ // Repository kullanıma hazır
87
+ }
88
+
89
+ // Reset (test için)
90
+ resetCreditsRepository();
91
+ ```
92
+
93
+ ### CreditsRepository
94
+
95
+ Kendi repository implementasyonunuzu oluşturun:
96
+
97
+ ```typescript
98
+ import {
99
+ createCreditsRepository,
100
+ type CreditsRepository,
101
+ type UserCredits,
102
+ type CreditsResult,
103
+ } from '@umituz/react-native-subscription';
104
+
105
+ class MyCreditsRepository implements CreditsRepository {
106
+ async getCredits(userId: string): Promise<UserCredits> {
107
+ // Veritabanından kredi bilgilerini getir
108
+ const doc = await db.collection('credits').doc(userId).get();
109
+ return doc.data();
110
+ }
111
+
112
+ async addCredits(
113
+ userId: string,
114
+ amount: number,
115
+ reason: string
116
+ ): Promise<CreditsResult> {
117
+ // Kredi ekle
118
+ await db.collection('credits').doc(userId).update({
119
+ balance: firebase.firestore.FieldValue.increment(amount),
120
+ lastUpdated: new Date().toISOString(),
121
+ });
122
+
123
+ return {
124
+ success: true,
125
+ newBalance: currentBalance + amount,
126
+ transaction: {
127
+ id: generateId(),
128
+ amount,
129
+ reason,
130
+ timestamp: new Date().toISOString(),
131
+ },
132
+ };
133
+ }
134
+
135
+ async deductCredits(
136
+ userId: string,
137
+ amount: number,
138
+ reason: string
139
+ ): Promise<CreditsResult> {
140
+ // Bakiye kontrolü
141
+ const current = await this.getCredits(userId);
142
+ if (current.balance < amount) {
143
+ return {
144
+ success: false,
145
+ error: 'Insufficient credits',
146
+ };
147
+ }
148
+
149
+ // Kredi düş
150
+ await db.collection('credits').doc(userId).update({
151
+ balance: firebase.firestore.FieldValue.increment(-amount),
152
+ lastUpdated: new Date().toISOString(),
153
+ });
154
+
155
+ return {
156
+ success: true,
157
+ newBalance: current.balance - amount,
158
+ transaction: {
159
+ id: generateId(),
160
+ amount: -amount,
161
+ reason,
162
+ timestamp: new Date().toISOString(),
163
+ },
164
+ };
165
+ }
166
+ }
167
+
168
+ // Repository oluştur ve kullan
169
+ const repository = new MyCreditsRepository();
170
+ ```
171
+
172
+ ## Services
173
+
174
+ ### SubscriptionService
175
+
176
+ Abonelik servisi implementasyonu:
177
+
178
+ ```typescript
179
+ import {
180
+ SubscriptionService,
181
+ initializeSubscriptionService,
182
+ type SubscriptionConfig,
183
+ } from '@umituz/react-native-subscription';
184
+
185
+ // Manuel oluşturma
186
+ const service = new SubscriptionService({
187
+ repository: myRepository,
188
+ onStatusChanged: (userId, newStatus) => {
189
+ console.log(`User ${userId}: ${newStatus.type}`);
190
+ },
191
+ onError: (error) => {
192
+ console.error('Error:', error);
193
+ },
194
+ });
195
+
196
+ // Helper ile başlatma
197
+ await initializeSubscriptionService({
198
+ repository: myRepository,
199
+ firebase: firebaseInstance,
200
+ revenueCatApiKey: 'your_api_key',
201
+ });
202
+
203
+ // Kullanım
204
+ const status = await service.getSubscriptionStatus('user-123');
205
+ const isPremium = await service.isPremium('user-123');
206
+ ```
207
+
208
+ ### SubscriptionInitializer
209
+
210
+ Uygulamanın başında abonlik sistemini başlatmak için:
211
+
212
+ ```typescript
213
+ import {
214
+ initializeSubscription,
215
+ type SubscriptionInitConfig,
216
+ type CreditPackageConfig,
217
+ } from '@umituz/react-native-subscription';
218
+
219
+ const config: SubscriptionInitConfig = {
220
+ revenueCatApiKey: process.env.REVENUECAT_API_KEY,
221
+ revenueCatEntitlementId: 'premium',
222
+
223
+ // Opsiyonel kredi konfigürasyonu
224
+ creditPackages: [
225
+ {
226
+ id: 'small',
227
+ productId: 'com.app.credits.100',
228
+ amount: 100,
229
+ price: 0.99,
230
+ },
231
+ {
232
+ id: 'medium',
233
+ productId: 'com.app.credits.500',
234
+ amount: 500,
235
+ price: 3.99,
236
+ },
237
+ ],
238
+
239
+ // Callback'ler
240
+ onInitialized: () => {
241
+ console.log('Subscription system initialized');
242
+ },
243
+ onError: (error) => {
244
+ console.error('Initialization error:', error);
245
+ },
246
+ };
247
+
248
+ // Başlat
249
+ await initializeSubscription(config);
250
+ ```
251
+
252
+ ## Firebase Integration
253
+
254
+ ### Firestore Repository
255
+
256
+ Firebase Firestore ile repository implementasyonu:
257
+
258
+ ```typescript
259
+ import firestore from '@react-native-firebase/firestore';
260
+ import type { ISubscriptionRepository } from '@umituz/react-native-subscription';
261
+
262
+ class FirestoreSubscriptionRepository implements ISubscriptionRepository {
263
+ private collection = firestore().collection('subscriptions');
264
+
265
+ async getSubscriptionStatus(userId: string) {
266
+ const doc = await this.collection.doc(userId).get();
267
+ if (!doc.exists) return null;
268
+ return doc.data();
269
+ }
270
+
271
+ async saveSubscriptionStatus(userId: string, status: any) {
272
+ await this.collection.doc(userId).set(status, { merge: true });
273
+ }
274
+
275
+ async deleteSubscriptionStatus(userId: string) {
276
+ await this.collection.doc(userId).delete();
277
+ }
278
+
279
+ isSubscriptionValid(status: any): boolean {
280
+ if (!status.isActive) return false;
281
+ if (!status.expirationDate) return true;
282
+ return new Date(status.expirationDate) > new Date();
283
+ }
284
+
285
+ // Real-time updates
286
+ subscribeToStatus(
287
+ userId: string,
288
+ callback: (status: any) => void
289
+ ): () => void {
290
+ const unsubscribe = this.collection
291
+ .doc(userId)
292
+ .onSnapshot((doc) => {
293
+ if (doc.exists) {
294
+ callback(doc.data());
295
+ }
296
+ });
297
+
298
+ return unsubscribe;
299
+ }
300
+ }
301
+ ```
302
+
303
+ ## Error Handling
304
+
305
+ Infrastructure hatalarını yönetme:
306
+
307
+ ```typescript
308
+ import {
309
+ SubscriptionRepositoryError,
310
+ SubscriptionValidationError,
311
+ } from '@umituz/react-native-subscription';
312
+
313
+ class SafeRepository {
314
+ async getSubscriptionStatus(userId: string) {
315
+ try {
316
+ if (!userId || userId.length === 0) {
317
+ throw new SubscriptionValidationError('Invalid user ID');
318
+ }
319
+
320
+ const data = await this.fetchFromDatabase(userId);
321
+
322
+ if (!data) {
323
+ return null;
324
+ }
325
+
326
+ return data;
327
+ } catch (error) {
328
+ if (error instanceof SubscriptionValidationError) {
329
+ // Validation hatası
330
+ console.error('Validation failed:', error.message);
331
+ throw error;
332
+ } else {
333
+ // Beklenmedik hata
334
+ throw new SubscriptionRepositoryError(
335
+ 'Failed to get subscription status',
336
+ error
337
+ );
338
+ }
339
+ }
340
+ }
341
+ }
342
+ ```
343
+
344
+ ## Caching
345
+
346
+ Performans için caching implementasyonu:
347
+
348
+ ```typescript
349
+ class CachedRepository {
350
+ private cache = new Map<string, any>();
351
+ private cacheTimeout = 5 * 60 * 1000; // 5 dakika
352
+
353
+ async getSubscriptionStatus(userId: string) {
354
+ // Cache kontrolü
355
+ const cached = this.cache.get(userId);
356
+ if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
357
+ return cached.data;
358
+ }
359
+
360
+ // Veritabanından getir
361
+ const data = await this.fetchFromDatabase(userId);
362
+
363
+ // Cache'e kaydet
364
+ this.cache.set(userId, {
365
+ data,
366
+ timestamp: Date.now(),
367
+ });
368
+
369
+ return data;
370
+ }
371
+
372
+ invalidateCache(userId: string) {
373
+ this.cache.delete(userId);
374
+ }
375
+
376
+ clearCache() {
377
+ this.cache.clear();
378
+ }
379
+ }
380
+ ```
381
+
382
+ ## Testing
383
+
384
+ Mock repository ile test:
385
+
386
+ ```typescript
387
+ class MockSubscriptionRepository {
388
+ private data = new Map<string, any>();
389
+
390
+ async getSubscriptionStatus(userId: string) {
391
+ return this.data.get(userId) || null;
392
+ }
393
+
394
+ async saveSubscriptionStatus(userId: string, status: any) {
395
+ this.data.set(userId, status);
396
+ }
397
+
398
+ async deleteSubscriptionStatus(userId: string) {
399
+ this.data.delete(userId);
400
+ }
401
+
402
+ isSubscriptionValid(status: any): boolean {
403
+ return status?.isActive ?? false;
404
+ }
405
+
406
+ // Test helper
407
+ __setTestData(userId: string, status: any) {
408
+ this.data.set(userId, status);
409
+ }
410
+
411
+ __clearData() {
412
+ this.data.clear();
413
+ }
414
+ }
415
+
416
+ // Testlerde
417
+ const mockRepo = new MockSubscriptionRepository();
418
+ const service = new SubscriptionService({
419
+ repository: mockRepo,
420
+ });
421
+
422
+ mockRepo.__setTestData('user-123', {
423
+ type: 'premium',
424
+ isActive: true,
425
+ isPremium: true,
426
+ });
427
+
428
+ const status = await service.getSubscriptionStatus('user-123');
429
+ expect(status?.type).toBe('premium');
430
+ ```
431
+
432
+ ## Best Practices
433
+
434
+ 1. **Dependency Injection**: Repository'leri constructor'da alın
435
+ 2. **Error Handling**: Tüm hataları yakalayın ve uygun şekilde handle edin
436
+ 3. **Caching**: Sık kullanılan verileri cache'leyin
437
+ 4. **Validation**: Girdileri validate edin
438
+ 5. **Logging**: Önemli operasyonları log'layın
439
+ 6. **Testing**: Mock implementasyonlarla test edilebilir yapın
440
+ 7. **Retry Logic**: Network hataları için retry logic ekleyin
441
+
442
+ ## Örnek: Full Implementation
443
+
444
+ ```typescript
445
+ import {
446
+ SubscriptionService,
447
+ type ISubscriptionRepository,
448
+ SubscriptionStatus,
449
+ } from '@umituz/react-native-subscription';
450
+ import firestore from '@react-native-firebase/firestore';
451
+
452
+ class FirestoreRepository implements ISubscriptionRepository {
453
+ private db = firestore();
454
+
455
+ async getSubscriptionStatus(userId: string): Promise<SubscriptionStatus | null> {
456
+ try {
457
+ const doc = await this.db
458
+ .collection('subscriptions')
459
+ .doc(userId)
460
+ .get();
461
+
462
+ if (!doc.exists) return null;
463
+ return doc.data() as SubscriptionStatus;
464
+ } catch (error) {
465
+ console.error('Error fetching subscription:', error);
466
+ throw error;
467
+ }
468
+ }
469
+
470
+ async saveSubscriptionStatus(
471
+ userId: string,
472
+ status: SubscriptionStatus
473
+ ): Promise<void> {
474
+ try {
475
+ await this.db
476
+ .collection('subscriptions')
477
+ .doc(userId)
478
+ .set(status, { merge: true });
479
+ } catch (error) {
480
+ console.error('Error saving subscription:', error);
481
+ throw error;
482
+ }
483
+ }
484
+
485
+ async deleteSubscriptionStatus(userId: string): Promise<void> {
486
+ try {
487
+ await this.db
488
+ .collection('subscriptions')
489
+ .doc(userId)
490
+ .delete();
491
+ } catch (error) {
492
+ console.error('Error deleting subscription:', error);
493
+ throw error;
494
+ }
495
+ }
496
+
497
+ isSubscriptionValid(status: SubscriptionStatus): boolean {
498
+ if (!status.isActive) return false;
499
+ if (!status.expirationDate) return true;
500
+ return new Date(status.expirationDate) > new Date();
501
+ }
502
+ }
503
+
504
+ // Kullanım
505
+ const repository = new FirestoreRepository();
506
+ const service = new SubscriptionService({
507
+ repository,
508
+ onStatusChanged: (userId, status) => {
509
+ console.log(`Status changed for ${userId}`);
510
+ },
511
+ });
512
+
513
+ await service.activateSubscription('user-123', 'premium_monthly', null);
514
+ ```
@@ -0,0 +1,34 @@
1
+ # Infrastructure Mappers
2
+
3
+ Data transformation mappers between layers.
4
+
5
+ ## Overview
6
+
7
+ This directory contains mapper functions that transform data between different layers (e.g., domain entities to DTOs, external API responses to domain models).
8
+
9
+ ## Contents
10
+
11
+ - **subscriptionMapper.ts** - Maps between subscription entities and external formats
12
+ - **creditsMapper.ts** - Maps between credit entities and Firestore documents
13
+
14
+ ## Purpose
15
+
16
+ Mappers provide clean separation between layers:
17
+
18
+ ```
19
+ External API → Mapper → Domain Entity
20
+ Domain Entity → Mapper → DTO/Model
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```typescript
26
+ import { mapToSubscriptionStatus } from './mappers/subscriptionMapper';
27
+
28
+ const entity = mapToSubscriptionStatus(apiResponse);
29
+ ```
30
+
31
+ ## Related
32
+
33
+ - [Models](../models/README.md)
34
+ - [Domain](../../domain/README.md)
@@ -0,0 +1,26 @@
1
+ # Infrastructure Models
2
+
3
+ Data models and schemas used by the infrastructure layer.
4
+
5
+ ## Overview
6
+
7
+ This directory contains data models, schemas, and interfaces used by infrastructure implementations.
8
+
9
+ ## Contents
10
+
11
+ - **SubscriptionModel.ts** - Subscription data model for persistence/transport
12
+ - **CreditsModel.ts** - Credits data model for Firestore
13
+
14
+ ## Purpose
15
+
16
+ Models provide structure for data storage and API communication:
17
+
18
+ - **Validation**: Ensure data integrity
19
+ - **Serialization**: Convert to/from storage formats
20
+ - **Type Safety**: Provide TypeScript interfaces
21
+
22
+ ## Related
23
+
24
+ - [Repositories](../repositories/README.md)
25
+ - [Services](../services/README.md)
26
+ - [Domain Entities](../../domain/entities/README.md)