/**
* @file
* @brief Builds the live settings object: clone defaults, merge user-settings.json, migrate any legacy user-settings.js. Exposes settings() / userSettings() / save / reload / replace. Notes: notes/systems/cli.md.
*/
import fs from "node:fs";
import { createRequire } from "node:module";
import _ from "lodash";
import createMissingUserSettings from "./createMissingUserSettings.js";
import diffSettings from "./diffSettings.js";
// Load settings
import basicSettings from "./settings.js";
import imageSettings from "./image-settings.js";
import upscaleSettings from "./upscale-settings.js";
import serverSettings from "./server-settings.js";
// Scoped require used only for the optional, synchronous legacy `user-settings.js`
// migration below (createRequire can load the old CommonJS settings file).
const require = createRequire(import.meta.url);
const isServer = process.env.server !== undefined;
// Ensure user-settings is created
createMissingUserSettings();
// Add whether we're runing inside a server or not
basicSettings.isServer = isServer;
// Combine them into a single object
// We use deep-clone to prevent the mfrom being modified
// This also prevents a bug where converting legacy settings which modifies these files
// therefore also modies this copy
const defSettings = _.cloneDeep({
settings: basicSettings,
imageSettings,
upscaleSettings,
serverSettings,
});
let settings;
/**
* (Re)build the live settings object: clone the defaults, merge `user-settings.json`,
* and migrate a legacy `user-settings.js` if present.
* @returns {void}
*/
// Does a complicated process of reloading settings
function reloadSettings() {
// Load "user-settings.json"
let userSettings = JSON.parse(fs.readFileSync("./user-settings.json").toString());
// Clone default settings as a basis
settings = _.cloneDeep(defSettings);
// Merge user settings into main settings
if (userSettings.settings != undefined) _.merge(settings.settings, userSettings.settings);
if (userSettings.imageSettings != undefined)
_.merge(settings.imageSettings, userSettings.imageSettings);
if (userSettings.upscaleSettings != undefined)
_.merge(settings.upscaleSettings, userSettings.upscaleSettings);
if (userSettings.serverSettings != undefined)
_.merge(settings.serverSettings, userSettings.serverSettings);
// Merge legacy user-settings.js if it exists
try {
// Import legacy settings
const legacySettings = require("../user-settings.js");
console.log("Found old user-settings.js, converting to user-settings.json...");
// Do a diff on it to extract the actual changes
const legacyDiff = diffSettings(legacySettings, defSettings);
// Merge changes in
_.merge(settings, legacyDiff);
// Remove legacy file
fs.unlinkSync("./user-settings.js");
} catch (err) {}
}
// Do initial settings load now
reloadSettings();
/**
* Compute the settings that differ from defaults, with internal-only / runtime
* fields (progress, lastCmd, animation bookkeeping, …) stripped.
* @returns {object} The persistable user settings.
*/
// Allows obtaining the user dettings that differ from the main settings
function userSettings() {
// Get diff between default and user settings
const ret = diffSettings(settings, defSettings);
// Remove these internal only settings
delete ret.settings.origPrompt;
delete ret.settings.randomPrompt;
delete ret.settings.animationPromptSet;
delete ret.imageSettings.lastCmd;
delete ret.imageSettings.variationOf;
delete ret.imageSettings.origPostPrompt;
delete ret.imageSettings.autoIncludedFx;
delete ret.imageSettings.autoIncludedArtists;
delete ret.imageSettings.animationOf;
delete ret.imageSettings.animationFrames;
delete ret.imageSettings.animationOfImg;
delete ret.imageSettings.resultPrompts;
delete ret.imageSettings.resultImages;
delete ret.imageSettings.progressOngoing;
delete ret.imageSettings.progressPercent;
delete ret.imageSettings.progressEta;
delete ret.imageSettings.progressCurImg;
delete ret.imageSettings.progressTotalImg;
delete ret.imageSettings.progressCurStep;
delete ret.imageSettings.progressTotalSteps;
delete ret.imageSettings.progressCurPrompt;
delete ret.imageSettings.progressTotalPrompts;
delete ret.imageSettings.progressUpscaling;
// Return
return ret;
}
/**
* Persist `userSettings()` to `user-settings.json`.
* @returns {void}
*/
// Save User Settings
function saveSettings() {
// Save user settings as user-settings.json
fs.writeFileSync("./user-settings.json", JSON.stringify(userSettings(), null, 4));
}
// Do initial save now
saveSettings();
export default {
// Settings (Use function to get up-to-date settings)
settings() {
return settings;
},
userSettings,
// Default settings (Debug, use deep clone to prevent tampering)
defSettings() {
return _.cloneDeep(defSettings);
},
// Replace Settings
replaceSettings(newSettings) {
settings = newSettings;
},
reloadSettings,
saveSettings,
};