Better loading of nested settings

-Improved loading of settings including warning of missing and/or invalid settings and the ability to load the explorer using defaults without a settings.json file
This commit is contained in:
joeuhren
2021-01-23 16:51:46 -07:00
parent 4790764e2c
commit a538be2dbb
2 changed files with 147 additions and 51 deletions
+142 -50
View File
@@ -955,64 +955,156 @@ exports.blockchain_specific = {
}
};
exports.reloadSettings = function reloadSettings() {
// Discover where the settings file lives
var settingsFilename = "settings.json";
settingsFilename = "./" + settingsFilename;
var settingsStr;
try{
//read the settings sync
settingsStr = fs.readFileSync(settingsFilename).toString();
} catch(e){
console.warn('No settings file found. Continuing using defaults!');
}
// try to parse the settings
exports.loadSettings = function loadSettings() {
var settings_filename = "./settings.json";
var settings;
try {
if(settingsStr) {
settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}");
settings = JSON.parse(settingsStr);
var json_settings;
// define an exception list of setting json paths (period separated) that do not have defaults and should not throw 'unknown setting' errors
var exceptions = ['labels'];
// check if the settings.json file exists
if (fs.existsSync(settings_filename)) {
try {
// read settings.json into a string variable
settings = fs.readFileSync(settings_filename).toString();
} catch(e) {
console.warn('The settings.json file is missing. Continuing using defaults.');
}
}catch(e){
console.error('There was an error processing your settings.json file: '+e.message);
} else
console.warn('The settings.json file is missing. Continuing using defaults.');
try {
// check if the settings string was populated
if (settings) {
// get settings string ready for json conversion
settings = jsonminify(settings).replace(",]","]").replace(",}","}");
// convert settings string to json object
json_settings = JSON.parse(settings);
}
} catch(e) {
console.error('There was an error processing your settings.json file: ' + e.message);
process.exit(1);
}
//loop trough the settings
for(var i in settings)
{
//test if the setting start with a low character
if(i.charAt(0).search("[a-z]") !== 0)
{
console.warn("Settings should start with a low character: '" + i + "'");
// check if the json settings were populated
if (json_settings != null) {
// loop through all settings from the settings.json file
for (var current_setting in json_settings) {
// merge settings from settings.json with the defaults from settings.js
merge_settings(json_settings, exceptions, json_settings[current_setting], current_setting);
}
//we know this setting, so we overwrite it
if(exports[i] !== undefined)
{
// This check uses old .user and .pass config strings if they exist, and .username, .password don't.
if (i == 'wallet')
{
if (!settings.wallet.hasOwnProperty('username') && settings.wallet.hasOwnProperty('user'))
{
settings.wallet.username = settings.wallet.user;
}
if (!settings.wallet.hasOwnProperty('password') && settings.wallet.hasOwnProperty('pass'))
{
settings.wallet.password = settings.wallet.pass;
}
}
exports[i] = settings[i];
}
//this setting is unkown, output a warning and throw it away
else
{
console.warn("Unknown Setting: '" + i + "'. This setting doesn't exist or it was removed");
// re-initialize the exceptions list
exceptions = ['loadSettings'];
// loop through the loaded/default settings (settings.js) to look for missing settings
for (var current_setting in exports) {
// look for missing settings from settings.json based on the defaults from settings.js
check_missing_settings(json_settings, exceptions, exports[current_setting], current_setting);
}
}
};
// initially load settings
exports.reloadSettings();
// define a recursive function used to merge settings from different json objects
merge_settings = function(json_settings, exceptions, current_setting, path) {
// check if this is an object with more properties
if (typeof current_setting === 'object' && current_setting !== null) {
// this is an object
// check if this object already exists in the default settings (settings.js)
if (Object.byString(exports, path) == null) {
// this setting object does not exist in settings.js
// show warning msg
console.warn("Unknown setting '" + path + "' has been ignored. This setting doesn't exist or was removed.");
} else {
// the object exists in the loaded settings
// check if the object is an array or is one of the exceptions
if (Array.isArray(current_setting) || exceptions.indexOf(path) > -1) {
// the object is an array or is an exception
// merge the object into settings.js without checking object keys
eval('exports' + fix_object_path(path) + ' = ' + JSON.stringify(Object.byString(json_settings, path)));
} else {
// the object is not an array or an exception
// loop through the object keys to continue checking for missing properties
for (var setting_name in current_setting) {
// recursively step through all properties of this object and merge setting values
merge_settings(json_settings, exceptions, current_setting[setting_name], path + '.' + setting_name);
}
}
}
} else {
// this is a property
// check if this property already exists in the default settings (settings.js)
if (Object.byString(exports, path) == null) {
// this setting property does not exist in settings.js
// show warning msg
console.warn("Unknown setting '" + path + "' has been ignored. This setting doesn't exist or was removed.");
} else {
// the property exists in the loaded settings
// get the settings.json value
var setting_value = Object.byString(json_settings, path);
// overwrite the property value with the value from settings.json
eval('exports' + fix_object_path(path) + ' = ' + (typeof setting_value === "string" ? '"' : '') + setting_value + (typeof setting_value === "string" ? '"' : ''));
}
}
}
// define a recursive function used to check settings for missing entries between json objects
check_missing_settings = function(json_settings, exceptions, current_setting, path) {
// check if this is an object with more properties
if (typeof current_setting === 'object' && current_setting !== null) {
// this is an object
// check if this object exists in the json settings (settings.json)
if (Object.byString(json_settings, path) == null) {
// this setting object does not exist in settings.json
// check if it is an exception
if (exceptions.indexOf(path) == -1) {
// this is not one of the exceptions
// show warning msg
console.warn("setting '" + path + "' is missing. Loading default value.");
}
} else {
// the object exists in the json settings
// loop through the object keys to continue checking for missing properties
for (var setting_name in current_setting) {
// recursively step through all properties of this object
check_missing_settings(json_settings, exceptions, current_setting[setting_name], path + '.' + setting_name);
}
}
} else {
// this is a property
// check if this property exists in the json settings (settings.json)
if (Object.byString(json_settings, path) == null) {
// this setting property does not exist in settings.json
// check if it is an exception
if (exceptions.indexOf(path) == -1) {
// this is not one of the exceptions
// show warning msg
console.warn("setting '" + path + "' is missing. Loading default value.");
}
}
}
}
// define a function used to fix object paths
fix_object_path = function(path) {
return "['" + path.replace(/\./g, "']['") + "']";
}
/* Special thanks to Alnitak for the Object.byString function: https://stackoverflow.com/a/6491621/3038650 */
Object.byString = function(o, s) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
for (var i = 0, n = a.length; i < n; ++i) {
var k = a[i];
if (k in o) {
o = o[k];
} else {
return;
}
}
return o;
}
// populate settings
exports.loadSettings();
+5 -1
View File
@@ -1,3 +1,7 @@
#!/bin/bash
echo "\$theme-name: \"$(./node_modules/.bin/strip-json-comments settings.json | ./node_modules/.bin/json shared_pages.theme)\";" > ./public/css/_theme-selector.scss
if [ -f ./settings.json ]; then
echo "\$theme-name: \"$(./node_modules/.bin/strip-json-comments settings.json | ./node_modules/.bin/json shared_pages.theme)\";" > ./public/css/_theme-selector.scss
else
echo "\$theme-name: \"Exor\";" > ./public/css/_theme-selector.scss
fi