diff --git a/src/server.js b/src/server.js index 75800a6..fbebf0d 100644 --- a/src/server.js +++ b/src/server.js @@ -29,120 +29,71 @@ let globalVariableContext = {}; /** * Load all files from globalVariables/ directory into globalVariableContext * Pattern: globalVariables/filename.{json|js} -> globalVariableContext['filename'] - * - .json files: Parsed as JSON data - * - .js files: Executed via vm.Script, must return object via IIFE */ function loadGlobalVariables() { const globalDir = join(__dirname, "globalVariables"); + const jsonFiles = []; + const jsFiles = []; - try { - const allFiles = readdirSync(globalDir).filter( - (f) => (f.endsWith(".json") || f.endsWith(".js")) && !f.endsWith(".example.json") && !f.endsWith(".example.js") - ); + // Scan and categorize files in one pass + readdirSync(globalDir).forEach((file) => { + if (file.includes(".example")) return; + if (file.endsWith(".json")) jsonFiles.push(file); + else if (file.endsWith(".js")) jsFiles.push(file); + }); - // Separate files by type - const jsonFiles = allFiles.filter((f) => f.endsWith(".json")); - const jsFiles = allFiles.filter((f) => f.endsWith(".js")); + // Load JSON files first (data) + jsonFiles.forEach((file) => { + const varName = file.replace(".json", ""); + const data = JSON.parse(readFileSync(join(globalDir, file), "utf-8")); + globalVariableContext[varName] = data; + logger.info(`Loaded global data: ${varName}`, { keys: Object.keys(data) }); + }); - // Load JSON files first (data) - jsonFiles.forEach((file) => { - const objectName = file.replace(".json", ""); - const filePath = join(globalDir, file); + // Load JS files second (functions can reference JSON data) + jsFiles.forEach((file) => { + const varName = file.replace(".js", ""); + const code = readFileSync(join(globalDir, file), "utf-8"); + const script = new vm.Script(code, { filename: file }); + const context = vm.createContext({ ...globalVMContext, ...globalVariableContext }); + globalVariableContext[varName] = script.runInContext(context); + logger.info(`Loaded global functions: ${varName}`); + }); - try { - const content = readFileSync(filePath, "utf-8"); - const data = JSON.parse(content); - globalVariableContext[objectName] = data; - logger.info(`Loaded global data: ${objectName}`, { - file: file, - keys: Object.keys(data), - }); - } catch (error) { - logger.error(`Failed to load ${file}`, { error: error.message }); - throw error; - } - }); - - // Load JS files second (functions) - can reference JSON data - jsFiles.forEach((file) => { - const functionName = file.replace(".js", ""); - const filePath = join(globalDir, file); - - try { - const code = readFileSync(filePath, "utf-8"); - const script = new vm.Script(code, { filename: file }); - - // Execute in context with all VM globals and previously loaded variables - const tempContext = vm.createContext({ - ...globalVMContext, - ...globalVariableContext, - }); - - const exportedObject = script.runInContext(tempContext); - globalVariableContext[functionName] = exportedObject; - logger.info(`Loaded global functions: ${functionName}`, { - file: file, - exports: Object.keys(exportedObject || {}).length, - }); - } catch (error) { - logger.error(`Failed to load ${file}`, { error: error.message }); - throw error; - } - }); - - logger.info( - `Loaded ${allFiles.length} global variables from ${globalDir}`, - { json: jsonFiles.length, js: jsFiles.length } - ); - } catch (error) { - logger.error("Failed to load global variables", { - directory: globalDir, - error: error.message, - }); - throw error; - } + logger.info(`Loaded ${jsonFiles.length + jsFiles.length} global variables`, + { json: jsonFiles.length, js: jsFiles.length } + ); } /** - * Load configuration from config/default.json - * Merges with environment variables (ENV takes precedence) - * - * @returns {Object} Configuration object + * Load configuration from config/default.json and merge with environment variables */ function loadConfig() { const configPath = join(__dirname, "..", "config", "default.json"); const configData = readFileSync(configPath, "utf-8"); const config = JSON.parse(configData); - // Merge environment variables (ENV vars take precedence) - config.server.port = process.env.PORT - ? parseInt(process.env.PORT, 10) - : config.server.port; - config.server.host = process.env.HOST || config.server.host; - config.logging.level = process.env.LOG_LEVEL || config.logging.level; - - return config; + // Merge environment variables (ENV takes precedence) + return { + ...config, + server: { + ...config.server, + port: process.env.PORT ? parseInt(process.env.PORT, 10) : config.server.port, + host: process.env.HOST || config.server.host, + }, + logging: { + ...config.logging, + level: process.env.LOG_LEVEL || config.logging.level, + }, + }; } /** * Validate configuration - * @param {Object} config - Configuration object - * @throws {Error} If configuration is invalid */ function validateConfig(config) { - const errors = []; - - // Validate server configuration - if ( - !config.server.port || - config.server.port < 1 || - config.server.port > 65535 - ) { - errors.push("Invalid server.port (must be 1-65535)"); - } - - if (errors.length > 0) { - throw new Error(`Configuration validation failed:\n${errors.join("\n")}`); + if (!config.server.port || config.server.port < 1 || config.server.port > 65535) { + throw new Error("Invalid server.port (must be 1-65535)"); } } @@ -177,8 +128,6 @@ async function startServer() { // Create HTTP server that delegates all requests to proxy const server = http.createServer((req, res) => { try { - // Create a context with all globals that proxy.js needs - // globalVariableContext includes both JSON data and helpers object const context = vm.createContext({ ...globalVMContext, ...globalVariableContext,