@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.
- package/LICENSE +21 -0
- package/README.md +461 -0
- package/package.json +1 -3
- package/src/application/README.md +229 -0
- package/src/application/ports/README.md +103 -0
- package/src/domain/README.md +402 -0
- package/src/domain/constants/README.md +80 -0
- package/src/domain/entities/README.md +176 -0
- package/src/domain/errors/README.md +307 -0
- package/src/domain/value-objects/README.md +186 -0
- package/src/domains/README.md +240 -0
- package/src/domains/config/README.md +390 -0
- package/src/domains/config/domain/README.md +390 -0
- package/src/domains/config/domain/entities/README.md +350 -0
- package/src/domains/paywall/README.md +371 -0
- package/src/domains/paywall/components/PaywallHeader.tsx +8 -11
- package/src/domains/paywall/components/README.md +185 -0
- package/src/domains/paywall/entities/README.md +199 -0
- package/src/domains/paywall/hooks/README.md +129 -0
- package/src/domains/wallet/README.md +292 -0
- package/src/domains/wallet/domain/README.md +108 -0
- package/src/domains/wallet/domain/entities/README.md +122 -0
- package/src/domains/wallet/domain/errors/README.md +157 -0
- package/src/domains/wallet/infrastructure/README.md +96 -0
- package/src/domains/wallet/presentation/components/BalanceCard.tsx +6 -12
- package/src/domains/wallet/presentation/components/README.md +231 -0
- package/src/domains/wallet/presentation/hooks/README.md +255 -0
- package/src/infrastructure/README.md +514 -0
- package/src/infrastructure/mappers/README.md +34 -0
- package/src/infrastructure/models/README.md +26 -0
- package/src/infrastructure/repositories/README.md +385 -0
- package/src/infrastructure/services/README.md +374 -0
- package/src/presentation/README.md +410 -0
- package/src/presentation/components/README.md +183 -0
- package/src/presentation/components/details/CreditRow.md +337 -0
- package/src/presentation/components/details/DetailRow.md +283 -0
- package/src/presentation/components/details/PremiumDetailsCard.md +266 -0
- package/src/presentation/components/details/PremiumStatusBadge.md +266 -0
- package/src/presentation/components/details/README.md +449 -0
- package/src/presentation/components/feedback/PaywallFeedbackModal.md +314 -0
- package/src/presentation/components/feedback/README.md +447 -0
- package/src/presentation/components/paywall/PaywallModal.md +444 -0
- package/src/presentation/components/paywall/README.md +190 -0
- package/src/presentation/components/sections/README.md +468 -0
- package/src/presentation/components/sections/SubscriptionSection.md +246 -0
- package/src/presentation/hooks/README.md +743 -0
- package/src/presentation/hooks/useAuthAwarePurchase.md +359 -0
- package/src/presentation/hooks/useAuthGate.md +403 -0
- package/src/presentation/hooks/useAuthSubscriptionSync.md +398 -0
- package/src/presentation/hooks/useCreditChecker.md +407 -0
- package/src/presentation/hooks/useCredits.md +342 -0
- package/src/presentation/hooks/useCreditsGate.md +346 -0
- package/src/presentation/hooks/useDeductCredit.md +176 -0
- package/src/presentation/hooks/useDevTestCallbacks.md +422 -0
- package/src/presentation/hooks/useFeatureGate.md +157 -0
- package/src/presentation/hooks/useInitializeCredits.md +458 -0
- package/src/presentation/hooks/usePaywall.md +334 -0
- package/src/presentation/hooks/usePaywallOperations.md +486 -0
- package/src/presentation/hooks/usePaywallVisibility.md +344 -0
- package/src/presentation/hooks/usePremium.md +230 -0
- package/src/presentation/hooks/usePremiumGate.md +423 -0
- package/src/presentation/hooks/usePremiumWithCredits.md +429 -0
- package/src/presentation/hooks/useSubscription.md +450 -0
- package/src/presentation/hooks/useSubscriptionDetails.md +438 -0
- package/src/presentation/hooks/useSubscriptionGate.md +168 -0
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +374 -0
- package/src/presentation/hooks/useSubscriptionStatus.md +424 -0
- package/src/presentation/hooks/useUserTier.md +356 -0
- package/src/presentation/hooks/useUserTierWithRepository.md +452 -0
- package/src/presentation/screens/README.md +194 -0
- package/src/presentation/types/README.md +38 -0
- package/src/presentation/utils/README.md +52 -0
- package/src/revenuecat/README.md +523 -0
- package/src/revenuecat/application/README.md +158 -0
- package/src/revenuecat/application/ports/README.md +169 -0
- package/src/revenuecat/domain/README.md +147 -0
- package/src/revenuecat/domain/constants/README.md +183 -0
- package/src/revenuecat/domain/entities/README.md +382 -0
- package/src/revenuecat/domain/errors/README.md +197 -0
- package/src/revenuecat/domain/types/README.md +373 -0
- package/src/revenuecat/domain/value-objects/README.md +441 -0
- package/src/revenuecat/infrastructure/README.md +50 -0
- package/src/revenuecat/infrastructure/config/README.md +40 -0
- package/src/revenuecat/infrastructure/handlers/README.md +218 -0
- package/src/revenuecat/infrastructure/managers/README.md +49 -0
- package/src/revenuecat/infrastructure/services/README.md +325 -0
- package/src/revenuecat/infrastructure/utils/README.md +382 -0
- package/src/revenuecat/presentation/README.md +184 -0
- package/src/revenuecat/presentation/hooks/README.md +56 -0
- package/src/utils/README.md +529 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Application Layer
|
|
2
|
+
|
|
3
|
+
Abonelik uygulamasının iş mantığını ve servis kontratlarını içeren katman.
|
|
4
|
+
|
|
5
|
+
## Sorumluluklar
|
|
6
|
+
|
|
7
|
+
- **Service Contracts**: Servis arayüzlerini tanımlama
|
|
8
|
+
- **Use Cases**: İş kullanım durumlarını gerçekleştirme
|
|
9
|
+
- **Business Logic**: Uygulama kurallarını yönetme
|
|
10
|
+
|
|
11
|
+
## Yapı
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
application/
|
|
15
|
+
├── ports/
|
|
16
|
+
│ ├── ISubscriptionService.ts # Subscription servisi kontratı
|
|
17
|
+
│ └── ISubscriptionRepository.ts # Repository kontratı
|
|
18
|
+
└── [future use cases]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Port Interfaces
|
|
22
|
+
|
|
23
|
+
### ISubscriptionService
|
|
24
|
+
|
|
25
|
+
Abonelik servisi için ana kontrat:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
interface ISubscriptionService {
|
|
29
|
+
getStatus(userId: string): Promise<SubscriptionStatus | null>;
|
|
30
|
+
activateSubscription(
|
|
31
|
+
userId: string,
|
|
32
|
+
productId: string,
|
|
33
|
+
expiresAt: string | null
|
|
34
|
+
): Promise<SubscriptionStatus>;
|
|
35
|
+
deactivateSubscription(userId: string): Promise<SubscriptionStatus>;
|
|
36
|
+
isPremium(userId: string): Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Kullanım:**
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import type { ISubscriptionService } from '@umituz/react-native-subscription';
|
|
44
|
+
|
|
45
|
+
class MyService {
|
|
46
|
+
constructor(private subscriptionService: ISubscriptionService) {}
|
|
47
|
+
|
|
48
|
+
async checkUserAccess(userId: string) {
|
|
49
|
+
const isPremium = await this.subscriptionService.isPremium(userId);
|
|
50
|
+
return isPremium;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### ISubscriptionRepository
|
|
56
|
+
|
|
57
|
+
Abonelik verisi erişimi için kontrat:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
interface ISubscriptionRepository {
|
|
61
|
+
getSubscriptionStatus(userId: string): Promise<SubscriptionStatus | null>;
|
|
62
|
+
saveSubscriptionStatus(
|
|
63
|
+
userId: string,
|
|
64
|
+
status: SubscriptionStatus
|
|
65
|
+
): Promise<void>;
|
|
66
|
+
deleteSubscriptionStatus(userId: string): Promise<void>;
|
|
67
|
+
isSubscriptionValid(status: SubscriptionStatus): boolean;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Kullanım:**
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import type { ISubscriptionRepository } from '@umituz/react-native-subscription';
|
|
75
|
+
|
|
76
|
+
class FirebaseRepository implements ISubscriptionRepository {
|
|
77
|
+
async getSubscriptionStatus(userId: string) {
|
|
78
|
+
// Firebase'den abonelik durumu getir
|
|
79
|
+
const doc = await firestore().collection('subscriptions').doc(userId).get();
|
|
80
|
+
return doc.data();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async saveSubscriptionStatus(userId: string, status: SubscriptionStatus) {
|
|
84
|
+
// Firebase'e abonelik durumu kaydet
|
|
85
|
+
await firestore().collection('subscriptions').doc(userId).set(status);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
isSubscriptionValid(status: SubscriptionStatus): boolean {
|
|
89
|
+
// Abonelik geçerliliğini kontrol et
|
|
90
|
+
return status.isActive && !isExpired(status.expirationDate);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Dependency Injection
|
|
96
|
+
|
|
97
|
+
Application layer bağımlılıkları dependency injection ile alır:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { SubscriptionService } from '@umituz/react-native-subscription';
|
|
101
|
+
|
|
102
|
+
const subscriptionService = new SubscriptionService({
|
|
103
|
+
repository: myRepository,
|
|
104
|
+
onStatusChanged: (userId, newStatus) => {
|
|
105
|
+
console.log(`User ${userId} status changed to ${newStatus.type}`);
|
|
106
|
+
},
|
|
107
|
+
onError: (error) => {
|
|
108
|
+
console.error('Subscription error:', error);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Repository Implementation
|
|
114
|
+
|
|
115
|
+
Kendi repository'nizi oluşturun:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import {
|
|
119
|
+
type ISubscriptionRepository,
|
|
120
|
+
SubscriptionStatus,
|
|
121
|
+
} from '@umituz/react-native-subscription';
|
|
122
|
+
|
|
123
|
+
class CustomRepository implements ISubscriptionRepository {
|
|
124
|
+
constructor(private db: Database) {}
|
|
125
|
+
|
|
126
|
+
async getSubscriptionStatus(userId: string): Promise<SubscriptionStatus | null> {
|
|
127
|
+
const data = await this.db.query(
|
|
128
|
+
'SELECT * FROM subscriptions WHERE user_id = ?',
|
|
129
|
+
[userId]
|
|
130
|
+
);
|
|
131
|
+
return data ? SubscriptionStatus.parse(data) : null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async saveSubscriptionStatus(
|
|
135
|
+
userId: string,
|
|
136
|
+
status: SubscriptionStatus
|
|
137
|
+
): Promise<void> {
|
|
138
|
+
await this.db.execute(
|
|
139
|
+
'INSERT OR REPLACE INTO subscriptions (user_id, status, expires_at) VALUES (?, ?, ?)',
|
|
140
|
+
[userId, status.type, status.expirationDate]
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async deleteSubscriptionStatus(userId: string): Promise<void> {
|
|
145
|
+
await this.db.execute(
|
|
146
|
+
'DELETE FROM subscriptions WHERE user_id = ?',
|
|
147
|
+
[userId]
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
isSubscriptionValid(status: SubscriptionStatus): boolean {
|
|
152
|
+
if (!status.isActive) return false;
|
|
153
|
+
if (!status.expirationDate) return true; // Lifetime
|
|
154
|
+
return new Date(status.expirationDate) > new Date();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Best Practices
|
|
160
|
+
|
|
161
|
+
1. **Interface Segregation**: Küçük, odaklanmış interface'ler tanımlayın
|
|
162
|
+
2. **Dependency Inversion**: High-level modüller low-level modüllere bağımlı olmamalı
|
|
163
|
+
3. **Single Responsibility**: Her service/repository tek bir sorumluluğa sahip olmalı
|
|
164
|
+
4. **Error Handling**: Hataları uygun şekilde handle edin ve yukarı传播 edin
|
|
165
|
+
5. **Testing**: Interface'ler mock ile kolay test edilebilir
|
|
166
|
+
|
|
167
|
+
## Örnek: Service Kullanımı
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import {
|
|
171
|
+
SubscriptionService,
|
|
172
|
+
type SubscriptionConfig,
|
|
173
|
+
} from '@umituz/react-native-subscription';
|
|
174
|
+
|
|
175
|
+
// Konfigürasyon
|
|
176
|
+
const config: SubscriptionConfig = {
|
|
177
|
+
repository: myRepository,
|
|
178
|
+
onStatusChanged: (userId, status) => {
|
|
179
|
+
// Status değiştiğinde çalışacak callback
|
|
180
|
+
analytics.track('subscription_status_changed', {
|
|
181
|
+
userId,
|
|
182
|
+
status: status.type,
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
onError: (error) => {
|
|
186
|
+
// Hata yönetimi
|
|
187
|
+
crashlytics().recordError(error);
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Service oluştur
|
|
192
|
+
const service = new SubscriptionService(config);
|
|
193
|
+
|
|
194
|
+
// Kullan
|
|
195
|
+
async function manageSubscription(userId: string) {
|
|
196
|
+
// Durumu kontrol et
|
|
197
|
+
const status = await service.getSubscriptionStatus(userId);
|
|
198
|
+
console.log('Current status:', status?.type);
|
|
199
|
+
|
|
200
|
+
// Premium kontrolü
|
|
201
|
+
const isPremium = await service.isPremium(userId);
|
|
202
|
+
if (!isPremium) {
|
|
203
|
+
// Aboneliği aktifleştir
|
|
204
|
+
await service.activateSubscription(
|
|
205
|
+
userId,
|
|
206
|
+
'com.app.premium.monthly',
|
|
207
|
+
'2025-01-01T00:00:00Z'
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Aboneliği iptal et
|
|
212
|
+
// await service.deactivateSubscription(userId);
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Type Safety
|
|
217
|
+
|
|
218
|
+
Tüm interface'ler tam tip güvenliği sağlar:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// ✓ Type-safe
|
|
222
|
+
const status: SubscriptionStatus = await service.getStatus(userId);
|
|
223
|
+
|
|
224
|
+
// ✗ Compile error
|
|
225
|
+
const wrong = await service.getStatus(123);
|
|
226
|
+
|
|
227
|
+
// ✓ Type-safe repository
|
|
228
|
+
const repository: ISubscriptionRepository = new MyRepository();
|
|
229
|
+
```
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Application Ports
|
|
2
|
+
|
|
3
|
+
Interfaces defining contracts between application layer and external dependencies.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This directory contains port interfaces that define how the application layer interacts with external services and repositories. This enables dependency inversion and testability.
|
|
8
|
+
|
|
9
|
+
## Ports
|
|
10
|
+
|
|
11
|
+
### ISubscriptionService
|
|
12
|
+
Port for subscription management service.
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
interface ISubscriptionService {
|
|
16
|
+
getSubscriptionStatus(userId: string): Promise<SubscriptionStatus | null>;
|
|
17
|
+
activateSubscription(
|
|
18
|
+
userId: string,
|
|
19
|
+
productId: string,
|
|
20
|
+
expiresAt: string | null
|
|
21
|
+
): Promise<SubscriptionStatus | null>;
|
|
22
|
+
deactivateSubscription(userId: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Implementation:** Infrastructure services implement this interface.
|
|
27
|
+
|
|
28
|
+
### ISubscriptionRepository
|
|
29
|
+
Port for subscription data persistence.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
interface ISubscriptionRepository {
|
|
33
|
+
getSubscriptionStatus(userId: string): Promise<SubscriptionStatus | null>;
|
|
34
|
+
saveSubscriptionStatus(userId: string, status: SubscriptionStatus): Promise<void>;
|
|
35
|
+
deleteSubscriptionStatus(userId: string): Promise<void>;
|
|
36
|
+
isSubscriptionValid(status: SubscriptionStatus | null): boolean;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Implementation:** Infrastructure repositories implement this interface.
|
|
41
|
+
|
|
42
|
+
### ICreditsRepository
|
|
43
|
+
Port for credits data persistence.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
interface ICreditsRepository {
|
|
47
|
+
getCredits(userId: string): Promise<UserCredits | null>;
|
|
48
|
+
initializeCredits(
|
|
49
|
+
userId: string,
|
|
50
|
+
purchaseId?: string,
|
|
51
|
+
productId?: string
|
|
52
|
+
): Promise<CreditsResult>;
|
|
53
|
+
deductCredit(userId: string, amount: number): Promise<CreditsResult>;
|
|
54
|
+
addCredits(userId: string, amount: number): Promise<CreditsResult>;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage in Application Layer
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import type { ISubscriptionService } from '../application/ports/ISubscriptionService';
|
|
62
|
+
|
|
63
|
+
class SubscriptionManager {
|
|
64
|
+
constructor(private service: ISubscriptionService) {}
|
|
65
|
+
|
|
66
|
+
async manageSubscription(userId: string) {
|
|
67
|
+
// Port interface enables swapping implementations
|
|
68
|
+
const status = await this.service.getSubscriptionStatus(userId);
|
|
69
|
+
return status;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Testing with Mocks
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const mockService: ISubscriptionService = {
|
|
78
|
+
getSubscriptionStatus: async (userId) => ({
|
|
79
|
+
productId: 'premium',
|
|
80
|
+
isActive: true,
|
|
81
|
+
type: 'premium',
|
|
82
|
+
expirationDate: null,
|
|
83
|
+
}),
|
|
84
|
+
activateSubscription: async () => ({} as any),
|
|
85
|
+
deactivateSubscription: async () => {},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Use mock in tests
|
|
89
|
+
const manager = new SubscriptionManager(mockService);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Best Practices
|
|
93
|
+
|
|
94
|
+
1. **Interface Segregation** - Keep interfaces focused
|
|
95
|
+
2. **Clear Contracts** - Document behavior thoroughly
|
|
96
|
+
3. **Return Types** - Use domain entities in return types
|
|
97
|
+
4. **Async Operations** - All I/O operations should be async
|
|
98
|
+
|
|
99
|
+
## Related
|
|
100
|
+
|
|
101
|
+
- [Application README](../README.md)
|
|
102
|
+
- [Infrastructure Services](../../infrastructure/services/README.md)
|
|
103
|
+
- [Infrastructure Repositories](../../infrastructure/repositories/README.md)
|