@plyaz/core 1.0.0
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 +439 -0
- package/dist/backend/featureFlags/feature-flag.controller.d.ts +135 -0
- package/dist/backend/featureFlags/feature-flag.controller.d.ts.map +1 -0
- package/dist/backend/featureFlags/feature-flag.module.d.ts +114 -0
- package/dist/backend/featureFlags/feature-flag.module.d.ts.map +1 -0
- package/dist/backend/featureFlags/feature-flag.repository.d.ts +85 -0
- package/dist/backend/featureFlags/feature-flag.repository.d.ts.map +1 -0
- package/dist/backend/featureFlags/feature-flag.service.d.ts +123 -0
- package/dist/backend/featureFlags/feature-flag.service.d.ts.map +1 -0
- package/dist/backend/featureFlags/index.d.ts +49 -0
- package/dist/backend/featureFlags/index.d.ts.map +1 -0
- package/dist/backend/index.d.ts +5 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/cache/index.d.ts +98 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/strategies/memory.d.ts +103 -0
- package/dist/cache/strategies/memory.d.ts.map +1 -0
- package/dist/cache/strategies/redis.d.ts +105 -0
- package/dist/cache/strategies/redis.d.ts.map +1 -0
- package/dist/domain/featureFlags/index.d.ts +49 -0
- package/dist/domain/featureFlags/index.d.ts.map +1 -0
- package/dist/domain/featureFlags/provider.d.ts +166 -0
- package/dist/domain/featureFlags/provider.d.ts.map +1 -0
- package/dist/domain/featureFlags/providers/api.d.ts +78 -0
- package/dist/domain/featureFlags/providers/api.d.ts.map +1 -0
- package/dist/domain/featureFlags/providers/database.d.ts +102 -0
- package/dist/domain/featureFlags/providers/database.d.ts.map +1 -0
- package/dist/domain/featureFlags/providers/factory.d.ts +116 -0
- package/dist/domain/featureFlags/providers/factory.d.ts.map +1 -0
- package/dist/domain/featureFlags/providers/file.d.ts +84 -0
- package/dist/domain/featureFlags/providers/file.d.ts.map +1 -0
- package/dist/domain/featureFlags/providers/memory.d.ts +179 -0
- package/dist/domain/featureFlags/providers/memory.d.ts.map +1 -0
- package/dist/domain/featureFlags/providers/redis.d.ts +80 -0
- package/dist/domain/featureFlags/providers/redis.d.ts.map +1 -0
- package/dist/domain/index.d.ts +6 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/types.d.ts +18 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/engine/featureFlags/engine.d.ts +193 -0
- package/dist/engine/featureFlags/engine.d.ts.map +1 -0
- package/dist/engine/featureFlags/index.d.ts +10 -0
- package/dist/engine/featureFlags/index.d.ts.map +1 -0
- package/dist/engine/index.d.ts +5 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlag.d.ts +103 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlag.d.ts.map +1 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlagActions.d.ts +35 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlagActions.d.ts.map +1 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlagHelpers.d.ts +55 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlagHelpers.d.ts.map +1 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlagProvider.d.ts +57 -0
- package/dist/frontend/featureFlags/hooks/useFeatureFlagProvider.d.ts.map +1 -0
- package/dist/frontend/featureFlags/index.d.ts +14 -0
- package/dist/frontend/featureFlags/index.d.ts.map +1 -0
- package/dist/frontend/featureFlags/providers/FeatureFlagProvider.d.ts +99 -0
- package/dist/frontend/featureFlags/providers/FeatureFlagProvider.d.ts.map +1 -0
- package/dist/frontend/featureFlags/providers/FeatureFlagProviderHelpers.d.ts +45 -0
- package/dist/frontend/featureFlags/providers/FeatureFlagProviderHelpers.d.ts.map +1 -0
- package/dist/frontend/index.d.ts +2 -0
- package/dist/frontend/index.d.ts.map +1 -0
- package/dist/index.cjs +3951 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +3902 -0
- package/dist/index.mjs.map +1 -0
- package/dist/utils/common/hash.d.ts +81 -0
- package/dist/utils/common/hash.d.ts.map +1 -0
- package/dist/utils/common/index.d.ts +11 -0
- package/dist/utils/common/index.d.ts.map +1 -0
- package/dist/utils/common/values.d.ts +48 -0
- package/dist/utils/common/values.d.ts.map +1 -0
- package/dist/utils/featureFlags/conditions.d.ts +114 -0
- package/dist/utils/featureFlags/conditions.d.ts.map +1 -0
- package/dist/utils/featureFlags/context.d.ts +241 -0
- package/dist/utils/featureFlags/context.d.ts.map +1 -0
- package/dist/utils/featureFlags/index.d.ts +11 -0
- package/dist/utils/featureFlags/index.d.ts.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/package.json +144 -0
package/README.md
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
# @plyaz/core
|
|
2
|
+
|
|
3
|
+
> Foundational full-stack package for the Plyaz ecosystem
|
|
4
|
+
|
|
5
|
+
The `@plyaz/core` package serves as the orchestration layer that combines functionality from specialized packages to provide core business logic, domain models, and SDK foundations.
|
|
6
|
+
|
|
7
|
+
## 🎯 Key Objectives
|
|
8
|
+
|
|
9
|
+
- **Business Logic Orchestration**: Centralize core business logic that coordinates between specialized packages
|
|
10
|
+
- **Full-Stack Support**: Environment-aware conditional loading for frontend, backend, and B2B integrations
|
|
11
|
+
- **SDK Foundations**: Standardized interfaces for B2B partnerships and external integrations
|
|
12
|
+
- **Type Safety**: Maintain strict architectural boundaries across all environments
|
|
13
|
+
|
|
14
|
+
## 🏗️ Architecture Philosophy
|
|
15
|
+
|
|
16
|
+
`@plyaz/core` acts as the **orchestration layer** - it doesn't reimplement functionality but coordinates between specialized packages:
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
// Core orchestrates other packages
|
|
20
|
+
import { getUser, createTransaction } from '@plyaz/api';
|
|
21
|
+
import { executeSmartContract, getWalletBalance } from '@plyaz/web3';
|
|
22
|
+
import { validateUser, checkPermissions } from '@plyaz/auth';
|
|
23
|
+
import { trackBusinessMetric } from '@plyaz/monitoring';
|
|
24
|
+
import { FEATURE_FLAGS } from '@plyaz/config';
|
|
25
|
+
import { createLogger } from '@plyaz/logger';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 📁 Package Structure
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
@plyaz/core/
|
|
32
|
+
├── src/
|
|
33
|
+
│ ├── cache/ # Business logic caching layer
|
|
34
|
+
│ ├── domain/ # Pure business domain logic
|
|
35
|
+
│ │ ├── user/ # User entity models and business rules
|
|
36
|
+
│ │ ├── asset/ # Digital asset models and economics
|
|
37
|
+
│ │ ├── transaction/ # Transaction domain and validation
|
|
38
|
+
│ │ └── community/ # Community governance and interaction
|
|
39
|
+
│ ├── engine/ # Core computational engines
|
|
40
|
+
│ │ ├── calculation/ # Mathematical computation algorithms
|
|
41
|
+
│ │ ├── incentive/ # Reward and incentive systems
|
|
42
|
+
│ │ ├── validation/ # Business rule validation engines
|
|
43
|
+
│ │ └── insights/ # Data analysis and pattern recognition
|
|
44
|
+
│ ├── feature-flags/ # Complete feature flag system
|
|
45
|
+
│ ├── frontend/ # Frontend-specific implementations
|
|
46
|
+
│ ├── backend/ # Backend-specific implementations
|
|
47
|
+
│ ├── sdk/ # B2B SDK foundation
|
|
48
|
+
│ └── contracts/ # External service contracts
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 🚀 Feature Flag System
|
|
52
|
+
|
|
53
|
+
The feature flag system is currently the most mature component of `@plyaz/core`:
|
|
54
|
+
|
|
55
|
+
### Backend Integration (NestJS)
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// app.module.ts
|
|
59
|
+
import { FeatureFlagModule } from '@plyaz/core/backend';
|
|
60
|
+
|
|
61
|
+
@Module({
|
|
62
|
+
imports: [
|
|
63
|
+
FeatureFlagModule.forRoot({
|
|
64
|
+
provider: 'redis',
|
|
65
|
+
isCacheEnabled: true,
|
|
66
|
+
cacheTtl: 600,
|
|
67
|
+
redisConfig: { url: 'redis://localhost:6379' }
|
|
68
|
+
})
|
|
69
|
+
],
|
|
70
|
+
})
|
|
71
|
+
export class AppModule {}
|
|
72
|
+
|
|
73
|
+
// my.service.ts
|
|
74
|
+
import { FeatureFlagService } from '@plyaz/core/backend';
|
|
75
|
+
|
|
76
|
+
@Injectable()
|
|
77
|
+
export class MyService {
|
|
78
|
+
constructor(private featureFlagService: FeatureFlagService) {}
|
|
79
|
+
|
|
80
|
+
async processPayment(userId: string) {
|
|
81
|
+
const isEnabled = await this.featureFlagService.isEnabled('NEW_PAYMENT_FLOW', {
|
|
82
|
+
userId,
|
|
83
|
+
environment: 'production'
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (isEnabled) {
|
|
87
|
+
// New payment implementation
|
|
88
|
+
} else {
|
|
89
|
+
// Legacy payment implementation
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Backend Integration (Express/Node.js)
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// server.js
|
|
99
|
+
import { MemoryFeatureFlagProvider } from '@plyaz/core/domain';
|
|
100
|
+
import { FEATURES } from '@plyaz/config';
|
|
101
|
+
|
|
102
|
+
// Initialize provider
|
|
103
|
+
const featureFlagProvider = new MemoryFeatureFlagProvider({
|
|
104
|
+
provider: 'memory',
|
|
105
|
+
isCacheEnabled: true,
|
|
106
|
+
cacheTtl: 300
|
|
107
|
+
}, FEATURES);
|
|
108
|
+
|
|
109
|
+
await featureFlagProvider.initialize();
|
|
110
|
+
|
|
111
|
+
// Use in routes
|
|
112
|
+
app.get('/api/features/:key', async (req, res) => {
|
|
113
|
+
const evaluation = await featureFlagProvider.getFlag(req.params.key, {
|
|
114
|
+
userId: req.user?.id,
|
|
115
|
+
environment: process.env.NODE_ENV
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
res.json(evaluation);
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Frontend Integration (React)
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// App.tsx
|
|
126
|
+
import { FeatureFlagAppProvider } from '@plyaz/core/frontend';
|
|
127
|
+
import { FEATURES } from '@plyaz/config';
|
|
128
|
+
|
|
129
|
+
function App() {
|
|
130
|
+
return (
|
|
131
|
+
<FeatureFlagAppProvider
|
|
132
|
+
config={{
|
|
133
|
+
provider: 'api',
|
|
134
|
+
apiEndpoint: 'https://api.example.com/feature-flags',
|
|
135
|
+
isCacheEnabled: true,
|
|
136
|
+
cacheTtl: 300
|
|
137
|
+
}}
|
|
138
|
+
features={FEATURES}
|
|
139
|
+
>
|
|
140
|
+
<MyApplication />
|
|
141
|
+
</FeatureFlagAppProvider>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Component.tsx
|
|
146
|
+
import { useFeatureFlag, useFeatureFlagEnabled } from '@plyaz/core/frontend';
|
|
147
|
+
|
|
148
|
+
function PaymentComponent() {
|
|
149
|
+
// Full feature flag data with loading state
|
|
150
|
+
const { value, isLoading, error } = useFeatureFlag('NEW_PAYMENT_FLOW');
|
|
151
|
+
|
|
152
|
+
// Simple boolean check
|
|
153
|
+
const isGoogleAuthEnabled = useFeatureFlagEnabled('AUTH_GOOGLE');
|
|
154
|
+
|
|
155
|
+
if (isLoading) return <Spinner />;
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<div>
|
|
159
|
+
{value && <NewPaymentFlow />}
|
|
160
|
+
{isGoogleAuthEnabled && <GoogleSignInButton />}
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Frontend Integration (Vanilla JavaScript)
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { MemoryFeatureFlagProvider } from '@plyaz/core/domain';
|
|
170
|
+
import { FEATURES } from '@plyaz/config';
|
|
171
|
+
|
|
172
|
+
// Initialize provider
|
|
173
|
+
const provider = new MemoryFeatureFlagProvider({
|
|
174
|
+
provider: 'memory',
|
|
175
|
+
isCacheEnabled: true
|
|
176
|
+
}, FEATURES);
|
|
177
|
+
|
|
178
|
+
await provider.initialize();
|
|
179
|
+
|
|
180
|
+
// Check feature flags
|
|
181
|
+
async function renderPaymentButton() {
|
|
182
|
+
const isEnabled = await provider.isEnabled('NEW_PAYMENT_FLOW', {
|
|
183
|
+
userId: getCurrentUserId(),
|
|
184
|
+
environment: 'production'
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (isEnabled) {
|
|
188
|
+
document.getElementById('payment-btn').innerHTML = 'New Payment';
|
|
189
|
+
} else {
|
|
190
|
+
document.getElementById('payment-btn').innerHTML = 'Legacy Payment';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Subscribe to changes
|
|
195
|
+
provider.subscribe(() => {
|
|
196
|
+
renderPaymentButton();
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Testing Support
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { MemoryFeatureFlagProvider } from '@plyaz/core/domain';
|
|
204
|
+
import { FEATURES } from '@plyaz/config';
|
|
205
|
+
|
|
206
|
+
// Initialize for testing with overrides
|
|
207
|
+
const testProvider = new MemoryFeatureFlagProvider({
|
|
208
|
+
provider: 'memory',
|
|
209
|
+
isLoggingEnabled: false
|
|
210
|
+
}, FEATURES);
|
|
211
|
+
|
|
212
|
+
await testProvider.initialize();
|
|
213
|
+
|
|
214
|
+
// Override specific flags for testing
|
|
215
|
+
testProvider.setOverride('NEW_PAYMENT_FLOW', true);
|
|
216
|
+
testProvider.setOverride('BETA_FEATURE', false);
|
|
217
|
+
|
|
218
|
+
// Use in tests
|
|
219
|
+
describe('Payment Flow', () => {
|
|
220
|
+
it('should use new payment flow when enabled', async () => {
|
|
221
|
+
const isEnabled = await testProvider.isEnabled('NEW_PAYMENT_FLOW');
|
|
222
|
+
expect(isEnabled).toBe(true);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## 🗄️ Cache System
|
|
228
|
+
|
|
229
|
+
The cache system provides intelligent caching strategies for business logic coordination:
|
|
230
|
+
|
|
231
|
+
### Basic Usage
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { CacheManager } from '@plyaz/core/cache';
|
|
235
|
+
|
|
236
|
+
// Initialize with memory strategy
|
|
237
|
+
const cache = new CacheManager({
|
|
238
|
+
isEnabled: true,
|
|
239
|
+
ttl: 300, // 5 minutes
|
|
240
|
+
strategy: 'memory',
|
|
241
|
+
memoryConfig: {
|
|
242
|
+
maxSize: 1000,
|
|
243
|
+
cleanupInterval: 60000 // 1 minute
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Store data
|
|
248
|
+
await cache.set('user:123', userData, 600); // Custom TTL of 10 minutes
|
|
249
|
+
|
|
250
|
+
// Retrieve data
|
|
251
|
+
const user = await cache.get<User>('user:123');
|
|
252
|
+
|
|
253
|
+
// Check existence
|
|
254
|
+
const exists = await cache.has('user:123');
|
|
255
|
+
|
|
256
|
+
// Remove specific key
|
|
257
|
+
await cache.delete('user:123');
|
|
258
|
+
|
|
259
|
+
// Clear all cache
|
|
260
|
+
await cache.clear();
|
|
261
|
+
|
|
262
|
+
// Get cache statistics
|
|
263
|
+
const stats = await cache.getStats();
|
|
264
|
+
console.log(`Cache hit ratio: ${stats.hitRatio}`);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Redis Strategy
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import { CacheManager } from '@plyaz/core/cache';
|
|
271
|
+
|
|
272
|
+
const cache = new CacheManager({
|
|
273
|
+
isEnabled: true,
|
|
274
|
+
ttl: 300,
|
|
275
|
+
strategy: 'redis',
|
|
276
|
+
redisConfig: {
|
|
277
|
+
url: 'redis://localhost:6379',
|
|
278
|
+
keyPrefix: 'myapp:',
|
|
279
|
+
db: 0
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Integration with Feature Flags
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
// Feature flags use the cache system internally
|
|
288
|
+
const provider = new MemoryFeatureFlagProvider({
|
|
289
|
+
provider: 'memory',
|
|
290
|
+
isCacheEnabled: true, // Enables caching
|
|
291
|
+
cacheTtl: 300 // Cache TTL in seconds
|
|
292
|
+
}, FEATURES);
|
|
293
|
+
|
|
294
|
+
// The provider automatically caches evaluations for performance
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Business Logic Caching Patterns
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { CacheManager } from '@plyaz/core/cache';
|
|
301
|
+
|
|
302
|
+
class UserService {
|
|
303
|
+
constructor(private cache: CacheManager) {}
|
|
304
|
+
|
|
305
|
+
async getUser(userId: string): Promise<User> {
|
|
306
|
+
// Try cache first
|
|
307
|
+
const cacheKey = `user:${userId}`;
|
|
308
|
+
const cached = await this.cache.get<User>(cacheKey);
|
|
309
|
+
|
|
310
|
+
if (cached) {
|
|
311
|
+
return cached;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Fetch from database
|
|
315
|
+
const user = await this.fetchUserFromDb(userId);
|
|
316
|
+
|
|
317
|
+
// Cache for future requests
|
|
318
|
+
await this.cache.set(cacheKey, user, 600); // 10 minutes
|
|
319
|
+
|
|
320
|
+
return user;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async invalidateUser(userId: string): Promise<void> {
|
|
324
|
+
await this.cache.delete(`user:${userId}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## 🔧 Key Features
|
|
330
|
+
|
|
331
|
+
- **Environment Isolation**: Complete separation of frontend and backend code
|
|
332
|
+
- **Business Caching**: Intelligent caching strategies for cross-package data coordination
|
|
333
|
+
- **Feature Flags**: Complete feature flag system with multiple providers
|
|
334
|
+
- **Domain-Driven Design**: Clear bounded contexts for different business domains
|
|
335
|
+
- **SDK Ready**: B2B partner integration capabilities
|
|
336
|
+
- **Type Safe**: Full TypeScript support across all environments
|
|
337
|
+
|
|
338
|
+
## 🏛️ Microservice Strategy
|
|
339
|
+
|
|
340
|
+
Install `@plyaz/core` into individual microservices and import only needed functionality:
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
// User Service - only imports user-related functionality
|
|
344
|
+
import { UserDomainService, UserCacheService } from '@plyaz/core/domain';
|
|
345
|
+
|
|
346
|
+
// Asset Service - only imports asset-related functionality
|
|
347
|
+
import { AssetDomainService, CalculationEngine } from '@plyaz/core';
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## 📚 Documentation
|
|
351
|
+
|
|
352
|
+
For detailed architecture information, implementation guides, and examples:
|
|
353
|
+
|
|
354
|
+
**[📖 Full Documentation](https://plyaz.atlassian.net/wiki/spaces/SD/pages/37257227/Core+Package?atlOrigin=eyJpIjoiNmQxZmNhYTllYmZjNDU2Njk0YmRhYWI2M2JkNTA3NDMiLCJwIjoiYyJ9)**
|
|
355
|
+
|
|
356
|
+
## 🔗 Related Packages
|
|
357
|
+
|
|
358
|
+
| Package | Purpose | Core Usage |
|
|
359
|
+
|---------|---------|------------|
|
|
360
|
+
| `@plyaz/api` | HTTP/REST API calls | Business data operations |
|
|
361
|
+
| `@plyaz/web3` | Blockchain interactions | Asset operations, smart contracts |
|
|
362
|
+
| `@plyaz/auth` | Authentication & authorization | User validation, permissions |
|
|
363
|
+
| `@plyaz/config` | Configuration & feature flags | Business rules, environment settings |
|
|
364
|
+
| `@plyaz/monitoring` | Metrics & performance tracking | Business KPI tracking |
|
|
365
|
+
| `@plyaz/logger` | Logging infrastructure | Business operation logging |
|
|
366
|
+
| `@plyaz/events` | Event-driven communication | Business event coordination |
|
|
367
|
+
|
|
368
|
+
## 🛡️ Security & Performance
|
|
369
|
+
|
|
370
|
+
- **Authentication Integration**: Built-in security via `@plyaz/auth`
|
|
371
|
+
- **Input Validation**: Comprehensive validation using `@plyaz/errors`
|
|
372
|
+
- **Audit Logging**: Full audit trail via `@plyaz/logger`
|
|
373
|
+
- **Intelligent Caching**: Business-aware caching strategies
|
|
374
|
+
- **Tree Shaking**: Environment-specific code loading
|
|
375
|
+
|
|
376
|
+
## 🏗️ Development
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# Install dependencies
|
|
380
|
+
pnpm install
|
|
381
|
+
|
|
382
|
+
# Development with watch mode
|
|
383
|
+
pnpm dev
|
|
384
|
+
|
|
385
|
+
# Build package
|
|
386
|
+
pnpm build
|
|
387
|
+
|
|
388
|
+
# Testing
|
|
389
|
+
pnpm test # Run tests once
|
|
390
|
+
pnpm test:watch # Run tests in watch mode
|
|
391
|
+
pnpm test:coverage # Run tests with coverage
|
|
392
|
+
pnpm test:ui # Run tests with UI
|
|
393
|
+
|
|
394
|
+
# Code quality
|
|
395
|
+
pnpm lint # Lint code
|
|
396
|
+
pnpm lint:fix # Lint and fix issues
|
|
397
|
+
pnpm format # Format code
|
|
398
|
+
pnpm format:check # Check formatting
|
|
399
|
+
pnpm type:check # Type checking
|
|
400
|
+
|
|
401
|
+
# Security
|
|
402
|
+
pnpm security:check # Run security audit
|
|
403
|
+
pnpm audit:fix # Fix security issues
|
|
404
|
+
|
|
405
|
+
# Clean build artifacts
|
|
406
|
+
pnpm clean
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### TypeScript Path Aliases
|
|
410
|
+
|
|
411
|
+
The package uses TypeScript path aliases for cleaner imports:
|
|
412
|
+
|
|
413
|
+
**Before:**
|
|
414
|
+
```typescript
|
|
415
|
+
import { CacheManager } from '../../cache';
|
|
416
|
+
import { FeatureFlagEngine } from '../../../engine/featureFlags/engine';
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**After:**
|
|
420
|
+
```typescript
|
|
421
|
+
import { CacheManager } from '@cache/index';
|
|
422
|
+
import { FeatureFlagEngine } from '@engine/featureFlags/engine';
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**Available aliases:**
|
|
426
|
+
- `@/*` → `src/*`
|
|
427
|
+
- `@domain/*` → `src/domain/*`
|
|
428
|
+
- `@engine/*` → `src/engine/*`
|
|
429
|
+
- `@backend/*` → `src/backend/*`
|
|
430
|
+
- `@frontend/*` → `src/frontend/*`
|
|
431
|
+
- `@cache/*` → `src/cache/*`
|
|
432
|
+
- `@utils/*` → `src/utils/*`
|
|
433
|
+
- `@tests/*` → `tests/*`
|
|
434
|
+
|
|
435
|
+
**Important:** When importing from index files, always specify `/index` explicitly (e.g., `@cache/index` not `@cache`).
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
**Note**: This package is part of the Plyaz monorepo architecture. See the [full documentation](https://plyaz.atlassian.net/wiki/spaces/SD/pages/37257227/Core+Package) for complete implementation details and architectural decisions.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Flag Controller
|
|
3
|
+
*
|
|
4
|
+
* NestJS controller for feature flag management.
|
|
5
|
+
* Provides REST API endpoints for feature flag operations.
|
|
6
|
+
*
|
|
7
|
+
* @fileoverview NestJS controller for feature flags
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
import type { FeatureFlagValue, FeatureFlagContext, FeatureFlagEvaluation, FeatureFlag, FeatureFlagRule } from '@plyaz/types';
|
|
11
|
+
import type { FeatureFlagService } from './feature-flag.service';
|
|
12
|
+
import type { FeatureFlagKey } from '@domain/types';
|
|
13
|
+
/**
|
|
14
|
+
* Request DTO for flag evaluation.
|
|
15
|
+
*/
|
|
16
|
+
interface EvaluateFlagRequest {
|
|
17
|
+
context?: FeatureFlagContext;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Request DTO for creating/updating flags.
|
|
21
|
+
*/
|
|
22
|
+
interface CreateFlagRequest {
|
|
23
|
+
name: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
value: FeatureFlagValue;
|
|
26
|
+
isEnabled?: boolean;
|
|
27
|
+
environment?: 'all' | 'development' | 'staging' | 'production';
|
|
28
|
+
rolloutPercentage?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Feature Flag Controller
|
|
32
|
+
*
|
|
33
|
+
* Provides REST endpoints for feature flag management and evaluation.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* // GET /feature-flags/AUTH_GOOGLE/evaluate
|
|
38
|
+
* // POST /feature-flags
|
|
39
|
+
* // PUT /feature-flags/AUTH_GOOGLE
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare class FeatureFlagController {
|
|
43
|
+
private readonly featureFlagService;
|
|
44
|
+
constructor(featureFlagService: FeatureFlagService);
|
|
45
|
+
/**
|
|
46
|
+
* Evaluates a feature flag for the given context.
|
|
47
|
+
*
|
|
48
|
+
* @param key - Feature flag key
|
|
49
|
+
* @param body - Evaluation context
|
|
50
|
+
* @returns Feature flag evaluation result
|
|
51
|
+
*/
|
|
52
|
+
evaluateFlag(key: FeatureFlagKey, body?: EvaluateFlagRequest): Promise<FeatureFlagEvaluation<FeatureFlagKey>>;
|
|
53
|
+
/**
|
|
54
|
+
* Checks if a feature flag is enabled.
|
|
55
|
+
*
|
|
56
|
+
* @param key - Feature flag key
|
|
57
|
+
* @param body - Evaluation context
|
|
58
|
+
* @returns Boolean indicating if flag is enabled
|
|
59
|
+
*/
|
|
60
|
+
isEnabled(key: FeatureFlagKey, body?: EvaluateFlagRequest): Promise<{
|
|
61
|
+
isEnabled: boolean;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Gets all feature flags with their evaluations.
|
|
65
|
+
*
|
|
66
|
+
* @param body - Evaluation context
|
|
67
|
+
* @returns All feature flag evaluations
|
|
68
|
+
*/
|
|
69
|
+
evaluateAllFlags(body?: EvaluateFlagRequest): Promise<Record<string, FeatureFlagEvaluation<FeatureFlagKey>>>;
|
|
70
|
+
/**
|
|
71
|
+
* Creates a new feature flag.
|
|
72
|
+
*
|
|
73
|
+
* @param key - Feature flag key
|
|
74
|
+
* @param createData - Flag creation data
|
|
75
|
+
* @returns Created feature flag
|
|
76
|
+
*/
|
|
77
|
+
createFlag(createData: CreateFlagRequest & {
|
|
78
|
+
key: FeatureFlagKey;
|
|
79
|
+
}): Promise<FeatureFlag<FeatureFlagKey>>;
|
|
80
|
+
/**
|
|
81
|
+
* Updates an existing feature flag.
|
|
82
|
+
*
|
|
83
|
+
* @param key - Feature flag key
|
|
84
|
+
* @param updateData - Flag update data
|
|
85
|
+
* @returns Updated feature flag
|
|
86
|
+
*/
|
|
87
|
+
updateFlag(key: FeatureFlagKey, updateData: Partial<CreateFlagRequest>): Promise<FeatureFlag<FeatureFlagKey>>;
|
|
88
|
+
/**
|
|
89
|
+
* Deletes a feature flag.
|
|
90
|
+
*
|
|
91
|
+
* @param key - Feature flag key
|
|
92
|
+
*/
|
|
93
|
+
deleteFlag(key: FeatureFlagKey): Promise<{
|
|
94
|
+
isSuccessful: boolean;
|
|
95
|
+
}>;
|
|
96
|
+
/**
|
|
97
|
+
* Sets a manual override for a flag.
|
|
98
|
+
*
|
|
99
|
+
* @param key - Feature flag key
|
|
100
|
+
* @param value - Override value
|
|
101
|
+
*/
|
|
102
|
+
setOverride(key: FeatureFlagKey, value: FeatureFlagValue): Promise<{
|
|
103
|
+
isSuccessful: boolean;
|
|
104
|
+
}>;
|
|
105
|
+
/**
|
|
106
|
+
* Removes a manual override for a flag.
|
|
107
|
+
*
|
|
108
|
+
* @param key - Feature flag key
|
|
109
|
+
*/
|
|
110
|
+
removeOverride(key: FeatureFlagKey): Promise<{
|
|
111
|
+
isSuccessful: boolean;
|
|
112
|
+
}>;
|
|
113
|
+
/**
|
|
114
|
+
* Gets all available feature flags.
|
|
115
|
+
*
|
|
116
|
+
* @param environment - Filter by environment
|
|
117
|
+
* @returns List of feature flags
|
|
118
|
+
*/
|
|
119
|
+
getAllFeatureFlags(environment?: string): Promise<FeatureFlag<FeatureFlagKey>[]>;
|
|
120
|
+
/**
|
|
121
|
+
* Gets all rules for a specific flag.
|
|
122
|
+
*
|
|
123
|
+
* @param key - Feature flag key
|
|
124
|
+
* @returns List of rules for the flag
|
|
125
|
+
*/
|
|
126
|
+
getFlagRules(key: FeatureFlagKey): Promise<FeatureFlagRule<FeatureFlagKey>[]>;
|
|
127
|
+
/**
|
|
128
|
+
* Forces a refresh of the feature flag cache.
|
|
129
|
+
*/
|
|
130
|
+
refreshCache(): Promise<{
|
|
131
|
+
isSuccessful: boolean;
|
|
132
|
+
}>;
|
|
133
|
+
}
|
|
134
|
+
export {};
|
|
135
|
+
//# sourceMappingURL=feature-flag.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-flag.controller.d.ts","sourceRoot":"","sources":["../../../src/backend/featureFlags/feature-flag.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;GAEG;AACH,UAAU,mBAAmB;IAC3B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;GAEG;AACH,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,KAAK,GAAG,aAAa,GAAG,SAAS,GAAG,YAAY,CAAC;IAC/D,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,qBACa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,kBAAkB;IAEnE;;;;;;OAMG;IAEG,YAAY,CACF,GAAG,EAAE,cAAc,EACzB,IAAI,GAAE,mBAAwB,GACrC,OAAO,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC;IAWjD;;;;;;OAMG;IAEG,SAAS,CACC,GAAG,EAAE,cAAc,EACzB,IAAI,GAAE,mBAAwB,GACrC,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAYlC;;;;;OAKG;IAEG,gBAAgB,CACZ,IAAI,GAAE,mBAAwB,GACrC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAC,CAAC;IAWjE;;;;;;OAMG;IAEG,UAAU,CACN,UAAU,EAAE,iBAAiB,GAAG;QAAE,GAAG,EAAE,cAAc,CAAA;KAAE,GAC9D,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IAWvC;;;;;;OAMG;IAEG,UAAU,CACA,GAAG,EAAE,cAAc,EACzB,UAAU,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAC7C,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IAWvC;;;;OAIG;IAEG,UAAU,CAAe,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAYvF;;;;;OAKG;IAEG,WAAW,CACD,GAAG,EAAE,cAAc,EAClB,KAAK,EAAE,gBAAgB,GACrC,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAYrC;;;;OAIG;IAEG,cAAc,CAAe,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAY3F;;;;;OAKG;IAEG,kBAAkB,CACA,WAAW,CAAC,EAAE,MAAM,GACzC,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;IAWzC;;;;;OAKG;IAEG,YAAY,CACF,GAAG,EAAE,cAAc,GAChC,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,CAAC;IAW7C;;OAEG;IAEG,YAAY,IAAI,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;CAWzD"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Flag Module
|
|
3
|
+
*
|
|
4
|
+
* NestJS module for feature flag functionality.
|
|
5
|
+
* Configures providers, controllers, and dependencies.
|
|
6
|
+
*
|
|
7
|
+
* @fileoverview NestJS module for feature flags
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Feature Flag Module
|
|
12
|
+
*
|
|
13
|
+
* Provides feature flag functionality as a NestJS module.
|
|
14
|
+
* Can be imported by other modules to access feature flag services.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // In your app.module.ts
|
|
19
|
+
* import { FeatureFlagModule } from '@plyaz/config/backend/featureFlags';
|
|
20
|
+
*
|
|
21
|
+
* @Module({
|
|
22
|
+
* imports: [FeatureFlagModule],
|
|
23
|
+
* // ... other module configuration
|
|
24
|
+
* })
|
|
25
|
+
* export class AppModule {}
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // In your service
|
|
31
|
+
* import { FeatureFlagService } from '@plyaz/config/backend/featureFlags';
|
|
32
|
+
*
|
|
33
|
+
* @Injectable()
|
|
34
|
+
* export class MyService {
|
|
35
|
+
* constructor(private readonly featureFlagService: FeatureFlagService) {}
|
|
36
|
+
*
|
|
37
|
+
* async doSomething() {
|
|
38
|
+
* const isEnabled = await this.featureFlagService.isEnabled('MY_FEATURE');
|
|
39
|
+
* if (isEnabled) {
|
|
40
|
+
* // Execute new feature logic
|
|
41
|
+
* }
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare class FeatureFlagModule {
|
|
47
|
+
/**
|
|
48
|
+
* Static method for importing the module with configuration.
|
|
49
|
+
* This allows customization of the feature flag system.
|
|
50
|
+
*
|
|
51
|
+
* @param options - Module configuration options
|
|
52
|
+
* @returns Configured module
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* @Module({
|
|
57
|
+
* imports: [
|
|
58
|
+
* FeatureFlagModule.forRoot({
|
|
59
|
+
* provider: 'redis',
|
|
60
|
+
* cacheEnabled: true,
|
|
61
|
+
* cacheTtl: 600,
|
|
62
|
+
* })
|
|
63
|
+
* ],
|
|
64
|
+
* })
|
|
65
|
+
* export class AppModule {}
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
static forRoot(options?: {
|
|
69
|
+
provider?: 'memory' | 'database' | 'redis' | 'api' | 'file';
|
|
70
|
+
isCacheEnabled?: boolean;
|
|
71
|
+
cacheTtl?: number;
|
|
72
|
+
refreshInterval?: number;
|
|
73
|
+
isLoggingEnabled?: boolean;
|
|
74
|
+
}): {
|
|
75
|
+
module: typeof FeatureFlagModule;
|
|
76
|
+
providers: unknown[];
|
|
77
|
+
exports: unknown[];
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Static method for importing the module asynchronously.
|
|
81
|
+
* Useful when configuration depends on other services.
|
|
82
|
+
*
|
|
83
|
+
* @param options - Async module configuration options
|
|
84
|
+
* @returns Configured async module
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* @Module({
|
|
89
|
+
* imports: [
|
|
90
|
+
* FeatureFlagModule.forRootAsync({
|
|
91
|
+
* imports: [ConfigModule],
|
|
92
|
+
* inject: [ConfigService],
|
|
93
|
+
* useFactory: (configService: ConfigService) => ({
|
|
94
|
+
* provider: configService.get('FEATURE_FLAG_PROVIDER'),
|
|
95
|
+
* cacheEnabled: configService.get('FEATURE_FLAG_CACHE_ENABLED'),
|
|
96
|
+
* }),
|
|
97
|
+
* })
|
|
98
|
+
* ],
|
|
99
|
+
* })
|
|
100
|
+
* export class AppModule {}
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
static forRootAsync(options: {
|
|
104
|
+
imports?: unknown[];
|
|
105
|
+
inject?: unknown[];
|
|
106
|
+
useFactory?: (...args: unknown[]) => unknown;
|
|
107
|
+
}): {
|
|
108
|
+
module: typeof FeatureFlagModule;
|
|
109
|
+
imports: unknown[];
|
|
110
|
+
providers: unknown[];
|
|
111
|
+
exports: unknown[];
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=feature-flag.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-flag.module.d.ts","sourceRoot":"","sources":["../../../src/backend/featureFlags/feature-flag.module.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAMa,iBAAiB;IAC5B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QACvB,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;QAC5D,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,GAAG;QACF,MAAM,EAAE,OAAO,iBAAiB,CAAC;QACjC,SAAS,EAAE,OAAO,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,EAAE,CAAC;KACpB;IAiBD;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE;QAC3B,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;QACpB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;QACnB,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;KAC9C,GAAG;QACF,MAAM,EAAE,OAAO,iBAAiB,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,CAAC;QACnB,SAAS,EAAE,OAAO,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,EAAE,CAAC;KACpB;CAgBF"}
|