@plyaz/core 1.1.0 → 1.2.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.
Files changed (65) hide show
  1. package/dist/backend/featureFlags/config/feature-flag.config.d.ts +111 -0
  2. package/dist/backend/featureFlags/config/feature-flag.config.d.ts.map +1 -0
  3. package/dist/backend/featureFlags/config/validation.d.ts +181 -0
  4. package/dist/backend/featureFlags/config/validation.d.ts.map +1 -0
  5. package/dist/backend/featureFlags/database/connection.d.ts +321 -0
  6. package/dist/backend/featureFlags/database/connection.d.ts.map +1 -0
  7. package/dist/backend/featureFlags/database/repository.d.ts +518 -0
  8. package/dist/backend/featureFlags/database/repository.d.ts.map +1 -0
  9. package/dist/backend/featureFlags/decorators/feature-disabled.decorator.d.ts +6 -0
  10. package/dist/backend/featureFlags/decorators/feature-disabled.decorator.d.ts.map +1 -0
  11. package/dist/backend/featureFlags/decorators/feature-enabled.decorator.d.ts +8 -0
  12. package/dist/backend/featureFlags/decorators/feature-enabled.decorator.d.ts.map +1 -0
  13. package/dist/backend/featureFlags/decorators/feature-flag.decorator.d.ts +11 -0
  14. package/dist/backend/featureFlags/decorators/feature-flag.decorator.d.ts.map +1 -0
  15. package/dist/backend/featureFlags/feature-flag.controller.d.ts +1 -2
  16. package/dist/backend/featureFlags/feature-flag.controller.d.ts.map +1 -1
  17. package/dist/backend/featureFlags/feature-flag.module.d.ts +2 -3
  18. package/dist/backend/featureFlags/feature-flag.module.d.ts.map +1 -1
  19. package/dist/backend/featureFlags/feature-flag.service.d.ts +149 -8
  20. package/dist/backend/featureFlags/feature-flag.service.d.ts.map +1 -1
  21. package/dist/backend/featureFlags/guards/feature-flag.guard.d.ts +19 -0
  22. package/dist/backend/featureFlags/guards/feature-flag.guard.d.ts.map +1 -0
  23. package/dist/backend/featureFlags/index.d.ts +10 -36
  24. package/dist/backend/featureFlags/index.d.ts.map +1 -1
  25. package/dist/backend/featureFlags/interceptors/error-handling-interceptor.d.ts +16 -0
  26. package/dist/backend/featureFlags/interceptors/error-handling-interceptor.d.ts.map +1 -0
  27. package/dist/backend/featureFlags/interceptors/feature-flag-logging-interceptor.d.ts +18 -0
  28. package/dist/backend/featureFlags/interceptors/feature-flag-logging-interceptor.d.ts.map +1 -0
  29. package/dist/backend/featureFlags/middleware/feature-flag-middleware.d.ts +167 -0
  30. package/dist/backend/featureFlags/middleware/feature-flag-middleware.d.ts.map +1 -0
  31. package/dist/base/cache/feature/caching.d.ts +16 -0
  32. package/dist/base/cache/feature/caching.d.ts.map +1 -0
  33. package/dist/base/cache/index.d.ts +1 -0
  34. package/dist/base/cache/index.d.ts.map +1 -1
  35. package/dist/domain/featureFlags/providers/database.d.ts +17 -12
  36. package/dist/domain/featureFlags/providers/database.d.ts.map +1 -1
  37. package/dist/frontend/index.d.ts +1 -0
  38. package/dist/frontend/index.d.ts.map +1 -1
  39. package/dist/frontend/providers/ApiProvider.d.ts +41 -0
  40. package/dist/frontend/providers/ApiProvider.d.ts.map +1 -0
  41. package/dist/frontend/providers/index.d.ts +7 -0
  42. package/dist/frontend/providers/index.d.ts.map +1 -0
  43. package/dist/index.cjs +2325 -273
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.mjs +2315 -275
  48. package/dist/index.mjs.map +1 -1
  49. package/dist/services/ApiClientService.d.ts +90 -0
  50. package/dist/services/ApiClientService.d.ts.map +1 -0
  51. package/dist/services/index.d.ts +8 -0
  52. package/dist/services/index.d.ts.map +1 -0
  53. package/dist/utils/common/index.d.ts +1 -1
  54. package/dist/utils/common/index.d.ts.map +1 -1
  55. package/dist/utils/common/validation.d.ts +20 -0
  56. package/dist/utils/common/validation.d.ts.map +1 -0
  57. package/dist/utils/db/databaseService.d.ts +6 -0
  58. package/dist/utils/db/databaseService.d.ts.map +1 -0
  59. package/dist/utils/db/index.d.ts +2 -0
  60. package/dist/utils/db/index.d.ts.map +1 -0
  61. package/dist/web_app/auth/add_user.d.ts +3 -0
  62. package/dist/web_app/auth/add_user.d.ts.map +1 -0
  63. package/dist/web_app/auth/update_user.d.ts +2 -0
  64. package/dist/web_app/auth/update_user.d.ts.map +1 -0
  65. package/package.json +20 -7
