Twan07's picture
Create server/html.ts
24761b1 verified
import type { Request, Response, Application } from 'express';
import path from 'path';
import { readFileSync, existsSync } from 'fs';
function safeReadFile(filePath: string, encoding: BufferEncoding = 'utf-8'): string {
if (existsSync(filePath)) {
try {
return readFileSync(filePath, encoding);
} catch (e) {
console.error(`Error reading file ${filePath} (safeReadFile):`, e);
return '';
}
}
console.warn(`Warning: File not found at ${filePath} (safeReadFile). Returning empty string.`);
return '';
}
export function html(app: Application): void {
const fileSystemPublicBasePath = path.resolve(__dirname, '..', 'public');
const header = safeReadFile(path.join(fileSystemPublicBasePath, 'templates', 'header.html'));
const chatheadai = safeReadFile(path.join(fileSystemPublicBasePath, 'templates', 'chatheadai.html'));
const footer = safeReadFile(path.join(fileSystemPublicBasePath, 'templates', 'footer.html'));
function renderPage(title: string, scriptPath: string): string {
const hostScript = safeReadFile(path.join(fileSystemPublicBasePath, 'src', scriptPath));
const basePublicPath = '/private/server/exocore/web/public';
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" type="image/jpeg" href="https://i.ibb.co/G4vDj7Fm/FB-IMG-1749809298614.jpg">
<title>${title}</title>
<script>
(function() {
const getToken = () => localStorage.getItem('exocore-token') || '';
const getCookies = () => localStorage.getItem('exocore-cookies') || '';
const baseRedirectPath = '/private/server/exocore/web/public';
const panelLoginLandingUrl = baseRedirectPath;
const accountLoginUrl = \`\${baseRedirectPath}/login\`;
const registerUrl = \`\${baseRedirectPath}/register\`;
const otpUrl = \`\${baseRedirectPath}/otp\`;
const forgotPasswordUrl = \`\${baseRedirectPath}/forgot-password\`;
const currentPathname = window.location.pathname;
const isPanelLoginSuccess = localStorage.getItem('panelLogin') === 'success';
const hasAccountAuthTokens = getToken() && getCookies();
if (!isPanelLoginSuccess) {
if (currentPathname !== panelLoginLandingUrl) {
console.log("'panelLogin' is not 'success'. Redirecting to panel login landing page...");
window.location.href = panelLoginLandingUrl;
throw new Error("Redirecting to panel login landing to halt script execution.");
}
return;
}
const postPanelLogin_AccountAuthPages = [accountLoginUrl, registerUrl, otpUrl, forgotPasswordUrl];
if (!hasAccountAuthTokens) {
if (!postPanelLogin_AccountAuthPages.includes(currentPathname)) {
console.log('User has panel access but no account session tokens. Redirecting to account login page...');
window.location.href = accountLoginUrl;
throw new Error("Redirecting to account login to halt script execution.");
}
return;
}
})();
</script>
<script src="https://cdn.jsdelivr.net/npm/ansi_up@5.1.0/ansi_up.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
<style>
html, body { height: 100%; margin: 0; }
.page-wrapper { min-height: 100%; display: flex; flex-direction: column; }
.page-content { flex: 1; }
#app { min-height: 100vh; }
h2, h3, h4 { color: #333; margin-top: 0.5rem; margin-bottom: 1rem; }
ul { list-style-type: none; padding: 0; margin: 0; }
li { padding: 0.2rem 0; }
.status-box { padding: 0.5rem; margin: 0.5rem 0; border: 1px solid #ddd; background: #f9f9f9; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; }
input[type="file"] { display: none; }
@media (max-width: 767px) {
.main-content-flex { flex-direction: column; gap: 15px !important; }
.file-list-panel, .file-editor-panel { width: 100%; min-width: unset !important; }
}
pre { background: #1e1e1e; padding: 1em; overflow: auto; border-radius: 5px; color: #ccc; }
code { font-family: 'monospace'; display: block; }
</style>
</head>
<body>
<div class="page-wrapper">
${header}
<div id="app" class="page-content"></div>
${chatheadai}
${footer}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
if (typeof hljs !== 'undefined') {
hljs.highlightAll();
}
});
</script>
<script>
async function checkProjectStatusAndRedirect() {
const projectStatusUrl = '/private/server/exocore/web/project/status';
const redirectUrl = '${basePublicPath}/project';
if (window.location.pathname === redirectUrl) {
console.log('Currently on the project setup page. Status check will not redirect further from here.');
return;
}
try {
const response = await fetch(projectStatusUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
console.error(\`Failed to fetch project status. Server responded with \${response.status}: \${response.statusText}\`);
return;
}
const statusData = await response.json();
if (statusData && typeof statusData.exists === 'boolean' && !statusData.exists) {
console.log('Project status indicates it does not exist or is not properly configured. Redirecting to project setup...');
window.location.href = redirectUrl;
} else if (statusData && statusData.exists === true) {
console.log('Project exists. No redirection necessary from project status check.');
} else {
console.warn('Received an unexpected or malformed response from the project status API:', statusData);
}
} catch (error) {
console.error('Error during project status check or processing:', error);
}
}
const currentPathnameForProjectCheck = window.location.pathname;
const baseRedirectPathForProjectCheck = '/private/server/exocore/web/public';
const accountLoginUrlForProjectCheck = \`\${baseRedirectPathForProjectCheck}/login\`;
const registerUrlForProjectCheck = \`\${baseRedirectPathForProjectCheck}/register\`;
const otpUrlForProjectCheck = \`\${baseRedirectPathForProjectCheck}/otp\`;
if ( localStorage.getItem('exocore-token') &&
localStorage.getItem('exocore-cookies') &&
localStorage.getItem('panelLogin') === 'success' &&
currentPathnameForProjectCheck !== accountLoginUrlForProjectCheck &&
currentPathnameForProjectCheck !== registerUrlForProjectCheck &&
currentPathnameForProjectCheck !== otpUrlForProjectCheck
) {
checkProjectStatusAndRedirect();
}
</script>
<script type="module">${hostScript}</script>
</body>
</html>`;
}
const urlSegmentForPublicRoutes = '/private/server/exocore/web/public';
app.get(`${urlSegmentForPublicRoutes}/register`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Signup', 'register.js'));
});
app.get(`${urlSegmentForPublicRoutes}/login`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Login', 'login.js'));
});
app.get(`${urlSegmentForPublicRoutes}/project`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Project', 'project.js'));
});
app.get(`${urlSegmentForPublicRoutes}/otp`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Otp', 'otp.js'));
});
app.get(`${urlSegmentForPublicRoutes}/profile`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Profile', 'profile.js'));
});
app.get(`${urlSegmentForPublicRoutes}/forgot-password`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('ForgotPass', 'forgot.js'));
});
app.get(`${urlSegmentForPublicRoutes}/dashboard`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Dashboard', 'dashboard.js'));
});
app.get(`${urlSegmentForPublicRoutes}/plans`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('plans', 'plans.js'));
});
app.get(`${urlSegmentForPublicRoutes}/console`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Console', 'console.js'));
});
app.get(`${urlSegmentForPublicRoutes}/shell`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('Shell', 'shell.js'));
});
app.get(`${urlSegmentForPublicRoutes}/manager`, (_req: Request, res: Response): void => {
res.setHeader('Content-Type', 'text/html');
res.send(renderPage('File Manager', 'FileManager.js'));
});
app.get(urlSegmentForPublicRoutes, (_req: Request, res: Response): void => {
const panelHtmlFilePath = path.join(fileSystemPublicBasePath, 'panel.html');
if (!existsSync(panelHtmlFilePath)) {
console.warn(`Static file not found: ${panelHtmlFilePath} for URL ${urlSegmentForPublicRoutes}. Sending 404.`);
res.status(404).send('Page not found.');
return;
}
try {
const fileContent = readFileSync(panelHtmlFilePath, 'utf-8');
res.setHeader('Content-Type', 'text/html');
res.send(fileContent);
} catch (error) {
console.error(`Error reading static file ${panelHtmlFilePath} for URL ${urlSegmentForPublicRoutes}:`, error);
res.status(500).send('Error loading page.');
}
});
}