mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-06 05:32:06 +00:00
Add NodeCG preflight step and sanity script
This commit is contained in:
@@ -30,6 +30,7 @@ Desktop app (Electron + TypeScript) to run and package `scoreko-dev` (Electron h
|
||||
### Quality and diagnostics
|
||||
|
||||
- `npm run test`: build and tests (`node:test`).
|
||||
- `npm run sanity`: runs `typecheck`, `lint`, and `test` as a quick pre-release gate.
|
||||
- `npm run doctor`: environment/configuration diagnostics.
|
||||
- `npm run lint`: lint with ESLint.
|
||||
- `npm run lint:fix`: lint with auto-fix.
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"rebuild:native": "node scripts/rebuild-nodecg-native.mjs",
|
||||
"rebuild:better-sqlite3": "electron-rebuild --version 40.6.1 --module-dir lib/scoreko-dev/workspaces/database-adapter-sqlite-legacy --only better-sqlite3 -f",
|
||||
"test": "npm run build && node --test dist/tests/**/*.test.js",
|
||||
"sanity": "npm run typecheck && npm run lint && npm run test",
|
||||
"doctor": "node scripts/doctor.mjs",
|
||||
"lint": "eslint . --ext .ts,.js,.mjs",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
|
||||
@@ -56,6 +56,8 @@ function focusExistingWindow(): void {
|
||||
}
|
||||
|
||||
async function launchApplication(): Promise<void> {
|
||||
await nodecgManager.runPreflightChecks();
|
||||
|
||||
// We create both windows early so startup feels instant while NodeCG is booting in the background.
|
||||
mainWindow = createMainWindow({ appConfig, rootPath, mainDashboardUrl });
|
||||
loadingWindow = createLoadingWindow({ appConfig, rootPath });
|
||||
|
||||
@@ -30,6 +30,7 @@ type NodecgProcessManagerDeps = {
|
||||
};
|
||||
|
||||
export type NodecgProcessManager = {
|
||||
runPreflightChecks: () => Promise<void>;
|
||||
startNodecgProcess: () => Promise<ChildProcess>;
|
||||
waitForNodecgReady: (startTime: number) => Promise<void>;
|
||||
stopNodecgProcessGracefully: () => Promise<void>;
|
||||
@@ -51,7 +52,7 @@ export function createNodecgProcessManager({
|
||||
let lastExit: { code: number | null; signal: NodeJS.Signals | null } | null = null;
|
||||
let lastStderrLine: string | null = null;
|
||||
|
||||
const startNodecgProcess = async (): Promise<ChildProcess> => {
|
||||
const runPreflightChecks = async (): Promise<void> => {
|
||||
validateNodecgInstall(
|
||||
nodecgRootPath,
|
||||
resolvedDeps.platform,
|
||||
@@ -66,6 +67,10 @@ export function createNodecgProcessManager({
|
||||
`Port ${appConfig.nodecgPort} is already in use. Stop the process using it or set NODECG_PORT before starting.`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const startNodecgProcess = async (): Promise<ChildProcess> => {
|
||||
await runPreflightChecks();
|
||||
|
||||
const command = resolvedDeps.platform === "win32" ? "npx.cmd" : "npx";
|
||||
const child = resolvedDeps.spawnProcess(command, ["nodecg", "start"], {
|
||||
@@ -186,6 +191,7 @@ export function createNodecgProcessManager({
|
||||
};
|
||||
|
||||
return {
|
||||
runPreflightChecks,
|
||||
startNodecgProcess,
|
||||
waitForNodecgReady,
|
||||
stopNodecgProcessGracefully,
|
||||
|
||||
@@ -70,6 +70,32 @@ test("startNodeCG fails when there are no read/write permissions", async () => {
|
||||
}, /No read\/write permissions on scoreko app folder/);
|
||||
});
|
||||
|
||||
test("runPreflightChecks validates install and port availability without starting NodeCG", async () => {
|
||||
let spawnCalls = 0;
|
||||
|
||||
const manager = createNodecgProcessManager({
|
||||
isDev: true,
|
||||
nodecgRootPath: "/fake/scoreko-dev",
|
||||
nodecgBaseUrl: "http://127.0.0.1:9090",
|
||||
appConfig: getBaseConfig(),
|
||||
log: () => undefined,
|
||||
deps: {
|
||||
pathExists: () => true,
|
||||
hasReadWriteAccess: () => true,
|
||||
probePortAvailable: async () => true,
|
||||
spawnProcess: () => {
|
||||
spawnCalls += 1;
|
||||
throw new Error("should not spawn during preflight");
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await assert.doesNotReject(async () => {
|
||||
await manager.runPreflightChecks();
|
||||
});
|
||||
|
||||
assert.equal(spawnCalls, 0);
|
||||
});
|
||||
test("waitForNodeCGReady resolves when endpoint returns 404", async () => {
|
||||
const child = new MockChildProcess(4321);
|
||||
const manager = createNodecgProcessManager({
|
||||
|
||||
Reference in New Issue
Block a user