@@ -0,0 +1,518 @@
1
+ /**
2
+ * Database Repository Implementation
3
+ *
4
+ * Database adapter integration with @plyaz/db for feature flag storage.
5
+ * Provides optimized queries and transaction management.
6
+ *
7
+ * @fileoverview Database repository for feature flags
8
+ */
9
+ import { type FeatureFlag, type FeatureFlagRule, type FeatureFlagValue, type CreateFlagRequest, type FeatureFlagContext } from '@plyaz/types';
10
+ import type { FeatureFlagKey } from '@domain/types';
11
+ /**
12
+ * Database Repository for Feature Flags
13
+ *
14
+ * **FOURTH COMPONENT CALLED** - Handles all database operations for feature flags
15
+ *
16
+ * **EXECUTION ORDER:**
17
+ * 1. FeatureFlagService.onModuleInit()
18
+ * 2. → FeatureFlagConfigFactory.fromEnvironment()
19
+ * 3. → DatabaseConnectionManager.initialize()
20
+ * 4. → **THIS REPOSITORY USED** ← YOU ARE HERE
21
+ * 5. → Database queries executed via Drizzle ORM
22
+ *
23
+ * **PURPOSE:**
24
+ * - Executes optimized SQL queries using Drizzle ORM
25
+ * - Maps database rows to TypeScript types
26
+ * - Handles CRUD operations for flags, rules, evaluations, and overrides
27
+ * - Provides audit logging and user override functionality
28
+ *
29
+ * **PERFORMANCE FEATURES:**
30
+ * - Uses database indexes for fast queries
31
+ * - Batch operations where possible
32
+ * - Connection pooling via DatabaseConnectionManager
33
+ * - Optimized queries with proper WHERE clauses and ordering
34
+ *
35
+ * @template TKey - Feature flag key type (extends string)
36
+ *
37
+ * @example Basic Usage (automatically called by provider):
38
+ * ```typescript
39
+ * const repository = new FeatureFlagDatabaseRepository();
40
+ *
41
+ * // Get all flags (called during system initialization)
42
+ * const flags = await repository.getAllFlags();
43
+ *
44
+ * // Get specific flag (called during runtime evaluation)
45
+ * const flag = await repository.getFlag('PREMIUM_FEATURE');
46
+ *
47
+ * // Create new flag (called via admin API)
48
+ * const newFlag = await repository.createFlag({
49
+ * key: 'NEW_FEATURE',
50
+ * value: true,
51
+ * isEnabled: true,
52
+ * description: 'New awesome feature'
53
+ * });
54
+ * ```
55
+ *
56
+ * @example Query Performance:
57
+ * ```sql
58
+ * -- Optimized queries with indexes:
59
+ * SELECT * FROM feature_flags WHERE key = 'PREMIUM_FEATURE'; -- Uses primary key index
60
+ * SELECT * FROM feature_flag_rules WHERE flag_key = 'PREMIUM_FEATURE' AND is_enabled = true ORDER BY priority DESC; -- Uses composite index
61
+ * ```
62
+ */
63
+ export declare class FeatureFlagDatabaseRepository<TKey extends string = FeatureFlagKey> {
64
+ private connectionManager;
65
+ /**
66
+ * Retrieves all feature flags from the database with optional environment filtering
67
+ *
68
+ * @description Fetches all feature flags from the database. This method is primarily called
69
+ * during system initialization to load flags into cache, but can also be used for
70
+ * administrative purposes or cache refresh operations.
71
+ *
72
+ * @param {string} [environment] - Optional environment filter (e.g., 'production', 'staging')
73
+ * @returns {Promise<FeatureFlag<TKey>[]>} Array of feature flags matching the criteria
74
+ *
75
+ * @throws {Error} When database query fails critically
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // Get all flags for system initialization
80
+ * const repository = new FeatureFlagDatabaseRepository();
81
+ * const allFlags = await repository.getAllFlags();
82
+ * console.log(`Loaded ${allFlags.length} feature flags`);
83
+ *
84
+ * // Get only production flags
85
+ * const prodFlags = await repository.getAllFlags('production');
86
+ * console.log(`Production flags: ${prodFlags.length}`);
87
+ *
88
+ * // Handle empty results
89
+ * const flags = await repository.getAllFlags('nonexistent');
90
+ * if (flags.length === 0) {
91
+ * console.log('No flags found for environment');
92
+ * }
93
+ * ```
94
+ *
95
+ */
96
+ getAllFlags(environment?: string): Promise<FeatureFlag<TKey>[]>;
97
+ /**
98
+ * Retrieves a specific feature flag by its key
99
+ *
100
+ * @description Fetches a single feature flag from the database using its unique key.
101
+ * This method is optimized for runtime flag evaluation and uses the primary key index
102
+ * for O(1) lookup performance.
103
+ *
104
+ * @param {TKey} key - The unique identifier of the feature flag to retrieve
105
+ * @returns {Promise<FeatureFlag<TKey> | null>} The feature flag object or null if not found
106
+ *
107
+ * @throws {Error} When database operation fails
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const repository = new FeatureFlagDatabaseRepository();
112
+ *
113
+ * // Get a specific flag for evaluation
114
+ * const premiumFlag = await repository.getFlag('PREMIUM_FEATURE');
115
+ * if (premiumFlag) {
116
+ * console.log(`Flag enabled: ${premiumFlag.isEnabled}`);
117
+ * console.log(`Flag value:`, premiumFlag.value);
118
+ * } else {
119
+ * console.log('Flag not found');
120
+ * }
121
+ *
122
+ * // Handle flag evaluation
123
+ * const checkoutFlag = await repository.getFlag('NEW_CHECKOUT');
124
+ * const isNewCheckoutEnabled = checkoutFlag?.isEnabled ?? false;
125
+ * ```
126
+ *
127
+ */
128
+ getFlag(key: TKey): Promise<FeatureFlag<TKey> | null>;
129
+ /**
130
+ * Creates a new feature flag in the database
131
+ *
132
+ * @description Creates a new feature flag record with the provided configuration.
133
+ * This method is typically called through administrative interfaces or during
134
+ * system setup and migration processes.
135
+ *
136
+ * @param {CreateFlagRequest<TKey>} data - The feature flag creation data
137
+ * @returns {Promise<FeatureFlag<TKey>>} The created feature flag object
138
+ *
139
+ * @throws {Error} When flag key already exists (primary key constraint violation)
140
+ * @throws {Error} When database operation fails
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const repository = new FeatureFlagDatabaseRepository();
145
+ *
146
+ * // Create a simple boolean flag
147
+ * const simpleFlag = await repository.createFlag({
148
+ * key: 'ENABLE_DARK_MODE',
149
+ * value: true,
150
+ * isEnabled: true,
151
+ * environment: 'production',
152
+ * description: 'Enable dark mode theme'
153
+ * });
154
+ *
155
+ * // Create a complex flag with object value
156
+ * const complexFlag = await repository.createFlag({
157
+ * key: 'CHECKOUT_CONFIG',
158
+ * value: {
159
+ * variant: 'blue',
160
+ * showPromo: true,
161
+ * maxItems: 10
162
+ * },
163
+ * isEnabled: false,
164
+ * environment: 'staging',
165
+ * description: 'Checkout page configuration'
166
+ * });
167
+ *
168
+ * console.log(`Created flag: ${simpleFlag.key}`);
169
+ * ```
170
+ *
171
+ */
172
+ createFlag(data: CreateFlagRequest<TKey>): Promise<FeatureFlag<TKey>>;
173
+ /**
174
+ * Updates an existing feature flag in the database
175
+ *
176
+ * @description Updates specific fields of an existing feature flag. Only provided
177
+ * fields will be updated, leaving other fields unchanged. The updated_at timestamp
178
+ * is automatically set to the current time.
179
+ *
180
+ * @param {TKey} key - The unique identifier of the feature flag to update
181
+ * @param {Partial<CreateFlagRequest<TKey>>} data - Partial flag data to update
182
+ * @returns {Promise<FeatureFlag<TKey>>} The updated feature flag object
183
+ *
184
+ * @throws {Error} When flag with the specified key is not found
185
+ * @throws {Error} When database operation fails
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * const repository = new FeatureFlagDatabaseRepository();
190
+ *
191
+ * // Enable a flag
192
+ * const enabledFlag = await repository.updateFlag('BETA_FEATURE', {
193
+ * isEnabled: true
194
+ * });
195
+ *
196
+ * // Update flag value and description
197
+ * const updatedFlag = await repository.updateFlag('CHECKOUT_CONFIG', {
198
+ * value: { variant: 'green', showPromo: false },
199
+ * description: 'Updated checkout configuration'
200
+ * });
201
+ *
202
+ * // Change environment
203
+ * const prodFlag = await repository.updateFlag('NEW_FEATURE', {
204
+ * environment: 'production'
205
+ * });
206
+ *
207
+ * console.log(`Updated flag: ${updatedFlag.key}`);
208
+ * ```
209
+ *
210
+ */
211
+ updateFlag(key: TKey, data: Partial<CreateFlagRequest<TKey>>): Promise<FeatureFlag<TKey>>;
212
+ /**
213
+ * Deletes a feature flag from the database
214
+ *
215
+ * @description Permanently removes a feature flag from the database. This operation
216
+ * cannot be undone. All associated rules, evaluations, and overrides should be
217
+ * cleaned up separately if needed.
218
+ *
219
+ * @param {TKey} key - The unique identifier of the feature flag to delete
220
+ * @returns {Promise<void>} Promise that resolves when deletion is complete
221
+ *
222
+ * @throws {Error} When flag with the specified key is not found
223
+ * @throws {Error} When database operation fails
224
+ *
225
+ * @example
226
+ * ```typescript
227
+ * const repository = new FeatureFlagDatabaseRepository();
228
+ *
229
+ * // Delete a flag
230
+ * try {
231
+ * await repository.deleteFlag('OLD_FEATURE');
232
+ * console.log('Flag deleted successfully');
233
+ * } catch (error) {
234
+ * console.error('Failed to delete flag:', error.message);
235
+ * }
236
+ *
237
+ * // Verify deletion
238
+ * const deletedFlag = await repository.getFlag('OLD_FEATURE');
239
+ * console.log(deletedFlag === null); // true
240
+ * ```
241
+ *
242
+ */
243
+ deleteFlag(key: TKey): Promise<void>;
244
+ /**
245
+ * Retrieves all rules associated with a specific feature flag
246
+ *
247
+ * @description Fetches all rules configured for a specific feature flag, ordered by
248
+ * priority in descending order. Rules are used for advanced flag evaluation logic
249
+ * based on user context and conditions.
250
+ *
251
+ * @param {TKey} key - The feature flag key to get rules for
252
+ * @returns {Promise<FeatureFlagRule<TKey>[]>} Array of rules for the specified flag
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * const repository = new FeatureFlagDatabaseRepository();
257
+ *
258
+ * // Get rules for a flag
259
+ * const rules = await repository.getFlagRules('PREMIUM_FEATURE');
260
+ * console.log(`Found ${rules.length} rules`);
261
+ *
262
+ * // Process rules by priority
263
+ * rules.forEach(rule => {
264
+ * console.log(`Rule: ${rule.name}, Priority: ${rule.priority}`);
265
+ * });
266
+ * ```
267
+ *
268
+ */
269
+ getFlagRules(key: TKey): Promise<FeatureFlagRule<TKey>[]>;
270
+ /**
271
+ * Retrieves all enabled feature flag rules from the database
272
+ *
273
+ * @description Fetches all enabled rules across all feature flags, sorted by flag key
274
+ * and then by priority. This method is used during system initialization to load
275
+ * all active rules into the evaluation engine.
276
+ *
277
+ * @returns {Promise<FeatureFlagRule<TKey>[]>} Array of all enabled rules
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const repository = new FeatureFlagDatabaseRepository();
282
+ *
283
+ * // Load all rules for evaluation engine
284
+ * const allRules = await repository.getAllRules();
285
+ * console.log(`Loaded ${allRules.length} active rules`);
286
+ *
287
+ * // Group rules by flag
288
+ * const rulesByFlag = allRules.reduce((acc, rule) => {
289
+ * if (!acc[rule.flagKey]) acc[rule.flagKey] = [];
290
+ * acc[rule.flagKey].push(rule);
291
+ * return acc;
292
+ * }, {});
293
+ * ```
294
+ *
295
+ */
296
+ getAllRules(): Promise<FeatureFlagRule<TKey>[]>;
297
+ /**
298
+ * Logs a feature flag evaluation for audit and analytics purposes
299
+ *
300
+ * @description Records feature flag evaluation events for compliance tracking,
301
+ * debugging, and analytics. This method is called after each flag evaluation
302
+ * when audit logging is enabled.
303
+ *
304
+ * @param {Object} params - The evaluation parameters
305
+ * @param {TKey} params.flagKey - The feature flag key that was evaluated
306
+ * @param {string} [params.userId] - Optional user ID who triggered the evaluation
307
+ * @param {FeatureFlagContext} [params.context] - Optional evaluation context
308
+ * @param {FeatureFlagValue} params.result - The evaluation result
309
+ * @returns {Promise<void>} Promise that resolves when log entry is created
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * const repository = new FeatureFlagDatabaseRepository();
314
+ *
315
+ * // Log a user evaluation
316
+ * await repository.logEvaluation({
317
+ * flagKey: 'PREMIUM_FEATURE',
318
+ * userId: 'user123',
319
+ * context: {
320
+ * userRole: 'premium',
321
+ * environment: 'production',
322
+ * requestId: 'req-456'
323
+ * },
324
+ * result: true
325
+ * });
326
+ *
327
+ * // Log anonymous evaluation
328
+ * await repository.logEvaluation({
329
+ * flagKey: 'PUBLIC_FEATURE',
330
+ * result: { variant: 'blue', enabled: true }
331
+ * });
332
+ * ```
333
+ *
334
+ */
335
+ logEvaluation(params: {
336
+ flagKey: TKey;
337
+ userId?: string;
338
+ context?: FeatureFlagContext;
339
+ result: FeatureFlagValue;
340
+ }): Promise<void>;
341
+ /**
342
+ * Sets a user-specific override for a feature flag
343
+ *
344
+ * @description Creates a user-specific override that takes precedence over the
345
+ * default flag value and rules. Overrides can have optional expiration times
346
+ * and are useful for testing, gradual rollouts, or user-specific configurations.
347
+ *
348
+ * @param {TKey} flagKey - The feature flag key to override
349
+ * @param {string} userId - The user ID for whom to set the override
350
+ * @param {FeatureFlagValue} value - The override value
351
+ * @param {Date} [expiresAt] - Optional expiration date for the override
352
+ * @returns {Promise<void>} Promise that resolves when override is created
353
+ *
354
+ * @example
355
+ * ```typescript
356
+ * const repository = new FeatureFlagDatabaseRepository();
357
+ *
358
+ * // Set permanent override
359
+ * await repository.setOverride(
360
+ * 'BETA_FEATURE',
361
+ * 'user123',
362
+ * true
363
+ * );
364
+ *
365
+ * // Set temporary override (expires in 1 hour)
366
+ * const expiresAt = new Date(Date.now() + 60 * 60 * 1000);
367
+ * await repository.setOverride(
368
+ * 'PREMIUM_FEATURE',
369
+ * 'testuser456',
370
+ * { enabled: true, variant: 'premium' },
371
+ * expiresAt
372
+ * );
373
+ * ```
374
+ *
375
+ */
376
+ setOverride(flagKey: TKey, userId: string, value: FeatureFlagValue, expiresAt?: Date): Promise<void>;
377
+ /**
378
+ * Retrieves a user-specific override for a feature flag
379
+ *
380
+ * @description Fetches the override value for a specific user and flag combination.
381
+ * Automatically filters out expired overrides. Returns null if no valid override
382
+ * exists for the user.
383
+ *
384
+ * @param {TKey} flagKey - The feature flag key to check for overrides
385
+ * @param {string} userId - The user ID to get the override for
386
+ * @returns {Promise<FeatureFlagValue | null>} The override value or null if none exists
387
+ *
388
+ * @example
389
+ * ```typescript
390
+ * const repository = new FeatureFlagDatabaseRepository();
391
+ *
392
+ * // Check for user override
393
+ * const override = await repository.getOverride('BETA_FEATURE', 'user123');
394
+ * if (override !== null) {
395
+ * console.log('User has override:', override);
396
+ * } else {
397
+ * console.log('No override found, using default flag value');
398
+ * }
399
+ *
400
+ * // Use in flag evaluation
401
+ * const userOverride = await repository.getOverride('PREMIUM_FEATURE', userId);
402
+ * const flagValue = userOverride ?? defaultFlagValue;
403
+ * ```
404
+ *
405
+ */
406
+ getOverride(flagKey: TKey, userId: string): Promise<FeatureFlagValue | null>;
407
+ /**
408
+ * Removes user-specific overrides for a feature flag
409
+ *
410
+ * @description Deletes all override records for a specific user and flag combination.
411
+ * This operation cannot be undone and will cause the user to receive the default
412
+ * flag value or rule-based evaluation on subsequent requests.
413
+ *
414
+ * @param {TKey} flagKey - The feature flag key to remove overrides for
415
+ * @param {string} userId - The user ID to remove overrides for
416
+ * @returns {Promise<void>} Promise that resolves when overrides are removed
417
+ *
418
+ * @example
419
+ * ```typescript
420
+ * const repository = new FeatureFlagDatabaseRepository();
421
+ *
422
+ * // Remove user override
423
+ * await repository.removeOverride('BETA_FEATURE', 'user123');
424
+ * console.log('Override removed, user will get default flag value');
425
+ *
426
+ * // Verify removal
427
+ * const override = await repository.getOverride('BETA_FEATURE', 'user123');
428
+ * console.log(override === null); // true
429
+ *
430
+ * // Bulk cleanup - remove overrides for multiple users
431
+ * const userIds = ['user1', 'user2', 'user3'];
432
+ * for (const userId of userIds) {
433
+ * await repository.removeOverride('OLD_FEATURE', userId);
434
+ * }
435
+ * ```
436
+ *
437
+ */
438
+ removeOverride(flagKey: TKey, userId: string): Promise<void>;
439
+ /**
440
+ * Maps a database row to a FeatureFlag object
441
+ *
442
+ * @description Converts raw database row data to a properly typed FeatureFlag object.
443
+ * Handles field name variations between database schema and application types,
444
+ * provides default values for missing fields, and ensures type safety.
445
+ *
446
+ * @private
447
+ * @param {DatabaseFeatureFlagRow} row - Raw database row data
448
+ * @returns {FeatureFlag<TKey>} Typed FeatureFlag object
449
+ *
450
+ * @example
451
+ * ```typescript
452
+ * // Database row input:
453
+ * const dbRow = {
454
+ * key: 'PREMIUM_FEATURE',
455
+ * value: { enabled: true, variant: 'blue' },
456
+ * is_enabled: true,
457
+ * environments: ['production'],
458
+ * description: 'Premium feature toggle',
459
+ * created_at: '2024-01-15T10:30:00Z'
460
+ * };
461
+ *
462
+ * // Mapped output:
463
+ * const flag = this.mapToFeatureFlag(dbRow);
464
+ * // {
465
+ * // key: 'PREMIUM_FEATURE',
466
+ * // type: 'boolean',
467
+ * // name: 'PREMIUM_FEATURE',
468
+ * // value: { enabled: true, variant: 'blue' },
469
+ * // isEnabled: true,
470
+ * // environment: 'production',
471
+ * // description: 'Premium feature toggle',
472
+ * // createdAt: Date('2024-01-15T10:30:00Z'),
473
+ * // updatedAt: Date('2024-01-15T10:30:00Z'),
474
+ * // createdBy: 'system',
475
+ * // updatedBy: 'system'
476
+ * // }
477
+ * ```
478
+ *
479
+ */
480
+ private mapToFeatureFlag;
481
+ /**
482
+ * Extracts the enabled status from a database row
483
+ *
484
+ * @private
485
+ * @param {DatabaseFeatureFlagRow} row - Database row with enabled field variations
486
+ * @returns {boolean} The enabled status, defaulting to true if not specified
487
+ */
488
+ private getIsEnabled;
489
+ /**
490
+ * Extracts the creation date from a database row
491
+ *
492
+ * @private
493
+ * @param {DatabaseFeatureFlagRow} row - Database row with creation date field variations
494
+ * @returns {Date} The creation date, defaulting to current date if not specified
495
+ */
496
+ private getCreatedAt;
497
+ /**
498
+ * Extracts the update date from a database row
499
+ *
500
+ * @private
501
+ * @param {DatabaseFeatureFlagRow} row - Database row with update date field variations
502
+ * @returns {Date} The update date, defaulting to current date if not specified
503
+ */
504
+ private getUpdatedAt;
505
+ /**
506
+ * Maps a database row to a FeatureFlagRule object
507
+ *
508
+ * @description Converts raw database rule row data to a properly typed FeatureFlagRule object.
509
+ * Handles field name variations and ensures type safety for rule evaluation.
510
+ *
511
+ * @private
512
+ * @param {DatabaseFeatureFlagRuleRow} row - Raw database rule row data
513
+ * @returns {FeatureFlagRule<TKey>} Typed FeatureFlagRule object
514
+ *
515
+ */
516
+ private mapToFeatureFlagRule;
517
+ }
518
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../src/backend/featureFlags/database/repository.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAExB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAqBpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,qBAAa,6BAA6B,CAAC,IAAI,SAAS,MAAM,GAAG,cAAc;IAC7E,OAAO,CAAC,iBAAiB,CAA2C;IAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACG,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;IA+BrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACG,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAe3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACG,UAAU,CAAC,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAwB3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACG,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAoB/F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACG,UAAU,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1C;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACG,YAAY,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;IA+B/D;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;IA6BrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACG,aAAa,CAAC,MAAM,EAAE;QAC1B,OAAO,EAAE,IAAI,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,kBAAkB,CAAC;QAC7B,MAAM,EAAE,gBAAgB,CAAC;KAC1B,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACG,WAAW,CACf,OAAO,EAAE,IAAI,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,gBAAgB,EACvB,SAAS,CAAC,EAAE,IAAI,GACf,OAAO,CAAC,IAAI,CAAC;IAmBhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IA8BlF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACG,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACH,OAAO,CAAC,gBAAgB;IAgBxB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,oBAAoB;CAW7B"}
@@ -0,0 +1,6 @@
1
+ import type { FeatureFlagKey } from '@domain/types';
2
+ /**
3
+ * Shortcut decorator to require a feature flag to be disabled (false).
4
+ */
5
+ export declare function FeatureDisabled(key: FeatureFlagKey): MethodDecorator;
6
+ //# sourceMappingURL=feature-disabled.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-disabled.decorator.d.ts","sourceRoot":"","sources":["../../../../src/backend/featureFlags/decorators/feature-disabled.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,CAEpE"}
@@ -0,0 +1,8 @@
1
+ import type { FeatureFlagKey } from '@domain/types';
2
+ /**
3
+ * FeatureEnabled decorator
4
+ * Shorthand for enabling a feature flag with `true`
5
+ */
6
+ export declare function FeatureEnabled(key: FeatureFlagKey): MethodDecorator;
7
+ export {};
8
+ //# sourceMappingURL=feature-enabled.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-enabled.decorator.d.ts","sourceRoot":"","sources":["../../../../src/backend/featureFlags/decorators/feature-enabled.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,CAEnE;AAGD,OAAO,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { FeatureFlagValue } from '@plyaz/types';
2
+ import type { FeatureFlagKey } from '@domain/types';
3
+ /**
4
+ * Decorator to require a feature flag to be in a specific state
5
+ * before allowing access to the route handler.
6
+ *
7
+ * @param key - The feature flag key
8
+ * @param expected - Expected flag value (default: true)
9
+ */
10
+ export declare function FeatureFlag(key: FeatureFlagKey, expected?: FeatureFlagValue): MethodDecorator;
11
+ //# sourceMappingURL=feature-flag.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flag.decorator.d.ts","sourceRoot":"","sources":["../../../../src/backend/featureFlags/decorators/feature-flag.decorator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,cAAc,EACnB,QAAQ,GAAE,gBAAuB,GAChC,eAAe,CAEjB"}
@@ -5,9 +5,8 @@
5
5
  * Provides REST API endpoints for feature flag operations.
