@tamyla/clodo-framework 3.1.5 → 3.1.8

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 (62) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/bin/clodo-service.js +29 -947
  3. package/bin/database/enterprise-db-manager.js +7 -5
  4. package/bin/security/security-cli.js +0 -0
  5. package/bin/service-management/create-service.js +0 -0
  6. package/bin/service-management/init-service.js +0 -0
  7. package/bin/shared/cloudflare/domain-discovery.js +11 -10
  8. package/bin/shared/cloudflare/ops.js +1 -1
  9. package/bin/shared/config/ConfigurationManager.js +539 -0
  10. package/bin/shared/config/index.js +13 -1
  11. package/bin/shared/database/connection-manager.js +2 -2
  12. package/bin/shared/database/orchestrator.js +5 -4
  13. package/bin/shared/deployment/auditor.js +9 -8
  14. package/bin/shared/logging/Logger.js +214 -0
  15. package/bin/shared/monitoring/production-monitor.js +21 -9
  16. package/bin/shared/utils/ErrorHandler.js +675 -0
  17. package/bin/shared/utils/error-recovery.js +33 -13
  18. package/bin/shared/utils/file-manager.js +162 -0
  19. package/bin/shared/utils/formatters.js +247 -0
  20. package/bin/shared/utils/index.js +14 -4
  21. package/bin/shared/validation/ValidationRegistry.js +143 -0
  22. package/dist/deployment/auditor.js +23 -8
  23. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  24. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +401 -0
  25. package/dist/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  26. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  27. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  28. package/dist/deployment/orchestration/index.js +17 -0
  29. package/dist/index.js +12 -0
  30. package/dist/orchestration/modules/DomainResolver.js +8 -6
  31. package/dist/orchestration/multi-domain-orchestrator.js +13 -1
  32. package/dist/security/index.js +2 -2
  33. package/dist/service-management/ConfirmationEngine.js +8 -7
  34. package/dist/service-management/ErrorTracker.js +7 -2
  35. package/dist/service-management/InputCollector.js +18 -12
  36. package/dist/service-management/ServiceCreator.js +22 -7
  37. package/dist/service-management/ServiceInitializer.js +12 -18
  38. package/dist/shared/cloudflare/domain-discovery.js +11 -10
  39. package/dist/shared/cloudflare/ops.js +1 -1
  40. package/dist/shared/config/ConfigurationManager.js +519 -0
  41. package/dist/shared/config/index.js +5 -1
  42. package/dist/shared/database/connection-manager.js +2 -2
  43. package/dist/shared/database/orchestrator.js +13 -4
  44. package/dist/shared/deployment/auditor.js +23 -8
  45. package/dist/shared/logging/Logger.js +209 -0
  46. package/dist/shared/monitoring/production-monitor.js +24 -8
  47. package/dist/{utils → shared/utils}/ErrorHandler.js +306 -28
  48. package/dist/shared/utils/error-recovery.js +33 -13
  49. package/dist/shared/utils/file-manager.js +155 -0
  50. package/dist/shared/utils/formatters.js +215 -0
  51. package/dist/shared/utils/index.js +14 -4
  52. package/dist/shared/validation/ValidationRegistry.js +126 -0
  53. package/dist/utils/config/unified-config-manager.js +14 -12
  54. package/dist/utils/deployment/config-cache.js +3 -1
  55. package/dist/utils/deployment/secret-generator.js +32 -29
  56. package/dist/utils/framework-config.js +6 -3
  57. package/dist/utils/ui-structures-loader.js +3 -0
  58. package/dist/worker/integration.js +11 -1
  59. package/package.json +31 -3
  60. package/dist/config/FeatureManager.js +0 -426
  61. package/dist/config/features.js +0 -230
  62. package/dist/utils/error-recovery.js +0 -240
