import { render } from 'solid-js/web'; import { createSignal, onMount, Show, For } from 'solid-js'; const FullscreenIcon = () => ; const ExitFullscreenIcon = () => ; const StartIcon = () => ; const RestartIcon = () => ; const StopIcon = () => ; function App() { const [loading, setLoading] = createSignal(true); const [initialLoadComplete, setInitialLoadComplete] = createSignal(false); const [status, setStatus] = createSignal(''); const [userData, setUserData] = createSignal(null); const [logs, setLogs] = createSignal([]); const [wsStatus, setWsStatus] = createSignal('Disconnected'); const [isFullScreen, setIsFullScreen] = createSignal(false); const [siteLinkVisible, setSiteLinkVisible] = createSignal(false); const [isAwaitingInput, setIsAwaitingInput] = createSignal(false); const [inputValue, setInputValue] = createSignal(''); let ws, inputRef, consoleContainerRef, ansiUpInstance; let logIdCounter = 0; const getToken = () => localStorage.getItem('exocore-token') || ''; const getCookies = () => localStorage.getItem('exocore-cookies') || ''; async function fetchUserInfo() { setLoading(true); const token = getToken(); const cookies = getCookies(); if (!token || !cookies) { setLoading(false); setInitialLoadComplete(true); window.location.href = '/private/server/exocore/web/public/login'; return; } try { const res = await fetch('/private/server/exocore/web/userinfo', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token, cookies }), }); if (!res.ok) { let errorMsg = `Server error: ${res.status}`; try { const errorData = await res.json(); errorMsg = errorData.message || errorMsg; } catch (parseError) {} throw new Error(errorMsg); } const data = await res.json(); if (data.data?.user && data.data.user.verified === 'success') { setUserData(data.data.user); setStatus(''); } else { setUserData(null); setStatus(data.message || 'User verification failed. Redirecting...'); localStorage.removeItem('exocore-token'); localStorage.removeItem('exocore-cookies'); setTimeout(() => { window.location.href = '/private/server/exocore/web/public/login'; }, 2500); } } catch (err) { setUserData(null); setStatus('Failed to fetch user info: ' + err.message + '. Redirecting...'); localStorage.removeItem('exocore-token'); localStorage.removeItem('exocore-cookies'); setTimeout(() => { window.location.href = '/private/server/exocore/web/public/login'; }, 2500); } finally { setLoading(false); setInitialLoadComplete(true); } } const scrollToBottom = () => { if (consoleContainerRef) { requestAnimationFrame(() => { consoleContainerRef.scrollTop = consoleContainerRef.scrollHeight; }); } }; function addLog(line, isSystemMessage = false) { let htmlContent; if (ansiUpInstance) { htmlContent = ansiUpInstance.ansi_to_html(line); } else { const escapeHtml = (unsafe) => unsafe.replace(/[&<"']/g, (match) => ({ '&': '&', '<': '<', '"': '"', "'": ''' })[match] || match); htmlContent = isSystemMessage ? `${escapeHtml(line)}` : escapeHtml(line); } if (typeof line === 'string' && line.includes(window.origin)) { setSiteLinkVisible(true); } const newLogEntry = { id: logIdCounter++, html: htmlContent, isSystem: isSystemMessage }; setLogs((prev) => [...prev, newLogEntry].slice(-250)); scrollToBottom(); } function handleInputSubmit(e) { if (e.key === 'Enter') { e.preventDefault(); if (!ws || ws.readyState !== WebSocket.OPEN) { addLog('\x1b[31mError: WebSocket is not connected.\x1b[0m', true); return; } const commandToSend = inputValue(); ws.send(JSON.stringify({ type: 'STDIN_INPUT', payload: commandToSend })); addLog(`\x1b[38;5;39m> ${commandToSend}\x1b[0m`, true); setIsAwaitingInput(false); setInputValue(''); } } function sendCommand(endpoint) { const commandName = endpoint.split('/').pop(); fetch(endpoint, { method: 'POST' }) .then((res) => { if (!res.ok) { addLog(`\x1b[31mERROR: Command '${commandName}' failed - HTTP ${res.status}\x1b[0m`, true); } else { addLog(`\x1b[32mSUCCESS: Command '${commandName}' sent.\x1b[0m`, true); } }) .catch((err) => { addLog(`\x1b[31mERROR: Failed to send command '${commandName}': ${err.message}\x1b[0m`, true); }); } const handleStartCommand = () => { setSiteLinkVisible(false); setLogs([]); addLog('INFO: Starting server...', true); sendCommand('/private/server/exocore/web/start'); }; const handleRestartCommand = () => { setSiteLinkVisible(false); setLogs([]); addLog('INFO: Restarting server...', true); sendCommand('/private/server/exocore/web/restart'); }; const handleStopCommand = () => { setSiteLinkVisible(false); addLog('INFO: Stop command sent.', true); sendCommand('/private/server/exocore/web/stop'); }; function toggleFullScreen() { const el = document.querySelector('.console-wrapper'); if (!el) return; if (!document.fullscreenElement) { el.requestFullscreen().catch((err) => addLog('Error entering fullscreen: ' + err.message, true)); } else { document.exitFullscreen(); } } onMount(() => { const fontLink = document.createElement('link'); fontLink.href = 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Fira+Code:wght@400;500&display=swap'; fontLink.rel = 'stylesheet'; document.head.appendChild(fontLink); const ansiScript = document.createElement('script'); ansiScript.src = 'https://cdn.jsdelivr.net/npm/ansi_up@5.1.0/ansi_up.min.js'; ansiScript.onload = () => { if (typeof AnsiUp !== 'undefined') { ansiUpInstance = new AnsiUp(); ansiUpInstance.use_classes = false; addLog('\x1b[32mINFO: ANSI color processing enabled.\x1b[0m', true); } }; document.head.appendChild(ansiScript); fetchUserInfo(); const wsUrl = (window.location.protocol === 'https:' ? 'wss' : 'ws') + '://' + window.location.host + '/private/server/exocore/web/console'; function connectWebSocket() { ws = new WebSocket(wsUrl); ws.onopen = () => setWsStatus('Connected'); ws.onclose = () => { setWsStatus('Disconnected'); setTimeout(connectWebSocket, 2000); }; ws.onerror = () => setWsStatus('Error'); ws.onmessage = (e) => { try { const message = JSON.parse(e.data); if (message?.type === 'INPUT_REQUIRED') { addLog(message.payload || 'Input required:'); setIsAwaitingInput(true); setTimeout(() => inputRef?.focus(), 50); scrollToBottom(); } } catch (error) { if (typeof e.data === 'string') { addLog(e.data.trim()); } else { addLog(e.data); } } }; } connectWebSocket(); document.addEventListener('fullscreenchange', () => setIsFullScreen(!!document.fullscreenElement)); }); return (
Initializing...
}> Redirecting to login...}>

Exocore Console

Welcome, {userData()?.user || 'User'}
inputRef?.focus()}> {(log) =>
}
> setInputValue(e.currentTarget.value)} onKeyDown={handleInputSubmit} autofocus />
); } render(() => , document.getElementById('app'));