From 650696b9f55390d006fe4186f09d0bc02a2b84f0 Mon Sep 17 00:00:00 2001 From: MasterAcnolo Date: Wed, 28 Oct 2026 21:40:13 +0100 Subject: [PATCH] feat(config): add default configuration path resolver and merge missing feature flags --- config.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/config.js b/config.js index 5eb260f..66f6910 100644 --- a/config.js +++ b/config.js @@ -57,6 +57,40 @@ function resolveConfigPath() { */ const featuresPath = resolveConfigPath(); +/** + * Resolves the bundled default configuration path. + * + * @returns {string} Absolute path to the default configuration file + */ +function getDefaultConfigPath() { + return devMode + ? path.join(__dirname, "config", "config.default.json") + : path.join(process.resourcesPath, "config", "config.default.json"); +} + +/** + * Adds missing default feature flags without overwriting user settings. + * + * Unknown user-defined keys are intentionally preserved. + * + * @param {Object} defaults - Default feature flags + * @param {Object} current - User feature flags + * @returns {{features: Object, changed: boolean}} Merged features and migration state + */ +function mergeMissingFeatures(defaults, current) { + if (!defaults || typeof defaults !== "object" || Array.isArray(defaults)) { + throw new Error("Default configuration must be a JSON object"); + } + if (!current || typeof current !== "object" || Array.isArray(current)) { + throw new Error("User configuration must be a JSON object"); + } + + const features = { ...defaults, ...current }; + const changed = Object.keys(defaults).some((key) => !Object.prototype.hasOwnProperty.call(current, key)); + + return { features, changed }; +} + /** * Loads and parses the feature configuration file. * @@ -64,8 +98,15 @@ const featuresPath = resolveConfigPath(); * @throws {Error} If the configuration file is missing or invalid */ function loadFeatures() { - const raw = fs.readFileSync(featuresPath, "utf-8"); - return JSON.parse(raw); + const defaults = JSON.parse(fs.readFileSync(getDefaultConfigPath(), "utf-8")); + const current = JSON.parse(fs.readFileSync(featuresPath, "utf-8")); + const { features, changed } = mergeMissingFeatures(defaults, current); + + if (changed) { + fs.writeFileSync(featuresPath, JSON.stringify(features, null, 2), "utf-8"); + } + + return features; } /** @@ -77,8 +118,7 @@ function loadFeatures() { */ function reloadFeatures() { try { - const raw = fs.readFileSync(featuresPath, "utf-8"); - return JSON.parse(raw); + return loadFeatures(); } catch (err) { // Fallback to cached snapshot if file read fails return configFeatures; @@ -128,4 +168,9 @@ module.exports = { * Path to the active configuration file */ featuresPath, + + /** + * Merges missing default feature flags into user configuration without overwriting existing settings. + */ + mergeMissingFeatures, }; \ No newline at end of file