@morojs/moro 1.4.0 → 1.5.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 (52) hide show
  1. package/dist/core/config/index.d.ts +0 -1
  2. package/dist/core/config/index.js +0 -4
  3. package/dist/core/config/index.js.map +1 -1
  4. package/dist/core/config/loader.js +219 -226
  5. package/dist/core/config/loader.js.map +1 -1
  6. package/dist/core/config/schema.d.ts +30 -335
  7. package/dist/core/config/schema.js +133 -224
  8. package/dist/core/config/schema.js.map +1 -1
  9. package/dist/core/config/utils.d.ts +3 -2
  10. package/dist/core/config/utils.js.map +1 -1
  11. package/dist/core/config/validation.d.ts +0 -1
  12. package/dist/core/config/validation.js +5 -10
  13. package/dist/core/config/validation.js.map +1 -1
  14. package/dist/core/docs/index.js +1 -1
  15. package/dist/core/docs/index.js.map +1 -1
  16. package/dist/core/docs/simple-docs.js +5 -5
  17. package/dist/core/docs/zod-to-openapi.d.ts +2 -3
  18. package/dist/core/docs/zod-to-openapi.js +28 -0
  19. package/dist/core/docs/zod-to-openapi.js.map +1 -1
  20. package/dist/core/networking/websocket-manager.js +19 -19
  21. package/dist/core/networking/websocket-manager.js.map +1 -1
  22. package/dist/core/validation/index.d.ts +0 -2
  23. package/dist/core/validation/index.js +3 -8
  24. package/dist/core/validation/index.js.map +1 -1
  25. package/dist/index.d.ts +3 -1
  26. package/dist/index.js +9 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/moro.js +16 -15
  29. package/dist/moro.js.map +1 -1
  30. package/dist/{core/config/types.d.ts → types/config.d.ts} +0 -1
  31. package/dist/types/config.js +4 -0
  32. package/dist/types/config.js.map +1 -0
  33. package/package.json +6 -7
  34. package/src/core/config/index.ts +0 -3
  35. package/src/core/config/loader.ts +571 -247
  36. package/src/core/config/schema.ts +146 -279
  37. package/src/core/config/utils.ts +1 -2
  38. package/src/core/config/validation.ts +5 -10
  39. package/src/core/docs/index.ts +1 -1
  40. package/src/core/docs/simple-docs.ts +5 -5
  41. package/src/core/docs/zod-to-openapi.ts +50 -20
  42. package/src/core/networking/websocket-manager.ts +17 -17
  43. package/src/core/validation/index.ts +2 -8
  44. package/src/index.ts +11 -1
  45. package/src/moro.ts +16 -15
  46. package/src/{core/config/types.ts → types/config.ts} +0 -120
  47. package/dist/core/config/types.js +0 -124
  48. package/dist/core/config/types.js.map +0 -1
  49. package/dist/core/config/typescript-loader.d.ts +0 -6
  50. package/dist/core/config/typescript-loader.js +0 -268
  51. package/dist/core/config/typescript-loader.js.map +0 -1
  52. package/src/core/config/typescript-loader.ts +0 -571
