Files
scoreko-electron-dev/scripts/doctor.mjs
T
Pandipipas 865c3589bd Refactor NodeCG runtime preparation and update handling
- Updated paths and configurations in doctor.mjs and prepare-nodecg-runtime.mjs to use new build-config.mjs imports.
- Enhanced runtime installation checks and permissions validation.
- Introduced new update configuration management in update-config.ts, including loading and validating update settings.
- Implemented update service for managing update checks and downloads in update-service.ts.
- Replaced update-utils.ts with update-schema.ts for better structure and clarity in update handling.
- Added comprehensive tests for update download and settings management.
- Ensured secure handling of download URLs and improved error handling in update processes.
2026-05-24 23:20:59 +02:00

101 lines
3.1 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import net from "node:net";
import path from "node:path";
import { bundleName, nodecgRuntimeRoot } from "./build-config.mjs";
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} invalid`, `It must be an integer between 1 and 65535. Received value: '${raw}'.`);
return null;
}
addCheck(true, `${name} valid`, `${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} invalid`, `It must be an integer between ${min} and ${max}. Received value: '${raw}'.`);
return;
}
addCheck(true, `${name} valid`, `${parsed}`);
}
function checkNodecgInstall() {
const indexPath = path.join(nodecgRuntimeRoot, "index.js");
const bootstrapPath = path.join(nodecgRuntimeRoot, "node_modules", "nodecg", "dist", "server", "bootstrap.js");
const manifestPath = path.join(nodecgRuntimeRoot, ".scoreko-runtime.json");
const bundlePath = path.join(nodecgRuntimeRoot, "bundles", bundleName);
addCheck(fs.existsSync(nodecgRuntimeRoot), "Packaged NodeCG runtime", nodecgRuntimeRoot);
addCheck(fs.existsSync(indexPath), "Runtime index.js", indexPath);
addCheck(fs.existsSync(bootstrapPath), "NodeCG bootstrap", bootstrapPath);
addCheck(fs.existsSync(manifestPath), "Runtime manifest", manifestPath);
addCheck(fs.existsSync(bundlePath), `Packaged bundle '${bundleName}'`, bundlePath);
try {
fs.accessSync(nodecgRuntimeRoot, fs.constants.R_OK | fs.constants.W_OK);
addCheck(true, "lib/nodecg permissions", "Read/write OK for local development");
} catch {
addCheck(false, "lib/nodecg permissions", "No read/write permissions in lib/nodecg");
}
}
function checkPortAvailability(port) {
return new Promise((resolve) => {
const server = net.createServer();
server.once("error", () => {
addCheck(false, `Port ${port}`, "It is in use. Free it or change NODECG_PORT.");
resolve();
});
server.listen(port, "127.0.0.1", () => {
server.close(() => {
addCheck(true, `Port ${port}`, "Available");
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 ? "OK" : "FAIL";
console.log(`${icon} ${check.title}: ${check.details}`);
}
const hasFailures = checks.some((check) => !check.ok);
if (hasFailures) {
process.exitCode = 1;
return;
}
console.log("\nDoctor finished: valid configuration.");
}
main();