import { spawn, ChildProcess, exec } from "child_process"; import path from "path"; import fs from "fs"; const rootDir = __dirname; const exocoreWebDir = path.join(rootDir, "exocore-web"); process.env.FORCE_COLOR = "3"; const ANSI = { cyan: (s: string) => `\x1b[96m${s}\x1b[0m`, yellow: (s: string) => `\x1b[93m${s}\x1b[0m`, red: (s: string) => `\x1b[91m${s}\x1b[0m`, green: (s: string) => `\x1b[92m${s}\x1b[0m`, bold: (s: string) => `\x1b[1m${s}\x1b[0m`, }; const log = { info: (msg: string) => console.log(ANSI.cyan("[INFO]"), msg), warn: (msg: string) => console.log(ANSI.yellow("[WARN]"), msg), error: (msg: string) => console.log(ANSI.red("[ERROR]"), msg), success: (msg: string) => console.log(ANSI.green("[SUCCESS]"), msg), }; function printLogo(): void { const lines = [ " ███████╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗", " ██╔════╝╚██╗██╔╝██╔═══██╗██╔════╝██╔═══██╗██╔══██╗██╔════╝", " █████╗ ╚███╔╝ ██║ ██║██║ ██║ ██║██████╔╝█████╗ ", " ██╔══╝ ██╔██╗ ██║ ██║██║ ██║ ██║██╔══██╗██╔══╝ ", " ███████╗██╔╝ ██╗╚██████╔╝╚██████╗╚██████╔╝██║ ██║███████╗", " ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝", ]; const colors = ["\x1b[96m", "\x1b[96m", "\x1b[36m", "\x1b[36m", "\x1b[32m", "\x1b[32m"]; console.log(""); lines.forEach((line, i) => console.log(`${colors[i]}${line}\x1b[0m`)); console.log(""); console.log(ANSI.bold(ANSI.green(" ⚡ EXOCORE 2026 — Full System Architecture"))); console.log(""); } interface BinResult { cmd: string; args: string[]; } function resolveBin(name: string): BinResult { const rootBin = path.join(rootDir, "node_modules", ".bin", name); const webBin = path.join(exocoreWebDir, "node_modules", ".bin", name); if (fs.existsSync(rootBin)) return { cmd: rootBin, args: [] }; if (fs.existsSync(webBin)) return { cmd: webBin, args: [] }; return { cmd: "npx", args: [name] }; } function runProcess(name: string, command: string, args: string[], options: any = {}): ChildProcess { const mergedOptions = { stdio: "inherit" as const, shell: false, ...options }; log.info(`[START] ${name}: ${command} ${args.join(" ")}`); return spawn(command, args, mergedOptions); } function waitForProcess(child: ChildProcess): Promise { return new Promise((resolve, reject) => { child.on("exit", (code) => { if (code === 0) resolve(); else reject(new Error(`Failed with exit code ${code}`)); }); child.on("error", (err) => reject(err)); }); } function freePort(port: number): Promise { return new Promise((resolve) => { exec(`fuser -k ${port}/tcp 2>/dev/null || true`, () => { setTimeout(resolve, 500); }); }); } async function runTypeCheck(): Promise { const tsc = resolveBin("tsc"); log.warn("Running standard TypeScript check..."); const serverCheck = runProcess("TypeCheck", tsc.cmd, [ ...tsc.args, "-p", path.join(exocoreWebDir, "tsconfig.server.json"), "--noEmit" ], { cwd: exocoreWebDir }); await waitForProcess(serverCheck); log.success("TypeScript check passed!"); } async function runViteBuild(): Promise { const vite = resolveBin("vite"); log.warn("Building web assets with Vite..."); const buildProcess = runProcess("ViteBuild", vite.cmd, [ ...vite.args, "build" ], { cwd: exocoreWebDir }); await waitForProcess(buildProcess); log.success("Vite build successful!"); } async function startServer(): Promise { log.info("Launching Exocore server..."); const tsx = resolveBin("tsx"); return runProcess("Server", tsx.cmd, [...tsx.args, "index.ts"], { cwd: exocoreWebDir, }); } async function main(): Promise { try { printLogo(); const port = process.env.PORT ? parseInt(process.env.PORT) : 5000; log.info(`Clearing network port ${port}...`); await freePort(port); await runTypeCheck(); await runViteBuild(); const server = await startServer(); process.on("SIGINT", () => { console.log(""); log.warn("System shutdown requested."); server.kill(); process.exit(0); }); } catch (err) { const error = err instanceof Error ? err : new Error(String(err)); console.log(""); log.error("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); log.error(`STARTUP FAILED: ${error.message}`); log.error("Please resolve the build errors above to continue."); log.error("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); process.exit(1); } } main();