UNPKG

@v4fire/config

Version:

Простой [config](https://www.npmjs.com/package/config)-like конфигуратор с поддержкой параметров командной строки, переменных среды и вычисляемых опций, преобразования значений и их валидации.

144 lines (105 loc) 3.21 kB
'use strict'; const $C = require('collection.js'), joi = require('joi'), Sugar = require('sugar'); const cliArgv = require('../core/argv'), bultInTypes = require('../core/types'); const paramsSchema = joi.object().keys({ default: joi.any().default(null), argv: joi.alternatives().try(joi.string().min(1), joi.boolean()).default(true), env: joi.alternatives().try(joi.string().min(1), joi.boolean()).default(true), short: joi .string() .min(1) .max(1) .regex(/^[a-z]$/i, 'short flag name') .default(null), type: joi.valid(Object.keys(bultInTypes)), valuesFlags: joi.alternatives(joi.array().items(joi.string()), joi.object()), coerce: joi.func(), validate: joi.alternatives(joi.func(), joi.object().type(RegExp), joi.array()) }); /** * * @param {string} name * @param {Object} [params = {}] * @param {?} [params.default] * @param {boolean | string} [params.argv = true] * @param {boolean | string} [params.env = true] * @param {string} [params.short] * @param {string} [params.type] * @param {Object | Array} [params.valuesFlags] * @param {Function} [params.coerce] * @param {RegExp | Array | Function} [params.validate] */ function option(name, params = {}) { if (!name || typeof name !== 'string') { throw new TypeError(`Parameter "name" expected string, got ${name} (${typeof name})`); } const validation = joi.validate(params, paramsSchema); if (validation.error) { throw validation.error; } params = validation.value; if (params.type) { $C.extend({deep: false, traits: true}, params, bultInTypes[params.type]); } const {argv, env, short, valuesFlags, coerce = (v) => v} = params; let validate = () => true; if (Sugar.Object.isRegExp(params.validate)) { validate = (v) => params.validate.test(v); } if (Array.isArray(params.validate)) { validate = (v) => params.validate.indexOf(v) !== -1; } if (Sugar.Object.isFunction(params.validate)) { validate = params.validate; } let source = null, value = params.default; if (params.default !== null) { source = 'default'; } if (env) { const envName = Sugar.Object.isString(env) ? env : name.toUpperCase().replace(/-/g, '_'); if (envName in process.env) { value = process.env[envName]; source = 'env'; } } if (argv) { const argvName = Sugar.Object.isString(argv) ? argv : name; if (argvName in cliArgv) { value = cliArgv[argvName]; source = 'cli'; } } if (short && (short in cliArgv)) { value = cliArgv[short]; source = 'cli'; } if (valuesFlags) { let val = null; if (Array.isArray(valuesFlags)) { val = $C(valuesFlags).one.get((el) => el in cliArgv); } else { val = $C(valuesFlags).one.get((el, key) => key in cliArgv); } if (val !== undefined) { value = val; source = 'cli'; } } if (value !== null) { value = coerce(value, source); if (!validate(value, source)) { throw new Error(`Invalid value "${value}" for option "${name}"${source !== null ? `, source: ${source}` : ''}`); } } return value; } module.exports = option;