@@ -1,426 +0,0 @@
1
- /**
2
- * Feature Flag System for CLODO Framework
3
- * Enables gradual migration and progressive enhancement
4
- */
5
-
6
- /**
7
- * Default feature flags configuration
8
- */
9
- const DEFAULT_FEATURES = {
10
- // Schema Manager Features
11
- ENABLE_ENHANCED_SCHEMA: true,
12
- ENABLE_SCHEMA_CACHING: true,
13
- ENABLE_COMPREHENSIVE_VALIDATION: true,
14
- ENABLE_SQL_CACHING: true,
15
- // Generic Data Service Features
16
- ENABLE_QUERY_CACHING: true,
17
- ENABLE_SECURITY_CONTROLS: true,
18
- ENABLE_ADVANCED_PAGINATION: true,
19
- ENABLE_RELATIONSHIP_LOADING: true,
20
- // Module Manager Features
21
- ENABLE_ENHANCED_HOOKS: true,
22
- ENABLE_HOOK_TIMEOUT: true,
23
- ENABLE_HOOK_METRICS: true,
24
- ENABLE_PARALLEL_EXECUTION: true,
25
- // Performance Features
26
- ENABLE_PERFORMANCE_MONITORING: true,
27
- ENABLE_CACHE_METRICS: true,
28
- ENABLE_QUERY_OPTIMIZATION: true,
29
- // Development Features
30
- ENABLE_DEBUG_LOGGING: false,
31
- ENABLE_DEVELOPMENT_MODE: false,
32
- ENABLE_STRICT_VALIDATION: false,
33
- // Migration Features
34
- ENABLE_LEGACY_COMPATIBILITY: true,
35
- ENABLE_DEPRECATION_WARNINGS: true,
36
- ENABLE_MIGRATION_HELPERS: true
37
- };
38
-
39
- /**
40
- * Feature flag manager for controlling framework capabilities
41
- */
42
- export class FeatureManager {
43
- constructor(config = {}) {
44
- this.features = {
45
- ...DEFAULT_FEATURES,
46
- ...config
47
- };
48
- this.listeners = new Map();
49
- this.context = {
50
- environment: this._detectEnvironment(),
51
- version: this._getFrameworkVersion(),
52
- timestamp: Date.now()
53
- };
54
- this._logFeatureState();
55
- }
56
-
57
- /**
58
- * Check if a feature is enabled
59
- * @param {string} featureName - Name of the feature flag
60
- * @returns {boolean} Whether the feature is enabled
61
- */
62
- isEnabled(featureName) {
63
- // Check for environment-specific overrides
64
- const envOverride = this._getEnvironmentOverride(featureName);
65
- if (envOverride !== null) {
66
- return envOverride;
67
- }
68
-
69
- // Check for runtime overrides
70
- const runtimeOverride = this._getRuntimeOverride(featureName);
71
- if (runtimeOverride !== null) {
72
- return runtimeOverride;
73
- }
74
-
75
- // Return default configuration
76
- return this.features[featureName] ?? false;
77
- }
78
-
79
- /**
80
- * Enable a feature flag
81
- * @param {string} featureName - Name of the feature flag
82
- * @param {Object} options - Enable options
83
- */
84
- enable(featureName, options = {}) {
85
- const previousValue = this.features[featureName];
86
- this.features[featureName] = true;
87
- this._logFeatureChange(featureName, previousValue, true, options);
88
- this._notifyListeners(featureName, true, previousValue);
89
-
90
- // Auto-enable dependencies if specified
91
- if (options.dependencies) {
92
- options.dependencies.forEach(dep => {
93
- if (!this.isEnabled(dep)) {
94
- this.enable(dep, {
95
- reason: `Required by ${featureName}`
96
- });
97
- }
98
- });
99
- }
100
- }
101
-
102
- /**
103
- * Disable a feature flag
104
- * @param {string} featureName - Name of the feature flag
105
- * @param {Object} options - Disable options
106
- */
107
- disable(featureName, options = {}) {
108
- const previousValue = this.features[featureName];
109
- this.features[featureName] = false;
110
- this._logFeatureChange(featureName, previousValue, false, options);
111
- this._notifyListeners(featureName, false, previousValue);
112
-
113
- // Auto-disable dependents if specified
114
- if (options.disableDependents) {
115
- this._disableDependents(featureName);
116
- }
117
- }
118
-
119
- /**
120
- * Toggle a feature flag
121
- * @param {string} featureName - Name of the feature flag
122
- * @returns {boolean} New state of the feature
123
- */
124
- toggle(featureName) {
125
- const currentState = this.isEnabled(featureName);
126
- if (currentState) {
127
- this.disable(featureName, {
128
- reason: 'Toggled off'
129
- });
130
- } else {
131
- this.enable(featureName, {
132
- reason: 'Toggled on'
133
- });
134
- }
135
- return !currentState;
136
- }
137
-
138
- /**
139
- * Get all feature flags and their states
140
- * @returns {Object} All feature flags with their current states
141
- */
142
- getAllFeatures() {
143
- const features = {};
144
- for (const [name] of Object.entries(DEFAULT_FEATURES)) {
145
- features[name] = {
146
- enabled: this.isEnabled(name),
147
- default: DEFAULT_FEATURES[name],
148
- configured: this.features[name],
149
- overridden: this.isEnabled(name) !== this.features[name]
150
- };
151
- }
152
- return features;
153
- }
154
-
155
- /**
156
- * Get features by category
157
- * @param {string} category - Feature category (e.g., 'SCHEMA', 'DATA_SERVICE')
158
- * @returns {Object} Features in the specified category
159
- */
160
- getFeaturesByCategory(category) {
161
- const prefix = `ENABLE_${category}`;
162
- const categoryFeatures = {};
163
- for (const [name, value] of Object.entries(this.features)) {
164
- if (name.startsWith(prefix)) {
165
- categoryFeatures[name] = {
166
- enabled: this.isEnabled(name),
167
- configured: value
168
- };
169
- }
170
- }
171
- return categoryFeatures;
172
- }
173
-
174
- /**
175
- * Listen for feature flag changes
176
- * @param {string} featureName - Name of the feature flag to listen for
177
- * @param {Function} callback - Callback function
178
- */
179
- onFeatureChange(featureName, callback) {
180
- if (!this.listeners.has(featureName)) {
181
- this.listeners.set(featureName, []);
182
- }
183
- this.listeners.get(featureName).push(callback);
184
-
185
- // Return unsubscribe function
186
- return () => {
187
- const callbacks = this.listeners.get(featureName);
188
- if (callbacks) {
189
- const index = callbacks.indexOf(callback);
190
- if (index > -1) {
191
- callbacks.splice(index, 1);
192
- }
193
- }
194
- };
195
- }
196
-
197
- /**
198
- * Safely execute code with feature flag check
199
- * @param {string} featureName - Name of the feature flag
200
- * @param {Function} enabledCallback - Function to execute if feature is enabled
201
- * @param {Function} disabledCallback - Function to execute if feature is disabled
202
- * @returns {any} Result of the executed callback
203
- */
204
- withFeature(featureName, enabledCallback, disabledCallback = null) {
205
- if (this.isEnabled(featureName)) {
206
- try {
207
- return enabledCallback();
208
- } catch (error) {
209
- console.warn(`Feature '${featureName}' execution failed:`, error);
210
- if (disabledCallback) {
211
- return disabledCallback();
212
- }
213
- throw error;
214
- }
215
- } else {
216
- if (this.isEnabled('ENABLE_DEPRECATION_WARNINGS')) {
217
- console.warn(`Feature '${featureName}' is disabled. Consider enabling it for enhanced functionality.`);
218
- }
219
- return disabledCallback ? disabledCallback() : null;
220
- }
221
- }
222
-
223
- /**
224
- * Create a feature-gated wrapper function
225
- * @param {string} featureName - Name of the feature flag
226
- * @param {Function} enhancedFunction - Enhanced function to use when feature is enabled
227
- * @param {Function} legacyFunction - Legacy function to use when feature is disabled
228
- * @returns {Function} Wrapped function that chooses implementation based on feature flag
229
- */
230
- createFeatureGate(featureName, enhancedFunction, legacyFunction) {
231
- return (...args) => {
232
- return this.withFeature(featureName, () => enhancedFunction(...args), legacyFunction ? () => legacyFunction(...args) : null);
233
- };
234
- }
235
-
236
- /**
237
- * Validate feature flag configuration
238
- * @returns {Array} Array of validation errors
239
- */
240
- validateConfiguration() {
241
- const errors = [];
242
-
243
- // Check for unknown feature flags
244
- for (const featureName of Object.keys(this.features)) {
245
- if (!(featureName in DEFAULT_FEATURES)) {
246
- errors.push(`Unknown feature flag: ${featureName}`);
247
- }
248
- }
249
-
250
- // Check for conflicting features
251
- const conflicts = [['ENABLE_LEGACY_COMPATIBILITY', 'ENABLE_STRICT_VALIDATION'], ['ENABLE_DEVELOPMENT_MODE', 'ENABLE_QUERY_OPTIMIZATION']];
252
- for (const [feature1, feature2] of conflicts) {
253
- if (this.isEnabled(feature1) && this.isEnabled(feature2)) {
254
- errors.push(`Conflicting features enabled: ${feature1} and ${feature2}`);
255
- }
256
- }
257
- return errors;
258
- }
259
-
260
- // Private methods
261
-
262
- /**
263
- * Detect current environment
264
- * @private
265
- */
266
- _detectEnvironment() {
267
- if (typeof process !== 'undefined' && process.env) {
268
- return process.env.NODE_ENV || 'development';
269
- }
270
- if (typeof globalThis !== 'undefined' && globalThis.navigator) {
271
- return 'browser';
272
- }
273
- return 'worker';
274
- }
275
-
276
- /**
277
- * Get framework version
278
- * @private
279
- */
280
- _getFrameworkVersion() {
281
- // Try to get version from package.json if available
282
- return '2.0.0'; // Placeholder - should be dynamically determined
283
- }
284
-
285
- /**
286
- * Get environment-specific override
287
- * @private
288
- */
289
- _getEnvironmentOverride(featureName) {
290
- if (typeof process !== 'undefined' && process.env) {
291
- const envVar = `CLODO_${featureName}`;
292
- if (process.env[envVar] !== undefined) {
293
- return process.env[envVar] === 'true';
294
- }
295
- }
296
- return null;
297
- }
298
-
299
- /**
300
- * Get runtime override
301
- * @private
302
- */
303
- _getRuntimeOverride(featureName) {
304
- // Check for URL parameters in browser environment
305
- if (typeof URLSearchParams !== 'undefined' && typeof globalThis !== 'undefined' && globalThis.location) {
306
- const params = new URLSearchParams(globalThis.location.search);
307
- const override = params.get(`clodo_${featureName.toLowerCase()}`);
308
- if (override !== null) {
309
- return override === 'true';
310
- }
311
- }
312
- return null;
313
- }
314
-
315
- /**
316
- * Log feature flag state on initialization
317
- * @private
318
- */
319
- _logFeatureState() {
320
- if (this.isEnabled('ENABLE_DEBUG_LOGGING')) {
321
- console.log('CLODO Framework Feature Flags:', {
322
- context: this.context,
323
- features: this.getAllFeatures()
324
- });
325
- }
326
- }
327
-
328
- /**
329
- * Log feature flag changes
330
- * @private
331
- */
332
- _logFeatureChange(featureName, previousValue, newValue, options) {
333
- if (this.isEnabled('ENABLE_DEBUG_LOGGING')) {
334
- console.log(`Feature flag changed: ${featureName}`, {
335
- from: previousValue,
336
- to: newValue,
337
- options,
338
- timestamp: new Date().toISOString()
339
- });
340
- }
341
- }
342
-
343
- /**
344
- * Notify listeners of feature flag changes
345
- * @private
346
- */
347
- _notifyListeners(featureName, newValue, previousValue) {
348
- const callbacks = this.listeners.get(featureName);
349
- if (callbacks) {
350
- callbacks.forEach(callback => {
351
- try {
352
- callback(newValue, previousValue, featureName);
353
- } catch (error) {
354
- console.error(`Feature listener error for '${featureName}':`, error);
355
- }
356
- });
357
- }
358
- }
359
-
360
- /**
361
- * Disable features that depend on the given feature
362
- * @private
363
- */
364
- _disableDependents(featureName) {
365
- const dependents = this._findDependents(featureName);
366
- dependents.forEach(dependent => {
367
- if (this.isEnabled(dependent)) {
368
- this.disable(dependent, {
369
- reason: `Dependency ${featureName} was disabled`,
370
- cascade: true
371
- });
372
- }
373
- });
374
- }
375
-
376
- /**
377
- * Find features that depend on the given feature
378
- * @private
379
- */
380
- _findDependents(featureName) {
381
- // Simple dependency mapping - in a real implementation, this would be more sophisticated
382
- const dependencies = {
383
- 'ENABLE_ENHANCED_SCHEMA': ['ENABLE_SCHEMA_CACHING', 'ENABLE_COMPREHENSIVE_VALIDATION'],
384
- 'ENABLE_QUERY_CACHING': ['ENABLE_CACHE_METRICS'],
385
- 'ENABLE_ENHANCED_HOOKS': ['ENABLE_HOOK_TIMEOUT', 'ENABLE_HOOK_METRICS']
386
- };
387
- const dependents = [];
388
- for (const [feature, deps] of Object.entries(dependencies)) {
389
- if (deps.includes(featureName)) {
390
- dependents.push(feature);
391
- }
392
- }
393
- return dependents;
394
- }
395
- }
396
-
397
- // Create global feature manager instance
398
- export const featureManager = new FeatureManager();
399
-
400
- /**
401
- * Convenience function to check if a feature is enabled
402
- * @param {string} featureName - Name of the feature flag
403
- * @returns {boolean} Whether the feature is enabled
404
- */
405
- export function isFeatureEnabled(featureName) {
406
- return featureManager.isEnabled(featureName);
407
- }
408
-
409
- /**
410
- * Convenience function to execute code with feature flag check
411
- * @param {string} featureName - Name of the feature flag
412
- * @param {Function} enabledCallback - Function to execute if feature is enabled
413
- * @param {Function} disabledCallback - Function to execute if feature is disabled
414
- * @returns {any} Result of the executed callback
415
- */
416
- export function withFeature(featureName, enabledCallback, disabledCallback = null) {
417
- return featureManager.withFeature(featureName, enabledCallback, disabledCallback);
418
- }
419
-
420
- /**
421
- * Export feature flag constants for easy use
422
- */
423
- export const FEATURES = Object.keys(DEFAULT_FEATURES).reduce((acc, key) => {
424
- acc[key] = key;
425
- return acc;
426
- }, {});
@@ -1,230 +0,0 @@
1
- // Simple inline logger to avoid circular dependency with index.js
2
- const logger = {
3
- info: (message, ...args) => console.log(`[FeatureFlagManager] ${message}`, ...args),
4
- error: (message, ...args) => console.error(`[FeatureFlagManager] ${message}`, ...args),
5
- warn: (message, ...args) => console.warn(`[FeatureFlagManager] ${message}`, ...args),
6
- debug: (message, ...args) => console.debug(`[FeatureFlagManager] ${message}`, ...args)
7
- };
8
-
9
- /**
10
- * Feature Flag Manager Class
11
- * Manages feature flags for domain-specific functionality
12
- */
13
- export class FeatureFlagManager {
14
- constructor() {
15
- this.currentDomain = null;
16
- this.globalOverrides = new Map();
17
- this.listeners = new Set();
18
- }
19
-
20
- /**
21
- * Sets the current domain configuration
22
- * @param {Object} domainConfig - Domain configuration object
23
- */
24
- setDomain(domainConfig) {
25
- if (!domainConfig) {
26
- throw new Error('Domain configuration is required');
27
- }
28
- this.currentDomain = domainConfig;
29
- logger.info(`Domain set for feature flags: ${domainConfig.name}`);
30
-
31
- // Notify listeners of domain change
32
- this._notifyListeners('domainChanged', {
33
- domain: domainConfig.name
34
- });
35
- }
36
-
37
- /**
38
- * Checks if a feature is enabled
39
- * @param {string} featureName - Name of the feature to check
40
- * @param {boolean} defaultValue - Default value if feature not configured
41
- * @returns {boolean} Whether the feature is enabled
42
- */
43
- isEnabled(featureName, defaultValue = false) {
44
- if (!this.currentDomain) {
45
- logger.warn('No domain set, using default value for feature check');
46
- return defaultValue;
47
- }
48
-
49
- // Check global overrides first
50
- if (this.globalOverrides.has(featureName)) {
51
- return this.globalOverrides.get(featureName);
52
- }
53
-
54
- // Check domain-specific features
55
- const features = this.currentDomain.features || {};
56
- const enabled = features[featureName] ?? defaultValue;
57
- logger.debug(`Feature ${featureName}: ${enabled ? 'enabled' : 'disabled'}`);
58
- return enabled;
59
- }
60
-
61
- /**
62
- * Gets all enabled features for current domain
63
- * @returns {string[]} Array of enabled feature names
64
- */
65
- getEnabledFeatures() {
66
- if (!this.currentDomain?.features) {
67
- return [];
68
- }
69
- return Object.entries(this.currentDomain.features).filter(([, enabled]) => enabled === true).map(([feature]) => feature);
70
- }
71
-
72
- /**
73
- * Gets all disabled features for current domain
74
- * @returns {string[]} Array of disabled feature names
75
- */
76
- getDisabledFeatures() {
77
- if (!this.currentDomain?.features) {
78
- return [];
79
- }
80
- return Object.entries(this.currentDomain.features).filter(([, enabled]) => enabled === false).map(([feature]) => feature);
81
- }
82
-
83
- /**
84
- * Gets all configured features with their status
85
- * @returns {Object} Object mapping feature names to enabled status
86
- */
87
- getAllFeatures() {
88
- return this.currentDomain?.features || {};
89
- }
90
-
91
- /**
92
- * Sets a global feature override
93
- * @param {string} featureName - Name of the feature
94
- * @param {boolean} enabled - Whether to enable the feature
95
- */
96
- setGlobalOverride(featureName, enabled) {
97
- this.globalOverrides.set(featureName, enabled);
98
- logger.info(`Global override set: ${featureName} = ${enabled}`);
99
- this._notifyListeners('overrideChanged', {
100
- feature: featureName,
101
- enabled
102
- });
103
- }
104
-
105
- /**
106
- * Removes a global feature override
107
- * @param {string} featureName - Name of the feature
108
- */
109
- removeGlobalOverride(featureName) {
110
- const hadOverride = this.globalOverrides.has(featureName);
111
- this.globalOverrides.delete(featureName);
112
- if (hadOverride) {
113
- logger.info(`Global override removed: ${featureName}`);
114
- this._notifyListeners('overrideChanged', {
115
- feature: featureName,
116
- removed: true
117
- });
118
- }
119
- }
120
-
121
- /**
122
- * Clears all global overrides
123
- */
124
- clearGlobalOverrides() {
125
- const count = this.globalOverrides.size;
126
- this.globalOverrides.clear();
127
- if (count > 0) {
128
- logger.info(`Cleared ${count} global overrides`);
129
- this._notifyListeners('overridesCleared', {
130
- count
131
- });
132
- }
133
- }
134
-
135
- /**
136
- * Adds a listener for feature flag changes
137
- * @param {Function} listener - Callback function
138
- */
139
- addListener(listener) {
140
- this.listeners.add(listener);
141
- }
142
-
143
- /**
144
- * Removes a listener
145
- * @param {Function} listener - Callback function to remove
146
- */
147
- removeListener(listener) {
148
- this.listeners.delete(listener);
149
- }
150
-
151
- /**
152
- * Gets feature flag status with metadata
153
- * @param {string} featureName - Name of the feature
154
- * @returns {Object} Feature status information
155
- */
156
- getFeatureInfo(featureName) {
157
- const domainEnabled = this.currentDomain?.features?.[featureName] ?? null;
158
- const globalOverride = this.globalOverrides.get(featureName);
159
- const effectiveEnabled = this.isEnabled(featureName);
160
- return {
161
- name: featureName,
162
- domainEnabled,
163
- globalOverride,
164
- effectiveEnabled,
165
- hasOverride: globalOverride !== undefined,
166
- domain: this.currentDomain?.name
167
- };
168
- }
169
-
170
- /**
171
- * Creates a feature toggle function
172
- * @param {string} featureName - Name of the feature
173
- * @param {Function} enabledHandler - Function to call when enabled
174
- * @param {Function} disabledHandler - Function to call when disabled
175
- * @returns {Function} Toggle function
176
- */
177
- createToggle(featureName, enabledHandler, disabledHandler) {
178
- return (...args) => {
179
- if (this.isEnabled(featureName)) {
180
- return enabledHandler?.(...args);
181
- } else {
182
- return disabledHandler?.(...args);
183
- }
184
- };
185
- }
186
-
187
- /**
188
- * Notifies all listeners of changes
189
- * @private
190
- */
191
- _notifyListeners(event, data) {
192
- this.listeners.forEach(listener => {
193
- try {
194
- listener(event, data);
195
- } catch (error) {
196
- logger.error(`Error in feature flag listener: ${error.message}`);
197
- }
198
- });
199
- }
200
- }
201
-
202
- // Default singleton instance
203
- export const featureManager = new FeatureFlagManager();
204
-
205
- // Convenience functions for common operations
206
- export const isFeatureEnabled = (featureName, defaultValue = false) => featureManager.isEnabled(featureName, defaultValue);
207
- export const getEnabledFeatures = () => featureManager.getEnabledFeatures();
208
- export const setFeatureOverride = (featureName, enabled) => featureManager.setGlobalOverride(featureName, enabled);
209
-
210
- // Feature flag constants for common features
211
- export const COMMON_FEATURES = {
212
- AUTHENTICATION: 'authentication',
213
- AUTHORIZATION: 'authorization',
214
- LOGGING: 'logging',
215
- MONITORING: 'monitoring',
216
- ANALYTICS: 'analytics',
217
- CACHING: 'caching',
218
- RATE_LIMITING: 'rateLimiting',
219
- FILE_STORAGE: 'fileStorage',
220
- EMAIL_NOTIFICATIONS: 'emailNotifications',
221
- PUSH_NOTIFICATIONS: 'pushNotifications',
222
- SEARCH: 'search',
223
- FILTERING: 'filtering',
224
- SORTING: 'sorting',
225
- PAGINATION: 'pagination',
226
- EXPORT: 'export',
227
- IMPORT: 'import',
228
- BACKUP: 'backup',
229
- RESTORE: 'restore'
230
- };