6
6
  *
7
7
  * @fileoverview NestJS controller for feature flags
8
- * @version 1.0.0
9
8
  */
10
- import type { FeatureFlagValue, FeatureFlagContext, FeatureFlagEvaluation, FeatureFlag, FeatureFlagRule } from '@plyaz/types';
9
+ import { type FeatureFlagValue, type FeatureFlagContext, type FeatureFlagEvaluation, type FeatureFlag, type FeatureFlagRule } from '@plyaz/types';
11
10
  import type { FeatureFlagService } from './feature-flag.service';
12
11
  import type { FeatureFlagKey } from '@domain/types';
13
12
  /**
@@ -1 +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"}
1
+ {"version":3,"file":"feature-flag.controller.d.ts","sourceRoot":"","sources":["../../../src/backend/featureFlags/feature-flag.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,eAAe,EAGrB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD;;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;IAYjD;;;;;;OAMG;IAEG,SAAS,CACC,GAAG,EAAE,cAAc,EACzB,IAAI,GAAE,mBAAwB,GACrC,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAalC;;;;;OAKG;IAEG,gBAAgB,CACZ,IAAI,GAAE,mBAAwB,GACrC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAC,CAAC;IAYjE;;;;;;OAMG;IAEG,UAAU,CACN,UAAU,EAAE,iBAAiB,GAAG;QAAE,GAAG,EAAE,cAAc,CAAA;KAAE,GAC9D,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IAYvC;;;;;;OAMG;IAEG,UAAU,CACA,GAAG,EAAE,cAAc,EACzB,UAAU,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAC7C,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IAYvC;;;;OAIG;IAEG,UAAU,CAAe,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAavF;;;;;OAKG;IAEG,WAAW,CACD,GAAG,EAAE,cAAc,EAClB,KAAK,EAAE,gBAAgB,GACrC,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAarC;;;;OAIG;IAEG,cAAc,CAAe,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAa3F;;;;;OAKG;IAEG,kBAAkB,CACA,WAAW,CAAC,EAAE,MAAM,GACzC,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;IAYzC;;;;;OAKG;IAEG,YAAY,CACF,GAAG,EAAE,cAAc,GAChC,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,CAAC;IAY7C;;OAEG;IAEG,YAAY,IAAI,OAAO,CAAC;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;CAYzD"}
@@ -5,7 +5,6 @@
5
5
  * Configures providers, controllers, and dependencies.
6
6
  *
7
7
  * @fileoverview NestJS module for feature flags
8
- * @version 1.0.0
9
8
  */
10
9
  /**
11
10
  * Feature Flag Module
@@ -56,8 +55,8 @@ export declare class FeatureFlagModule {
56
55
  * @Module({
57
56
  * imports: [
58
57
  * FeatureFlagModule.forRoot({
59
- * provider: 'redis',
60
- * cacheEnabled: true,
58
+ * provider: 'database',
59
+ * isCacheEnabled: true,
61
60
  * cacheTtl: 600,
62
61
  * })
63
62
  * ],
@@ -1 +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"}
1
+ {"version":3,"file":"feature-flag.module.d.ts","sourceRoot":"","sources":["../../../src/backend/featureFlags/feature-flag.module.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;IAkBD;;;;;;;;;;;;;;;;;;;;;;;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"}