deleted unnecesary

This commit is contained in:
2026-05-31 18:45:57 +02:00
parent ce59c5db89
commit 8e6b79ca68
8 changed files with 41 additions and 135 deletions
+13 -9
View File
@@ -1,24 +1,28 @@
# Runtime / app
# SCOREKO Configuration File Template
# Copy this file to '.env' in the application root and edit as needed.
# Application Information (Required)
SCOREKO_APP_TITLE=Scoreko
SCOREKO_APP_USER_MODEL_ID=com.scoreko.desktop
SCOREKO_APP_USER_DATA_DIRECTORY=scoreko
# SCOREKO_APP_ICON_PATH=static/icons/icon.ico
SCOREKO_APP_ICON_PATH=static/icons/icon.ico
# NodeCG
# NodeCG Managed Runtime Configuration (Required)
NODECG_BUNDLE_NAME=scoreko-dev
NODECG_PORT=9090
SCOREKO_DASHBOARD_ROUTE=dashboard/scoreko-dev/main.html?standalone=true
SCOREKO_LOADING_ROUTE=dashboard/loading/main.html?standalone=true
# Timing
# Timing & Lifecycles (Required)
ELECTRON_LOAD_DELAY_MS=10000
NODECG_STARTUP_TIMEOUT_MS=120000
NODECG_KILL_TIMEOUT_MS=2500
# Updates
# Automated Updates Configuration (Required)
SCOREKO_UPDATES_ENABLED=true
# SCOREKO_UPDATE_API_URL=http://gitea.local/api/v1/repos/OWNER/REPO/releases/latest
# SCOREKO_UPDATE_RELEASE_PAGE_URL=http://gitea.local/OWNER/REPO/releases
SCOREKO_UPDATE_ASSET_PATTERN=Scoreko-setup-.*\.exe$
SCOREKO_UPDATE_CHECK_DELAY_MS=5000
# SCOREKO_UPDATE_CONFIG_PATH=static/updates.json
# Optional Update Release Source (Only required if SCOREKO_UPDATES_ENABLED is true)
SCOREKO_UPDATE_API_URL=http://gitea.local/api/v1/repos/OWNER/REPO/releases/latest
SCOREKO_UPDATE_RELEASE_PAGE_URL=http://gitea.local/OWNER/REPO/releases
SCOREKO_UPDATE_ASSET_PATTERN=Scoreko-setup-.*\.exe$
-4
View File
@@ -27,10 +27,6 @@ export function getSourceNodecgRuntimePath(rootPath: string): string {
return path.resolve(rootPath, "lib", "nodecg");
}
export function getDefaultUpdateConfigPath(rootPath: string): string {
return path.join(rootPath, "static", "updates.json");
}
export function getUpdateDownloadDirectory(tempDirectory: string): string {
return path.join(tempDirectory, "scoreko-updates");
}
-2
View File
@@ -16,7 +16,6 @@ export type AppRuntimeConfig = {
updateApiUrl?: string;
updateReleasePageUrl?: string;
updateAssetPattern?: string;
updateConfigPathOverride?: string;
updateCheckDelayMs: number;
};
@@ -55,7 +54,6 @@ export function getRuntimeConfig(): AppRuntimeConfig {
updateApiUrl: parseOptionalHttpUrl("SCOREKO_UPDATE_API_URL"),
updateReleasePageUrl: parseOptionalHttpUrl("SCOREKO_UPDATE_RELEASE_PAGE_URL"),
updateAssetPattern: getOptionalEnv("SCOREKO_UPDATE_ASSET_PATTERN"),
updateConfigPathOverride: getOptionalEnv("SCOREKO_UPDATE_CONFIG_PATH"),
updateCheckDelayMs: parseRequiredEnvIntInRange("SCOREKO_UPDATE_CHECK_DELAY_MS", 0, 600000),
};
}
+7 -49
View File
@@ -1,9 +1,6 @@
import fs from "node:fs";
import { getDefaultUpdateConfigPath } from "../app/paths";
import { AppRuntimeConfig } from "../config/runtime-config";
import { isRecord, readNonEmptyString } from "../utils/unknown-values";
import { UpdateFileConfig, validateHttpUrl } from "./update-schema";
import { readNonEmptyString } from "../utils/unknown-values";
import { validateHttpUrl } from "./update-schema";
const DEFAULT_UPDATE_ASSET_PATTERN = "Scoreko-setup-.*\\.exe$";
@@ -20,11 +17,7 @@ type UpdateConfigOptions = {
type UpdateRuntimeConfig = Pick<
AppRuntimeConfig,
| "updateApiUrl"
| "updateAssetPattern"
| "updateConfigPathOverride"
| "updateReleasePageUrl"
| "updatesEnabled"
"updateApiUrl" | "updateAssetPattern" | "updateReleasePageUrl" | "updatesEnabled"
>;
export function loadUpdateSettings(
@@ -33,49 +26,14 @@ export function loadUpdateSettings(
log: (...args: unknown[]) => void,
options: UpdateConfigOptions = { allowInsecureHttp: true },
): UpdateSettings {
const fileConfig = readUpdateFileConfig(appConfig, rootPath, log);
const apiUrl = readOptionalHttpUrl(appConfig.updateApiUrl ?? fileConfig.apiUrl, options);
const releasePageUrl = readOptionalHttpUrl(appConfig.updateReleasePageUrl ?? fileConfig.releasePageUrl, options);
const apiUrl = readOptionalHttpUrl(appConfig.updateApiUrl, options);
const releasePageUrl = readOptionalHttpUrl(appConfig.updateReleasePageUrl, options);
return {
enabled: appConfig.updatesEnabled && (Boolean(fileConfig.enabled) || Boolean(appConfig.updateApiUrl)) && Boolean(apiUrl),
enabled: appConfig.updatesEnabled && Boolean(apiUrl),
...(apiUrl ? { apiUrl } : {}),
...(releasePageUrl ? { releasePageUrl } : {}),
assetPattern:
appConfig.updateAssetPattern || readNonEmptyString(fileConfig.assetPattern) || DEFAULT_UPDATE_ASSET_PATTERN,
};
}
export function readUpdateFileConfig(
appConfig: Pick<AppRuntimeConfig, "updateConfigPathOverride">,
rootPath: string,
log: (...args: unknown[]) => void,
): UpdateFileConfig {
const configPath = appConfig.updateConfigPathOverride ?? getDefaultUpdateConfigPath(rootPath);
if (!fs.existsSync(configPath)) {
return {};
}
try {
const parsedConfig: unknown = JSON.parse(fs.readFileSync(configPath, "utf8"));
return normalizeUpdateFileConfig(parsedConfig);
} catch (error) {
log(`Could not read update config at ${configPath}.`, error);
return {};
}
}
function normalizeUpdateFileConfig(value: unknown): UpdateFileConfig {
if (!isRecord(value)) {
return {};
}
return {
enabled: value.enabled,
apiUrl: value.apiUrl,
releasePageUrl: value.releasePageUrl,
assetPattern: value.assetPattern,
assetPattern: appConfig.updateAssetPattern || DEFAULT_UPDATE_ASSET_PATTERN,
};
}
-7
View File
@@ -26,13 +26,6 @@ export type ReleaseUpdate = {
installer: InstallerAsset;
};
export type UpdateFileConfig = {
enabled?: unknown;
apiUrl?: unknown;
releasePageUrl?: unknown;
assetPattern?: unknown;
};
type UrlPolicy = {
allowInsecureHttp: boolean;
};
-2
View File
@@ -5,7 +5,6 @@ import test from "node:test";
import {
getApplicationPaths,
getDashboardUrl,
getDefaultUpdateConfigPath,
getManagedNodecgRuntimePath,
getNodecgBaseUrl,
getRootPath,
@@ -23,7 +22,6 @@ test("app path helpers build deterministic development paths and URLs", () => {
assert.equal(getSourceNodecgRuntimePath(rootPath), path.resolve(rootPath, "lib", "nodecg"));
assert.equal(getUserDataPath("/app-data", "scoreko"), path.join("/app-data", "scoreko"));
assert.equal(getManagedNodecgRuntimePath("/app-data/scoreko"), path.join("/app-data/scoreko", "nodecg"));
assert.equal(getDefaultUpdateConfigPath(rootPath), path.join(rootPath, "static", "updates.json"));
assert.equal(getUpdateDownloadDirectory("/tmp"), path.join("/tmp", "scoreko-updates"));
assert.equal(getNodecgBaseUrl("9090"), "http://127.0.0.1:9090");
assert.equal(
+21 -56
View File
@@ -1,11 +1,8 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { AppRuntimeConfig } from "../main/config/runtime-config";
import { loadUpdateSettings, readUpdateFileConfig } from "../main/updates/update-config";
import { loadUpdateSettings } from "../main/updates/update-config";
const baseConfig: AppRuntimeConfig = {
title: "Scoreko",
@@ -23,37 +20,36 @@ const baseConfig: AppRuntimeConfig = {
};
test("loadUpdateSettings keeps updates disabled when the runtime config disables them", () => {
const rootPath = makeTempRoot({
enabled: true,
apiUrl: "https://gitea.local/releases/latest",
});
const settings = loadUpdateSettings({ ...baseConfig, updatesEnabled: false }, rootPath, () => undefined);
const settings = loadUpdateSettings(
{
...baseConfig,
updatesEnabled: false,
updateApiUrl: "https://gitea.local/releases/latest",
},
"",
() => undefined,
);
assert.equal(settings.enabled, false);
assert.equal(settings.apiUrl, "https://gitea.local/releases/latest");
});
test("loadUpdateSettings fails closed on insecure production update URLs", () => {
const rootPath = makeTempRoot({
enabled: true,
apiUrl: "http://gitea.local/releases/latest",
});
const settings = loadUpdateSettings(baseConfig, rootPath, () => undefined, { allowInsecureHttp: false });
const settings = loadUpdateSettings(
{
...baseConfig,
updateApiUrl: "http://gitea.local/releases/latest",
},
"",
() => undefined,
{ allowInsecureHttp: false },
);
assert.equal(settings.enabled, false);
assert.equal(settings.apiUrl, undefined);
});
test("loadUpdateSettings lets runtime config override file settings", () => {
const rootPath = makeTempRoot({
enabled: true,
apiUrl: "https://file.local/releases/latest",
releasePageUrl: "https://file.local/releases",
assetPattern: "File-.*\\.exe$",
});
test("loadUpdateSettings lets runtime config specify settings", () => {
const settings = loadUpdateSettings(
{
...baseConfig,
@@ -61,7 +57,7 @@ test("loadUpdateSettings lets runtime config override file settings", () => {
updateReleasePageUrl: "https://env.local/releases",
updateAssetPattern: "Env-.*\\.exe$",
},
rootPath,
"",
() => undefined,
);
@@ -72,34 +68,3 @@ test("loadUpdateSettings lets runtime config override file settings", () => {
assetPattern: "Env-.*\\.exe$",
});
});
test("readUpdateFileConfig normalizes malformed config into an empty file config", () => {
const rootPath = makeTempRoot(["not", "an", "object"]);
assert.deepEqual(readUpdateFileConfig(baseConfig, rootPath, () => undefined), {});
});
test("readUpdateFileConfig logs invalid JSON and returns an empty file config", () => {
const rootPath = fs.mkdtempSync(path.join(os.tmpdir(), "scoreko-update-config-"));
const staticPath = path.join(rootPath, "static");
fs.mkdirSync(staticPath, { recursive: true });
fs.writeFileSync(path.join(staticPath, "updates.json"), "{ invalid", "utf8");
const messages: unknown[][] = [];
const settings = readUpdateFileConfig(baseConfig, rootPath, (...args: unknown[]) => {
messages.push(args);
});
assert.deepEqual(settings, {});
assert.equal(messages.length, 1);
});
function makeTempRoot(config: unknown): string {
const rootPath = fs.mkdtempSync(path.join(os.tmpdir(), "scoreko-update-config-"));
const staticPath = path.join(rootPath, "static");
fs.mkdirSync(staticPath, { recursive: true });
fs.writeFileSync(path.join(staticPath, "updates.json"), JSON.stringify(config), "utf8");
return rootPath;
}
-6
View File
@@ -1,6 +0,0 @@
{
"enabled": false,
"apiUrl": "http://gitea.local/api/v1/repos/OWNER/REPO/releases/latest",
"releasePageUrl": "http://gitea.local/OWNER/REPO/releases",
"assetPattern": "Scoreko-setup-.*\\.exe$"
}