@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,390 @@
|
|
|
1
|
+
# Config Domain
|
|
2
|
+
|
|
3
|
+
Domain layer for configuration management.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This directory contains the business logic and domain models for subscription and feature configuration.
|
|
8
|
+
|
|
9
|
+
## Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
domain/
|
|
13
|
+
├── entities/ # Configuration entities
|
|
14
|
+
└── value-objects/ # Configuration value objects
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Entities
|
|
18
|
+
|
|
19
|
+
### PackageConfig
|
|
20
|
+
|
|
21
|
+
Represents a subscription package configuration.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
class PackageConfig {
|
|
25
|
+
readonly identifier: string;
|
|
26
|
+
readonly productId: string;
|
|
27
|
+
readonly period: PackagePeriod;
|
|
28
|
+
readonly price: Money;
|
|
29
|
+
readonly features: Feature[];
|
|
30
|
+
readonly credits?: number;
|
|
31
|
+
readonly metadata: PackageMetadata;
|
|
32
|
+
|
|
33
|
+
constructor(config: PackageConfigData) {
|
|
34
|
+
this.identifier = config.identifier;
|
|
35
|
+
this.productId = config.productId;
|
|
36
|
+
this.period = config.period;
|
|
37
|
+
this.price = new Money(config.price, config.currency);
|
|
38
|
+
this.features = config.features;
|
|
39
|
+
this.credits = config.credits;
|
|
40
|
+
this.metadata = config.metadata || {};
|
|
41
|
+
this.validate();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private validate(): void {
|
|
45
|
+
if (!this.identifier) {
|
|
46
|
+
throw new Error('Package identifier is required');
|
|
47
|
+
}
|
|
48
|
+
if (!this.productId) {
|
|
49
|
+
throw new Error('Product ID is required');
|
|
50
|
+
}
|
|
51
|
+
if (this.price.getAmount() < 0) {
|
|
52
|
+
throw new Error('Price cannot be negative');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
isAnnual(): boolean {
|
|
57
|
+
return this.period === 'annual';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
isMonthly(): boolean {
|
|
61
|
+
return this.period === 'monthly';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
isLifetime(): boolean {
|
|
65
|
+
return this.period === 'lifetime';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
hasCredits(): boolean {
|
|
69
|
+
return !!this.credits && this.credits > 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
isRecommended(): boolean {
|
|
73
|
+
return this.metadata.recommended === true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
isHighlighted(): boolean {
|
|
77
|
+
return this.metadata.highlight === true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getDiscountPercentage(): number | null {
|
|
81
|
+
return this.metadata.discount?.percentage ?? null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getBadge(): string | null {
|
|
85
|
+
return this.metadata.badge ?? null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
getPerMonthPrice(): Money | null {
|
|
89
|
+
if (this.period === 'monthly') {
|
|
90
|
+
return this.price;
|
|
91
|
+
}
|
|
92
|
+
if (this.period === 'annual') {
|
|
93
|
+
return this.price.divide(12);
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### FeatureConfig
|
|
101
|
+
|
|
102
|
+
Represents a feature configuration.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
class FeatureConfig {
|
|
106
|
+
readonly id: string;
|
|
107
|
+
readonly name: string;
|
|
108
|
+
readonly description?: string;
|
|
109
|
+
readonly requiresPremium: boolean;
|
|
110
|
+
readonly requiresCredits: boolean;
|
|
111
|
+
readonly creditCost?: number;
|
|
112
|
+
readonly enabled: boolean;
|
|
113
|
+
readonly gateType: 'premium' | 'credits' | 'both';
|
|
114
|
+
|
|
115
|
+
constructor(config: FeatureConfigData) {
|
|
116
|
+
this.id = config.id;
|
|
117
|
+
this.name = config.name;
|
|
118
|
+
this.description = config.description;
|
|
119
|
+
this.requiresPremium = config.requiresPremium;
|
|
120
|
+
this.requiresCredits = config.requiresCredits ?? false;
|
|
121
|
+
this.creditCost = config.creditCost;
|
|
122
|
+
this.enabled = config.enabled ?? true;
|
|
123
|
+
this.gateType = config.gateType ?? this.inferGateType();
|
|
124
|
+
this.validate();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private inferGateType(): 'premium' | 'credits' | 'both' {
|
|
128
|
+
if (this.requiresPremium && this.requiresCredits) {
|
|
129
|
+
return 'both';
|
|
130
|
+
}
|
|
131
|
+
if (this.requiresPremium) {
|
|
132
|
+
return 'premium';
|
|
133
|
+
}
|
|
134
|
+
return 'credits';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private validate(): void {
|
|
138
|
+
if (!this.id) {
|
|
139
|
+
throw new Error('Feature ID is required');
|
|
140
|
+
}
|
|
141
|
+
if (this.requiresCredits && !this.creditCost) {
|
|
142
|
+
throw new Error('Credit cost required when requiresCredits is true');
|
|
143
|
+
}
|
|
144
|
+
if (this.creditCost && this.creditCost < 0) {
|
|
145
|
+
throw new Error('Credit cost cannot be negative');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
isAccessible(userHasPremium: boolean, userCredits: number): boolean {
|
|
150
|
+
if (!this.enabled) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (this.gateType === 'premium') {
|
|
155
|
+
return userHasPremium;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (this.gateType === 'credits') {
|
|
159
|
+
return userCredits >= (this.creditCost ?? 0);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (this.gateType === 'both') {
|
|
163
|
+
return userHasPremium && userCredits >= (this.creditCost ?? 0);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
getRequiredCredits(): number {
|
|
170
|
+
return this.creditCost ?? 0;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### PaywallConfig
|
|
176
|
+
|
|
177
|
+
Represents paywall configuration.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
class PaywallConfig {
|
|
181
|
+
readonly id: string;
|
|
182
|
+
readonly title: string;
|
|
183
|
+
readonly subtitle?: string;
|
|
184
|
+
readonly features: string[];
|
|
185
|
+
readonly packages: PackageConfig[];
|
|
186
|
+
readonly highlightPackage?: string;
|
|
187
|
+
readonly style: PaywallStyle;
|
|
188
|
+
readonly triggers: PaywallTrigger[];
|
|
189
|
+
|
|
190
|
+
constructor(config: PaywallConfigData) {
|
|
191
|
+
this.id = config.id;
|
|
192
|
+
this.title = config.title;
|
|
193
|
+
this.subtitle = config.subtitle;
|
|
194
|
+
this.features = config.features;
|
|
195
|
+
this.packages = config.packages.map(p => new PackageConfig(p));
|
|
196
|
+
this.highlightPackage = config.highlightPackage;
|
|
197
|
+
this.style = config.style;
|
|
198
|
+
this.triggers = config.triggers ?? [];
|
|
199
|
+
this.validate();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private validate(): void {
|
|
203
|
+
if (!this.id) {
|
|
204
|
+
throw new Error('Paywall ID is required');
|
|
205
|
+
}
|
|
206
|
+
if (this.packages.length === 0) {
|
|
207
|
+
throw new Error('At least one package is required');
|
|
208
|
+
}
|
|
209
|
+
if (this.highlightPackage) {
|
|
210
|
+
const exists = this.packages.some(p => p.identifier === this.highlightPackage);
|
|
211
|
+
if (!exists) {
|
|
212
|
+
throw new Error('Highlight package not found');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
getHighlightedPackage(): PackageConfig | null {
|
|
218
|
+
if (!this.highlightPackage) {
|
|
219
|
+
return this.packages.find(p => p.isHighlighted()) ?? null;
|
|
220
|
+
}
|
|
221
|
+
return this.packages.find(p => p.identifier === this.highlightPackage) ?? null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
getPackageByIdentifier(identifier: string): PackageConfig | null {
|
|
225
|
+
return this.packages.find(p => p.identifier === identifier) ?? null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
shouldTrigger(triggerType: string): boolean {
|
|
229
|
+
return this.triggers.some(t => t.type === triggerType);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Value Objects
|
|
235
|
+
|
|
236
|
+
### PackagePeriod
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
class PackagePeriod {
|
|
240
|
+
readonly value: 'monthly' | 'annual' | 'lifetime' | 'weekly';
|
|
241
|
+
|
|
242
|
+
constructor(value: string) {
|
|
243
|
+
const valid = ['monthly', 'annual', 'lifetime', 'weekly'];
|
|
244
|
+
if (!valid.includes(value)) {
|
|
245
|
+
throw new Error(`Invalid period: ${value}`);
|
|
246
|
+
}
|
|
247
|
+
this.value = value as PackagePeriod['value'];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
isRecurring(): boolean {
|
|
251
|
+
return this.value === 'monthly' || this.value === 'annual' || this.value === 'weekly';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
getDurationInMonths(): number | null {
|
|
255
|
+
switch (this.value) {
|
|
256
|
+
case 'monthly': return 1;
|
|
257
|
+
case 'annual': return 12;
|
|
258
|
+
case 'weekly': return 1 / 4;
|
|
259
|
+
case 'lifetime': return null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
toString(): string {
|
|
264
|
+
return this.value;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Money
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
class Money {
|
|
273
|
+
readonly amount: number;
|
|
274
|
+
readonly currency: string;
|
|
275
|
+
|
|
276
|
+
constructor(amount: number, currency: string) {
|
|
277
|
+
if (amount < 0) {
|
|
278
|
+
throw new Error('Amount cannot be negative');
|
|
279
|
+
}
|
|
280
|
+
this.amount = amount;
|
|
281
|
+
this.currency = currency;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
format(locale: string = 'en-US'): string {
|
|
285
|
+
return new Intl.NumberFormat(locale, {
|
|
286
|
+
style: 'currency',
|
|
287
|
+
currency: this.currency,
|
|
288
|
+
}).format(this.amount);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
divide(factor: number): Money {
|
|
292
|
+
return new Money(this.amount / factor, this.currency);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
multiply(factor: number): Money {
|
|
296
|
+
return new Money(this.amount * factor, this.currency);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
equals(other: Money): boolean {
|
|
300
|
+
return this.amount === other.amount && this.currency === other.currency;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Usage
|
|
306
|
+
|
|
307
|
+
### Creating Package Configuration
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
import { PackageConfig } from './entities/PackageConfig';
|
|
311
|
+
|
|
312
|
+
const monthlyPackage = new PackageConfig({
|
|
313
|
+
identifier: 'premium_monthly',
|
|
314
|
+
productId: 'com.app.premium.monthly',
|
|
315
|
+
period: 'monthly',
|
|
316
|
+
price: 9.99,
|
|
317
|
+
currency: 'USD',
|
|
318
|
+
features: ['Unlimited Access', 'Ad-Free'],
|
|
319
|
+
credits: 100,
|
|
320
|
+
metadata: {
|
|
321
|
+
recommended: true,
|
|
322
|
+
badge: 'Most Popular',
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
console.log(monthlyPackage.isMonthly()); // true
|
|
327
|
+
console.log(monthlyPackage.getPerMonthPrice()?.format()); // '$9.99'
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Creating Feature Configuration
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
import { FeatureConfig } from './entities/FeatureConfig';
|
|
334
|
+
|
|
335
|
+
const aiFeature = new FeatureConfig({
|
|
336
|
+
id: 'ai_generation',
|
|
337
|
+
name: 'AI Generation',
|
|
338
|
+
description: 'Generate AI content',
|
|
339
|
+
requiresPremium: false,
|
|
340
|
+
requiresCredits: true,
|
|
341
|
+
creditCost: 5,
|
|
342
|
+
enabled: true,
|
|
343
|
+
gateType: 'credits',
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
console.log(aiFeature.isAccessible(false, 10)); // true
|
|
347
|
+
console.log(aiFeature.isAccessible(false, 3)); // false
|
|
348
|
+
console.log(aiFeature.getRequiredCredits()); // 5
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Creating Paywall Configuration
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
import { PaywallConfig } from './entities/PaywallConfig';
|
|
355
|
+
|
|
356
|
+
const paywall = new PaywallConfig({
|
|
357
|
+
id: 'premium_upgrade',
|
|
358
|
+
title: 'Upgrade to Premium',
|
|
359
|
+
subtitle: 'Get unlimited access',
|
|
360
|
+
features: ['Feature 1', 'Feature 2'],
|
|
361
|
+
packages: [monthlyPackage, annualPackage],
|
|
362
|
+
highlightPackage: 'premium_annual',
|
|
363
|
+
style: {
|
|
364
|
+
primaryColor: '#007AFF',
|
|
365
|
+
backgroundColor: '#FFFFFF',
|
|
366
|
+
},
|
|
367
|
+
triggers: [
|
|
368
|
+
{ type: 'credit_gate', enabled: true },
|
|
369
|
+
{ type: 'manual', enabled: true },
|
|
370
|
+
],
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
const highlighted = paywall.getHighlightedPackage();
|
|
374
|
+
console.log(highlighted?.identifier); // 'premium_annual'
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Best Practices
|
|
378
|
+
|
|
379
|
+
1. **Validation**: Validate in constructor, fail fast
|
|
380
|
+
2. **Immutability**: Keep entities immutable
|
|
381
|
+
3. **Type Safety**: Use TypeScript for compile-time checks
|
|
382
|
+
4. **Business Logic**: Encapsulate business logic in entities
|
|
383
|
+
5. **Equality**: Implement proper equality methods
|
|
384
|
+
6. **Formatting**: Provide formatting methods
|
|
385
|
+
|
|
386
|
+
## Related
|
|
387
|
+
|
|
388
|
+
- [Config Domain](../../README.md)
|
|
389
|
+
- [Config Entities](./entities/README.md)
|
|
390
|
+
- [Config Value Objects](./value-objects/README.md)
|