Sursă publicată
Descarcă sursa ZIP
CH-J Server Manager
Navighează directoarele și fișierele pentru o anumită versiune a aplicației.
CH-J / Server Manager
339 fișiere
core-20261014T184258Z-3fbed0b93fdf
Adăugat: Data neînregistrată · Construit:
1
"use strict";3
const fs = require("node:fs");4
const path = require("node:path");5
const { atomicWriteJson } = require("../storage/atomicFile");7
const SUPPORTED_LANGUAGES = Object.freeze(["cs", "de", "en"]);8
const CATALOG_CHANNELS = Object.freeze(["alpha", "beta", "stable", "all"]);10
const DEFAULT_CONFIG = Object.freeze({11
schemaVersion: 1,12
ui: {13
language: "cs",14
theme: "system",15
navigationOrder: []16
},17
updates: {18
channel: "alpha",19
autoCheck: true,20
lastLaunchedRelease: null,21
baseUrls: [22
"https://www.sm.ch-j.de/",23
"https://sm.ch-j.de/"24
]25
},26
plugins: {27
channel: "alpha",28
display: {}29
},30
security: { autoLockMinutes: 0, lockOnBlur: false, requireSystemAuthentication: false }31
});33
function clone(value) {34
return JSON.parse(JSON.stringify(value));35
}37
function normalizeReleaseMarker(value) {38
if (!value || typeof value !== "object" || Array.isArray(value)) return null;39
const id = String(value.id || "").trim();40
const version = String(value.version || "").trim();41
const publishedAt = String(value.publishedAt || "").trim();42
const sha512 = String(value.sha512 || "").trim().toLowerCase();43
if (!id || !version || Number.isNaN(Date.parse(publishedAt)) || !/^[a-f0-9]{128}$/.test(sha512)) return null;44
return { id, version, publishedAt, sha512 };45
}47
function normalizeConfig(input = {}) {48
const source = input && typeof input === "object" && !Array.isArray(input) ? input : {};49
const channel = CATALOG_CHANNELS.includes(source.updates?.channel)50
? source.updates.channel51
: DEFAULT_CONFIG.updates.channel;52
const pluginChannel = CATALOG_CHANNELS.includes(source.plugins?.channel)53
? source.plugins.channel54
: DEFAULT_CONFIG.plugins.channel;55
const theme = ["system", "dark", "light"].includes(source.ui?.theme)56
? source.ui.theme57
: DEFAULT_CONFIG.ui.theme;58
const language = SUPPORTED_LANGUAGES.includes(String(source.ui?.language || ""))59
? String(source.ui.language)60
: DEFAULT_CONFIG.ui.language;62
return {63
schemaVersion: 1,64
ui: { language, theme, navigationOrder: Array.isArray(source.ui?.navigationOrder) ? [...new Set(source.ui.navigationOrder.filter((id) => typeof id === "string" && /^(overview|terminal|profiles|updates|plugins|diagnostics|settings|plugin:[a-z0-9][a-z0-9.-]{2,63})$/.test(id)))].slice(0, 200) : [] },65
updates: {66
channel,67
autoCheck: source.updates?.autoCheck !== false,68
lastLaunchedRelease: normalizeReleaseMarker(source.updates?.lastLaunchedRelease),69
baseUrls: clone(DEFAULT_CONFIG.updates.baseUrls)70
},71
plugins: { channel: pluginChannel, display: Object.fromEntries(Object.entries(source.plugins?.display && typeof source.plugins.display === "object" && !Array.isArray(source.plugins.display) ? source.plugins.display : {}).filter(([id, mode]) => /^[a-z0-9][a-z0-9.-]{2,63}$/.test(id) && ["hidden", "visible", "navigation"].includes(mode))) },72
security: {73
autoLockMinutes: [0, 1, 5, 10, 15, 30, 60].includes(source.security?.autoLockMinutes) ? source.security.autoLockMinutes : 0,74
lockOnBlur: source.security?.lockOnBlur === true,75
requireSystemAuthentication: source.security?.requireSystemAuthentication === true76
}77
};78
}80
class ConfigStore {81
constructor(rootDir) {82
this.rootDir = rootDir;83
this.filePath = path.join(rootDir, "config", "config.json");84
this.value = clone(DEFAULT_CONFIG);85
}87
load() {88
try {89
const raw = fs.readFileSync(this.filePath, "utf8");90
this.value = normalizeConfig(JSON.parse(raw));91
} catch (error) {92
if (error?.code !== "ENOENT") {93
const backup = `${this.filePath}.invalid-${Date.now()}`;94
try { fs.renameSync(this.filePath, backup); } catch {}95
}96
this.value = clone(DEFAULT_CONFIG);97
this.save();98
}99
return this.get();100
}102
get() {103
return clone(this.value);104
}106
update(patch = {}) {107
const updatePatch = patch.updates && typeof patch.updates === "object" ? patch.updates : {};108
const next = {109
...this.value,110
ui: { ...this.value.ui, ...(patch.ui || {}) },111
updates: {112
...this.value.updates,113
channel: updatePatch.channel ?? this.value.updates.channel,114
autoCheck: updatePatch.autoCheck ?? this.value.updates.autoCheck115
},116
plugins: { ...this.value.plugins, ...(patch.plugins || {}) },117
security: { ...this.value.security, ...(patch.security || {}) }118
};119
this.value = normalizeConfig(next);120
this.save();121
return this.get();122
}124
recordLaunchedRelease(release) {125
const marker = normalizeReleaseMarker(release);126
if (!marker) throw new Error("Invalid launched update release metadata.");127
this.value = normalizeConfig({128
...this.value,129
updates: { ...this.value.updates, lastLaunchedRelease: marker }130
});131
this.save();132
return clone(marker);133
}135
save() {136
atomicWriteJson(this.filePath, this.value);137
}138
}140
module.exports = {141
ConfigStore,142
CATALOG_CHANNELS,143
DEFAULT_CONFIG,144
SUPPORTED_LANGUAGES,145
normalizeReleaseMarker,146
normalizeConfig147
};SHA-256
744d184ccea7c6979d4a111b89a3b8e6ec7f8ee3a602242b7e1e669335ca187fCH-J Proprietary Software License 1.14 · Sursa este furnizată în cadrul CH-J Proprietary Software License 1.14. Disponibilitatea sa nu modifică termenii licenţei sau nu acordă drepturi suplimentare.
Archive SHA-256
3df08cf5e899262a6ce92d7ec2caf5c42b683f1f2b57055662b845ff7dde67a8