mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-05 21:22:07 +00:00
deleted unnecesary
This commit is contained in:
+13
-9
@@ -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_TITLE=Scoreko
|
||||||
SCOREKO_APP_USER_MODEL_ID=com.scoreko.desktop
|
SCOREKO_APP_USER_MODEL_ID=com.scoreko.desktop
|
||||||
SCOREKO_APP_USER_DATA_DIRECTORY=scoreko
|
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_BUNDLE_NAME=scoreko-dev
|
||||||
NODECG_PORT=9090
|
NODECG_PORT=9090
|
||||||
SCOREKO_DASHBOARD_ROUTE=dashboard/scoreko-dev/main.html?standalone=true
|
SCOREKO_DASHBOARD_ROUTE=dashboard/scoreko-dev/main.html?standalone=true
|
||||||
SCOREKO_LOADING_ROUTE=dashboard/loading/main.html?standalone=true
|
SCOREKO_LOADING_ROUTE=dashboard/loading/main.html?standalone=true
|
||||||
|
|
||||||
# Timing
|
# Timing & Lifecycles (Required)
|
||||||
ELECTRON_LOAD_DELAY_MS=10000
|
ELECTRON_LOAD_DELAY_MS=10000
|
||||||
NODECG_STARTUP_TIMEOUT_MS=120000
|
NODECG_STARTUP_TIMEOUT_MS=120000
|
||||||
NODECG_KILL_TIMEOUT_MS=2500
|
NODECG_KILL_TIMEOUT_MS=2500
|
||||||
|
|
||||||
# Updates
|
# Automated Updates Configuration (Required)
|
||||||
SCOREKO_UPDATES_ENABLED=true
|
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_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$
|
||||||
|
|||||||
@@ -27,10 +27,6 @@ export function getSourceNodecgRuntimePath(rootPath: string): string {
|
|||||||
return path.resolve(rootPath, "lib", "nodecg");
|
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 {
|
export function getUpdateDownloadDirectory(tempDirectory: string): string {
|
||||||
return path.join(tempDirectory, "scoreko-updates");
|
return path.join(tempDirectory, "scoreko-updates");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export type AppRuntimeConfig = {
|
|||||||
updateApiUrl?: string;
|
updateApiUrl?: string;
|
||||||
updateReleasePageUrl?: string;
|
updateReleasePageUrl?: string;
|
||||||
updateAssetPattern?: string;
|
updateAssetPattern?: string;
|
||||||
updateConfigPathOverride?: string;
|
|
||||||
updateCheckDelayMs: number;
|
updateCheckDelayMs: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,7 +54,6 @@ export function getRuntimeConfig(): AppRuntimeConfig {
|
|||||||
updateApiUrl: parseOptionalHttpUrl("SCOREKO_UPDATE_API_URL"),
|
updateApiUrl: parseOptionalHttpUrl("SCOREKO_UPDATE_API_URL"),
|
||||||
updateReleasePageUrl: parseOptionalHttpUrl("SCOREKO_UPDATE_RELEASE_PAGE_URL"),
|
updateReleasePageUrl: parseOptionalHttpUrl("SCOREKO_UPDATE_RELEASE_PAGE_URL"),
|
||||||
updateAssetPattern: getOptionalEnv("SCOREKO_UPDATE_ASSET_PATTERN"),
|
updateAssetPattern: getOptionalEnv("SCOREKO_UPDATE_ASSET_PATTERN"),
|
||||||
updateConfigPathOverride: getOptionalEnv("SCOREKO_UPDATE_CONFIG_PATH"),
|
|
||||||
updateCheckDelayMs: parseRequiredEnvIntInRange("SCOREKO_UPDATE_CHECK_DELAY_MS", 0, 600000),
|
updateCheckDelayMs: parseRequiredEnvIntInRange("SCOREKO_UPDATE_CHECK_DELAY_MS", 0, 600000),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import fs from "node:fs";
|
|
||||||
|
|
||||||
import { getDefaultUpdateConfigPath } from "../app/paths";
|
|
||||||
import { AppRuntimeConfig } from "../config/runtime-config";
|
import { AppRuntimeConfig } from "../config/runtime-config";
|
||||||
import { isRecord, readNonEmptyString } from "../utils/unknown-values";
|
import { readNonEmptyString } from "../utils/unknown-values";
|
||||||
import { UpdateFileConfig, validateHttpUrl } from "./update-schema";
|
import { validateHttpUrl } from "./update-schema";
|
||||||
|
|
||||||
const DEFAULT_UPDATE_ASSET_PATTERN = "Scoreko-setup-.*\\.exe$";
|
const DEFAULT_UPDATE_ASSET_PATTERN = "Scoreko-setup-.*\\.exe$";
|
||||||
|
|
||||||
@@ -20,11 +17,7 @@ type UpdateConfigOptions = {
|
|||||||
|
|
||||||
type UpdateRuntimeConfig = Pick<
|
type UpdateRuntimeConfig = Pick<
|
||||||
AppRuntimeConfig,
|
AppRuntimeConfig,
|
||||||
| "updateApiUrl"
|
"updateApiUrl" | "updateAssetPattern" | "updateReleasePageUrl" | "updatesEnabled"
|
||||||
| "updateAssetPattern"
|
|
||||||
| "updateConfigPathOverride"
|
|
||||||
| "updateReleasePageUrl"
|
|
||||||
| "updatesEnabled"
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export function loadUpdateSettings(
|
export function loadUpdateSettings(
|
||||||
@@ -33,49 +26,14 @@ export function loadUpdateSettings(
|
|||||||
log: (...args: unknown[]) => void,
|
log: (...args: unknown[]) => void,
|
||||||
options: UpdateConfigOptions = { allowInsecureHttp: true },
|
options: UpdateConfigOptions = { allowInsecureHttp: true },
|
||||||
): UpdateSettings {
|
): UpdateSettings {
|
||||||
const fileConfig = readUpdateFileConfig(appConfig, rootPath, log);
|
const apiUrl = readOptionalHttpUrl(appConfig.updateApiUrl, options);
|
||||||
const apiUrl = readOptionalHttpUrl(appConfig.updateApiUrl ?? fileConfig.apiUrl, options);
|
const releasePageUrl = readOptionalHttpUrl(appConfig.updateReleasePageUrl, options);
|
||||||
const releasePageUrl = readOptionalHttpUrl(appConfig.updateReleasePageUrl ?? fileConfig.releasePageUrl, options);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
enabled: appConfig.updatesEnabled && (Boolean(fileConfig.enabled) || Boolean(appConfig.updateApiUrl)) && Boolean(apiUrl),
|
enabled: appConfig.updatesEnabled && Boolean(apiUrl),
|
||||||
...(apiUrl ? { apiUrl } : {}),
|
...(apiUrl ? { apiUrl } : {}),
|
||||||
...(releasePageUrl ? { releasePageUrl } : {}),
|
...(releasePageUrl ? { releasePageUrl } : {}),
|
||||||
assetPattern:
|
assetPattern: appConfig.updateAssetPattern || DEFAULT_UPDATE_ASSET_PATTERN,
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,13 +26,6 @@ export type ReleaseUpdate = {
|
|||||||
installer: InstallerAsset;
|
installer: InstallerAsset;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateFileConfig = {
|
|
||||||
enabled?: unknown;
|
|
||||||
apiUrl?: unknown;
|
|
||||||
releasePageUrl?: unknown;
|
|
||||||
assetPattern?: unknown;
|
|
||||||
};
|
|
||||||
|
|
||||||
type UrlPolicy = {
|
type UrlPolicy = {
|
||||||
allowInsecureHttp: boolean;
|
allowInsecureHttp: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import test from "node:test";
|
|||||||
import {
|
import {
|
||||||
getApplicationPaths,
|
getApplicationPaths,
|
||||||
getDashboardUrl,
|
getDashboardUrl,
|
||||||
getDefaultUpdateConfigPath,
|
|
||||||
getManagedNodecgRuntimePath,
|
getManagedNodecgRuntimePath,
|
||||||
getNodecgBaseUrl,
|
getNodecgBaseUrl,
|
||||||
getRootPath,
|
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(getSourceNodecgRuntimePath(rootPath), path.resolve(rootPath, "lib", "nodecg"));
|
||||||
assert.equal(getUserDataPath("/app-data", "scoreko"), path.join("/app-data", "scoreko"));
|
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(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(getUpdateDownloadDirectory("/tmp"), path.join("/tmp", "scoreko-updates"));
|
||||||
assert.equal(getNodecgBaseUrl("9090"), "http://127.0.0.1:9090");
|
assert.equal(getNodecgBaseUrl("9090"), "http://127.0.0.1:9090");
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import assert from "node:assert/strict";
|
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 test from "node:test";
|
||||||
|
|
||||||
import { AppRuntimeConfig } from "../main/config/runtime-config";
|
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 = {
|
const baseConfig: AppRuntimeConfig = {
|
||||||
title: "Scoreko",
|
title: "Scoreko",
|
||||||
@@ -23,37 +20,36 @@ const baseConfig: AppRuntimeConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
test("loadUpdateSettings keeps updates disabled when the runtime config disables them", () => {
|
test("loadUpdateSettings keeps updates disabled when the runtime config disables them", () => {
|
||||||
const rootPath = makeTempRoot({
|
const settings = loadUpdateSettings(
|
||||||
enabled: true,
|
{
|
||||||
apiUrl: "https://gitea.local/releases/latest",
|
...baseConfig,
|
||||||
});
|
updatesEnabled: false,
|
||||||
|
updateApiUrl: "https://gitea.local/releases/latest",
|
||||||
const settings = loadUpdateSettings({ ...baseConfig, updatesEnabled: false }, rootPath, () => undefined);
|
},
|
||||||
|
"",
|
||||||
|
() => undefined,
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(settings.enabled, false);
|
assert.equal(settings.enabled, false);
|
||||||
assert.equal(settings.apiUrl, "https://gitea.local/releases/latest");
|
assert.equal(settings.apiUrl, "https://gitea.local/releases/latest");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("loadUpdateSettings fails closed on insecure production update URLs", () => {
|
test("loadUpdateSettings fails closed on insecure production update URLs", () => {
|
||||||
const rootPath = makeTempRoot({
|
const settings = loadUpdateSettings(
|
||||||
enabled: true,
|
{
|
||||||
apiUrl: "http://gitea.local/releases/latest",
|
...baseConfig,
|
||||||
});
|
updateApiUrl: "http://gitea.local/releases/latest",
|
||||||
|
},
|
||||||
const settings = loadUpdateSettings(baseConfig, rootPath, () => undefined, { allowInsecureHttp: false });
|
"",
|
||||||
|
() => undefined,
|
||||||
|
{ allowInsecureHttp: false },
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(settings.enabled, false);
|
assert.equal(settings.enabled, false);
|
||||||
assert.equal(settings.apiUrl, undefined);
|
assert.equal(settings.apiUrl, undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("loadUpdateSettings lets runtime config override file settings", () => {
|
test("loadUpdateSettings lets runtime config specify settings", () => {
|
||||||
const rootPath = makeTempRoot({
|
|
||||||
enabled: true,
|
|
||||||
apiUrl: "https://file.local/releases/latest",
|
|
||||||
releasePageUrl: "https://file.local/releases",
|
|
||||||
assetPattern: "File-.*\\.exe$",
|
|
||||||
});
|
|
||||||
|
|
||||||
const settings = loadUpdateSettings(
|
const settings = loadUpdateSettings(
|
||||||
{
|
{
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
@@ -61,7 +57,7 @@ test("loadUpdateSettings lets runtime config override file settings", () => {
|
|||||||
updateReleasePageUrl: "https://env.local/releases",
|
updateReleasePageUrl: "https://env.local/releases",
|
||||||
updateAssetPattern: "Env-.*\\.exe$",
|
updateAssetPattern: "Env-.*\\.exe$",
|
||||||
},
|
},
|
||||||
rootPath,
|
"",
|
||||||
() => undefined,
|
() => undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -72,34 +68,3 @@ test("loadUpdateSettings lets runtime config override file settings", () => {
|
|||||||
assetPattern: "Env-.*\\.exe$",
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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$"
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user