@morojs/moro 1.5.17 → 1.6.1
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 +48 -65
- package/dist/core/auth/morojs-adapter.js +12 -16
- package/dist/core/auth/morojs-adapter.js.map +1 -1
- package/dist/core/config/file-loader.d.ts +5 -0
- package/dist/core/config/file-loader.js +171 -0
- package/dist/core/config/file-loader.js.map +1 -1
- package/dist/core/config/index.d.ts +10 -39
- package/dist/core/config/index.js +29 -66
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.d.ts +7 -0
- package/dist/core/config/loader.js +269 -0
- package/dist/core/config/loader.js.map +1 -0
- package/dist/core/config/schema.js +31 -41
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +2 -9
- package/dist/core/config/utils.js +32 -19
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/config/validation.d.ts +17 -0
- package/dist/core/config/validation.js +131 -0
- package/dist/core/config/validation.js.map +1 -0
- package/dist/core/database/adapters/mongodb.d.ts +0 -10
- package/dist/core/database/adapters/mongodb.js +2 -23
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.d.ts +0 -11
- package/dist/core/database/adapters/mysql.js +0 -1
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.d.ts +1 -9
- package/dist/core/database/adapters/postgresql.js +1 -1
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.d.ts +0 -9
- package/dist/core/database/adapters/redis.js +4 -14
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/framework.d.ts +7 -6
- package/dist/core/framework.js +16 -131
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +0 -12
- package/dist/core/http/http-server.js +23 -151
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/router.d.ts +0 -12
- package/dist/core/http/router.js +36 -114
- package/dist/core/http/router.js.map +1 -1
- package/dist/core/logger/filters.js +4 -12
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/index.d.ts +1 -1
- package/dist/core/logger/index.js +1 -2
- package/dist/core/logger/index.js.map +1 -1
- package/dist/core/logger/logger.d.ts +13 -29
- package/dist/core/logger/logger.js +203 -380
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.js +2 -0
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/middleware/built-in/auth.js +17 -88
- package/dist/core/middleware/built-in/auth.js.map +1 -1
- package/dist/core/middleware/built-in/cache.js +1 -3
- package/dist/core/middleware/built-in/cache.js.map +1 -1
- package/dist/core/middleware/built-in/index.d.ts +0 -1
- package/dist/core/middleware/built-in/index.js +1 -6
- package/dist/core/middleware/built-in/index.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger.js +2 -3
- package/dist/core/middleware/built-in/request-logger.js.map +1 -1
- package/dist/core/middleware/built-in/sse.js +7 -9
- package/dist/core/middleware/built-in/sse.js.map +1 -1
- package/dist/core/modules/auto-discovery.d.ts +0 -17
- package/dist/core/modules/auto-discovery.js +12 -367
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/modules.js +2 -12
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.d.ts +1 -1
- package/dist/core/networking/adapters/ws-adapter.js +2 -2
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/service-discovery.js +7 -7
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/core/routing/index.d.ts +0 -20
- package/dist/core/routing/index.js +13 -178
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/runtime/node-adapter.js +6 -12
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/moro.d.ts +0 -48
- package/dist/moro.js +148 -456
- package/dist/moro.js.map +1 -1
- package/dist/types/config.d.ts +2 -58
- package/dist/types/core.d.ts +40 -34
- package/dist/types/http.d.ts +1 -16
- package/dist/types/logger.d.ts +0 -7
- package/dist/types/module.d.ts +0 -11
- package/package.json +2 -2
- package/src/core/auth/morojs-adapter.ts +13 -18
- package/src/core/config/file-loader.ts +233 -0
- package/src/core/config/index.ts +32 -77
- package/src/core/config/loader.ts +633 -0
- package/src/core/config/schema.ts +31 -41
- package/src/core/config/utils.ts +29 -22
- package/src/core/config/validation.ts +140 -0
- package/src/core/database/README.md +16 -26
- package/src/core/database/adapters/mongodb.ts +2 -30
- package/src/core/database/adapters/mysql.ts +0 -14
- package/src/core/database/adapters/postgresql.ts +2 -12
- package/src/core/database/adapters/redis.ts +4 -27
- package/src/core/framework.ts +23 -163
- package/src/core/http/http-server.ts +36 -176
- package/src/core/http/router.ts +38 -127
- package/src/core/logger/filters.ts +4 -12
- package/src/core/logger/index.ts +0 -1
- package/src/core/logger/logger.ts +216 -427
- package/src/core/logger/outputs.ts +2 -0
- package/src/core/middleware/built-in/auth.ts +17 -98
- package/src/core/middleware/built-in/cache.ts +1 -3
- package/src/core/middleware/built-in/index.ts +0 -8
- package/src/core/middleware/built-in/request-logger.ts +1 -3
- package/src/core/middleware/built-in/sse.ts +7 -9
- package/src/core/modules/auto-discovery.ts +13 -476
- package/src/core/modules/modules.ts +9 -20
- package/src/core/networking/adapters/ws-adapter.ts +5 -2
- package/src/core/networking/service-discovery.ts +7 -6
- package/src/core/routing/index.ts +14 -198
- package/src/core/runtime/node-adapter.ts +6 -12
- package/src/moro.ts +166 -554
- package/src/types/config.ts +2 -59
- package/src/types/core.ts +45 -47
- package/src/types/http.ts +1 -23
- package/src/types/logger.ts +0 -9
- package/src/types/module.ts +0 -12
- package/dist/core/config/config-manager.d.ts +0 -44
- package/dist/core/config/config-manager.js +0 -114
- package/dist/core/config/config-manager.js.map +0 -1
- package/dist/core/config/config-sources.d.ts +0 -21
- package/dist/core/config/config-sources.js +0 -502
- package/dist/core/config/config-sources.js.map +0 -1
- package/dist/core/config/config-validator.d.ts +0 -21
- package/dist/core/config/config-validator.js +0 -765
- package/dist/core/config/config-validator.js.map +0 -1
- package/dist/core/middleware/built-in/jwt-helpers.d.ts +0 -118
- package/dist/core/middleware/built-in/jwt-helpers.js +0 -221
- package/dist/core/middleware/built-in/jwt-helpers.js.map +0 -1
- package/src/core/config/config-manager.ts +0 -133
- package/src/core/config/config-sources.ts +0 -596
- package/src/core/config/config-validator.ts +0 -1078
- package/src/core/middleware/built-in/jwt-helpers.ts +0 -240
|
@@ -172,3 +172,236 @@ async function setupTypeScriptLoader(): Promise<void> {
|
|
|
172
172
|
// the TypeScript transpilation is already handled by those tools.
|
|
173
173
|
logger.debug('TypeScript config loading delegated to runtime environment');
|
|
174
174
|
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Convert a configuration object to environment variable mappings
|
|
178
|
+
* This function flattens the config object and sets corresponding environment variables
|
|
179
|
+
*/
|
|
180
|
+
export function applyConfigAsEnvironmentVariables(config: Partial<AppConfig>): void {
|
|
181
|
+
if (!config || typeof config !== 'object') {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Apply server configuration
|
|
186
|
+
if (config.server) {
|
|
187
|
+
setEnvIfNotSet('PORT', config.server.port?.toString());
|
|
188
|
+
setEnvIfNotSet('HOST', config.server.host);
|
|
189
|
+
setEnvIfNotSet('NODE_ENV', config.server.environment);
|
|
190
|
+
setEnvIfNotSet('MAX_CONNECTIONS', config.server.maxConnections?.toString());
|
|
191
|
+
setEnvIfNotSet('REQUEST_TIMEOUT', config.server.timeout?.toString());
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Apply database configuration
|
|
195
|
+
if (config.database) {
|
|
196
|
+
setEnvIfNotSet('DATABASE_URL', config.database.url);
|
|
197
|
+
|
|
198
|
+
if (config.database.redis) {
|
|
199
|
+
setEnvIfNotSet('REDIS_URL', config.database.redis.url);
|
|
200
|
+
setEnvIfNotSet('REDIS_MAX_RETRIES', config.database.redis.maxRetries?.toString());
|
|
201
|
+
setEnvIfNotSet('REDIS_RETRY_DELAY', config.database.redis.retryDelay?.toString());
|
|
202
|
+
setEnvIfNotSet('REDIS_KEY_PREFIX', config.database.redis.keyPrefix);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (config.database.mysql) {
|
|
206
|
+
setEnvIfNotSet('MYSQL_HOST', config.database.mysql.host);
|
|
207
|
+
setEnvIfNotSet('MYSQL_PORT', config.database.mysql.port?.toString());
|
|
208
|
+
setEnvIfNotSet('MYSQL_DATABASE', config.database.mysql.database);
|
|
209
|
+
setEnvIfNotSet('MYSQL_USERNAME', config.database.mysql.username);
|
|
210
|
+
setEnvIfNotSet('MYSQL_PASSWORD', config.database.mysql.password);
|
|
211
|
+
setEnvIfNotSet('MYSQL_CONNECTION_LIMIT', config.database.mysql.connectionLimit?.toString());
|
|
212
|
+
setEnvIfNotSet('MYSQL_ACQUIRE_TIMEOUT', config.database.mysql.acquireTimeout?.toString());
|
|
213
|
+
setEnvIfNotSet('MYSQL_TIMEOUT', config.database.mysql.timeout?.toString());
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Apply service discovery configuration
|
|
218
|
+
if (config.serviceDiscovery) {
|
|
219
|
+
setEnvIfNotSet('SERVICE_DISCOVERY_ENABLED', config.serviceDiscovery.enabled?.toString());
|
|
220
|
+
setEnvIfNotSet('DISCOVERY_TYPE', config.serviceDiscovery.type);
|
|
221
|
+
setEnvIfNotSet('CONSUL_URL', config.serviceDiscovery.consulUrl);
|
|
222
|
+
setEnvIfNotSet('K8S_NAMESPACE', config.serviceDiscovery.kubernetesNamespace);
|
|
223
|
+
setEnvIfNotSet(
|
|
224
|
+
'HEALTH_CHECK_INTERVAL',
|
|
225
|
+
config.serviceDiscovery.healthCheckInterval?.toString()
|
|
226
|
+
);
|
|
227
|
+
setEnvIfNotSet('DISCOVERY_RETRY_ATTEMPTS', config.serviceDiscovery.retryAttempts?.toString());
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Apply logging configuration
|
|
231
|
+
if (config.logging) {
|
|
232
|
+
setEnvIfNotSet('LOG_LEVEL', config.logging.level);
|
|
233
|
+
setEnvIfNotSet('LOG_FORMAT', config.logging.format);
|
|
234
|
+
setEnvIfNotSet('LOG_COLORS', config.logging.enableColors?.toString());
|
|
235
|
+
setEnvIfNotSet('LOG_TIMESTAMP', config.logging.enableTimestamp?.toString());
|
|
236
|
+
setEnvIfNotSet('LOG_CONTEXT', config.logging.enableContext?.toString());
|
|
237
|
+
|
|
238
|
+
if (config.logging.outputs) {
|
|
239
|
+
setEnvIfNotSet('LOG_CONSOLE', config.logging.outputs.console?.toString());
|
|
240
|
+
|
|
241
|
+
if (config.logging.outputs.file) {
|
|
242
|
+
setEnvIfNotSet('LOG_FILE_ENABLED', config.logging.outputs.file.enabled?.toString());
|
|
243
|
+
setEnvIfNotSet('LOG_FILE_PATH', config.logging.outputs.file.path);
|
|
244
|
+
setEnvIfNotSet('LOG_FILE_MAX_SIZE', config.logging.outputs.file.maxSize);
|
|
245
|
+
setEnvIfNotSet('LOG_FILE_MAX_FILES', config.logging.outputs.file.maxFiles?.toString());
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (config.logging.outputs.webhook) {
|
|
249
|
+
setEnvIfNotSet('LOG_WEBHOOK_ENABLED', config.logging.outputs.webhook.enabled?.toString());
|
|
250
|
+
setEnvIfNotSet('LOG_WEBHOOK_URL', config.logging.outputs.webhook.url);
|
|
251
|
+
if (config.logging.outputs.webhook.headers) {
|
|
252
|
+
setEnvIfNotSet(
|
|
253
|
+
'LOG_WEBHOOK_HEADERS',
|
|
254
|
+
JSON.stringify(config.logging.outputs.webhook.headers)
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Apply module defaults
|
|
262
|
+
if (config.modules) {
|
|
263
|
+
if (config.modules.cache) {
|
|
264
|
+
setEnvIfNotSet('CACHE_ENABLED', config.modules.cache.enabled?.toString());
|
|
265
|
+
setEnvIfNotSet('DEFAULT_CACHE_TTL', config.modules.cache.defaultTtl?.toString());
|
|
266
|
+
setEnvIfNotSet('CACHE_MAX_SIZE', config.modules.cache.maxSize?.toString());
|
|
267
|
+
setEnvIfNotSet('CACHE_STRATEGY', config.modules.cache.strategy);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (config.modules.rateLimit) {
|
|
271
|
+
setEnvIfNotSet('RATE_LIMIT_ENABLED', config.modules.rateLimit.enabled?.toString());
|
|
272
|
+
setEnvIfNotSet(
|
|
273
|
+
'DEFAULT_RATE_LIMIT_REQUESTS',
|
|
274
|
+
config.modules.rateLimit.defaultRequests?.toString()
|
|
275
|
+
);
|
|
276
|
+
setEnvIfNotSet(
|
|
277
|
+
'DEFAULT_RATE_LIMIT_WINDOW',
|
|
278
|
+
config.modules.rateLimit.defaultWindow?.toString()
|
|
279
|
+
);
|
|
280
|
+
setEnvIfNotSet(
|
|
281
|
+
'RATE_LIMIT_SKIP_SUCCESS',
|
|
282
|
+
config.modules.rateLimit.skipSuccessfulRequests?.toString()
|
|
283
|
+
);
|
|
284
|
+
setEnvIfNotSet(
|
|
285
|
+
'RATE_LIMIT_SKIP_FAILED',
|
|
286
|
+
config.modules.rateLimit.skipFailedRequests?.toString()
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (config.modules.validation) {
|
|
291
|
+
setEnvIfNotSet('VALIDATION_ENABLED', config.modules.validation.enabled?.toString());
|
|
292
|
+
setEnvIfNotSet(
|
|
293
|
+
'VALIDATION_STRIP_UNKNOWN',
|
|
294
|
+
config.modules.validation.stripUnknown?.toString()
|
|
295
|
+
);
|
|
296
|
+
setEnvIfNotSet('VALIDATION_ABORT_EARLY', config.modules.validation.abortEarly?.toString());
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Apply security configuration
|
|
301
|
+
if (config.security) {
|
|
302
|
+
if (config.security.cors) {
|
|
303
|
+
setEnvIfNotSet('CORS_ENABLED', config.security.cors.enabled?.toString());
|
|
304
|
+
if (typeof config.security.cors.origin === 'string') {
|
|
305
|
+
setEnvIfNotSet('CORS_ORIGIN', config.security.cors.origin);
|
|
306
|
+
} else if (Array.isArray(config.security.cors.origin)) {
|
|
307
|
+
setEnvIfNotSet('CORS_ORIGIN', config.security.cors.origin.join(','));
|
|
308
|
+
} else if (typeof config.security.cors.origin === 'boolean') {
|
|
309
|
+
setEnvIfNotSet('CORS_ORIGIN', config.security.cors.origin.toString());
|
|
310
|
+
}
|
|
311
|
+
setEnvIfNotSet('CORS_METHODS', config.security.cors.methods?.join(','));
|
|
312
|
+
setEnvIfNotSet('CORS_HEADERS', config.security.cors.allowedHeaders?.join(','));
|
|
313
|
+
setEnvIfNotSet('CORS_CREDENTIALS', config.security.cors.credentials?.toString());
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (config.security.helmet) {
|
|
317
|
+
setEnvIfNotSet('HELMET_ENABLED', config.security.helmet.enabled?.toString());
|
|
318
|
+
setEnvIfNotSet('HELMET_CSP', config.security.helmet.contentSecurityPolicy?.toString());
|
|
319
|
+
setEnvIfNotSet('HELMET_HSTS', config.security.helmet.hsts?.toString());
|
|
320
|
+
setEnvIfNotSet('HELMET_NO_SNIFF', config.security.helmet.noSniff?.toString());
|
|
321
|
+
setEnvIfNotSet('HELMET_FRAMEGUARD', config.security.helmet.frameguard?.toString());
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (config.security.rateLimit?.global) {
|
|
325
|
+
setEnvIfNotSet(
|
|
326
|
+
'GLOBAL_RATE_LIMIT_ENABLED',
|
|
327
|
+
config.security.rateLimit.global.enabled?.toString()
|
|
328
|
+
);
|
|
329
|
+
setEnvIfNotSet(
|
|
330
|
+
'GLOBAL_RATE_LIMIT_REQUESTS',
|
|
331
|
+
config.security.rateLimit.global.requests?.toString()
|
|
332
|
+
);
|
|
333
|
+
setEnvIfNotSet(
|
|
334
|
+
'GLOBAL_RATE_LIMIT_WINDOW',
|
|
335
|
+
config.security.rateLimit.global.window?.toString()
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Apply external services configuration
|
|
341
|
+
if (config.external) {
|
|
342
|
+
if (config.external.stripe) {
|
|
343
|
+
setEnvIfNotSet('STRIPE_SECRET_KEY', config.external.stripe.secretKey);
|
|
344
|
+
setEnvIfNotSet('STRIPE_PUBLISHABLE_KEY', config.external.stripe.publishableKey);
|
|
345
|
+
setEnvIfNotSet('STRIPE_WEBHOOK_SECRET', config.external.stripe.webhookSecret);
|
|
346
|
+
setEnvIfNotSet('STRIPE_API_VERSION', config.external.stripe.apiVersion);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (config.external.paypal) {
|
|
350
|
+
setEnvIfNotSet('PAYPAL_CLIENT_ID', config.external.paypal.clientId);
|
|
351
|
+
setEnvIfNotSet('PAYPAL_CLIENT_SECRET', config.external.paypal.clientSecret);
|
|
352
|
+
setEnvIfNotSet('PAYPAL_WEBHOOK_ID', config.external.paypal.webhookId);
|
|
353
|
+
setEnvIfNotSet('PAYPAL_ENVIRONMENT', config.external.paypal.environment);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (config.external.smtp) {
|
|
357
|
+
setEnvIfNotSet('SMTP_HOST', config.external.smtp.host);
|
|
358
|
+
setEnvIfNotSet('SMTP_PORT', config.external.smtp.port?.toString());
|
|
359
|
+
setEnvIfNotSet('SMTP_SECURE', config.external.smtp.secure?.toString());
|
|
360
|
+
setEnvIfNotSet('SMTP_USERNAME', config.external.smtp.username);
|
|
361
|
+
setEnvIfNotSet('SMTP_PASSWORD', config.external.smtp.password);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Apply performance configuration
|
|
366
|
+
if (config.performance) {
|
|
367
|
+
if (config.performance.compression) {
|
|
368
|
+
setEnvIfNotSet('COMPRESSION_ENABLED', config.performance.compression.enabled?.toString());
|
|
369
|
+
setEnvIfNotSet('COMPRESSION_LEVEL', config.performance.compression.level?.toString());
|
|
370
|
+
setEnvIfNotSet('COMPRESSION_THRESHOLD', config.performance.compression.threshold?.toString());
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (config.performance.circuitBreaker) {
|
|
374
|
+
setEnvIfNotSet(
|
|
375
|
+
'CIRCUIT_BREAKER_ENABLED',
|
|
376
|
+
config.performance.circuitBreaker.enabled?.toString()
|
|
377
|
+
);
|
|
378
|
+
setEnvIfNotSet(
|
|
379
|
+
'CIRCUIT_BREAKER_THRESHOLD',
|
|
380
|
+
config.performance.circuitBreaker.failureThreshold?.toString()
|
|
381
|
+
);
|
|
382
|
+
setEnvIfNotSet(
|
|
383
|
+
'CIRCUIT_BREAKER_RESET',
|
|
384
|
+
config.performance.circuitBreaker.resetTimeout?.toString()
|
|
385
|
+
);
|
|
386
|
+
setEnvIfNotSet(
|
|
387
|
+
'CIRCUIT_BREAKER_MONITOR',
|
|
388
|
+
config.performance.circuitBreaker.monitoringPeriod?.toString()
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (config.performance.clustering) {
|
|
393
|
+
setEnvIfNotSet('CLUSTERING_ENABLED', config.performance.clustering.enabled?.toString());
|
|
394
|
+
setEnvIfNotSet('CLUSTER_WORKERS', config.performance.clustering.workers?.toString());
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Set environment variable only if it's not already set
|
|
401
|
+
* This ensures environment variables take precedence over config file values
|
|
402
|
+
*/
|
|
403
|
+
function setEnvIfNotSet(key: string, value: string | undefined): void {
|
|
404
|
+
if (value !== undefined && process.env[key] === undefined) {
|
|
405
|
+
process.env[key] = value;
|
|
406
|
+
}
|
|
407
|
+
}
|
package/src/core/config/index.ts
CHANGED
|
@@ -1,105 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
* Configuration System - Immutable Config with createApp Override Support
|
|
3
|
-
*
|
|
4
|
-
* This is the main entry point for the MoroJS configuration system.
|
|
5
|
-
* It provides a clean, immutable configuration that is locked at createApp() time.
|
|
6
|
-
*
|
|
7
|
-
* Key Features:
|
|
8
|
-
* - Immutable configuration after initialization
|
|
9
|
-
* - Clear precedence: Env Vars > createApp Options > Config File > Defaults
|
|
10
|
-
* - Type-safe validation
|
|
11
|
-
* - Single source of truth
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// Export types and core components
|
|
1
|
+
// Configuration System - Main Exports and Utilities
|
|
15
2
|
export * from './schema';
|
|
16
|
-
export * from './
|
|
17
|
-
export * from './config-validator';
|
|
18
|
-
export * from './file-loader';
|
|
19
|
-
|
|
20
|
-
// Export specific functions from config-manager to avoid conflicts
|
|
21
|
-
export { initializeAndLockConfig, isConfigLocked, resetConfigForTesting } from './config-manager';
|
|
22
|
-
|
|
23
|
-
// Export utilities for backward compatibility
|
|
3
|
+
export * from './loader';
|
|
24
4
|
export * from './utils';
|
|
5
|
+
export * from './file-loader';
|
|
25
6
|
|
|
26
|
-
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
initializeAndLockConfig,
|
|
31
|
-
getGlobalConfig as getConfig,
|
|
32
|
-
isConfigLocked,
|
|
33
|
-
resetConfigForTesting,
|
|
34
|
-
} from './config-manager';
|
|
35
|
-
import { createFrameworkLogger } from '../logger';
|
|
7
|
+
// Main configuration loading function
|
|
8
|
+
import { loadConfig } from './loader';
|
|
9
|
+
import type { AppConfig } from './schema';
|
|
10
|
+
import { setConfig } from './utils';
|
|
36
11
|
|
|
37
|
-
|
|
12
|
+
// Global configuration instance
|
|
13
|
+
let globalConfig: AppConfig | null = null;
|
|
38
14
|
|
|
39
15
|
/**
|
|
40
|
-
* Initialize
|
|
41
|
-
* This
|
|
42
|
-
*
|
|
43
|
-
* @param options - createApp options that can override config file and defaults
|
|
44
|
-
* @returns Immutable, validated configuration object
|
|
16
|
+
* Initialize and load the global application configuration
|
|
17
|
+
* This should be called once at application startup
|
|
45
18
|
*/
|
|
46
|
-
export function initializeConfig(
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
return getConfig();
|
|
19
|
+
export function initializeConfig(): AppConfig {
|
|
20
|
+
if (globalConfig) {
|
|
21
|
+
return globalConfig;
|
|
50
22
|
}
|
|
51
23
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Load configuration from all sources with proper precedence
|
|
55
|
-
const config = loadConfigFromAllSources(options);
|
|
24
|
+
globalConfig = loadConfig();
|
|
56
25
|
|
|
57
|
-
//
|
|
58
|
-
|
|
26
|
+
// Also set the config for utils functions
|
|
27
|
+
setConfig(globalConfig);
|
|
59
28
|
|
|
60
|
-
|
|
61
|
-
`Configuration system initialized and locked: ${process.env.NODE_ENV || 'development'}:${config.server.port} (sources: env + file + options + defaults)`
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
return config;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Load configuration without locking (for testing and utilities)
|
|
69
|
-
* This maintains backward compatibility with existing code
|
|
70
|
-
*/
|
|
71
|
-
export function loadConfig(): AppConfig {
|
|
72
|
-
return loadConfigFromAllSources();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Load configuration with createApp options (for testing and utilities)
|
|
77
|
-
* This maintains backward compatibility with existing code
|
|
78
|
-
*/
|
|
79
|
-
export function loadConfigWithOptions(options: MoroOptions): AppConfig {
|
|
80
|
-
return loadConfigFromAllSources(options);
|
|
29
|
+
return globalConfig;
|
|
81
30
|
}
|
|
82
31
|
|
|
83
32
|
/**
|
|
84
33
|
* Get the current global configuration
|
|
85
|
-
*
|
|
34
|
+
* Throws if configuration hasn't been initialized
|
|
86
35
|
*/
|
|
87
|
-
export function getGlobalConfig():
|
|
88
|
-
|
|
36
|
+
export function getGlobalConfig(): AppConfig {
|
|
37
|
+
if (!globalConfig) {
|
|
38
|
+
throw new Error('Configuration not initialized. Call initializeConfig() first.');
|
|
39
|
+
}
|
|
40
|
+
return globalConfig;
|
|
89
41
|
}
|
|
90
42
|
|
|
91
43
|
/**
|
|
92
|
-
* Check if configuration has been initialized
|
|
93
|
-
* Alias for isConfigLocked() for backward compatibility
|
|
44
|
+
* Check if configuration has been initialized
|
|
94
45
|
*/
|
|
95
46
|
export function isConfigInitialized(): boolean {
|
|
96
|
-
return
|
|
47
|
+
return globalConfig !== null;
|
|
97
48
|
}
|
|
98
49
|
|
|
99
50
|
/**
|
|
100
|
-
* Reset configuration state (for testing
|
|
51
|
+
* Reset the global configuration state (for testing purposes)
|
|
101
52
|
* @internal
|
|
102
53
|
*/
|
|
103
54
|
export function resetConfig(): void {
|
|
104
|
-
|
|
55
|
+
globalConfig = null;
|
|
56
|
+
|
|
57
|
+
// Also reset the utils config (by setting it to null via direct access)
|
|
58
|
+
const { setConfig } = require('./utils');
|
|
59
|
+
setConfig(null as any);
|
|
105
60
|
}
|