mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-05 21:22:07 +00:00
Enhance application controller and runtime provisioner with loading window visibility and improved file handling
This commit is contained in:
@@ -134,6 +134,8 @@ export function createApplicationController({
|
||||
mainWindow = deps.createMainWindow();
|
||||
loadingWindow = deps.createLoadingWindow();
|
||||
|
||||
loadingWindow.show();
|
||||
|
||||
state = "starting";
|
||||
await startNodecg();
|
||||
|
||||
@@ -143,7 +145,6 @@ export function createApplicationController({
|
||||
}
|
||||
|
||||
await loadingWindow.loadURL(paths.loadingDashboardUrl);
|
||||
loadingWindow.show();
|
||||
|
||||
const loadingShownAt = now();
|
||||
|
||||
|
||||
@@ -23,11 +23,13 @@ type RuntimeProvisionerDeps = {
|
||||
recursive: true;
|
||||
force: true;
|
||||
dereference: true;
|
||||
filter: (sourcePath: string) => boolean;
|
||||
filter?: (sourcePath: string) => boolean;
|
||||
},
|
||||
) => unknown;
|
||||
readFileSync: (filePath: string) => string | Buffer;
|
||||
writeFileSync: (filePath: string, content: string) => unknown;
|
||||
statSync: (filePath: string) => { isDirectory: () => boolean };
|
||||
symlinkSync: (target: string, path: string, type: "junction") => unknown;
|
||||
};
|
||||
|
||||
export type PreparedNodecgRuntime = {
|
||||
@@ -84,6 +86,8 @@ function resolveDeps(deps?: Partial<RuntimeProvisionerDeps>): RuntimeProvisioner
|
||||
cpSync: deps?.cpSync ?? fs.cpSync,
|
||||
readFileSync: deps?.readFileSync ?? fs.readFileSync,
|
||||
writeFileSync: deps?.writeFileSync ?? fs.writeFileSync,
|
||||
statSync: deps?.statSync ?? fs.statSync,
|
||||
symlinkSync: deps?.symlinkSync ?? fs.symlinkSync,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -150,16 +154,20 @@ function installManagedRuntime(
|
||||
deps.rmSync(path.join(targetRuntimePath, entry), { recursive: true, force: true });
|
||||
}
|
||||
|
||||
deps.cpSync(sourceRuntimePath, targetRuntimePath, {
|
||||
recursive: true,
|
||||
force: true,
|
||||
dereference: true,
|
||||
filter: (sourcePath) => {
|
||||
const relativePath = path.relative(sourceRuntimePath, sourcePath);
|
||||
const firstSegment = relativePath.split(path.sep)[0];
|
||||
return !WRITABLE_NODECG_DIRS.includes(firstSegment as (typeof WRITABLE_NODECG_DIRS)[number]);
|
||||
},
|
||||
});
|
||||
for (const entry of MANAGED_RUNTIME_ENTRIES) {
|
||||
const sourcePath = path.join(sourceRuntimePath, entry);
|
||||
const targetPath = path.join(targetRuntimePath, entry);
|
||||
|
||||
if (!deps.existsSync(sourcePath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (deps.statSync(sourcePath).isDirectory()) {
|
||||
deps.symlinkSync(sourcePath, targetPath, "junction");
|
||||
} else {
|
||||
deps.cpSync(sourcePath, targetPath, { recursive: true, force: true, dereference: true });
|
||||
}
|
||||
}
|
||||
|
||||
const sourceRuntime = readJson(path.join(sourceRuntimePath, ".scoreko-runtime.json"), deps);
|
||||
deps.writeFileSync(
|
||||
|
||||
@@ -133,10 +133,10 @@ test("ApplicationController preserves startup ordering and schedules updates aft
|
||||
"create-manager",
|
||||
"create-main",
|
||||
"create-loading",
|
||||
"loading:show",
|
||||
"start-nodecg",
|
||||
"wait-nodecg",
|
||||
`loading:load:${paths.loadingDashboardUrl}`,
|
||||
"loading:show",
|
||||
`main:load:${paths.mainDashboardUrl}`,
|
||||
"main:show",
|
||||
"loading:close",
|
||||
@@ -192,10 +192,10 @@ test("ApplicationController directly launches packaged app after runtime install
|
||||
"create-manager",
|
||||
"create-main",
|
||||
"create-loading",
|
||||
"loading:show",
|
||||
"start-nodecg",
|
||||
"wait-nodecg",
|
||||
"loading:load:http://localhost:9090/loading",
|
||||
"loading:show",
|
||||
"main:load:http://localhost:9090/main",
|
||||
"main:show",
|
||||
"loading:close",
|
||||
|
||||
@@ -38,10 +38,21 @@ function createFakeFs(initialPaths: string[] = [], initialFiles: Record<string,
|
||||
cpSync: (from: string, to: string) => {
|
||||
state.copied.push({ from: path.normalize(from), to: path.normalize(to) });
|
||||
state.paths.add(path.normalize(to));
|
||||
state.paths.add(path.join(path.normalize(to), "index.js"));
|
||||
state.paths.add(path.join(path.normalize(to), "package.json"));
|
||||
state.paths.add(path.join(path.normalize(to), "node_modules", "nodecg", "dist", "server", "bootstrap.js"));
|
||||
state.paths.add(path.join(path.normalize(to), "bundles", "scoreko-dev", "package.json"));
|
||||
},
|
||||
statSync: (filePath: string) => ({
|
||||
isDirectory: () => {
|
||||
const normalized = path.normalize(filePath);
|
||||
return normalized.endsWith("node_modules") || normalized.endsWith("bundles");
|
||||
},
|
||||
}),
|
||||
symlinkSync: (target: string, linkPath: string, type: string) => {
|
||||
state.copied.push({ from: path.normalize(target), to: path.normalize(linkPath) });
|
||||
state.paths.add(path.normalize(linkPath));
|
||||
if (target.endsWith("node_modules")) {
|
||||
state.paths.add(path.join(path.normalize(linkPath), "nodecg", "dist", "server", "bootstrap.js"));
|
||||
} else if (target.endsWith("bundles")) {
|
||||
state.paths.add(path.join(path.normalize(linkPath), "scoreko-dev", "package.json"));
|
||||
}
|
||||
},
|
||||
readFileSync: (filePath: string) => state.files.get(path.normalize(filePath)) ?? "{}",
|
||||
writeFileSync: (filePath: string, content: string) => {
|
||||
@@ -57,7 +68,9 @@ function getSourcePaths(source: string) {
|
||||
source,
|
||||
path.join(source, "index.js"),
|
||||
path.join(source, "package.json"),
|
||||
path.join(source, "node_modules"),
|
||||
path.join(source, "node_modules", "nodecg", "dist", "server", "bootstrap.js"),
|
||||
path.join(source, "bundles"),
|
||||
path.join(source, "bundles", "scoreko-dev", "package.json"),
|
||||
path.join(source, ".scoreko-runtime.json"),
|
||||
];
|
||||
@@ -81,7 +94,7 @@ test("prepareUserNodecgRuntime copies the packaged runtime into userData", () =>
|
||||
|
||||
assert.equal(preparedRuntime.runtimePath, path.join(userData, "nodecg"));
|
||||
assert.equal(preparedRuntime.installed, true);
|
||||
assert.equal(state.copied.length, 1);
|
||||
assert.equal(state.copied.length, 4);
|
||||
assert.ok(state.paths.has(path.join(userData, "nodecg", "cfg")));
|
||||
assert.ok(state.paths.has(path.join(userData, "nodecg", "db")));
|
||||
assert.ok(state.paths.has(path.join(userData, "nodecg", "logs")));
|
||||
@@ -150,7 +163,7 @@ test("prepareUserNodecgRuntime refreshes managed files when the app version chan
|
||||
});
|
||||
|
||||
assert.equal(preparedRuntime.installed, true);
|
||||
assert.equal(state.copied.length, 1);
|
||||
assert.equal(state.copied.length, 4);
|
||||
assert.ok(state.removed.includes(path.join(target, "node_modules")));
|
||||
assert.ok(state.removed.includes(path.join(target, "bundles")));
|
||||
assert.ok(!state.removed.includes(path.join(target, "db")));
|
||||
@@ -190,7 +203,7 @@ test("prepareUserNodecgRuntime refreshes managed files when the source runtime w
|
||||
});
|
||||
|
||||
assert.equal(preparedRuntime.installed, true);
|
||||
assert.equal(state.copied.length, 1);
|
||||
assert.equal(state.copied.length, 4);
|
||||
assert.ok(state.removed.includes(path.join(target, "bundles")));
|
||||
assert.ok(!state.removed.includes(path.join(target, "cfg")));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user