@morojs/moro 1.0.2 → 1.1.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.
@@ -32,12 +32,53 @@ function getConfig() {
32
32
  }
33
33
  return appConfig;
34
34
  }
35
+ /**
36
+ * Coerce environment variable string values to appropriate types
37
+ */
38
+ function coerceEnvironmentValue(value) {
39
+ // Handle boolean values
40
+ if (value.toLowerCase() === 'true')
41
+ return true;
42
+ if (value.toLowerCase() === 'false')
43
+ return false;
44
+ // Handle numeric values
45
+ if (/^\d+$/.test(value)) {
46
+ const num = parseInt(value, 10);
47
+ return num;
48
+ }
49
+ if (/^\d+\.\d+$/.test(value)) {
50
+ const num = parseFloat(value);
51
+ return num;
52
+ }
53
+ // Handle JSON objects/arrays
54
+ if ((value.startsWith('{') && value.endsWith('}')) ||
55
+ (value.startsWith('[') && value.endsWith(']'))) {
56
+ try {
57
+ return JSON.parse(value);
58
+ }
59
+ catch {
60
+ // If JSON parsing fails, return as string
61
+ return value;
62
+ }
63
+ }
64
+ // Return as string for all other cases
65
+ return value;
66
+ }
35
67
  /**
36
68
  * Create module-specific configuration with environment override support
37
69
  */
38
70
  function createModuleConfig(schema, defaultConfig, envPrefix) {
39
- const globalConfig = getConfig();
40
- // Build environment configuration object
71
+ // Try to get global config, but don't fail if not initialized
72
+ let globalConfig = {};
73
+ try {
74
+ const { getGlobalConfig } = require('./index');
75
+ globalConfig = getGlobalConfig();
76
+ }
77
+ catch {
78
+ // Global config not initialized - use empty object (module config can still work independently)
79
+ globalConfig = {};
80
+ }
81
+ // Build environment configuration object with type coercion
41
82
  const envConfig = {};
42
83
  if (envPrefix) {
43
84
  // Extract environment variables with the given prefix
@@ -47,13 +88,19 @@ function createModuleConfig(schema, defaultConfig, envPrefix) {
47
88
  .substring(envPrefix.length)
48
89
  .toLowerCase()
49
90
  .replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
50
- envConfig[configKey] = process.env[key];
91
+ const envValue = process.env[key];
92
+ if (envValue !== undefined) {
93
+ // Attempt basic type coercion for common types
94
+ envConfig[configKey] = coerceEnvironmentValue(envValue);
95
+ }
51
96
  }
52
97
  });
53
98
  }
54
99
  // Merge default config, global defaults, and environment overrides
100
+ // Priority: environment variables > global config > default config
55
101
  const mergedConfig = {
56
102
  ...defaultConfig,
103
+ ...globalConfig, // Now actually using global config!
57
104
  ...envConfig,
58
105
  };
