config-sets
Version:
Easily configure the app in real-time.
295 lines (209 loc) • 8.41 kB
JavaScript
/** Copyright (c) Manuel Lõhmus (MIT License). */
;
var path = require('path'),
dataContext = require('data-context'),
configFileName = 'config-sets.json',
scriptName = path.parse(process.argv[1]).base,
args = arg_options(),
configSettings = dataContext({
'-metadata': [
` Configuration settings for application. `,
],
'-metadata-isProduction': [
` Set to true to use production settings, `,
` false for development settings. Default is true. `
],
isProduction: true,
production: {
'-metadata': [
` Settings used in production mode. `,
` These settings are saved to "${configFileName}" file. `
],
},
development: {
'-metadata': [
` Settings used in development mode. `,
` These settings are not saved to file and are created from production settings. `,
` You can override these settings using command line arguments. `,
` Set only the settings you want to change. `
],
}
});
if ((args.help || args.help === '') && (scriptName === 'index' || scriptName === 'index.js')) {
print_help();
process.exit(0);
}
if (Object.keys(args).length) {
configSettings.production = assign(configSettings.production, args, true);
configSettings.resetChanges();
}
module.exports = Object.defineProperties(configSets, {
assign: { value: assign, configurable: false, enumerable: false, writable: false },
arg_options: { value: arg_options, configurable: false, enumerable: false, writable: false },
print_help: { value: print_help, configurable: false, enumerable: false, writable: false },
isProduction: {
configurable: false, enumerable: false,
get: function () { return configSettings.isProduction; },
set: function (val) { configSettings.isProduction = Boolean(val); }
},
production: {
configurable: false, enumerable: false,
get: function () { return configSettings.production; }
},
development: {
configurable: false, enumerable: false,
get: function () { return configSettings.development; }
},
enableFileReadWrite: {
configurable: false, enumerable: false,
get: function () { return dataContext.enableFileReadWrite; },
set: function (val) { dataContext.enableFileReadWrite = Boolean(val); }
}
});
function configSets(configModuleName, defaultConfigSettings, watchFile = true) {
var fileWatcher = null;
if (watchFile) { watchConfigFile(); }
if (defaultConfigSettings === undefined && typeof configModuleName === 'object') {
defaultConfigSettings = configModuleName;
configModuleName = undefined;
}
else if (defaultConfigSettings === undefined) {
defaultConfigSettings = {};
}
if (configModuleName) {
configModuleName = configModuleName + '';
if (!configSettings.production[configModuleName]) { configSettings.production[configModuleName] = dataContext({}); }
configSettings.production[configModuleName] = assign(configSettings.production[configModuleName], defaultConfigSettings);
}
else {
configSettings.production = assign(configSettings.production, defaultConfigSettings);
}
if (configSettings.isProduction) {
return configModuleName ? configSettings.production[configModuleName] : configSettings.production;
}
configSettings.development = assign(configSettings.development, configSettings.production);
configSettings.resetChanges();
return configModuleName ? configSettings.development[configModuleName] : configSettings.development;
function watchConfigFile() {
if (fileWatcher) { return; }
fileWatcher = dataContext.watchJsonFile({
filePath: path.join(process.cwd(), configFileName),
data: configSettings,
removeUnusedKeys: false
});
}
}
function assign(target, source, overwriteChanges = false) {
if (!target && typeof target !== "object") { target = {}; }
if (Array.isArray(source) && !Array.isArray(target) && target !== null) { target = []; }
if (source && typeof source === "object") {
for (var k in source) {
if (!source.hasOwnProperty(k)) continue;
if (typeof source[k] === "function" || k === "__proto__" || k === "constructor") { continue; }
if (k.startsWith('-metadata')) {
if (target[k] === undefined) {
Object.defineProperty(target, k, {
value: Array.isArray(source[k]) ? source[k] : [source[k]],
enumerable: false
});
}
else if (overwriteChanges) {
target[k] = Array.isArray(source[k]) ? source[k] : [source[k]];
}
continue;
}
if (!source[k] || typeof source[k] !== "object") {
if (target[k] === undefined || overwriteChanges) { target[k] = source[k]; }
}
else {
if (typeof target[k] !== "object") { target[k] = {}; }
target[k] = assign(target[k], source[k], overwriteChanges);
}
}
}
return target;
}
function arg_options() {
if ("undefined" === typeof process) { return {}; }
var isKey = false,
key = '',
values,
args = process.argv
.slice(2)
.join('')
.split('')
.reduce(function (args, c) {
if (c === '-') {
if (isKey && key && !args[key]) { args[key] = ['true']; }
isKey = true;
key = '';
return args;
}
if (c === '=') {
isKey = false;
if (!args[key]) { args[key] = []; }
values = args[key];
values.push('');
return args;
}
if (isKey && /\s/.test(c)) {
return args;
}
if (isKey) {
key += c;
return args;
}
if (values?.length) {
values[values.length - 1] += c;
}
return args;
}, {});
if (isKey && key && !args[key]) { args[key] = ['true']; }
Object.keys(args).forEach((k) => {
if (!args[k].length) {
args[k] = '';
return;
}
if (args[k].length === 1) {
args[k] = convertValue(args[k][0].trim());
return;
}
args[k] = args[k].map((s) => {
return convertValue(s.trim());
});
});
return args;
function convertValue(val) {
if (val === '') { return ''; }
if (val === 'null') { return null; }
if (val === 'true') { return true; }
if (val === 'false') { return false; }
if (!isNaN(Number(val))) { return Number(val); }
return val;
}
}
function print_help() {
var lines = [
`
The config-sets module is used to manage configuration settings for applications.
USAGE: ${scriptName} [--option=value] [--option2=value2] [--help] [--option] ...
The following options are supported:
`
],
options = { help: 'Display this help' };
for (var key in configSettings.production) {
if (configSettings.production['-metadata-' + key]) {
options[key] = configSettings.production['-metadata-' + key];
}
}
for (var [key, value] of Object.entries(options)) {
lines.push(
'\t--'
+ key
+ (key.length < 5 ? ':\t\t' : ':\t')
+ (value + '').trim()
);
}
lines.forEach((l) => console.log(l));
console.log();
}