config: refactor config parsing.
This commit is contained in:
parent
f576ab6e6c
commit
0a1c0d1890
6
bin/cli
6
bin/cli
@ -11,13 +11,13 @@ var Amount = require('../lib/btc/amount');
|
||||
var main;
|
||||
|
||||
function CLI() {
|
||||
this.config = config({
|
||||
this.config = config.parseRaw({
|
||||
config: true,
|
||||
arg: true,
|
||||
env: true,
|
||||
network: 'main'
|
||||
}).data;
|
||||
this.argv = this.config.args;
|
||||
});
|
||||
this.argv = this.config.argv;
|
||||
this.client = null;
|
||||
this.wallet = null;
|
||||
}
|
||||
|
||||
@ -6,10 +6,9 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var Network = require('../protocol/network');
|
||||
var util = require('../utils/util');
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
var util = require('../utils/util');
|
||||
var global = util.global;
|
||||
|
||||
/**
|
||||
@ -38,6 +37,90 @@ config.alias = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse env and args.
|
||||
* @param {Object} options
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
config.parseArgs = function parseArgs(options) {
|
||||
var data = Object.create(null);
|
||||
var argv = [];
|
||||
var raw;
|
||||
|
||||
if (options.network != null) {
|
||||
assert(isAlpha(options.network), 'Bad network.');
|
||||
data.network = options.network;
|
||||
}
|
||||
|
||||
if (options.prefix != null) {
|
||||
assert(typeof options.prefix === 'string');
|
||||
assert(typeof options.prefix.length > 0);
|
||||
data.prefix = options.prefix;
|
||||
}
|
||||
|
||||
if (options.config != null) {
|
||||
if (typeof options.config === 'string') {
|
||||
assert(options.config.length > 0);
|
||||
data.config = options.config;
|
||||
} else {
|
||||
assert(typeof options.config === 'boolean');
|
||||
}
|
||||
}
|
||||
|
||||
if (options.env) {
|
||||
raw = config.parseEnv();
|
||||
merge(data, raw);
|
||||
}
|
||||
|
||||
if (options.arg) {
|
||||
raw = config.parseArg();
|
||||
argv = raw.argv;
|
||||
merge(data, raw.data);
|
||||
}
|
||||
|
||||
if (options.query) {
|
||||
raw = config.parseQuery();
|
||||
merge(data, raw);
|
||||
}
|
||||
|
||||
if (options.hash) {
|
||||
raw = config.parseHash();
|
||||
merge(data, raw);
|
||||
}
|
||||
|
||||
data.argv = argv;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse env, args, and config.
|
||||
* @param {Object} options
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
config.parseRaw = function parseRaw(options) {
|
||||
var data = config.parseArgs(options);
|
||||
var prefix = config.getPrefix(data);
|
||||
var file = config.getFile(prefix, data);
|
||||
var argv = data.argv;
|
||||
var raw;
|
||||
|
||||
if (options.config) {
|
||||
raw = config.readConfig(file);
|
||||
merge(raw, data);
|
||||
data = raw;
|
||||
prefix = config.getPrefix(data);
|
||||
}
|
||||
|
||||
data.argv = argv;
|
||||
data.prefix = prefix;
|
||||
data.config = file;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse options and potentially env, args, and config.
|
||||
* @param {Object} options
|
||||
@ -45,108 +128,101 @@ config.alias = {
|
||||
*/
|
||||
|
||||
config.parse = function parse(options) {
|
||||
var data = Object.create(null);
|
||||
var raw = Object.create(null);
|
||||
var arg, conf, prefix, filename, dirname;
|
||||
var data = config.parseRaw(options);
|
||||
var opt = config.toOptions(data);
|
||||
var keys = Object.keys(options);
|
||||
var i, key, file;
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
key = keys[i];
|
||||
|
||||
merge(data, options);
|
||||
|
||||
if (options.env) {
|
||||
arg = config.parseEnv();
|
||||
merge(raw, arg.data);
|
||||
merge(data, arg);
|
||||
}
|
||||
|
||||
if (options.arg) {
|
||||
arg = config.parseArg();
|
||||
merge(raw, arg.data);
|
||||
merge(data, arg);
|
||||
}
|
||||
|
||||
if (options.query) {
|
||||
arg = config.parseQuery();
|
||||
merge(raw, arg.data);
|
||||
merge(data, arg);
|
||||
}
|
||||
|
||||
if (options.hash) {
|
||||
arg = config.parseHash();
|
||||
merge(raw, arg.data);
|
||||
merge(data, arg);
|
||||
}
|
||||
|
||||
if (data.config && !util.isBrowser) {
|
||||
prefix = config.getPrefix(data);
|
||||
filename = data.config;
|
||||
|
||||
if (typeof filename !== 'string')
|
||||
filename = resolve(prefix, 'bcoin.conf');
|
||||
|
||||
dirname = util.normalize(filename, true);
|
||||
conf = config.readConfig(filename, prefix, dirname);
|
||||
raw = merge(conf.data, raw);
|
||||
data = merge(conf, data);
|
||||
|
||||
prefix = config.getPrefix(data);
|
||||
|
||||
if (!data.knownPeers) {
|
||||
filename = resolve(prefix, 'known-peers');
|
||||
data.knownPeers = config.readKnown(filename);
|
||||
switch (key) {
|
||||
case 'env':
|
||||
case 'arg':
|
||||
case 'query':
|
||||
case 'hash':
|
||||
case 'config':
|
||||
case 'raw':
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!data.authPeers) {
|
||||
filename = resolve(prefix, 'authorized-peers');
|
||||
data.authPeers = config.readAuth(filename);
|
||||
if (opt[key] != null)
|
||||
continue;
|
||||
|
||||
opt[key] = options[key];
|
||||
}
|
||||
|
||||
if (options.config) {
|
||||
if (!opt.knownPeers) {
|
||||
file = resolve(data.prefix, 'known-peers');
|
||||
opt.knownPeers = config.readKnown(file);
|
||||
}
|
||||
|
||||
if (!opt.authPeers) {
|
||||
file = resolve(data.prefix, 'authorized-peers');
|
||||
opt.authPeers = config.readAuth(file);
|
||||
}
|
||||
}
|
||||
|
||||
data.data = raw;
|
||||
|
||||
// Force fast properties
|
||||
// after all those merges.
|
||||
util.fastProp(data);
|
||||
|
||||
return data;
|
||||
return opt;
|
||||
};
|
||||
|
||||
/**
|
||||
* Grab prefix from env, args, and options.
|
||||
* @param {Object} env
|
||||
* @param {Object} arg
|
||||
* @param {Object} options
|
||||
* Grab prefix from data.
|
||||
* @private
|
||||
* @param {Object} data
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
config.getPrefix = function getPrefix(data) {
|
||||
var prefix = data.prefix;
|
||||
var network;
|
||||
|
||||
if (!prefix)
|
||||
prefix = util.HOME + '/.bcoin';
|
||||
if (prefix)
|
||||
return prefix;
|
||||
|
||||
network = Network.get(data.network).type;
|
||||
prefix = util.HOME + '/.bcoin';
|
||||
|
||||
prefix = util.normalize(prefix);
|
||||
if (data.network) {
|
||||
assert(isAlpha(data.network), 'Bad network.');
|
||||
network = data.network;
|
||||
} else {
|
||||
network = 'main';
|
||||
}
|
||||
|
||||
if (network !== 'main')
|
||||
prefix += '/' + network;
|
||||
|
||||
return prefix;
|
||||
return util.normalize(prefix);
|
||||
};
|
||||
|
||||
/**
|
||||
* Grab config file from data.
|
||||
* @private
|
||||
* @param {String} prefix
|
||||
* @param {Object} data
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
config.getFile = function getFile(prefix, data) {
|
||||
var file = data.config;
|
||||
|
||||
if (!file)
|
||||
return resolve(prefix, 'bcoin.conf');
|
||||
|
||||
return util.normalize(file);
|
||||
};
|
||||
|
||||
/**
|
||||
* Enforce types on parsed data.
|
||||
* @param {Object} data
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
config.parseData = function parseData(data, prefix, dirname) {
|
||||
config.toOptions = function toOptions(data) {
|
||||
var prefix = data.prefix;
|
||||
var options = {};
|
||||
|
||||
// Config
|
||||
options.config = path(data.config);
|
||||
|
||||
// Options
|
||||
options.network = str(data.network);
|
||||
options.useWorkers = bool(data.useworkers);
|
||||
@ -155,20 +231,15 @@ config.parseData = function parseData(data, prefix, dirname) {
|
||||
options.sigcacheSize = num(data.sigcachesize);
|
||||
|
||||
// Node
|
||||
options.prefix = path(data.prefix, null, dirname);
|
||||
options.prefix = path(prefix, prefix);
|
||||
options.db = str(data.db);
|
||||
options.maxFiles = num(data.maxfiles);
|
||||
options.cacheSize = mul(data.cachesize, 1024 * 1024);
|
||||
options.fast = bool(data.fast);
|
||||
|
||||
// Update the prefix if we're using one.
|
||||
if (prefix && options.prefix)
|
||||
prefix = config.getPrefix(options);
|
||||
|
||||
// Logger
|
||||
options.logLevel = str(data.loglevel);
|
||||
options.logConsole = bool(data.logconsole);
|
||||
options.logFile = boolpath(data.logfile, prefix, dirname);
|
||||
options.logFile = boolpath(data.logfile, prefix);
|
||||
|
||||
// Chain
|
||||
options.forceWitness = bool(data.forcewitness);
|
||||
@ -203,16 +274,16 @@ config.parseData = function parseData(data, prefix, dirname) {
|
||||
options.host = str(data.host);
|
||||
options.port = num(data.port);
|
||||
options.listen = bool(data.listen);
|
||||
options.knownPeers = file(data.knownpeers, prefix, dirname, 'utf8');
|
||||
options.authPeers = file(data.authpeers, prefix, dirname, 'utf8');
|
||||
options.knownPeers = file(data.knownpeers, prefix, 'utf8');
|
||||
options.authPeers = file(data.authpeers, prefix, 'utf8');
|
||||
|
||||
// Miner
|
||||
options.payoutAddress = list(data.payoutaddress);
|
||||
options.coinbaseFlags = str(data.coinbaseflags);
|
||||
|
||||
// HTTP
|
||||
options.sslCert = file(data.sslcert, prefix, dirname);
|
||||
options.sslKey = file(data.sslkey, prefix, dirname);
|
||||
options.sslCert = file(data.sslcert, prefix);
|
||||
options.sslKey = file(data.sslkey, prefix);
|
||||
options.httpPort = num(data.httpport);
|
||||
options.httpHost = str(data.httphost);
|
||||
options.apiKey = str(data.apikey);
|
||||
@ -224,14 +295,14 @@ config.parseData = function parseData(data, prefix, dirname) {
|
||||
options.startHeight = num(data.startheight);
|
||||
options.wipeNoReally = bool(data.wipenoreally);
|
||||
|
||||
options.data = data;
|
||||
|
||||
if (options.knownPeers != null)
|
||||
options.knownPeers = config.parseKnown(options.knownPeers);
|
||||
|
||||
if (options.authPeers != null)
|
||||
options.authPeers = config.parseAuth(options.authPeers);
|
||||
|
||||
options.raw = data;
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
@ -241,8 +312,8 @@ config.parseData = function parseData(data, prefix, dirname) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
config.readConfig = function readConfig(file, prefix, dirname) {
|
||||
return config.parseConfig(readFile(file), prefix, dirname);
|
||||
config.readConfig = function readConfig(file) {
|
||||
return config.parseConfig(readFile(file));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -271,7 +342,7 @@ config.readAuth = function readAuth(file) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
config.parseConfig = function parseConfig(text, prefix, dirname) {
|
||||
config.parseConfig = function parseConfig(text) {
|
||||
var data = Object.create(null);
|
||||
var i, parts, line, key, value, eq, col, alias;
|
||||
|
||||
@ -318,7 +389,7 @@ config.parseConfig = function parseConfig(text, prefix, dirname) {
|
||||
data[key] = value;
|
||||
}
|
||||
|
||||
return config.parseData(data, prefix, dirname);
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -330,15 +401,13 @@ config.parseConfig = function parseConfig(text, prefix, dirname) {
|
||||
config.parseArg = function parseArg(argv) {
|
||||
var data = Object.create(null);
|
||||
var args = [];
|
||||
var i, arg, key, value, alias, equals;
|
||||
var i, j, arg, key, value, alias, equals;
|
||||
|
||||
if (!argv)
|
||||
argv = process.argv;
|
||||
|
||||
argv = argv.slice(2);
|
||||
|
||||
while (argv.length) {
|
||||
arg = argv.shift();
|
||||
for (i = 2; i < argv.length; i++) {
|
||||
arg = argv[i];
|
||||
|
||||
if (arg.indexOf('--') === 0) {
|
||||
// e.g. --opt
|
||||
@ -375,8 +444,8 @@ config.parseArg = function parseArg(argv) {
|
||||
// e.g. -abc
|
||||
arg = arg.substring(1);
|
||||
|
||||
for (i = 0; i < arg.length; i++) {
|
||||
key = arg[i];
|
||||
for (j = 0; j < arg.length; j++) {
|
||||
key = arg[j];
|
||||
alias = config.alias.arg[key];
|
||||
if (alias)
|
||||
key = alias;
|
||||
@ -401,9 +470,10 @@ config.parseArg = function parseArg(argv) {
|
||||
}
|
||||
}
|
||||
|
||||
data.args = args;
|
||||
|
||||
return config.parseData(data);
|
||||
return {
|
||||
data: data,
|
||||
argv: args
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@ -448,7 +518,7 @@ config.parseEnv = function parseEnv(env, prefix) {
|
||||
data[key] = value;
|
||||
}
|
||||
|
||||
return config.parseData(data);
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -535,7 +605,7 @@ config.parseForm = function parseForm(query) {
|
||||
data[key] = value;
|
||||
}
|
||||
|
||||
return config.parseData(data);
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -659,7 +729,7 @@ function key(value) {
|
||||
return key;
|
||||
}
|
||||
|
||||
function path(value, prefix, dirname) {
|
||||
function path(value, prefix) {
|
||||
if (!value)
|
||||
return null;
|
||||
|
||||
@ -668,12 +738,9 @@ function path(value, prefix, dirname) {
|
||||
value = util.HOME + value.substring(1);
|
||||
break;
|
||||
case '@': // prefix
|
||||
if (prefix)
|
||||
value = prefix + value.substring(1);
|
||||
value = prefix + value.substring(1);
|
||||
break;
|
||||
default: // dirname of config, or cwd
|
||||
if (dirname)
|
||||
value = resolve(dirname, value);
|
||||
default: // cwd
|
||||
break;
|
||||
}
|
||||
|
||||
@ -712,7 +779,7 @@ function mul(value, mult) {
|
||||
return value * mult;
|
||||
}
|
||||
|
||||
function boolpath(value, prefix, dirname) {
|
||||
function boolpath(value, prefix) {
|
||||
if (!value)
|
||||
return null;
|
||||
|
||||
@ -722,14 +789,14 @@ function boolpath(value, prefix, dirname) {
|
||||
if (value === 'false' || value === '0')
|
||||
return false;
|
||||
|
||||
return path(value, prefix, dirname);
|
||||
return path(value, prefix);
|
||||
}
|
||||
|
||||
function file(value, prefix, dirname, enc) {
|
||||
function file(value, prefix, enc) {
|
||||
if (fs.unsupported)
|
||||
return null;
|
||||
|
||||
value = path(value, prefix, dirname);
|
||||
value = path(value, prefix);
|
||||
|
||||
if (!value)
|
||||
return null;
|
||||
@ -789,6 +856,16 @@ function unescape(str) {
|
||||
}
|
||||
}
|
||||
|
||||
function isAlpha(str) {
|
||||
if (typeof str !== 'string')
|
||||
return false;
|
||||
|
||||
if (!/^[a-z0-9]+$/.test(str))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -69,8 +69,11 @@ Node.prototype.initOptions = function initOptions(options) {
|
||||
|
||||
this.options = options;
|
||||
|
||||
if (options.network != null)
|
||||
if (options.network != null) {
|
||||
this.network = Network.get(options.network);
|
||||
if (this.network !== Network.main)
|
||||
this.prefix += '/' + this.network.type;
|
||||
}
|
||||
|
||||
if (options.prefix != null) {
|
||||
assert(typeof options.prefix === 'string');
|
||||
@ -266,11 +269,7 @@ Node.prototype.error = function error(err) {
|
||||
*/
|
||||
|
||||
Node.prototype.location = function location(name) {
|
||||
var path = this.prefix;
|
||||
if (this.network !== Network.main)
|
||||
path += '/' + this.network.type;
|
||||
path += '/' + name;
|
||||
return path;
|
||||
return this.prefix + '/' + name;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user