pub const HMR_CLIENT_SCRIPT: &str = "// HMR client-side script for Orbit Framework\n// This is injected into HTML during development to enable hot module reloading\n\n(function() {\n // Configuration\n const config = {\n reconnectInterval: 2000, // Reconnection interval in ms\n reconnectMaxAttempts: 10,\n debug: true\n };\n\n // HMR state\n let socket = null;\n let reconnectAttempts = 0;\n let isConnected = false;\n\n // Create a logger that respects the debug setting\n const log = {\n info: (message) => {\n if (config.debug) console.info(`[Orbit HMR] ${message}`);\n },\n warn: (message) => {\n if (config.debug) console.warn(`[Orbit HMR] ${message}`);\n },\n error: (message) => {\n if (config.debug) console.error(`[Orbit HMR] ${message}`);\n }\n };\n\n // Initialize the HMR system\n function init() {\n log.info(\"Initializing HMR system\");\n \n // Connect to the WebSocket server\n const protocol = window.location.protocol === \'https:\' ? \'wss:\' : \'ws:\';\n const port = parseInt(window.location.port) + 1; // WebSocket server port\n const wsUrl = `${protocol}//${window.location.hostname}:${port}`;\n \n connectWebSocket(wsUrl);\n \n // Listen for page unload to close the socket\n window.addEventListener(\'beforeunload\', () => {\n if (socket && socket.readyState === WebSocket.OPEN) {\n socket.close();\n }\n });\n }\n\n // Connect to the WebSocket server\n function connectWebSocket(url) {\n if (socket) {\n socket.close();\n }\n\n try {\n log.info(`Connecting to WebSocket server: ${url}`);\n socket = new WebSocket(url);\n\n socket.onopen = () => {\n log.info(\'WebSocket connection established\');\n isConnected = true;\n reconnectAttempts = 0;\n \n // Register the client\n socket.send(JSON.stringify({\n type: \'register\',\n url: window.location.pathname\n }));\n };\n\n socket.onclose = () => {\n log.info(\'WebSocket connection closed\');\n isConnected = false;\n attemptReconnect(url);\n };\n\n socket.onerror = (error) => {\n log.error(`WebSocket error: ${error}`);\n isConnected = false;\n };\n\n socket.onmessage = (event) => {\n handleMessage(event.data);\n };\n } catch (error) {\n log.error(`Failed to connect to WebSocket: ${error}`);\n attemptReconnect(url);\n }\n }\n\n // Handle incoming WebSocket messages\n function handleMessage(data) {\n try {\n const message = JSON.parse(data);\n \n switch (message.type) {\n case \'fileChange\':\n log.info(`File change detected: ${message.paths.join(\', \')}`);\n break;\n \n case \'rebuild\':\n handleRebuild(message);\n break;\n \n case \'hmr\':\n handleHmrUpdate(message);\n break;\n \n default:\n log.warn(`Unknown message type: ${message.type}`);\n }\n } catch (error) {\n log.error(`Error handling message: ${error}`);\n }\n }\n\n // Handle rebuild messages\n function handleRebuild(message) {\n const statusIndicator = document.getElementById(\'orbit-hmr-status\') || \n createStatusIndicator();\n \n if (message.status === \'started\') {\n log.info(\'Project rebuild started\');\n statusIndicator.textContent = \'Rebuilding...\';\n statusIndicator.className = \'orbit-hmr-status rebuilding\';\n }\n else if (message.status === \'completed\') {\n log.info(\'Project rebuild completed successfully\');\n statusIndicator.textContent = \'Rebuild successful\';\n statusIndicator.className = \'orbit-hmr-status success\';\n \n // Hide the indicator after a delay\n setTimeout(() => {\n statusIndicator.className = \'orbit-hmr-status hidden\';\n }, 3000);\n }\n else if (message.status === \'failed\') {\n log.error(\'Project rebuild failed\');\n statusIndicator.textContent = \'Rebuild failed\';\n statusIndicator.className = \'orbit-hmr-status error\';\n }\n } // Handle HMR updates\n function handleHmrUpdate(message) {\n log.info(`HMR update for modules: ${message.modules.join(\', \')}`);\n \n // Create a status indicator to show HMR activity\n const statusIndicator = document.getElementById(\'orbit-hmr-status\') || \n createStatusIndicator();\n \n statusIndicator.textContent = \'Applying HMR updates...\';\n statusIndicator.className = \'orbit-hmr-status rebuilding\';\n \n try {\n // Apply HMR updates - the actual implementation depends on your framework\n if (window.__ORBIT_APPLY_HMR) {\n const result = window.__ORBIT_APPLY_HMR(message.modules);\n \n // Handle Promise or direct result\n if (result instanceof Promise) {\n result.then(() => {\n statusIndicator.textContent = \'HMR update successful\';\n statusIndicator.className = \'orbit-hmr-status success\';\n setTimeout(() => {\n statusIndicator.className = \'orbit-hmr-status hidden\';\n }, 3000);\n }).catch((error) => {\n log.error(`HMR update failed: ${error}`);\n statusIndicator.textContent = \'HMR failed, reloading page...\';\n statusIndicator.className = \'orbit-hmr-status error\';\n setTimeout(() => {\n window.location.reload();\n }, 1000);\n });\n } else {\n statusIndicator.textContent = \'HMR update successful\';\n statusIndicator.className = \'orbit-hmr-status success\';\n setTimeout(() => {\n statusIndicator.className = \'orbit-hmr-status hidden\';\n }, 3000);\n }\n } else {\n // If no HMR handler is registered, perform a full reload\n log.warn(\'No HMR handler registered, performing full page reload\');\n statusIndicator.textContent = \'No HMR handler, reloading page...\';\n statusIndicator.className = \'orbit-hmr-status rebuilding\';\n setTimeout(() => {\n window.location.reload();\n }, 500);\n }\n } catch (error) {\n log.error(`Error during HMR update: ${error}`);\n statusIndicator.textContent = \'HMR error, reloading page...\';\n statusIndicator.className = \'orbit-hmr-status error\';\n setTimeout(() => {\n window.location.reload();\n }, 1000);\n }\n }\n\n // Create a status indicator element\n function createStatusIndicator() {\n const indicator = document.createElement(\'div\');\n indicator.id = \'orbit-hmr-status\';\n indicator.className = \'orbit-hmr-status hidden\';\n \n const style = document.createElement(\'style\');\n style.textContent = `\n .orbit-hmr-status {\n position: fixed;\n bottom: 20px;\n right: 20px;\n padding: 8px 12px;\n border-radius: 4px;\n font-family: sans-serif;\n font-size: 14px;\n z-index: 9999;\n transition: opacity 0.3s ease;\n color: white;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n }\n .orbit-hmr-status.hidden {\n opacity: 0;\n pointer-events: none;\n }\n .orbit-hmr-status.rebuilding {\n background-color: #f39c12;\n }\n .orbit-hmr-status.success {\n background-color: #2ecc71;\n }\n .orbit-hmr-status.error {\n background-color: #e74c3c;\n }\n `;\n \n document.head.appendChild(style);\n document.body.appendChild(indicator);\n return indicator;\n }\n\n // Attempt to reconnect to the WebSocket server\n function attemptReconnect(url) {\n if (reconnectAttempts >= config.reconnectMaxAttempts) {\n log.error(\'Maximum reconnection attempts reached\');\n return;\n }\n \n reconnectAttempts++;\n \n const delay = config.reconnectInterval;\n log.info(`Attempting to reconnect in ${delay}ms (attempt ${reconnectAttempts}/${config.reconnectMaxAttempts})`);\n \n setTimeout(() => {\n connectWebSocket(url);\n }, delay);\n }\n\n // Register an HMR update handler\n window.__ORBIT_REGISTER_HMR_HANDLER = function(handler) {\n window.__ORBIT_APPLY_HMR = handler;\n log.info(\'HMR handler registered\');\n };\n\n // Initialize on page load\n if (document.readyState === \'complete\') {\n init();\n } else {\n window.addEventListener(\'load\', init);\n }\n})();\n";
Expand description
The HMR client script as a static string