@umituz/react-native-subscription 2.14.98 → 2.14.100
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/README.md +211 -395
- package/package.json +1 -1
- package/src/application/README.md +46 -225
- package/src/application/ports/README.md +42 -97
- package/src/domain/README.md +36 -384
- package/src/domain/constants/README.md +0 -56
- package/src/domain/entities/README.md +43 -169
- package/src/domain/errors/README.md +33 -287
- package/src/domain/value-objects/README.md +43 -179
- package/src/domains/README.md +52 -0
- package/src/domains/README.md.bak +274 -0
- package/src/domains/config/README.md +93 -383
- package/src/domains/config/domain/README.md +37 -0
- package/src/domains/config/domain/entities/README.md +41 -0
- package/src/domains/paywall/README.md +99 -369
- package/src/domains/paywall/components/README.md +34 -178
- package/src/domains/paywall/entities/README.md +34 -193
- package/src/domains/paywall/hooks/README.md +34 -122
- package/src/domains/wallet/README.md +34 -275
- package/src/domains/wallet/README.md.bak +209 -0
- package/src/domains/wallet/domain/README.md +34 -101
- package/src/domains/wallet/domain/entities/README.md +34 -115
- package/src/domains/wallet/domain/errors/README.md +34 -151
- package/src/domains/wallet/infrastructure/README.md +34 -89
- package/src/domains/wallet/presentation/components/README.md +34 -224
- package/src/domains/wallet/presentation/hooks/README.md +34 -248
- package/src/infrastructure/README.md +37 -496
- package/src/infrastructure/mappers/README.md +0 -13
- package/src/infrastructure/repositories/README.md +74 -360
- package/src/infrastructure/services/README.md +95 -370
- package/src/presentation/README.md +123 -408
- package/src/presentation/README.md.bak +172 -0
- package/src/presentation/components/README.md +151 -179
- package/src/presentation/components/README.md.bak +217 -0
- package/src/presentation/components/details/CreditRow.md +65 -310
- package/src/presentation/components/details/DetailRow.md +63 -255
- package/src/presentation/components/details/PremiumDetailsCard.md +65 -238
- package/src/presentation/components/details/PremiumStatusBadge.md +64 -239
- package/src/presentation/components/details/README.md +97 -447
- package/src/presentation/components/feedback/PaywallFeedbackModal.md +63 -287
- package/src/presentation/components/feedback/README.md +97 -445
- package/src/presentation/components/paywall/PaywallModal.md +66 -416
- package/src/presentation/components/paywall/README.md +50 -186
- package/src/presentation/components/sections/README.md +97 -466
- package/src/presentation/components/sections/SubscriptionSection.md +92 -244
- package/src/presentation/hooks/README.md +154 -741
- package/src/presentation/hooks/useAuthAwarePurchase.md +58 -325
- package/src/presentation/hooks/useAuthGate.md +61 -375
- package/src/presentation/hooks/useAuthSubscriptionSync.md +66 -370
- package/src/presentation/hooks/useCreditChecker.md +73 -378
- package/src/presentation/hooks/useCredits.md +74 -313
- package/src/presentation/hooks/useCredits.md.bak +231 -0
- package/src/presentation/hooks/useCreditsGate.md +66 -318
- package/src/presentation/hooks/useDeductCredit.md +96 -156
- package/src/presentation/hooks/useDevTestCallbacks.md +63 -394
- package/src/presentation/hooks/useFeatureGate.md +105 -150
- package/src/presentation/hooks/useFeatureGate.md.bak +284 -0
- package/src/presentation/hooks/useInitializeCredits.md +64 -430
- package/src/presentation/hooks/usePaywall.md +61 -306
- package/src/presentation/hooks/usePaywallOperations.md +64 -458
- package/src/presentation/hooks/usePaywallVisibility.md +67 -316
- package/src/presentation/hooks/usePremium.md +84 -226
- package/src/presentation/hooks/usePremiumGate.md +60 -395
- package/src/presentation/hooks/usePremiumWithCredits.md +64 -401
- package/src/presentation/hooks/useSubscription.md +66 -422
- package/src/presentation/hooks/useSubscriptionDetails.md +65 -410
- package/src/presentation/hooks/useSubscriptionGate.md +80 -164
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +66 -346
- package/src/presentation/hooks/useSubscriptionStatus.md +66 -396
- package/src/presentation/hooks/useUserTier.md +63 -328
- package/src/presentation/hooks/useUserTierWithRepository.md +64 -424
- package/src/presentation/screens/README.md +48 -190
- package/src/presentation/types/README.md +0 -16
- package/src/presentation/utils/README.md +0 -21
- package/src/revenuecat/README.md +99 -518
- package/src/revenuecat/application/README.md +43 -0
- package/src/revenuecat/application/ports/README.md +41 -0
- package/src/revenuecat/domain/README.md +42 -141
- package/src/revenuecat/domain/constants/README.md +41 -0
- package/src/revenuecat/domain/entities/README.md +42 -0
- package/src/revenuecat/domain/errors/README.md +47 -191
- package/src/revenuecat/domain/types/README.md +41 -0
- package/src/revenuecat/domain/value-objects/README.md +41 -0
- package/src/revenuecat/infrastructure/README.md +41 -0
- package/src/revenuecat/infrastructure/config/README.md +32 -23
- package/src/revenuecat/infrastructure/handlers/README.md +41 -0
- package/src/revenuecat/infrastructure/managers/README.md +34 -42
- package/src/revenuecat/infrastructure/services/README.md +42 -0
- package/src/revenuecat/infrastructure/utils/README.md +41 -0
- package/src/revenuecat/presentation/README.md +42 -0
- package/src/revenuecat/presentation/hooks/README.md +29 -35
- package/src/utils/README.md +38 -525
|
@@ -2,185 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
Value objects for the subscription domain.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
## Characteristics
|
|
48
|
-
|
|
49
|
-
### 1. Immutable
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
const config = SubscriptionConfig.create({...});
|
|
53
|
-
// config.apiKey = 'new_key'; // Error: Cannot assign
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### 2. Value-Based Equality
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
const config1 = SubscriptionConfig.create({...});
|
|
60
|
-
const config2 = SubscriptionConfig.create({...});
|
|
61
|
-
|
|
62
|
-
config1.equals(config2); // true (if same values)
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### 3. Self-Validating
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
const config = SubscriptionConfig.create({
|
|
69
|
-
apiKey: '', // Invalid!
|
|
70
|
-
entitlementId: 'premium',
|
|
71
|
-
});
|
|
72
|
-
// Throws ValidationError
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Creating Value Objects
|
|
76
|
-
|
|
77
|
-
### Factory Method
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
const config = SubscriptionConfig.create({
|
|
81
|
-
apiKey: 'your_key',
|
|
82
|
-
entitlementId: 'premium',
|
|
83
|
-
});
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Builder Pattern
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
const config = SubscriptionConfig.builder()
|
|
90
|
-
.apiKey('your_key')
|
|
91
|
-
.entitlementId('premium')
|
|
92
|
-
.addPlan('monthly', monthlyPlan)
|
|
93
|
-
.addPlan('annual', annualPlan)
|
|
94
|
-
.build();
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Common Value Objects
|
|
98
|
-
|
|
99
|
-
### Money
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
class Money {
|
|
103
|
-
private constructor(
|
|
104
|
-
private amount: number,
|
|
105
|
-
private currency: string
|
|
106
|
-
) {}
|
|
107
|
-
|
|
108
|
-
static create(amount: number, currency: string): Money {
|
|
109
|
-
if (amount < 0) throw new Error('Amount cannot be negative');
|
|
110
|
-
return new Money(amount, currency);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
format(): string {
|
|
114
|
-
return new Intl.NumberFormat('en-US', {
|
|
115
|
-
style: 'currency',
|
|
116
|
-
currency: this.currency,
|
|
117
|
-
}).format(this.amount);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
add(other: Money): Money {
|
|
121
|
-
if (this.currency !== other.currency) {
|
|
122
|
-
throw new Error('Cannot add different currencies');
|
|
123
|
-
}
|
|
124
|
-
return new Money(this.amount + other.amount, this.currency);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### DateRange
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
class DateRange {
|
|
133
|
-
constructor(
|
|
134
|
-
private start: Date,
|
|
135
|
-
private end: Date
|
|
136
|
-
) {}
|
|
137
|
-
|
|
138
|
-
includes(date: Date): boolean {
|
|
139
|
-
return date >= this.start && date <= this.end;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
durationInDays(): number {
|
|
143
|
-
return Math.ceil(
|
|
144
|
-
(this.end.getTime() - this.start.getTime()) / (1000 * 60 * 60 * 24)
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Best Practices
|
|
151
|
-
|
|
152
|
-
1. **Make immutable** - All properties readonly
|
|
153
|
-
2. **Validate on creation** - Fail fast
|
|
154
|
-
3. **Override equality** - Compare by value, not reference
|
|
155
|
-
4. **Use for complex attributes** - Don't use for simple primitives
|
|
156
|
-
5. **Keep small** - Value objects should be focused
|
|
157
|
-
|
|
158
|
-
## Testing
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
describe('SubscriptionConfig', () => {
|
|
162
|
-
it('should create valid config', () => {
|
|
163
|
-
const config = SubscriptionConfig.create({
|
|
164
|
-
apiKey: 'test_key',
|
|
165
|
-
entitlementId: 'premium',
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
expect(config.apiKey).toBe('test_key');
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('should reject invalid config', () => {
|
|
172
|
-
expect(() => {
|
|
173
|
-
SubscriptionConfig.create({
|
|
174
|
-
apiKey: '',
|
|
175
|
-
entitlementId: 'premium',
|
|
176
|
-
});
|
|
177
|
-
}).toThrow();
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Related
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/domain/value-objects/`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
|
|
11
|
+
Value objects are immutable objects that represent concepts by their attributes rather than identity. They ensure validity and prevent primitive obsession by providing type-safe, validated representations.
|
|
12
|
+
|
|
13
|
+
## Restrictions
|
|
14
|
+
|
|
15
|
+
### REQUIRED
|
|
16
|
+
|
|
17
|
+
- MUST be immutable (all properties readonly)
|
|
18
|
+
- MUST validate on creation (fail fast)
|
|
19
|
+
- MUST override equality (compare by value, not reference)
|
|
20
|
+
- MUST use for complex attributes (not simple primitives)
|
|
21
|
+
- MUST be small and focused
|
|
22
|
+
|
|
23
|
+
### PROHIBITED
|
|
24
|
+
|
|
25
|
+
- MUST NOT allow mutation after creation
|
|
26
|
+
- MUST NOT use reference equality for comparison
|
|
27
|
+
- MUST NOT contain invalid states
|
|
28
|
+
- MUST NOT have identity-based equality
|
|
29
|
+
|
|
30
|
+
### CRITICAL
|
|
31
|
+
|
|
32
|
+
- Always validate on creation
|
|
33
|
+
- Implement value-based equality comparison
|
|
34
|
+
- Keep value objects small and focused
|
|
35
|
+
- Use only for complex attributes, not simple primitives
|
|
36
|
+
|
|
37
|
+
## AI Agent Guidelines
|
|
38
|
+
|
|
39
|
+
When working with value objects:
|
|
40
|
+
1. Make immutable - all properties readonly
|
|
41
|
+
2. Validate on creation - fail fast
|
|
42
|
+
3. Override equality - compare by value, not reference
|
|
43
|
+
4. Use for complex attributes - don't use for simple primitives
|
|
44
|
+
5. Keep small - value objects should be focused
|
|
45
|
+
|
|
46
|
+
## Related Documentation
|
|
183
47
|
|
|
184
48
|
- [Domain Entities](../entities/README.md)
|
|
185
49
|
- [Domain Errors](../errors/README.md)
|
|
186
|
-
- [Domain Layer](
|
|
50
|
+
- [Domain Layer](../README.md)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Domains
|
|
2
|
+
|
|
3
|
+
Specialized domain modules implementing specific business logic and features.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/domains/`
|
|
8
|
+
|
|
9
|
+
## Strategy
|
|
10
|
+
|
|
11
|
+
Implements Domain-Driven Design (DDD) principles with self-contained domains. Each domain includes domain layer (business logic, entities, value objects), infrastructure layer (external integrations, repositories), and presentation layer (domain-specific hooks and components).
|
|
12
|
+
|
|
13
|
+
## Restrictions
|
|
14
|
+
|
|
15
|
+
### REQUIRED
|
|
16
|
+
|
|
17
|
+
- Domains MUST NOT directly depend on each other
|
|
18
|
+
- MUST use well-defined interfaces between layers
|
|
19
|
+
- MUST depend on abstractions, not concretions (Dependency Inversion)
|
|
20
|
+
- All domains MUST be testable in isolation
|
|
21
|
+
|
|
22
|
+
### PROHIBITED
|
|
23
|
+
|
|
24
|
+
- MUST NOT share domain logic between domains (use shared kernel if needed)
|
|
25
|
+
- MUST NOT create circular dependencies between domains
|
|
26
|
+
- MUST NOT bypass domain layer from presentation
|
|
27
|
+
- MUST NOT expose infrastructure details to other domains
|
|
28
|
+
|
|
29
|
+
### CRITICAL
|
|
30
|
+
|
|
31
|
+
- Always validate invariants at domain boundaries
|
|
32
|
+
- Always implement domain errors for business rule violations
|
|
33
|
+
- Never allow inconsistent domain state
|
|
34
|
+
- Must implement proper transaction boundaries
|
|
35
|
+
- Always sanitize inputs from external sources
|
|
36
|
+
|
|
37
|
+
## AI Agent Guidelines
|
|
38
|
+
|
|
39
|
+
When working with domains:
|
|
40
|
+
1. Always respect domain boundaries
|
|
41
|
+
2. Always use dependency inversion
|
|
42
|
+
3. Always implement domain-specific errors
|
|
43
|
+
4. Always validate invariants at boundaries
|
|
44
|
+
5. Never create circular dependencies
|
|
45
|
+
|
|
46
|
+
## Related Documentation
|
|
47
|
+
|
|
48
|
+
- [Wallet Domain](wallet/README.md)
|
|
49
|
+
- [Paywall Domain](paywall/README.md)
|
|
50
|
+
- [Config Domain](config/README.md)
|
|
51
|
+
- [Domain Layer](../domain/README.md)
|
|
52
|
+
- [Infrastructure](../infrastructure/README.md)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Domains
|
|
2
|
+
|
|
3
|
+
Specialized domain modules implementing specific business logic and features.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
**Directory**: `src/domains/`
|
|
8
|
+
|
|
9
|
+
**Type**: Domain Collection
|
|
10
|
+
|
|
11
|
+
## Strategy
|
|
12
|
+
|
|
13
|
+
### Domain-Driven Design
|
|
14
|
+
|
|
15
|
+
This directory implements Domain-Driven Design (DDD) principles:
|
|
16
|
+
|
|
17
|
+
1. **Wallet Domain**: Credit balance, transactions, and purchase flow
|
|
18
|
+
2. **Paywall Domain**: Upgrade prompts, subscription management
|
|
19
|
+
3. **Config Domain**: Feature flags, subscription configuration
|
|
20
|
+
|
|
21
|
+
Each domain is self-contained with:
|
|
22
|
+
- **Domain Layer**: Business logic, entities, value objects
|
|
23
|
+
- **Infrastructure Layer**: External integrations, repositories
|
|
24
|
+
- **Presentation Layer**: Domain-specific hooks and components
|
|
25
|
+
|
|
26
|
+
### Architecture Pattern
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌─────────────────────────────────────┐
|
|
30
|
+
│ Application Layer │
|
|
31
|
+
│ (Use Cases, Orchestration) │
|
|
32
|
+
└──────────────┬──────────────────────┘
|
|
33
|
+
│
|
|
34
|
+
┌───────┴────────┐
|
|
35
|
+
│ │
|
|
36
|
+
┌──────▼──────┐ ┌─────▼──────┐
|
|
37
|
+
│ Wallet │ │ Paywall │
|
|
38
|
+
│ Domain │ │ Domain │
|
|
39
|
+
├─────────────┤ ├────────────┤
|
|
40
|
+
│ Domain │ │ Domain │
|
|
41
|
+
│ Infra │ │ Infra │
|
|
42
|
+
│ Presentation│ │ Presentation│
|
|
43
|
+
└──────┬──────┘ └─────┬──────┘
|
|
44
|
+
│ │
|
|
45
|
+
└────────┬───────┘
|
|
46
|
+
│
|
|
47
|
+
┌────────▼──────────┐
|
|
48
|
+
│ Shared Infra │
|
|
49
|
+
│ (Firebase, etc) │
|
|
50
|
+
└───────────────────┘
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Domain Modules
|
|
54
|
+
|
|
55
|
+
### Wallet Domain (`wallet/`)
|
|
56
|
+
|
|
57
|
+
**Responsibility**: Credit balance and transaction management
|
|
58
|
+
|
|
59
|
+
**Key Features**:
|
|
60
|
+
- Credit balance tracking
|
|
61
|
+
- Transaction history
|
|
62
|
+
- Purchase initialization
|
|
63
|
+
- Real-time updates
|
|
64
|
+
|
|
65
|
+
**Documentation**: `wallet/README.md`
|
|
66
|
+
|
|
67
|
+
### Paywall Domain (`paywall/`)
|
|
68
|
+
|
|
69
|
+
**Responsibility**: Subscription upgrade flows and paywall UI
|
|
70
|
+
|
|
71
|
+
**Key Features**:
|
|
72
|
+
- Paywall display logic
|
|
73
|
+
- Subscription management
|
|
74
|
+
- Feature gating
|
|
75
|
+
- Upgrade prompts
|
|
76
|
+
|
|
77
|
+
**Documentation**: `paywall/README.md`
|
|
78
|
+
|
|
79
|
+
### Config Domain (`config/`)
|
|
80
|
+
|
|
81
|
+
**Responsibility**: Subscription configuration and feature flags
|
|
82
|
+
|
|
83
|
+
**Key Features**:
|
|
84
|
+
- Subscription tiers
|
|
85
|
+
- Feature configuration
|
|
86
|
+
- Pricing rules
|
|
87
|
+
- Feature flags
|
|
88
|
+
|
|
89
|
+
**Documentation**: `config/README.md`
|
|
90
|
+
|
|
91
|
+
## Restrictions
|
|
92
|
+
|
|
93
|
+
### REQUIRED
|
|
94
|
+
|
|
95
|
+
- **Domain Isolation**: Domains MUST NOT directly depend on each other
|
|
96
|
+
- **Interface Segregation**: Use well-defined interfaces between layers
|
|
97
|
+
- **Dependency Inversion**: Depend on abstractions, not concretions
|
|
98
|
+
- **Testability**: All domains MUST be testable in isolation
|
|
99
|
+
|
|
100
|
+
### PROHIBITED
|
|
101
|
+
|
|
102
|
+
- **NEVER** share domain logic between domains (use shared kernel if needed)
|
|
103
|
+
- **NEVER** create circular dependencies between domains
|
|
104
|
+
- **DO NOT** bypass domain layer from presentation
|
|
105
|
+
- **NEVER** expose infrastructure details to other domains
|
|
106
|
+
|
|
107
|
+
### CRITICAL SAFETY
|
|
108
|
+
|
|
109
|
+
- **ALWAYS** validate invariants at domain boundaries
|
|
110
|
+
- **ALWAYS** implement domain errors for business rule violations
|
|
111
|
+
- **NEVER** allow inconsistent domain state
|
|
112
|
+
- **MUST** implement proper transaction boundaries
|
|
113
|
+
- **ALWAYS** sanitize inputs from external sources
|
|
114
|
+
|
|
115
|
+
## Rules
|
|
116
|
+
|
|
117
|
+
### Domain Boundaries
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// CORRECT - Respecting domain boundaries
|
|
121
|
+
// Wallet domain handles credits
|
|
122
|
+
const { credits } = useCredits(); // From wallet domain
|
|
123
|
+
|
|
124
|
+
// Paywall domain handles upgrades
|
|
125
|
+
const { showPaywall } = usePaywallOperations(); // From paywall domain
|
|
126
|
+
|
|
127
|
+
// INCORRECT - Crossing domain boundaries
|
|
128
|
+
const walletRepository = new WalletRepository();
|
|
129
|
+
// Directly using wallet repo in paywall component
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Domain Errors
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// CORRECT - Domain-specific errors
|
|
136
|
+
class InsufficientCreditsError extends DomainError {
|
|
137
|
+
constructor(required: number, available: number) {
|
|
138
|
+
super(`Insufficient credits: need ${required}, have ${available}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// INCORRECT - Generic errors
|
|
143
|
+
throw new Error('Not enough credits'); // Loses domain context
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Dependency Direction
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// CORRECT - Dependency inversion
|
|
150
|
+
interface ICreditsRepository {
|
|
151
|
+
getBalance(userId: string): Promise<number>;
|
|
152
|
+
deductCredits(userId: string, amount: number): Promise<void>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Domain depends on interface, not implementation
|
|
156
|
+
class CreditService {
|
|
157
|
+
constructor(private repo: ICreditsRepository) {}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// INCORRECT - Concrete dependency
|
|
161
|
+
class CreditService {
|
|
162
|
+
constructor(private repo: FirebaseCreditsRepository) {}
|
|
163
|
+
// Tightly coupled to Firebase
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## AI Agent Guidelines
|
|
168
|
+
|
|
169
|
+
### When Working with Domains
|
|
170
|
+
|
|
171
|
+
1. **Always** respect domain boundaries
|
|
172
|
+
2. **Always** use dependency inversion
|
|
173
|
+
3. **Always** implement domain-specific errors
|
|
174
|
+
4. **Always** validate invariants at boundaries
|
|
175
|
+
5. **Never** create circular dependencies
|
|
176
|
+
|
|
177
|
+
### Integration Checklist
|
|
178
|
+
|
|
179
|
+
- [ ] Identify correct domain for feature
|
|
180
|
+
- [ ] Respect domain boundaries
|
|
181
|
+
- [ ] Use appropriate interfaces
|
|
182
|
+
- [ ] Handle domain errors
|
|
183
|
+
- [ ] Test domain in isolation
|
|
184
|
+
- [ ] Document domain interactions
|
|
185
|
+
- [ ] Validate invariants
|
|
186
|
+
- [ ] Implement transaction boundaries
|
|
187
|
+
- [ ] Test cross-domain scenarios
|
|
188
|
+
- [ ] Verify no circular dependencies
|
|
189
|
+
|
|
190
|
+
### Common Patterns
|
|
191
|
+
|
|
192
|
+
1. **Aggregate Root**: Single entry point for aggregate
|
|
193
|
+
2. **Value Objects**: Immutable values with no identity
|
|
194
|
+
3. **Domain Events**: Publish domain events for side effects
|
|
195
|
+
4. **Repositories**: Abstract data access
|
|
196
|
+
5. **Factories**: Complex object creation
|
|
197
|
+
6. **Domain Services**: Business logic that doesn't fit entities
|
|
198
|
+
7. **Specification**: Business rule encapsulation
|
|
199
|
+
8. **Anti-Corruption Layer**: Isolate from external systems
|
|
200
|
+
|
|
201
|
+
## Related Documentation
|
|
202
|
+
|
|
203
|
+
- **Wallet Domain**: `wallet/README.md`
|
|
204
|
+
- **Paywall Domain**: `paywall/README.md`
|
|
205
|
+
- **Config Domain**: `config/README.md`
|
|
206
|
+
- **Domain Layer**: `../domain/README.md`
|
|
207
|
+
- **Infrastructure**: `../infrastructure/README.md`
|
|
208
|
+
|
|
209
|
+
## Domain Structure
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
src/domains/
|
|
213
|
+
├── wallet/ # Wallet and credits domain
|
|
214
|
+
│ ├── domain/ # Business logic
|
|
215
|
+
│ ├── infrastructure/ # External integrations
|
|
216
|
+
│ └── presentation/ # UI hooks and components
|
|
217
|
+
├── paywall/ # Paywall and upgrades domain
|
|
218
|
+
│ ├── domain/
|
|
219
|
+
│ ├── infrastructure/
|
|
220
|
+
│ └── presentation/
|
|
221
|
+
└── config/ # Configuration domain
|
|
222
|
+
├── domain/
|
|
223
|
+
├── infrastructure/
|
|
224
|
+
└── presentation/
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Creating a New Domain
|
|
228
|
+
|
|
229
|
+
When creating a new domain:
|
|
230
|
+
|
|
231
|
+
1. **Define Boundaries**: What is the domain's responsibility?
|
|
232
|
+
2. **Identify Entities**: What are the core business objects?
|
|
233
|
+
3. **Define Invariants**: What rules must always be true?
|
|
234
|
+
4. **Design Interfaces**: How will other layers interact?
|
|
235
|
+
5. **Implement Repository**: Abstract data access
|
|
236
|
+
6. **Create Presentation Layer**: Hooks and components
|
|
237
|
+
7. **Write Tests**: Test domain logic in isolation
|
|
238
|
+
8. **Document**: Provide comprehensive README
|
|
239
|
+
|
|
240
|
+
Example:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
// Domain entity
|
|
244
|
+
export class FeatureFlag {
|
|
245
|
+
constructor(
|
|
246
|
+
public readonly id: string,
|
|
247
|
+
public readonly name: string,
|
|
248
|
+
private _isEnabled: boolean
|
|
249
|
+
) {}
|
|
250
|
+
|
|
251
|
+
get isEnabled(): boolean {
|
|
252
|
+
return this._isEnabled;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
enable(): void {
|
|
256
|
+
this._isEnabled = true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
disable(): void {
|
|
260
|
+
this._isEnabled = false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Repository interface
|
|
265
|
+
export interface IFeatureFlagRepository {
|
|
266
|
+
findById(id: string): Promise<FeatureFlag | null>;
|
|
267
|
+
save(flag: FeatureFlag): Promise<void>;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Presentation hook
|
|
271
|
+
export function useFeatureFlag(featureId: string) {
|
|
272
|
+
// Hook implementation
|
|
273
|
+
}
|
|
274
|
+
```
|