UNPKG

fortify2-js

Version:

MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.

600 lines (596 loc) 27.1 kB
'use strict'; var _default = require('./const/default.js'); var express = require('express'); var ConfigLoader = require('./utils/ConfigLoader.js'); var CacheManager = require('./components/fastapi/CacheManager.js'); var MiddlewareMethodsManager = require('./components/fastapi/middlewares/MiddlewareMethodsManager.js'); var RequestProcessor = require('./components/fastapi/RequestProcessor.js'); var RouteManager = require('./components/fastapi/RouteManager.js'); var PerformanceManager = require('./components/fastapi/PerformanceManager.js'); var MonitoringManager = require('./components/fastapi/MonitoringManager.js'); var PluginManager = require('./components/fastapi/PluginManager.js'); var ClusterManagerComponent = require('./components/fastapi/ClusterManagerComponent.js'); var FileWatcherManager = require('./components/fastapi/FileWatcherManager.js'); var PortManager = require('./utils/PortManager.js'); var Logger = require('./utils/Logger.js'); var middlewareManager = require('./components/fastapi/middlewares/middlewareManager.js'); var RedirectManager = require('./components/fastapi/RedirectManager.js'); var ConsoleInterceptor = require('./components/fastapi/console/ConsoleInterceptor.js'); var forceClosePort = require('./utils/forceClosePort.js'); /** * Ultra-Fast Express Server with Advanced Performance Optimization */ class UltraFastServer { constructor(userOptions = { server: { enableMiddleware: true, }, }) { this.ready = false; this.currentPort = 0; // Track the actual running port // Load configuration from file system if available const fileConfig = ConfigLoader.ConfigLoader.loadConfig(); // Merge configurations: defaults < file config < user options this.options = this.mergeWithDefaults(userOptions, fileConfig); // Initialize logger with user configuration this.logger = Logger.initializeLogger(this.options.logging); this.logger.startup("server", "Creating fast server..."); // Create Express app immediately this.app = express(); // Initialize components this.initializeComponents(); // Add middleware methods to app (synchronous) this.middlewareMethodsManager.addMiddlewareMethods(); this.routeManager.addMethods(); this.monitoringManager.addMonitoringEndpoints(); this.addStartMethod(); this.addConsoleInterceptionMethods(); // Initialize cache in background this.initPromise = this.cacheManager.initializeCache(); this.logger.debug("server", "Ultra-fast Express server created (cache initializing in background)"); } /** * Initialize all component instances with proper dependencies */ initializeComponents() { this.logger.startup("server", "Initializing components..."); // Initialize CacheManager first (foundation component) this.cacheManager = new CacheManager.CacheManager({ cache: this.options.cache, performance: this.options.performance, server: this.options.server, env: this.options.env, }); // Set cache on app for backward compatibility this.app.cache = this.cacheManager.getCache(); // Initialize PerformanceManager (depends on CacheManager) this.performanceManager = new PerformanceManager.PerformanceManager({ performance: this.options.performance, server: this.options.server, env: this.options.env, }, { app: this.app, cacheManager: this.cacheManager, }); // Initialize PluginManager (depends on CacheManager) this.pluginManager = new PluginManager.PluginManager({ app: this.app, cacheManager: this.cacheManager, }); // Initialize ClusterManager this.clusterManager = new ClusterManagerComponent.ClusterManagerComponent({ cluster: this.options.cluster, }, { app: this.app, }); // Initialize FileWatcherManager this.fileWatcherManager = new FileWatcherManager.FileWatcherManager({ fileWatcher: this.options.fileWatcher, }, { app: this.app, clusterManager: this.clusterManager, }); // Initialize RequestProcessor (depends on PerformanceManager and PluginManager) this.requestProcessor = new RequestProcessor.RequestProcessor({ performanceProfiler: this.performanceManager.getPerformanceProfiler(), executionPredictor: this.performanceManager.getExecutionPredictor(), requestPreCompiler: this.performanceManager.getRequestPreCompiler(), pluginEngine: this.pluginManager.getPluginEngine(), cacheManager: this.cacheManager, }); // Initialize middlewareManager (new middleware system) this.middlewareManager = new middlewareManager.MiddlewareManager({ server: this.options.server, security: this.options.security, performance: this.options.performance, middleware: this.options.middleware, }, { app: this.app, cache: this.cacheManager.getCache(), performanceProfiler: this.performanceManager.getPerformanceProfiler(), executionPredictor: this.performanceManager.getExecutionPredictor(), optimizationEnabled: this.performanceManager.isOptimizationEnabled(), optimizationStats: this.performanceManager.getOptimizationStats(), handleUltraFastPath: this.requestProcessor.handleUltraFastPath.bind(this.requestProcessor), handleFastPath: this.requestProcessor.handleFastPath.bind(this.requestProcessor), handleStandardPath: this.requestProcessor.handleStandardPath.bind(this.requestProcessor), }); // Initialize MiddlewareMethodsManager (adds methods to app) this.middlewareMethodsManager = new MiddlewareMethodsManager.MiddlewareMethodsManager({ app: this.app, middlewareManager: this.middlewareManager, }); // Initialize RouteManager (depends on CacheManager and middlewareManager) this.routeManager = new RouteManager.RouteManager({ app: this.app, cacheManager: this.cacheManager, middlewareManager: this.middlewareManager, ultraFastOptimizer: this.performanceManager.getUltraFastOptimizer(), }); // Initialize MonitoringManager (depends on CacheManager and PerformanceManager) this.monitoringManager = new MonitoringManager.MonitoringManager({ monitoring: this.options.monitoring, }, { app: this.app, cacheManager: this.cacheManager, performanceManager: this.performanceManager, }); // Initialize RedirectManager (lightweight component) this.redirectManager = new RedirectManager.RedirectManager(this.logger); // Initialize ConsoleInterceptor (logging enhancement) this.consoleInterceptor = new ConsoleInterceptor.ConsoleInterceptor(this.logger, this.options.logging); // Start console interception if enabled if (this.options.logging?.consoleInterception?.enabled) { this.consoleInterceptor.start(); this.logger.info("console", "Console interception system activated"); } // Add file watcher monitoring endpoints if enabled if (this.options.fileWatcher?.enabled) { this.fileWatcherManager.addFileWatcherMonitoringEndpoints("/fortify"); } // console.log("Components initialized successfully"); } /** * Get the Express app instance (ready to use immediately) */ getApp() { return this.app; } /** * Wait for full initialization (cache, console interceptor, and all components) */ async waitForReady() { // Wait for cache initialization await this.initPromise; // Wait for console interceptor to be ready if enabled if (this.options.logging?.consoleInterception?.enabled && this.consoleInterceptor) { // Give console interceptor a moment to fully initialize await new Promise((resolve) => setTimeout(resolve, 10)); } // Mark as ready this.ready = true; this.logger.debug("server", "All components initialized and ready"); } /** * Get the RequestPreCompiler instance for configuration */ getRequestPreCompiler() { return this.performanceManager.getRequestPreCompiler(); } /** * Get the ConsoleInterceptor instance for configuration */ getConsoleInterceptor() { return this.consoleInterceptor; } /** * Merge user options with defaults and file config */ mergeWithDefaults(userOptions, fileConfig = null) { const defaults = _default.DEFAULT_OPTIONS; // Use ConfigLoader's merge function for proper deep merging return ConfigLoader.ConfigLoader.mergeConfigs(defaults, fileConfig, userOptions); } /** * Handle automatic port switching when port is in use */ async handlePortSwitching(requestedPort) { const portManager = new PortManager.PortManager(requestedPort, this.options.server?.autoPortSwitch); const result = await portManager.findAvailablePort(); if (result.switched) { this.logger.portSwitching("server", `🔄 Port ${requestedPort} was in use, switched to port ${result.port}`); this.logger.portSwitching("server", ` Attempts: ${result.attempts}, Strategy: ${portManager.getConfig()?.strategy || "increment"}`); } if (!result.success) { const maxAttempts = this.options.server?.autoPortSwitch?.maxAttempts || 10; throw new Error(`Failed to find an available port after ${maxAttempts} attempts. ` + `Original port: ${requestedPort}, Last attempted: ${result.port}`); } return result; } /** * Start server with error handling and port switching */ async startServerWithPortHandling(port, host, callback) { try { // Try to start server on the requested port return new Promise((resolve, reject) => { const server = this.app.listen(port, host, () => { this.currentPort = port; // Track the actual running port this.logger.info("server", `Server running on ${host}:${port}`); this.logger.info("server", `State: ${this.ready ? "Ready" : "Initializing..."}`); if (callback) callback(); resolve(server); }); server.on("error", async (error) => { if (error.code === "EADDRINUSE") { // Port is in use, try auto-switching if enabled if (this.options.server?.autoPortSwitch?.enabled) { try { const result = await this.handlePortSwitching(port); // Recursively try with the new port const newServer = await this.startServerWithPortHandling(result.port, host, callback); resolve(newServer); } catch (switchError) { reject(switchError); } } else { reject(new Error(`Failed to start server. Port ${port} is already in use. ` + `Enable autoPortSwitch in server config to automatically find an available port.`)); } } else { reject(error); } }); }); } catch (error) { throw error; } } /** * Add start method to app with cluster support */ addStartMethod() { this.app.start = async (port, callback) => { const serverPort = port || this.options.server?.port || 3000; const host = this.options.server?.host || "localhost"; // If we're in main process and hot reloader is enabled, start it first if (this.fileWatcherManager.isInMainProcess() && this.fileWatcherManager.getHotReloader()) { this.logger.startup("fileWatcher", "Starting with hot reload support..."); try { // Start the hot reloader (which will spawn child process) await this.fileWatcherManager.getHotReloader().start(); // Start file watcher in main process to monitor changes if (this.fileWatcherManager.getFileWatcher()) { await this.fileWatcherManager.startFileWatcherWithHotReload(); } // Start the actual HTTP server in the main process too this.httpServer = await this.startServerWithPortHandling(serverPort, host, async () => { this.fileWatcherManager.setHttpServer(this.httpServer); if (callback) callback(); }); return this.httpServer; } catch (error) { this.logger.error("fileWatcher", "Hot reload startup failed:", error.message); // Fall through to regular startup } } // Regular startup (child process or hot reload disabled) // If cluster is enabled, use cluster manager if (this.clusterManager.isClusterEnabled()) { // console.log("Starting cluster..."); try { // Start cluster manager await this.clusterManager.startCluster(); // Check if we're in master or worker process if (process.env.NODE_ENV !== "worker") { this.logger.startup("cluster", "Starting as cluster master process"); // Setup cluster event handlers this.clusterManager.setupClusterEventHandlers(); // Start HTTP server in master process this.httpServer = await this.startServerWithPortHandling(serverPort, host, async () => { // Set HTTP server reference for file watcher restarts this.fileWatcherManager.setHttpServer(this.httpServer); const clusterStats = await this.clusterManager.getClusterStats(); this.logger.debug("cluster", `Cluster master started with ${clusterStats.workers?.total || 0} workers`); // Start file watcher if enabled if (this.fileWatcherManager.getFileWatcher()) { if (this.fileWatcherManager.isInMainProcess()) { // Main process: start with hot reload await this.fileWatcherManager.startFileWatcherWithHotReload(); } else { // Child process: start regular file watcher await this.fileWatcherManager.startFileWatcher(); } } if (callback) callback(); }); return this.httpServer; } else { // Worker process this.logger.startup("cluster", `Worker ${process.pid} started`); const httpServer = await this.startServerWithPortHandling(serverPort, host, () => { this.logger.info("cluster", `Worker ${process.pid} listening on ${host}:${serverPort}`); if (callback) callback(); }); return httpServer; } } catch (error) { this.logger.error("cluster", "Failed to start cluster:", error.message); // Fallback to single process this.logger.info("cluster", "Falling back to single process mode"); } } // Single process mode (default) this.httpServer = await this.startServerWithPortHandling(serverPort, host, async () => { // Set HTTP server reference for file watcher restarts this.fileWatcherManager.setHttpServer(this.httpServer); // Start file watcher if enabled if (this.fileWatcherManager.getFileWatcher()) { if (this.fileWatcherManager.isInMainProcess()) { // Main process: start with hot reload await this.fileWatcherManager.startFileWatcherWithHotReload(); } else { // Child process: start regular file watcher await this.fileWatcherManager.startFileWatcher(); } } if (callback) callback(); }); return this.httpServer; }; this.app.waitForReady = () => this.waitForReady(); // Add port management methods this.app.getPort = () => this.getPort(); this.app.forceClosePort = (port) => this.forceClosePort(port); this.app.redirectFromPort = (fromPort, toPort, options) => this.redirectManager.redirectFromPort(fromPort, toPort, options); // Add advanced redirect management methods this.app.getRedirectInstance = (fromPort) => this.redirectManager.getRedirectInstance(fromPort); this.app.getAllRedirectInstances = () => this.redirectManager.getAllRedirectInstances(); this.app.disconnectRedirect = (fromPort) => this.redirectManager.disconnectRedirect(fromPort); this.app.disconnectAllRedirects = () => this.redirectManager.disconnectAllRedirects(); this.app.getRedirectStats = (fromPort) => this.redirectManager.getRedirectStats(fromPort); // Cluster methods are already added in constructor if cluster is enabled } // File watcher functionality now handled by FileWatcherManager component /** * Stop file watcher */ async stopFileWatcher() { await this.fileWatcherManager.stopFileWatcher(); } /** * Get file watcher status */ getFileWatcherStatus() { return this.fileWatcherManager.getFileWatcherStatus(); } /** * Get file watcher restart stats */ getFileWatcherStats() { return this.fileWatcherManager.getFileWatcherStats(); } // ===== PLUGIN MANAGEMENT METHODS ===== /** * Register a plugin with the server */ async registerPlugin(plugin) { await this.pluginManager.registerPlugin(plugin); } /** * Unregister a plugin from the server */ async unregisterPlugin(pluginId) { await this.pluginManager.unregisterPlugin(pluginId); } /** * Get plugin by ID */ getPlugin(pluginId) { return this.pluginManager.getPlugin(pluginId); } /** * Get all registered plugins */ getAllPlugins() { return this.pluginManager.getAllPlugins(); } /** * Get plugins by type */ getPluginsByType(type) { return this.pluginManager.getPluginsByType(type); } /** * Get plugin execution statistics */ getPluginStats(pluginId) { return this.pluginManager.getPluginStats(pluginId); } /** * Get plugin registry statistics */ getPluginRegistryStats() { return this.pluginManager.getPluginRegistryStats(); } /** * Get plugin engine statistics */ getPluginEngineStats() { return this.pluginManager.getPluginEngineStats(); } /** * Initialize built-in plugins */ async initializeBuiltinPlugins() { try { // Import and register built-in plugins const { JWTAuthPlugin } = await Promise.resolve().then(function () { return require('./plugins/builtin/JWTAuthPlugin.js'); }); const { ResponseTimePlugin } = await Promise.resolve().then(function () { return require('./plugins/builtin/ResponseTimePlugin.js'); }); const { SmartCachePlugin } = await Promise.resolve().then(function () { return require('./plugins/builtin/SmartCachePlugin.js'); }); // Register security plugins await this.registerPlugin(new JWTAuthPlugin()); // Register performance plugins await this.registerPlugin(new ResponseTimePlugin()); // Register cache plugins await this.registerPlugin(new SmartCachePlugin()); this.logger.debug("plugins", "Built-in plugins initialized successfully"); } catch (error) { this.logger.error("plugins", "Failed to initialize built-in plugins:", error.message); } } /** * Get comprehensive server statistics including plugins */ async getServerStats() { const cacheStats = await this.cacheManager.getCacheStats(); const pluginRegistryStats = this.getPluginRegistryStats(); const pluginEngineStats = this.getPluginEngineStats(); return { server: { ready: this.ready, uptime: process.uptime(), memoryUsage: process.memoryUsage(), cpuUsage: process.cpuUsage(), }, cache: cacheStats, plugins: { registry: pluginRegistryStats, engine: pluginEngineStats, totalPlugins: pluginRegistryStats.totalPlugins, averageExecutionTime: pluginRegistryStats.averageExecutionTime, }, cluster: await this.clusterManager.getClusterStats(), fileWatcher: this.getFileWatcherStats(), }; } // ===== CONSOLE INTERCEPTION METHODS ===== /** * Add console interception methods to the Express app */ addConsoleInterceptionMethods() { // Get console interceptor instance this.app.getConsoleInterceptor = () => { return this.consoleInterceptor; }; // Enable console interception this.app.enableConsoleInterception = () => { this.consoleInterceptor.start(); }; // Disable console interception this.app.disableConsoleInterception = () => { this.consoleInterceptor.stop(); }; // Get console interception statistics this.app.getConsoleStats = () => { return this.consoleInterceptor.getStats(); }; // Reset console interception statistics this.app.resetConsoleStats = () => { this.consoleInterceptor.resetStats(); }; // File watcher methods this.app.getFileWatcherStatus = () => { return this.getFileWatcherStatus(); }; this.app.getFileWatcherStats = () => { return this.getFileWatcherStats(); }; this.app.stopFileWatcher = async () => { return await this.stopFileWatcher(); }; // TypeScript checking methods this.app.checkTypeScript = async (files) => { return await this.fileWatcherManager.checkTypeScript(files); }; this.app.getTypeScriptStatus = () => { return this.fileWatcherManager.getTypeScriptStatus(); }; this.app.enableTypeScriptChecking = () => { this.fileWatcherManager.enableTypeScriptChecking(); }; this.app.disableTypeScriptChecking = () => { this.fileWatcherManager.disableTypeScriptChecking(); }; // TypeScript checking methods this.app.checkTypeScript = async (files) => { return await this.fileWatcherManager.checkTypeScript(files); }; this.app.getTypeScriptStatus = () => { return this.fileWatcherManager.getTypeScriptStatus(); }; this.app.enableTypeScriptChecking = () => { this.fileWatcherManager.enableTypeScriptChecking(); }; this.app.disableTypeScriptChecking = () => { this.fileWatcherManager.disableTypeScriptChecking(); }; // 🔐 Console encryption methods this.app.enableConsoleEncryption = (key) => { this.consoleInterceptor.enableEncryption(key); }; this.app.disableConsoleEncryption = () => { this.consoleInterceptor.disableEncryption(); }; // Simple encrypt method this.app.encrypt = (key) => { this.consoleInterceptor.encrypt(key); }; this.app.setConsoleEncryptionKey = (key) => { this.consoleInterceptor.setEncryptionKey(key); }; this.app.setConsoleEncryptionDisplayMode = (displayMode, showEncryptionStatus) => { this.consoleInterceptor.setEncryptionDisplayMode(displayMode, showEncryptionStatus); }; this.app.getEncryptedLogs = () => { return this.consoleInterceptor.getEncryptedLogs(); }; this.app.restoreConsoleFromEncrypted = async (encryptedData, key) => { return await this.consoleInterceptor.restoreFromEncrypted(encryptedData, key); }; this.app.isConsoleEncryptionEnabled = () => { return this.consoleInterceptor.isEncryptionEnabled(); }; this.app.getConsoleEncryptionStatus = () => { return this.consoleInterceptor.getEncryptionStatus(); }; } // ===== PORT MANAGEMENT METHODS ===== /** * Get the actual running port number * @returns The current port the server is running on */ getPort() { return this.currentPort; } /** * Attempt to forcefully close/free up the specified port * @param port - The port number to force close * @returns Promise<boolean> - true if successful, false if failed */ async forceClosePort(port) { return await new forceClosePort.Port(port).forceClosePort(); } } exports.FastServer = UltraFastServer; exports.UltraFastServer = UltraFastServer; //# sourceMappingURL=FastServer.js.map