const fs = require("fs"); const path = require("path"); const root = path.resolve(__dirname, ".."); function fail(message, error) { console.error(`[verify] ${message}`); if (error) { console.error(`[verify] ${error instanceof Error ? error.message : String(error)}`); } if (process.platform === "win32") { console.error("[verify] Retry with windows\\install.bat."); console.error("[verify] Native fallback: run C:\\Program Files\\nodejs\\install_tools.bat as Administrator."); } process.exit(1); } function warn(message) { console.warn(`[verify] WARNING: ${message}`); } function compareVersions(left, right) { const leftParts = String(left || "").split(".").map((part) => Number(part) || 0); const rightParts = String(right || "").split(".").map((part) => Number(part) || 0); const length = Math.max(leftParts.length, rightParts.length); for (let index = 0; index < length; index += 1) { const difference = (leftParts[index] || 0) - (rightParts[index] || 0); if (difference !== 0) return difference; } return 0; } try { require("express"); } catch (error) { fail("Express could not be loaded.", error); } try { const Database = require("better-sqlite3"); const db = new Database(":memory:"); const row = db.prepare("SELECT 1 AS ok").get(); db.close(); if (row?.ok !== 1) { fail("SQLite verification query returned an unexpected result."); } } catch (error) { fail("better-sqlite3 could not be loaded or initialized.", error); } for (const directory of ["data", "logs"]) { fs.mkdirSync(path.join(root, directory), { recursive: true }); } if (process.platform === "win32") { const ammcDir = path.join(root, "AMMC", "windows64"); const requiredFiles = ["ammc-amb.exe", "ammc.dll", "MyLapsSDK.dll"]; const missingFiles = requiredFiles.filter((file) => !fs.existsSync(path.join(ammcDir, file))); if (missingFiles.length > 0) { fail(`Bundled AMMC runtime is incomplete: ${missingFiles.join(", ")}`); } console.log(`[verify] AMMC Windows runtime: ${ammcDir}`); } if (process.platform === "linux" && process.arch === "x64") { const ammcPath = path.join(root, "AMMC", "linux_x86-64", "ammc-amb"); const requiredGlibc = "2.39"; if (!fs.existsSync(ammcPath)) { warn(`Bundled Linux AMMC binary is missing: ${ammcPath}`); } else { try { fs.accessSync(ammcPath, fs.constants.X_OK); } catch { warn(`Bundled Linux AMMC is not executable. Run: chmod +x AMMC/linux_x86-64/ammc-amb`); } const glibcVersion = process.report?.getReport?.().header?.glibcVersionRuntime || ""; if (!glibcVersion) { warn(`Could not detect the host GLIBC version. The bundled Linux AMMC requires GLIBC ${requiredGlibc} or newer.`); } else if (compareVersions(glibcVersion, requiredGlibc) < 0) { warn(`Host GLIBC ${glibcVersion} is too old for the bundled Linux AMMC (requires >= ${requiredGlibc}). RC RaceCore can still run, but use a compatible AMMC build or a newer Linux distribution. Do not replace the system GLIBC manually.`); } else { console.log(`[verify] AMMC Linux runtime: ${ammcPath} (GLIBC ${glibcVersion}, requires >= ${requiredGlibc})`); } } } console.log(`[verify] Express and SQLite: OK (${process.platform}/${process.arch}, Node ${process.version})`); console.log(`[verify] Installation is ready. Start with: ${process.platform === "win32" ? "npm.cmd start" : "npm start"}`);