59
106
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/core/config/utils.ts"],"names":[],"mappings":";;AAaA,8BAGC;AAKD,8BAKC;AAKD,gDAoCC;AAKD,8BA2BC;AAKD,kCAWC;AAKD,gCAaC;AAKD,wCAYC;AAKD,wBAEC;AAKD,wCAMC;AAKD,sCAMC;AAKD,oCAMC;AAKD,8BAMC;AAtMD,sCAAkD;AAElD,MAAM,MAAM,GAAG,IAAA,8BAAqB,EAAC,aAAa,CAAC,CAAC;AAEpD,6BAA6B;AAC7B,IAAI,SAAS,GAAqB,IAAI,CAAC;AAEvC;;GAEG;AACH,SAAgB,SAAS,CAAC,MAAiB;IACzC,SAAS,GAAG,MAAM,CAAC;IACnB,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS;IACvB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAChC,MAAsB,EACtB,aAAyB,EACzB,SAAkB;IAElB,MAAM,YAAY,GAAG,SAAS,EAAE,CAAC;IAEjC,yCAAyC;IACzC,MAAM,SAAS,GAAwB,EAAE,CAAC;IAE1C,IAAI,SAAS,EAAE,CAAC;QACd,sDAAsD;QACtD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACrC,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9B,MAAM,SAAS,GAAG,GAAG;qBAClB,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC;qBAC3B,WAAW,EAAE;qBACb,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;gBAE7D,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,mEAAmE;IACnE,MAAM,YAAY,GAAG;QACnB,GAAG,aAAa;QAChB,GAAG,SAAS;KACb,CAAC;IAEF,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,qDAAqD,SAAS,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/F,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS,CAAI,GAAW,EAAE,YAAe,EAAE,SAAgC;IACzF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC;YACH,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,0CAA0C,GAAG,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC7E,OAAO,YAAY,CAAC;QACtB,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,IAAI,OAAO,YAAY,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,CAAM,CAAC;IAC/C,CAAC;IAED,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAM,CAAC;IAChD,CAAC;IAED,OAAO,KAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,GAAW,EAAE,eAAyB,EAAE;IAClE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SACxB,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU,CAAI,GAAW,EAAE,YAAe;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,6CAA6C,GAAG,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAChF,OAAO,YAAY,CAAC;IACtB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,GAAG,IAAc;IAC9C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,2CAA2C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,MAAM,CAAC,MAAc,EAAE,IAAY;IACjD,OAAO,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,IAAY;IACzC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACzC,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,CAAC,EAAE,MAAa,CAAC,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa;IAC3B,IAAI,CAAC;QACH,OAAO,SAAS,EAAE,CAAC,MAAM,CAAC,WAAW,KAAK,aAAa,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY;IAC1B,IAAI,CAAC;QACH,OAAO,SAAS,EAAE,CAAC,MAAM,CAAC,WAAW,KAAK,YAAY,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS;IACvB,IAAI,CAAC;QACH,OAAO,SAAS,EAAE,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/core/config/utils.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -21,7 +21,8 @@ export type { RouteBuilder, RouteSchema, CompiledRoute, HttpMethod, AuthConfig,
21
21
  export { DocumentationSystem, AppDocumentationManager, createDocumentationSystem, generateDocsFromIntelligentRoutes, } from './core/docs';
22
22
  export type { DocsConfig } from './core/docs';
23
23
  export { getConfig, createModuleConfig, getEnvVar, getEnvArray, getEnvJson, isDevelopment, isProduction, isStaging, requireEnvVars, envVar, getConfigValue, } from './core/config/utils';
24
- export { initializeConfig, getGlobalConfig, isConfigInitialized } from './core/config';
24
+ export { initializeConfig, getGlobalConfig, isConfigInitialized, resetConfig } from './core/config';
25
+ export type { AppConfig } from './core/config';
25
26
  export { MiddlewareManager } from './core/middleware';
26
27
  export type { MiddlewareInterface, MoroMiddleware } from './core/middleware';
27
28
  export type * from './types/core';
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.EXECUTION_PHASES = exports.defineRoute = exports.createRoute = exports.autoDiscoverModuleDirectories = exports.ModuleDiscovery = exports.ModuleLoader = exports.defineModule = exports.z = exports.combineSchemas = exports.params = exports.query = exports.body = exports.validate = exports.logger = exports.createFrameworkLogger = exports.MoroEventBus = exports.middleware = exports.HOOK_EVENTS = exports.HookManager = exports.CircuitBreaker = exports.withTimeout = exports.withRetry = exports.withCaching = exports.withLogging = exports.ServiceLifecycle = exports.ServiceScope = exports.FunctionalContainer = exports.Container = exports.ServiceRegistry = exports.WebSocketManager = exports.simpleMiddleware = exports.builtInMiddleware = exports.httpMiddleware = exports.MoroHttpServer = exports.createWorkerHandler = exports.createLambdaHandler = exports.createEdgeHandler = exports.createNodeHandler = exports.createRuntimeAdapter = exports.CloudflareWorkersAdapter = exports.AWSLambdaAdapter = exports.VercelEdgeAdapter = exports.NodeRuntimeAdapter = exports.createAppWorker = exports.createAppLambda = exports.createAppEdge = exports.createAppNode = exports.createApp = exports.MoroCore = exports.Moro = void 0;
18
- exports.MiddlewareManager = exports.isConfigInitialized = exports.getGlobalConfig = exports.initializeConfig = exports.getConfigValue = exports.envVar = exports.requireEnvVars = exports.isStaging = exports.isProduction = exports.isDevelopment = exports.getEnvJson = exports.getEnvArray = exports.getEnvVar = exports.createModuleConfig = exports.getConfig = exports.generateDocsFromIntelligentRoutes = exports.createDocumentationSystem = exports.AppDocumentationManager = exports.DocumentationSystem = exports.RouteRegistry = exports.IntelligentRoutingManager = void 0;
18
+ exports.MiddlewareManager = exports.resetConfig = exports.isConfigInitialized = exports.getGlobalConfig = exports.initializeConfig = exports.getConfigValue = exports.envVar = exports.requireEnvVars = exports.isStaging = exports.isProduction = exports.isDevelopment = exports.getEnvJson = exports.getEnvArray = exports.getEnvVar = exports.createModuleConfig = exports.getConfig = exports.generateDocsFromIntelligentRoutes = exports.createDocumentationSystem = exports.AppDocumentationManager = exports.DocumentationSystem = exports.RouteRegistry = exports.IntelligentRoutingManager = void 0;
19
19
  // MoroJS Framework - Main Entry Point
20
20
  var moro_1 = require("./moro");
21
21
  Object.defineProperty(exports, "Moro", { enumerable: true, get: function () { return moro_1.Moro; } });
@@ -112,6 +112,7 @@ var config_1 = require("./core/config");
112
112
  Object.defineProperty(exports, "initializeConfig", { enumerable: true, get: function () { return config_1.initializeConfig; } });
113
113
  Object.defineProperty(exports, "getGlobalConfig", { enumerable: true, get: function () { return config_1.getGlobalConfig; } });
114
114
  Object.defineProperty(exports, "isConfigInitialized", { enumerable: true, get: function () { return config_1.isConfigInitialized; } });
115
+ Object.defineProperty(exports, "resetConfig", { enumerable: true, get: function () { return config_1.resetConfig; } });
115
116
  // Middleware System
116
117
  var middleware_1 = require("./core/middleware");
117
118
  Object.defineProperty(exports, "MiddlewareManager", { enumerable: true, get: function () { return middleware_1.MiddlewareManager; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,sCAAsC;AACtC,+BAQgB;AAPd,4FAAA,IAAI,OAAA;AACJ,gGAAA,IAAI,OAAY;AAChB,iGAAA,SAAS,OAAA;AACT,qGAAA,aAAa,OAAA;AACb,qGAAA,aAAa,OAAA;AACb,uGAAA,eAAe,OAAA;AACf,uGAAA,eAAe,OAAA;AAajB,0CAUwB;AATtB,6GAAA,kBAAkB,OAAA;AAClB,4GAAA,iBAAiB,OAAA;AACjB,2GAAA,gBAAgB,OAAA;AAChB,mHAAA,wBAAwB,OAAA;AACxB,+GAAA,oBAAoB,OAAA;AACpB,4GAAA,iBAAiB,OAAA;AACjB,4GAAA,iBAAiB,OAAA;AACjB,8GAAA,mBAAmB,OAAA;AACnB,8GAAA,mBAAmB,OAAA;AAOrB,eAAe;AACf,oCAA2E;AAAlE,sGAAA,cAAc,OAAA;AAAE,sGAAA,UAAU,OAAkB;AACrD,uDAAiF;AAAxE,6GAAA,iBAAiB,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAE5C,oBAAoB;AACpB,gDAK2B;AAJzB,8GAAA,gBAAgB,OAAA;AAChB,6GAAA,eAAe,OAAA;AAKjB,iCAAiC;AACjC,8CAa0B;AAZxB,sGAAA,SAAS,OAAA;AACT,gHAAA,mBAAmB,OAAA;AACnB,yGAAA,YAAY,OAAA;AACZ,6GAAA,gBAAgB,OAAA;AAChB,wGAAA,WAAW,OAAA;AACX,wGAAA,WAAW,OAAA;AACX,sGAAA,SAAS,OAAA;AACT,wGAAA,WAAW,OAAA;AACX,2GAAA,cAAc,OAAA;AACd,wGAAA,WAAW,OAAA;AACX,wGAAA,WAAW,OAAA;AACX,uGAAA,UAAU,OAAA;AAGZ,eAAe;AACf,wCAA6C;AAApC,sGAAA,YAAY,OAAA;AAYrB,gBAAgB;AAChB,wCAA8D;AAArD,+GAAA,qBAAqB,OAAA;AAAE,gGAAA,MAAM,OAAA;AAEtC,gCAAgC;AAChC,gDAAqF;AAA5E,sGAAA,QAAQ,OAAA;AAAE,kGAAA,IAAI,OAAA;AAAE,mGAAA,KAAK,OAAA;AAAE,oGAAA,MAAM,OAAA;AAAE,4GAAA,cAAc,OAAA;AAAE,+FAAA,CAAC,OAAA;AAQzD,gBAAgB;AAChB,0CAKwB;AAJtB,uGAAA,YAAY,OAAA;AACZ,uGAAA,YAAY,OAAA;AACZ,0GAAA,eAAe,OAAA;AACf,wHAAA,6BAA6B,OAAA;AAI/B,6BAA6B;AAC7B,0CAA4E;AAAnE,sGAAA,WAAW,OAAA;AAAE,sGAAA,WAAW,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AACnD,kEAA0F;AAAjF,4HAAA,yBAAyB,OAAA;AAAE,gHAAA,aAAa,OAAA;AAajD,uBAAuB;AACvB,oCAKqB;AAJnB,2GAAA,mBAAmB,OAAA;AACnB,+GAAA,uBAAuB,OAAA;AACvB,iHAAA,yBAAyB,OAAA;AACzB,yHAAA,iCAAiC,OAAA;AAInC,0BAA0B;AAC1B,6CAY6B;AAX3B,kGAAA,SAAS,OAAA;AACT,2GAAA,kBAAkB,OAAA;AAClB,kGAAA,SAAS,OAAA;AACT,oGAAA,WAAW,OAAA;AACX,mGAAA,UAAU,OAAA;AACV,sGAAA,aAAa,OAAA;AACb,qGAAA,YAAY,OAAA;AACZ,kGAAA,SAAS,OAAA;AACT,uGAAA,cAAc,OAAA;AACd,+FAAA,MAAM,OAAA;AACN,uGAAA,cAAc,OAAA;AAGhB,wCAAuF;AAA9E,0GAAA,gBAAgB,OAAA;AAAE,yGAAA,eAAe,OAAA;AAAE,6GAAA,mBAAmB,OAAA;AAE/D,oBAAoB;AACpB,gDAAsD;AAA7C,+GAAA,iBAAiB,OAAA;AAc1B,WAAW;AACX,sEAAoD;AACpD,2DAAyC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morojs/moro",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "High-performance Node.js framework with intelligent routing, automatic middleware ordering, type-safe Zod validation, and functional architecture",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,398 @@
1
+ // Configuration File Loader - Load moro.config.js/ts files
2
+ import { existsSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { AppConfig } from './schema';
5
+ import { createFrameworkLogger } from '../logger';
6
+
7
+ const logger = createFrameworkLogger('ConfigFile');
8
+
9
+ /**
10
+ * Supported configuration file names in order of preference
11
+ */
12
+ const CONFIG_FILES = ['moro.config.js', 'moro.config.ts'] as const;
13
+
14
+ /**
15
+ * Find and load configuration from moro.config.js (synchronously)
16
+ * @param cwd Current working directory to search for config files
17
+ * @returns Partial configuration object or null if no config file found
18
+ */
19
+ export function loadConfigFileSync(cwd: string = process.cwd()): Partial<AppConfig> | null {
20
+ const configFile = findConfigFile(cwd);
21
+
22
+ if (!configFile) {
23
+ logger.debug('No configuration file found');
24
+ return null;
25
+ }
26
+
27
+ // Only support .js files for synchronous loading to avoid complexity
28
+ if (!configFile.endsWith('.js')) {
29
+ logger.debug(
30
+ 'Found config file, but only JavaScript files are supported in sync mode. Use loadConfigFile() for TypeScript support.'
31
+ );
32
+ return null;
33
+ }
34
+
35
+ logger.debug(`Loading configuration from: ${configFile}`);
36
+
37
+ try {
38
+ // Clear module cache to ensure fresh load
39
+ delete require.cache[require.resolve(configFile)];
40
+
41
+ const config = require(configFile);
42
+ const configData = config.default || config;
43
+
44
+ if (!configData || typeof configData !== 'object') {
45
+ logger.warn(`Configuration file ${configFile} did not export a valid configuration object`);
46
+ return null;
47
+ }
48
+
49
+ logger.info(`Configuration loaded from: ${configFile}`);
50
+ return configData;
51
+ } catch (error) {
52
+ logger.error(`Failed to load configuration file ${configFile}:`, String(error));
53
+ logger.warn('Falling back to environment variable configuration');
54
+ return null;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Find and load configuration from moro.config.js or moro.config.ts (async)
60
+ * @param cwd Current working directory to search for config files
61
+ * @returns Partial configuration object or null if no config file found
62
+ */
63
+ export async function loadConfigFile(
64
+ cwd: string = process.cwd()
65
+ ): Promise<Partial<AppConfig> | null> {
66
+ const configFile = findConfigFile(cwd);
67
+
68
+ if (!configFile) {
69
+ logger.debug('No configuration file found');
70
+ return null;
71
+ }
72
+
73
+ logger.debug(`Loading configuration from: ${configFile}`);
74
+
75
+ try {
76
+ const config = await importConfigFile(configFile);
77
+
78
+ if (!config || typeof config !== 'object') {
79
+ logger.warn(`Configuration file ${configFile} did not export a valid configuration object`);
80
+ return null;
81
+ }
82
+
83
+ logger.info(`Configuration loaded from: ${configFile}`);
84
+ return config;
85
+ } catch (error) {
86
+ logger.error(`Failed to load configuration file ${configFile}:`, String(error));
87
+ logger.warn('Falling back to environment variable configuration');
88
+ return null;
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Find the first existing configuration file in the given directory
94
+ */
95
+ function findConfigFile(cwd: string): string | null {
96
+ for (const fileName of CONFIG_FILES) {
97
+ const filePath = join(cwd, fileName);
98
+ if (existsSync(filePath)) {
99
+ return filePath;
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+
105
+ /**
106
+ * Dynamically import a configuration file
107
+ */
108
+ async function importConfigFile(filePath: string): Promise<Partial<AppConfig> | null> {
109
+ const isTypeScript = filePath.endsWith('.ts');
110
+
111
+ if (isTypeScript) {
112
+ // For TypeScript files, we need to handle ts-node/tsx or similar
113
+ await setupTypeScriptLoader();
114
+ }
115
+
116
+ try {
117
+ // Use dynamic import to load the configuration
118
+ const configModule = await import(filePath);
119
+
120
+ // Handle both default export and module.exports
121
+ const config = configModule.default || configModule;
122
+
123
+ return config;
124
+ } catch (error) {
125
+ // If TypeScript loading fails, provide helpful error message
126
+ if (
127
+ isTypeScript &&
128
+ error instanceof Error &&
129
+ error.message.includes('Unknown file extension')
130
+ ) {
131
+ throw new Error(
132
+ `Failed to load TypeScript config file. Make sure you have ts-node installed: npm install --save-dev ts-node`
133
+ );
134
+ }
135
+ throw error;
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Setup TypeScript loader for .ts config files
141
+ */
142
+ async function setupTypeScriptLoader(): Promise<void> {
143
+ try {
144
+ // Try to register ts-node if available
145
+ const tsNode = await import('ts-node');
146
+ if (!tsNode.register) {
147
+ // ts-node might already be registered
148
+ return;
149
+ }
150
+
151
+ tsNode.register({
152
+ transpileOnly: true,
153
+ compilerOptions: {
154
+ module: 'commonjs',
155
+ target: 'es2020',
156
+ moduleResolution: 'node',
157
+ allowSyntheticDefaultImports: true,
158
+ esModuleInterop: true,
159
+ },
160
+ });
161
+ } catch (error) {
162
+ // ts-node not available, try other methods or fail gracefully
163
+ logger.debug('ts-node not available for TypeScript config loading');
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Convert a configuration object to environment variable mappings
169
+ * This function flattens the config object and sets corresponding environment variables
170
+ */
171
+ export function applyConfigAsEnvironmentVariables(config: Partial<AppConfig>): void {
172
+ if (!config || typeof config !== 'object') {
173
+ return;
174
+ }
175
+
176
+ // Apply server configuration
177
+ if (config.server) {
178
+ setEnvIfNotSet('PORT', config.server.port?.toString());
179
+ setEnvIfNotSet('HOST', config.server.host);
180
+ setEnvIfNotSet('NODE_ENV', config.server.environment);
181
+ setEnvIfNotSet('MAX_CONNECTIONS', config.server.maxConnections?.toString());
182
+ setEnvIfNotSet('REQUEST_TIMEOUT', config.server.timeout?.toString());
183
+ }
184
+
185
+ // Apply database configuration
186
+ if (config.database) {
187
+ setEnvIfNotSet('DATABASE_URL', config.database.url);
188
+
189
+ if (config.database.redis) {
190
+ setEnvIfNotSet('REDIS_URL', config.database.redis.url);
191
+ setEnvIfNotSet('REDIS_MAX_RETRIES', config.database.redis.maxRetries?.toString());
192
+ setEnvIfNotSet('REDIS_RETRY_DELAY', config.database.redis.retryDelay?.toString());
193
+ setEnvIfNotSet('REDIS_KEY_PREFIX', config.database.redis.keyPrefix);
194
+ }
195
+
196
+ if (config.database.mysql) {
197
+ setEnvIfNotSet('MYSQL_HOST', config.database.mysql.host);
198
+ setEnvIfNotSet('MYSQL_PORT', config.database.mysql.port?.toString());
199
+ setEnvIfNotSet('MYSQL_DATABASE', config.database.mysql.database);
200
+ setEnvIfNotSet('MYSQL_USERNAME', config.database.mysql.username);
201
+ setEnvIfNotSet('MYSQL_PASSWORD', config.database.mysql.password);
202
+ setEnvIfNotSet('MYSQL_CONNECTION_LIMIT', config.database.mysql.connectionLimit?.toString());
203
+ setEnvIfNotSet('MYSQL_ACQUIRE_TIMEOUT', config.database.mysql.acquireTimeout?.toString());
204
+ setEnvIfNotSet('MYSQL_TIMEOUT', config.database.mysql.timeout?.toString());
205
+ }
206
+ }
207
+
208
+ // Apply service discovery configuration
209
+ if (config.serviceDiscovery) {
210
+ setEnvIfNotSet('SERVICE_DISCOVERY_ENABLED', config.serviceDiscovery.enabled?.toString());
211
+ setEnvIfNotSet('DISCOVERY_TYPE', config.serviceDiscovery.type);
212
+ setEnvIfNotSet('CONSUL_URL', config.serviceDiscovery.consulUrl);
213
+ setEnvIfNotSet('K8S_NAMESPACE', config.serviceDiscovery.kubernetesNamespace);
214
+ setEnvIfNotSet(
215
+ 'HEALTH_CHECK_INTERVAL',
216
+ config.serviceDiscovery.healthCheckInterval?.toString()
217
+ );
218
+ setEnvIfNotSet('DISCOVERY_RETRY_ATTEMPTS', config.serviceDiscovery.retryAttempts?.toString());
219
+ }
220
+
221
+ // Apply logging configuration
222
+ if (config.logging) {
223
+ setEnvIfNotSet('LOG_LEVEL', config.logging.level);
224
+ setEnvIfNotSet('LOG_FORMAT', config.logging.format);
225
+ setEnvIfNotSet('LOG_COLORS', config.logging.enableColors?.toString());
226
+ setEnvIfNotSet('LOG_TIMESTAMP', config.logging.enableTimestamp?.toString());
227
+ setEnvIfNotSet('LOG_CONTEXT', config.logging.enableContext?.toString());
228
+
229
+ if (config.logging.outputs) {
230
+ setEnvIfNotSet('LOG_CONSOLE', config.logging.outputs.console?.toString());
231
+
232
+ if (config.logging.outputs.file) {
233
+ setEnvIfNotSet('LOG_FILE_ENABLED', config.logging.outputs.file.enabled?.toString());
234
+ setEnvIfNotSet('LOG_FILE_PATH', config.logging.outputs.file.path);
235
+ setEnvIfNotSet('LOG_FILE_MAX_SIZE', config.logging.outputs.file.maxSize);
236
+ setEnvIfNotSet('LOG_FILE_MAX_FILES', config.logging.outputs.file.maxFiles?.toString());
237
+ }
238
+
239
+ if (config.logging.outputs.webhook) {
240
+ setEnvIfNotSet('LOG_WEBHOOK_ENABLED', config.logging.outputs.webhook.enabled?.toString());
241
+ setEnvIfNotSet('LOG_WEBHOOK_URL', config.logging.outputs.webhook.url);
242
+ if (config.logging.outputs.webhook.headers) {
243
+ setEnvIfNotSet(
244
+ 'LOG_WEBHOOK_HEADERS',
245
+ JSON.stringify(config.logging.outputs.webhook.headers)
246
+ );
247
+ }
248
+ }
249
+ }
250
+ }
251
+
252
+ // Apply module defaults
253
+ if (config.modules) {
254
+ if (config.modules.cache) {
255
+ setEnvIfNotSet('CACHE_ENABLED', config.modules.cache.enabled?.toString());
256
+ setEnvIfNotSet('DEFAULT_CACHE_TTL', config.modules.cache.defaultTtl?.toString());
257
+ setEnvIfNotSet('CACHE_MAX_SIZE', config.modules.cache.maxSize?.toString());
258
+ setEnvIfNotSet('CACHE_STRATEGY', config.modules.cache.strategy);
259
+ }
260
+
261
+ if (config.modules.rateLimit) {
262
+ setEnvIfNotSet('RATE_LIMIT_ENABLED', config.modules.rateLimit.enabled?.toString());
263
+ setEnvIfNotSet(
264
+ 'DEFAULT_RATE_LIMIT_REQUESTS',
265
+ config.modules.rateLimit.defaultRequests?.toString()
266
+ );
267
+ setEnvIfNotSet(
268
+ 'DEFAULT_RATE_LIMIT_WINDOW',
269
+ config.modules.rateLimit.defaultWindow?.toString()
270
+ );
271
+ setEnvIfNotSet(
272
+ 'RATE_LIMIT_SKIP_SUCCESS',
273
+ config.modules.rateLimit.skipSuccessfulRequests?.toString()
274
+ );
275
+ setEnvIfNotSet(
276
+ 'RATE_LIMIT_SKIP_FAILED',
277
+ config.modules.rateLimit.skipFailedRequests?.toString()
278
+ );
279
+ }
280
+
281
+ if (config.modules.validation) {
282
+ setEnvIfNotSet('VALIDATION_ENABLED', config.modules.validation.enabled?.toString());
283
+ setEnvIfNotSet(
284
+ 'VALIDATION_STRIP_UNKNOWN',
285
+ config.modules.validation.stripUnknown?.toString()
286
+ );
287
+ setEnvIfNotSet('VALIDATION_ABORT_EARLY', config.modules.validation.abortEarly?.toString());
288
+ }
289
+ }
290
+
291
+ // Apply security configuration
292
+ if (config.security) {
293
+ if (config.security.cors) {
294
+ setEnvIfNotSet('CORS_ENABLED', config.security.cors.enabled?.toString());
295
+ if (typeof config.security.cors.origin === 'string') {
296
+ setEnvIfNotSet('CORS_ORIGIN', config.security.cors.origin);
297
+ } else if (Array.isArray(config.security.cors.origin)) {
298
+ setEnvIfNotSet('CORS_ORIGIN', config.security.cors.origin.join(','));
299
+ } else if (typeof config.security.cors.origin === 'boolean') {
300
+ setEnvIfNotSet('CORS_ORIGIN', config.security.cors.origin.toString());
301
+ }
302
+ setEnvIfNotSet('CORS_METHODS', config.security.cors.methods?.join(','));
303
+ setEnvIfNotSet('CORS_HEADERS', config.security.cors.allowedHeaders?.join(','));
304
+ setEnvIfNotSet('CORS_CREDENTIALS', config.security.cors.credentials?.toString());
305
+ }
306
+
307
+ if (config.security.helmet) {
308
+ setEnvIfNotSet('HELMET_ENABLED', config.security.helmet.enabled?.toString());
309
+ setEnvIfNotSet('HELMET_CSP', config.security.helmet.contentSecurityPolicy?.toString());
310
+ setEnvIfNotSet('HELMET_HSTS', config.security.helmet.hsts?.toString());
311
+ setEnvIfNotSet('HELMET_NO_SNIFF', config.security.helmet.noSniff?.toString());
312
+ setEnvIfNotSet('HELMET_FRAMEGUARD', config.security.helmet.frameguard?.toString());
313
+ }
314
+
315
+ if (config.security.rateLimit?.global) {
316
+ setEnvIfNotSet(
317
+ 'GLOBAL_RATE_LIMIT_ENABLED',
318
+ config.security.rateLimit.global.enabled?.toString()
319
+ );
320
+ setEnvIfNotSet(
321
+ 'GLOBAL_RATE_LIMIT_REQUESTS',
322
+ config.security.rateLimit.global.requests?.toString()
323
+ );
324
+ setEnvIfNotSet(
325
+ 'GLOBAL_RATE_LIMIT_WINDOW',
326
+ config.security.rateLimit.global.window?.toString()
327
+ );
328
+ }
329
+ }
330
+
331
+ // Apply external services configuration
332
+ if (config.external) {
333
+ if (config.external.stripe) {
334
+ setEnvIfNotSet('STRIPE_SECRET_KEY', config.external.stripe.secretKey);
335
+ setEnvIfNotSet('STRIPE_PUBLISHABLE_KEY', config.external.stripe.publishableKey);
336
+ setEnvIfNotSet('STRIPE_WEBHOOK_SECRET', config.external.stripe.webhookSecret);
337
+ setEnvIfNotSet('STRIPE_API_VERSION', config.external.stripe.apiVersion);
338
+ }
339
+
340
+ if (config.external.paypal) {
341
+ setEnvIfNotSet('PAYPAL_CLIENT_ID', config.external.paypal.clientId);
342
+ setEnvIfNotSet('PAYPAL_CLIENT_SECRET', config.external.paypal.clientSecret);
343
+ setEnvIfNotSet('PAYPAL_WEBHOOK_ID', config.external.paypal.webhookId);
344
+ setEnvIfNotSet('PAYPAL_ENVIRONMENT', config.external.paypal.environment);
345
+ }
346
+
347
+ if (config.external.smtp) {
348
+ setEnvIfNotSet('SMTP_HOST', config.external.smtp.host);
349
+ setEnvIfNotSet('SMTP_PORT', config.external.smtp.port?.toString());
350
+ setEnvIfNotSet('SMTP_SECURE', config.external.smtp.secure?.toString());
351
+ setEnvIfNotSet('SMTP_USERNAME', config.external.smtp.username);
352
+ setEnvIfNotSet('SMTP_PASSWORD', config.external.smtp.password);
353
+ }
354
+ }
355
+
356
+ // Apply performance configuration
357
+ if (config.performance) {
358
+ if (config.performance.compression) {
359
+ setEnvIfNotSet('COMPRESSION_ENABLED', config.performance.compression.enabled?.toString());
360
+ setEnvIfNotSet('COMPRESSION_LEVEL', config.performance.compression.level?.toString());
361
+ setEnvIfNotSet('COMPRESSION_THRESHOLD', config.performance.compression.threshold?.toString());
362
+ }
363
+
364
+ if (config.performance.circuitBreaker) {
365
+ setEnvIfNotSet(
366
+ 'CIRCUIT_BREAKER_ENABLED',
367
+ config.performance.circuitBreaker.enabled?.toString()
368
+ );
369
+ setEnvIfNotSet(
370
+ 'CIRCUIT_BREAKER_THRESHOLD',
371
+ config.performance.circuitBreaker.failureThreshold?.toString()
372
+ );
373
+ setEnvIfNotSet(
374
+ 'CIRCUIT_BREAKER_RESET',
375
+ config.performance.circuitBreaker.resetTimeout?.toString()
376
+ );
377
+ setEnvIfNotSet(
378
+ 'CIRCUIT_BREAKER_MONITOR',
379
+ config.performance.circuitBreaker.monitoringPeriod?.toString()
380
+ );
381
+ }
382
+
383
+ if (config.performance.clustering) {
384
+ setEnvIfNotSet('CLUSTERING_ENABLED', config.performance.clustering.enabled?.toString());
385
+ setEnvIfNotSet('CLUSTER_WORKERS', config.performance.clustering.workers?.toString());
386
+ }
387
+ }
388
+ }
389
+
390
+ /**
391
+ * Set environment variable only if it's not already set
392
+ * This ensures environment variables take precedence over config file values
393
+ */
394
+ function setEnvIfNotSet(key: string, value: string | undefined): void {
395
+ if (value !== undefined && process.env[key] === undefined) {
396
+ process.env[key] = value;
397
+ }
398
+ }
@@ -2,6 +2,7 @@
2
2
  export * from './schema';
3
3
  export * from './loader';
4
4
  export * from './utils';
5
+ export * from './file-loader';
5
6
 
6
7
  // Re-export common Zod utilities for configuration
7
8
  export { z } from 'zod';
@@ -9,6 +10,7 @@ export { z } from 'zod';
9
10
  // Main configuration loading function
10
11
  import { loadConfig } from './loader';
11
12
  import type { AppConfig } from './schema';
13
+ import { setConfig } from './utils';
12
14
 
13
15
  // Global configuration instance
14
16
  let globalConfig: AppConfig | null = null;
@@ -23,6 +25,10 @@ export function initializeConfig(): AppConfig {
23
25
  }
24
26
 
25
27
  globalConfig = loadConfig();
28
+
29
+ // Also set the config for utils functions
30
+ setConfig(globalConfig);
31
+
26
32
  return globalConfig;
27
33
  }
28
34
 
@@ -43,3 +49,15 @@ export function getGlobalConfig(): AppConfig {
43
49
  export function isConfigInitialized(): boolean {
44
50
  return globalConfig !== null;
45
51
  }
52
+
53
+ /**
54
+ * Reset the global configuration state (for testing purposes)
55
+ * @internal
56
+ */
57
+ export function resetConfig(): void {
58
+ globalConfig = null;
59
+
60
+ // Also reset the utils config (by setting it to null via direct access)
61
+ const { setConfig } = require('./utils');
62
+ setConfig(null as any);
63
+ }
@@ -2,15 +2,31 @@
2
2
  import { ZodError } from 'zod';
3
3
  import { ConfigSchema, AppConfig } from './schema';
4
4
  import { createFrameworkLogger } from '../logger';
5
+ import { loadConfigFileSync, applyConfigAsEnvironmentVariables } from './file-loader';
5
6
 
6
7
  const logger = createFrameworkLogger('Config');
7
8
 
8
9
  /**
9
- * Load and validate configuration from environment variables
10
+ * Load and validate configuration from config files and environment variables
11
+ * Priority: Environment Variables > Config File > Schema Defaults
10
12
  * @returns Validated and typed application configuration
11
13
  */
12
14
  export function loadConfig(): AppConfig {
13
- logger.debug('Loading configuration from environment variables');
15
+ logger.debug('Loading configuration from config files and environment variables');
16
+
17
+ // First, try to load from config file and apply as environment variables (synchronously)
18
+ try {
19
+ const fileConfig = loadConfigFileSync();
20
+ if (fileConfig) {
21
+ logger.debug('Applying config file values as environment variables');
22
+ applyConfigAsEnvironmentVariables(fileConfig);
23
+ }
24
+ } catch (error) {
25
+ logger.warn(
26
+ 'Config file loading failed, continuing with environment variables only:',
27
+ String(error)
28
+ );
29
+ }
14
30
 
15
31
  // Map environment variables to configuration structure
16
32
  const envConfig = {