@@ -1,571 +0,0 @@
1
- // TypeScript-based Configuration Loader
2
- // Replaces Zod-based configuration system with pure TypeScript + validation
3
-
4
- import { AppConfig, DEFAULT_CONFIG } from './types';
5
- import {
6
- validatePort,
7
- validateBoolean,
8
- validateNumber,
9
- validateString,
10
- validateUrl,
11
- validateEnum,
12
- validateStringArray,
13
- validateOptional,
14
- coerceEnvValue,
15
- ConfigValidationError,
16
- } from './validation';
17
- import { createFrameworkLogger } from '../logger';
18
- import { loadConfigFileSync, applyConfigAsEnvironmentVariables } from './file-loader';
19
-
20
- const logger = createFrameworkLogger('TypeScriptConfig');
21
-
22
- /**
23
- * Load and validate configuration using TypeScript + simple validation
24
- * No Zod dependency required!
25
- */
26
- export function loadConfigWithTypeScript(): AppConfig {
27
- logger.debug('Loading configuration with TypeScript validation');
28
-
29
- // Load config file and apply as environment variables
30
- try {
31
- const fileConfig = loadConfigFileSync();
32
- if (fileConfig) {
33
- logger.debug('Applying config file values as environment variables');
34
- applyConfigAsEnvironmentVariables(fileConfig);
35
- }
36
- } catch (error) {
37
- logger.warn(
38
- 'Config file loading failed, continuing with environment variables only:',
39
- String(error)
40
- );
41
- }
42
-
43
- try {
44
- // Build configuration from environment variables with type-safe validation
45
- const config: AppConfig = {
46
- server: {
47
- port: validatePort(
48
- coerceEnvValue(process.env.MORO_SERVER_PORT || '') || DEFAULT_CONFIG.server.port,
49
- 'server.port'
50
- ),
51
- host: validateString(
52
- process.env.MORO_SERVER_HOST || DEFAULT_CONFIG.server.host,
53
- 'server.host'
54
- ),
55
- environment: validateEnum(
56
- process.env.NODE_ENV || DEFAULT_CONFIG.server.environment,
57
- ['development', 'staging', 'production'] as const,
58
- 'server.environment'
59
- ),
60
- maxConnections: validateNumber(
61
- coerceEnvValue(process.env.MORO_SERVER_MAX_CONNECTIONS || '') ||
62
- DEFAULT_CONFIG.server.maxConnections,
63
- 'server.maxConnections',
64
- { min: 1 }
65
- ),
66
- timeout: validateNumber(
67
- coerceEnvValue(process.env.MORO_SERVER_TIMEOUT || '') || DEFAULT_CONFIG.server.timeout,
68
- 'server.timeout',
69
- { min: 1000 }
70
- ),
71
- },
72
-
73
- serviceDiscovery: {
74
- enabled: validateBoolean(
75
- coerceEnvValue(process.env.MORO_SERVICE_DISCOVERY_ENABLED || '') ??
76
- DEFAULT_CONFIG.serviceDiscovery.enabled,
77
- 'serviceDiscovery.enabled'
78
- ),
79
- type: validateEnum(
80
- process.env.MORO_SERVICE_DISCOVERY_TYPE || DEFAULT_CONFIG.serviceDiscovery.type,
81
- ['memory', 'consul', 'kubernetes'] as const,
82
- 'serviceDiscovery.type'
83
- ),
84
- consulUrl: validateUrl(
85
- process.env.MORO_SERVICE_DISCOVERY_CONSUL_URL ||
86
- DEFAULT_CONFIG.serviceDiscovery.consulUrl,
87
- 'serviceDiscovery.consulUrl'
88
- ),
89
- kubernetesNamespace: validateString(
90
- process.env.MORO_SERVICE_DISCOVERY_KUBERNETES_NAMESPACE ||
91
- DEFAULT_CONFIG.serviceDiscovery.kubernetesNamespace,
92
- 'serviceDiscovery.kubernetesNamespace'
93
- ),
94
- healthCheckInterval: validateNumber(
95
- coerceEnvValue(process.env.MORO_SERVICE_DISCOVERY_HEALTH_CHECK_INTERVAL || '') ||
96
- DEFAULT_CONFIG.serviceDiscovery.healthCheckInterval,
97
- 'serviceDiscovery.healthCheckInterval',
98
- { min: 1000 }
99
- ),
100
- retryAttempts: validateNumber(
101
- coerceEnvValue(process.env.MORO_SERVICE_DISCOVERY_RETRY_ATTEMPTS || '') ||
102
- DEFAULT_CONFIG.serviceDiscovery.retryAttempts,
103
- 'serviceDiscovery.retryAttempts',
104
- { min: 0 }
105
- ),
106
- },
107
-
108
- database: {
109
- url: validateOptional(process.env.DATABASE_URL, validateString, 'database.url'),
110
- redis: {
111
- url: validateString(
112
- process.env.REDIS_URL || DEFAULT_CONFIG.database.redis.url,
113
- 'database.redis.url'
114
- ),
115
- maxRetries: validateNumber(
116
- coerceEnvValue(process.env.REDIS_MAX_RETRIES || '') ||
117
- DEFAULT_CONFIG.database.redis.maxRetries,
118
- 'database.redis.maxRetries',
119
- { min: 0 }
120
- ),
121
- retryDelay: validateNumber(
122
- coerceEnvValue(process.env.REDIS_RETRY_DELAY || '') ||
123
- DEFAULT_CONFIG.database.redis.retryDelay,
124
- 'database.redis.retryDelay',
125
- { min: 100 }
126
- ),
127
- keyPrefix: validateString(
128
- process.env.REDIS_KEY_PREFIX || DEFAULT_CONFIG.database.redis.keyPrefix,
129
- 'database.redis.keyPrefix'
130
- ),
131
- },
132
- mysql: process.env.MYSQL_HOST
133
- ? {
134
- host: validateString(process.env.MYSQL_HOST, 'database.mysql.host'),
135
- port: validatePort(process.env.MYSQL_PORT || '3306', 'database.mysql.port'),
136
- database: validateOptional(
137
- process.env.MYSQL_DATABASE,
138
- validateString,
139
- 'database.mysql.database'
140
- ),
141
- username: validateOptional(
142
- process.env.MYSQL_USERNAME,
143
- validateString,
144
- 'database.mysql.username'
145
- ),
146
- password: validateOptional(
147
- process.env.MYSQL_PASSWORD,
148
- validateString,
149
- 'database.mysql.password'
150
- ),
151
- connectionLimit: validateNumber(
152
- coerceEnvValue(process.env.MYSQL_CONNECTION_LIMIT || '') || 10,
153
- 'database.mysql.connectionLimit',
154
- { min: 1 }
155
- ),
156
- acquireTimeout: validateNumber(
157
- coerceEnvValue(process.env.MYSQL_ACQUIRE_TIMEOUT || '') || 60000,
158
- 'database.mysql.acquireTimeout',
159
- { min: 1000 }
160
- ),
161
- timeout: validateNumber(
162
- coerceEnvValue(process.env.MYSQL_TIMEOUT || '') || 60000,
163
- 'database.mysql.timeout',
164
- { min: 1000 }
165
- ),
166
- }
167
- : undefined,
168
- },
169
-
170
- modules: {
171
- cache: {
172
- enabled: validateBoolean(
173
- coerceEnvValue(process.env.MORO_MODULES_CACHE_ENABLED || '') ??
174
- DEFAULT_CONFIG.modules.cache.enabled,
175
- 'modules.cache.enabled'
176
- ),
177
- defaultTtl: validateNumber(
178
- coerceEnvValue(process.env.MORO_MODULES_CACHE_DEFAULT_TTL || '') ||
179
- DEFAULT_CONFIG.modules.cache.defaultTtl,
180
- 'modules.cache.defaultTtl',
181
- { min: 0 }
182
- ),
183
- maxSize: validateNumber(
184
- coerceEnvValue(process.env.MORO_MODULES_CACHE_MAX_SIZE || '') ||
185
- DEFAULT_CONFIG.modules.cache.maxSize,
186
- 'modules.cache.maxSize',
187
- { min: 1 }
188
- ),
189
- strategy: validateEnum(
190
- process.env.MORO_MODULES_CACHE_STRATEGY || DEFAULT_CONFIG.modules.cache.strategy,
191
- ['lru', 'lfu', 'fifo'] as const,
192
- 'modules.cache.strategy'
193
- ),
194
- },
195
- rateLimit: {
196
- enabled: validateBoolean(
197
- coerceEnvValue(process.env.MORO_MODULES_RATE_LIMIT_ENABLED || '') ??
198
- DEFAULT_CONFIG.modules.rateLimit.enabled,
199
- 'modules.rateLimit.enabled'
200
- ),
201
- defaultRequests: validateNumber(
202
- coerceEnvValue(process.env.MORO_MODULES_RATE_LIMIT_DEFAULT_REQUESTS || '') ||
203
- DEFAULT_CONFIG.modules.rateLimit.defaultRequests,
204
- 'modules.rateLimit.defaultRequests',
205
- { min: 1 }
206
- ),
207
- defaultWindow: validateNumber(
208
- coerceEnvValue(process.env.MORO_MODULES_RATE_LIMIT_DEFAULT_WINDOW || '') ||
209
- DEFAULT_CONFIG.modules.rateLimit.defaultWindow,
210
- 'modules.rateLimit.defaultWindow',
211
- { min: 1000 }
212
- ),
213
- skipSuccessfulRequests: validateBoolean(
214
- coerceEnvValue(process.env.MORO_MODULES_RATE_LIMIT_SKIP_SUCCESSFUL_REQUESTS || '') ??
215
- DEFAULT_CONFIG.modules.rateLimit.skipSuccessfulRequests,
216
- 'modules.rateLimit.skipSuccessfulRequests'
217
- ),
218
- skipFailedRequests: validateBoolean(
219
- coerceEnvValue(process.env.MORO_MODULES_RATE_LIMIT_SKIP_FAILED_REQUESTS || '') ??
220
- DEFAULT_CONFIG.modules.rateLimit.skipFailedRequests,
221
- 'modules.rateLimit.skipFailedRequests'
222
- ),
223
- },
224
- validation: {
225
- enabled: validateBoolean(
226
- coerceEnvValue(process.env.MORO_MODULES_VALIDATION_ENABLED || '') ??
227
- DEFAULT_CONFIG.modules.validation.enabled,
228
- 'modules.validation.enabled'
229
- ),
230
- stripUnknown: validateBoolean(
231
- coerceEnvValue(process.env.MORO_MODULES_VALIDATION_STRIP_UNKNOWN || '') ??
232
- DEFAULT_CONFIG.modules.validation.stripUnknown,
233
- 'modules.validation.stripUnknown'
234
- ),
235
- abortEarly: validateBoolean(
236
- coerceEnvValue(process.env.MORO_MODULES_VALIDATION_ABORT_EARLY || '') ??
237
- DEFAULT_CONFIG.modules.validation.abortEarly,
238
- 'modules.validation.abortEarly'
239
- ),
240
- },
241
- },
242
-
243
- logging: {
244
- level: validateEnum(
245
- process.env.MORO_LOGGING_LEVEL || DEFAULT_CONFIG.logging.level,
246
- ['debug', 'info', 'warn', 'error', 'fatal'] as const,
247
- 'logging.level'
248
- ),
249
- format: validateEnum(
250
- process.env.MORO_LOGGING_FORMAT || DEFAULT_CONFIG.logging.format,
251
- ['pretty', 'json', 'compact'] as const,
252
- 'logging.format'
253
- ),
254
- enableColors: validateBoolean(
255
- coerceEnvValue(process.env.MORO_LOGGING_ENABLE_COLORS || '') ??
256
- DEFAULT_CONFIG.logging.enableColors,
257
- 'logging.enableColors'
258
- ),
259
- enableTimestamp: validateBoolean(
260
- coerceEnvValue(process.env.MORO_LOGGING_ENABLE_TIMESTAMP || '') ??
261
- DEFAULT_CONFIG.logging.enableTimestamp,
262
- 'logging.enableTimestamp'
263
- ),
264
- enableContext: validateBoolean(
265
- coerceEnvValue(process.env.MORO_LOGGING_ENABLE_CONTEXT || '') ??
266
- DEFAULT_CONFIG.logging.enableContext,
267
- 'logging.enableContext'
268
- ),
269
- outputs: {
270
- console: validateBoolean(
271
- coerceEnvValue(process.env.MORO_LOGGING_OUTPUTS_CONSOLE || '') ??
272
- DEFAULT_CONFIG.logging.outputs.console,
273
- 'logging.outputs.console'
274
- ),
275
- file: {
276
- enabled: validateBoolean(
277
- coerceEnvValue(process.env.MORO_LOGGING_OUTPUTS_FILE_ENABLED || '') ??
278
- DEFAULT_CONFIG.logging.outputs.file.enabled,
279
- 'logging.outputs.file.enabled'
280
- ),
281
- path: validateString(
282
- process.env.MORO_LOGGING_OUTPUTS_FILE_PATH ||
283
- DEFAULT_CONFIG.logging.outputs.file.path,
284
- 'logging.outputs.file.path'
285
- ),
286
- maxSize: validateString(
287
- process.env.MORO_LOGGING_OUTPUTS_FILE_MAX_SIZE ||
288
- DEFAULT_CONFIG.logging.outputs.file.maxSize,
289
- 'logging.outputs.file.maxSize'
290
- ),
291
- maxFiles: validateNumber(
292
- coerceEnvValue(process.env.MORO_LOGGING_OUTPUTS_FILE_MAX_FILES || '') ||
293
- DEFAULT_CONFIG.logging.outputs.file.maxFiles,
294
- 'logging.outputs.file.maxFiles',
295
- { min: 1 }
296
- ),
297
- },
298
- webhook: {
299
- enabled: validateBoolean(
300
- coerceEnvValue(process.env.MORO_LOGGING_OUTPUTS_WEBHOOK_ENABLED || '') ??
301
- DEFAULT_CONFIG.logging.outputs.webhook.enabled,
302
- 'logging.outputs.webhook.enabled'
303
- ),
304
- url: validateOptional(
305
- process.env.MORO_LOGGING_OUTPUTS_WEBHOOK_URL,
306
- validateUrl,
307
- 'logging.outputs.webhook.url'
308
- ),
309
- headers: DEFAULT_CONFIG.logging.outputs.webhook.headers,
310
- },
311
- },
312
- },
313
-
314
- security: {
315
- cors: {
316
- enabled: validateBoolean(
317
- coerceEnvValue(process.env.MORO_SECURITY_CORS_ENABLED || '') ??
318
- DEFAULT_CONFIG.security.cors.enabled,
319
- 'security.cors.enabled'
320
- ),
321
- origin: process.env.MORO_SECURITY_CORS_ORIGIN || DEFAULT_CONFIG.security.cors.origin,
322
- methods: validateStringArray(
323
- process.env.MORO_SECURITY_CORS_METHODS || DEFAULT_CONFIG.security.cors.methods,
324
- 'security.cors.methods'
325
- ),
326
- allowedHeaders: validateStringArray(
327
- process.env.MORO_SECURITY_CORS_ALLOWED_HEADERS ||
328
- DEFAULT_CONFIG.security.cors.allowedHeaders,
329
- 'security.cors.allowedHeaders'
330
- ),
331
- credentials: validateBoolean(
332
- coerceEnvValue(process.env.MORO_SECURITY_CORS_CREDENTIALS || '') ??
333
- DEFAULT_CONFIG.security.cors.credentials,
334
- 'security.cors.credentials'
335
- ),
336
- },
337
- helmet: {
338
- enabled: validateBoolean(
339
- coerceEnvValue(process.env.MORO_SECURITY_HELMET_ENABLED || '') ??
340
- DEFAULT_CONFIG.security.helmet.enabled,
341
- 'security.helmet.enabled'
342
- ),
343
- contentSecurityPolicy: validateBoolean(
344
- coerceEnvValue(process.env.MORO_SECURITY_HELMET_CSP || '') ??
345
- DEFAULT_CONFIG.security.helmet.contentSecurityPolicy,
346
- 'security.helmet.contentSecurityPolicy'
347
- ),
348
- hsts: validateBoolean(
349
- coerceEnvValue(process.env.MORO_SECURITY_HELMET_HSTS || '') ??
350
- DEFAULT_CONFIG.security.helmet.hsts,
351
- 'security.helmet.hsts'
352
- ),
353
- noSniff: validateBoolean(
354
- coerceEnvValue(process.env.MORO_SECURITY_HELMET_NO_SNIFF || '') ??
355
- DEFAULT_CONFIG.security.helmet.noSniff,
356
- 'security.helmet.noSniff'
357
- ),
358
- frameguard: validateBoolean(
359
- coerceEnvValue(process.env.MORO_SECURITY_HELMET_FRAMEGUARD || '') ??
360
- DEFAULT_CONFIG.security.helmet.frameguard,
361
- 'security.helmet.frameguard'
362
- ),
363
- },
364
- rateLimit: {
365
- global: {
366
- enabled: validateBoolean(
367
- coerceEnvValue(process.env.MORO_SECURITY_RATE_LIMIT_GLOBAL_ENABLED || '') ??
368
- DEFAULT_CONFIG.security.rateLimit.global.enabled,
369
- 'security.rateLimit.global.enabled'
370
- ),
371
- requests: validateNumber(
372
- coerceEnvValue(process.env.MORO_SECURITY_RATE_LIMIT_GLOBAL_REQUESTS || '') ||
373
- DEFAULT_CONFIG.security.rateLimit.global.requests,
374
- 'security.rateLimit.global.requests',
375
- { min: 1 }
376
- ),
377
- window: validateNumber(
378
- coerceEnvValue(process.env.MORO_SECURITY_RATE_LIMIT_GLOBAL_WINDOW || '') ||
379
- DEFAULT_CONFIG.security.rateLimit.global.window,
380
- 'security.rateLimit.global.window',
381
- { min: 1000 }
382
- ),
383
- },
384
- },
385
- },
386
-
387
- external: {
388
- stripe: process.env.STRIPE_SECRET_KEY
389
- ? {
390
- secretKey: validateOptional(
391
- process.env.STRIPE_SECRET_KEY,
392
- validateString,
393
- 'external.stripe.secretKey'
394
- ),
395
- publishableKey: validateOptional(
396
- process.env.STRIPE_PUBLISHABLE_KEY,
397
- validateString,
398
- 'external.stripe.publishableKey'
399
- ),
400
- webhookSecret: validateOptional(
401
- process.env.STRIPE_WEBHOOK_SECRET,
402
- validateString,
403
- 'external.stripe.webhookSecret'
404
- ),
405
- apiVersion: validateString(
406
- process.env.STRIPE_API_VERSION || DEFAULT_CONFIG.external.stripe!.apiVersion,
407
- 'external.stripe.apiVersion'
408
- ),
409
- }
410
- : undefined,
411
- paypal: process.env.PAYPAL_CLIENT_ID
412
- ? {
413
- clientId: validateOptional(
414
- process.env.PAYPAL_CLIENT_ID,
415
- validateString,
416
- 'external.paypal.clientId'
417
- ),
418
- clientSecret: validateOptional(
419
- process.env.PAYPAL_CLIENT_SECRET,
420
- validateString,
421
- 'external.paypal.clientSecret'
422
- ),
423
- webhookId: validateOptional(
424
- process.env.PAYPAL_WEBHOOK_ID,
425
- validateString,
426
- 'external.paypal.webhookId'
427
- ),
428
- environment: validateEnum(
429
- process.env.PAYPAL_ENVIRONMENT || DEFAULT_CONFIG.external.paypal!.environment,
430
- ['sandbox', 'production'] as const,
431
- 'external.paypal.environment'
432
- ),
433
- }
434
- : undefined,
435
- smtp: process.env.SMTP_HOST
436
- ? {
437
- host: validateOptional(process.env.SMTP_HOST, validateString, 'external.smtp.host'),
438
- port: validatePort(
439
- process.env.SMTP_PORT || DEFAULT_CONFIG.external.smtp!.port.toString(),
440
- 'external.smtp.port'
441
- ),
442
- secure: validateBoolean(
443
- coerceEnvValue(process.env.SMTP_SECURE || '') ??
444
- DEFAULT_CONFIG.external.smtp!.secure,
445
- 'external.smtp.secure'
446
- ),
447
- username: validateOptional(
448
- process.env.SMTP_USERNAME,
449
- validateString,
450
- 'external.smtp.username'
451
- ),
452
- password: validateOptional(
453
- process.env.SMTP_PASSWORD,
454
- validateString,
455
- 'external.smtp.password'
456
- ),
457
- }
458
- : undefined,
459
- },
460
-
461
- performance: {
462
- compression: {
463
- enabled: validateBoolean(
464
- coerceEnvValue(process.env.MORO_PERFORMANCE_COMPRESSION_ENABLED || '') ??
465
- DEFAULT_CONFIG.performance.compression.enabled,
466
- 'performance.compression.enabled'
467
- ),
468
- level: validateNumber(
469
- coerceEnvValue(process.env.MORO_PERFORMANCE_COMPRESSION_LEVEL || '') ||
470
- DEFAULT_CONFIG.performance.compression.level,
471
- 'performance.compression.level',
472
- { min: 1, max: 9 }
473
- ),
474
- threshold: validateNumber(
475
- coerceEnvValue(process.env.MORO_PERFORMANCE_COMPRESSION_THRESHOLD || '') ||
476
- DEFAULT_CONFIG.performance.compression.threshold,
477
- 'performance.compression.threshold',
478
- { min: 0 }
479
- ),
480
- },
481
- circuitBreaker: {
482
- enabled: validateBoolean(
483
- coerceEnvValue(process.env.MORO_PERFORMANCE_CIRCUIT_BREAKER_ENABLED || '') ??
484
- DEFAULT_CONFIG.performance.circuitBreaker.enabled,
485
- 'performance.circuitBreaker.enabled'
486
- ),
487
- failureThreshold: validateNumber(
488
- coerceEnvValue(process.env.MORO_PERFORMANCE_CIRCUIT_BREAKER_FAILURE_THRESHOLD || '') ||
489
- DEFAULT_CONFIG.performance.circuitBreaker.failureThreshold,
490
- 'performance.circuitBreaker.failureThreshold',
491
- { min: 1 }
492
- ),
493
- resetTimeout: validateNumber(
494
- coerceEnvValue(process.env.MORO_PERFORMANCE_CIRCUIT_BREAKER_RESET_TIMEOUT || '') ||
495
- DEFAULT_CONFIG.performance.circuitBreaker.resetTimeout,
496
- 'performance.circuitBreaker.resetTimeout',
497
- { min: 1000 }
498
- ),
499
- monitoringPeriod: validateNumber(
500
- coerceEnvValue(process.env.MORO_PERFORMANCE_CIRCUIT_BREAKER_MONITORING_PERIOD || '') ||
501
- DEFAULT_CONFIG.performance.circuitBreaker.monitoringPeriod,
502
- 'performance.circuitBreaker.monitoringPeriod',
503
- { min: 1000 }
504
- ),
505
- },
506
- clustering: {
507
- enabled: validateBoolean(
508
- coerceEnvValue(process.env.MORO_PERFORMANCE_CLUSTERING_ENABLED || '') ??
509
- DEFAULT_CONFIG.performance.clustering.enabled,
510
- 'performance.clustering.enabled'
511
- ),
512
- workers:
513
- process.env.MORO_PERFORMANCE_CLUSTERING_WORKERS === 'auto'
514
- ? 'auto'
515
- : validateNumber(
516
- coerceEnvValue(process.env.MORO_PERFORMANCE_CLUSTERING_WORKERS || '') ||
517
- DEFAULT_CONFIG.performance.clustering.workers,
518
- 'performance.clustering.workers',
519
- { min: 1 }
520
- ),
521
- },
522
- },
523
- };
524
-
525
- logger.info('Configuration loaded and validated successfully with TypeScript');
526
- logger.debug(
527
- 'Configuration summary:',
528
- JSON.stringify({
529
- server: { port: config.server.port, environment: config.server.environment },
530
- serviceDiscovery: {
531
- enabled: config.serviceDiscovery.enabled,
532
- type: config.serviceDiscovery.type,
533
- },
534
- modules: {
535
- cache: config.modules.cache.enabled,
536
- rateLimit: config.modules.rateLimit.enabled,
537
- validation: config.modules.validation.enabled,
538
- },
539
- })
540
- );
541
-
542
- return config;
543
- } catch (error) {
544
- logger.error('❌ Configuration validation failed');
545
-
546
- if (error instanceof ConfigValidationError) {
547
- logger.error(`Configuration error in '${error.field}': ${error.message}`);
548
- logger.error(` Value: ${JSON.stringify(error.value)}`);
549
-
550
- // Provide helpful hints
551
- if (error.field.includes('port')) {
552
- logger.error(' Hint: Ports must be numbers between 1 and 65535');
553
- }
554
- if (error.field.includes('url')) {
555
- logger.error(' Hint: URLs must include protocol (http:// or https://)');
556
- }
557
- if (error.field.includes('environment')) {
558
- logger.error(' Hint: NODE_ENV must be one of: development, staging, production');
559
- }
560
- } else {
561
- logger.error('Unexpected configuration error:', String(error));
562
- }
563
-
564
- logger.error('\nConfiguration Help:');
565
- logger.error(' - Use MORO_* prefixed environment variables for framework-specific config');
566
- logger.error(' - Check .env.example for available configuration options');
567
- logger.error(' - See documentation for detailed configuration guide');
568
-
569
- process.exit(1);
570
- }
571
- }