mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-06 05:32:06 +00:00
feat: complete pending roadmap items with doctor, hardening, and code quality
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from "node:fs";
|
||||
import net from "node:net";
|
||||
import path from "node:path";
|
||||
|
||||
const cwd = process.cwd();
|
||||
const nodecgRootPath = path.resolve(cwd, "lib", "nodecg");
|
||||
|
||||
const checks = [];
|
||||
|
||||
function addCheck(ok, title, details) {
|
||||
checks.push({ ok, title, details });
|
||||
}
|
||||
|
||||
function parsePort(name, fallback) {
|
||||
const raw = process.env[name] ?? fallback;
|
||||
const parsed = Number.parseInt(raw, 10);
|
||||
if (!Number.isFinite(parsed) || parsed < 1 || parsed > 65535) {
|
||||
addCheck(false, `${name} inválido`, `Debe ser un entero entre 1 y 65535. Valor recibido: '${raw}'.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
addCheck(true, `${name} válido`, `${parsed}`);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function parseIntInRange(name, fallback, min, max) {
|
||||
const raw = process.env[name] ?? String(fallback);
|
||||
const parsed = Number.parseInt(raw, 10);
|
||||
if (!Number.isFinite(parsed) || parsed < min || parsed > max) {
|
||||
addCheck(false, `${name} inválido`, `Debe ser un entero entre ${min} y ${max}. Valor recibido: '${raw}'.`);
|
||||
return;
|
||||
}
|
||||
|
||||
addCheck(true, `${name} válido`, `${parsed}`);
|
||||
}
|
||||
|
||||
function checkNodecgInstall() {
|
||||
const indexPath = path.join(nodecgRootPath, "index.js");
|
||||
const bundleName = (process.env.NODECG_BUNDLE_NAME ?? "scoreko-dev").trim();
|
||||
const bundlePath = path.join(nodecgRootPath, "bundles", bundleName);
|
||||
|
||||
addCheck(fs.existsSync(nodecgRootPath), "NodeCG root", nodecgRootPath);
|
||||
addCheck(fs.existsSync(indexPath), "NodeCG index.js", indexPath);
|
||||
addCheck(fs.existsSync(bundlePath), `Bundle '${bundleName}'`, bundlePath);
|
||||
|
||||
try {
|
||||
fs.accessSync(nodecgRootPath, fs.constants.R_OK | fs.constants.W_OK);
|
||||
addCheck(true, "Permisos lib/nodecg", "Lectura/escritura OK");
|
||||
} catch {
|
||||
addCheck(false, "Permisos lib/nodecg", "Sin permisos de lectura/escritura en lib/nodecg");
|
||||
}
|
||||
}
|
||||
|
||||
function checkPortAvailability(port) {
|
||||
return new Promise((resolve) => {
|
||||
const server = net.createServer();
|
||||
|
||||
server.once("error", () => {
|
||||
addCheck(false, `Puerto ${port}`, "Está ocupado. Libéralo o cambia NODECG_PORT.");
|
||||
resolve();
|
||||
});
|
||||
|
||||
server.listen(port, "127.0.0.1", () => {
|
||||
server.close(() => {
|
||||
addCheck(true, `Puerto ${port}`, "Disponible");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const port = parsePort("NODECG_PORT", "9090");
|
||||
parseIntInRange("ELECTRON_LOAD_DELAY_MS", 10000, 0, 600000);
|
||||
parseIntInRange("NODECG_STARTUP_TIMEOUT_MS", 30000, 1000, 600000);
|
||||
parseIntInRange("NODECG_KILL_TIMEOUT_MS", 2500, 0, 120000);
|
||||
checkNodecgInstall();
|
||||
|
||||
if (port) {
|
||||
await checkPortAvailability(port);
|
||||
}
|
||||
|
||||
for (const check of checks) {
|
||||
const icon = check.ok ? "✅" : "❌";
|
||||
console.log(`${icon} ${check.title}: ${check.details}`);
|
||||
}
|
||||
|
||||
const hasFailures = checks.some((check) => !check.ok);
|
||||
if (hasFailures) {
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("\nDoctor finalizado: configuración válida.");
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user