UNPKG

read-conf

Version:
394 lines (372 loc) 9.64 kB
var __is, _is, allTrue, allTypes, getChecker, getKey, getRequired, getTypeError, getTypeNames, isValid, iterate, normalize, realKey, toStr; allTypes = [String, Number, Array, Object, Function, RegExp, Boolean]; toStr = Object.prototype.toString; _is = {}; __is = { Boolean: (bool) => { return typeof bool === "boolean"; } }; iterate = (obj, cb) => { var i, key, keys, len, results; keys = Object.keys(obj).sort(); results = []; for (i = 0, len = keys.length; i < len; i++) { key = keys[i]; results.push(cb(key, obj[key])); } return results; }; getChecker = (name) => { return (o) => { return toStr.call(o) === `[object ${name}]`; }; }; allTypes.forEach(({name}) => { return __is[name] != null ? __is[name] : __is[name] = _is[name.toLowerCase()] = getChecker(name); }); normalize = (schema) => { var k, types, v; for (k in schema) { v = schema[k]; if (k === "__strict") { continue; } if (v.type) { v.types = types = v.type; } else if ((types = v.types) == null) { v = schema[k] = { types: (types = [v]) }; } if (!Array.isArray(types)) { v.types = [types]; } if (!v._normalized) { v._normalized = true; if (v.types != null) { v._types = v.types.map((type) => { var tmp; if (!(tmp = __is[type.name])) { throw new Error(`Schema invalid. ${type} is no Type.`); } return tmp; }); } } } return schema; }; getRequired = (schema) => { var required; required = {}; iterate(schema, (k, v) => { if (v.required) { return required[k] = true; } }); return required; }; getTypeNames = (types) => { return types.map(({name}) => { return name; }); }; getTypeError = (obj, schema) => { var checker, name, str, types; for (name in __is) { checker = __is[name]; if (checker(obj)) { break; } } str = `of type '${name}'. Valid type`; if ((types = schema.types).length > 1) { str += "s are: ['" + getTypeNames(types).join("', '") + "']"; } else { str += ` is: '${types[0].name}'`; } return str; }; isValid = (obj, schema) => { var types; if (!(types = schema._types)) { return true; } return types.some((checker) => { return checker(obj); }); }; allTrue = (arr) => { var i, len, val; for (i = 0, len = arr.length; i < len; i++) { val = arr[i]; if (val === false) { return false; } } return true; }; getKey = (key, newKey) => { if (!key) { return newKey; } return key + "$" + newKey; }; realKey = (key) => { var char, i, lastChar, len, newChar, str; lastChar = ""; str = ""; for (i = 0, len = key.length; i < len; i++) { char = key[i]; if (char === "$") { newChar = "."; } else if (char === "_" && lastChar === "$") { newChar = "$"; } else { newChar = char; } lastChar = char; str += newChar; } return str; }; module.exports = (obj, schema, {isNormalized, ignore = []} = {}) => { return new Promise((resolve, reject) => { var addProblem, keys, problems, required, strict, walk; if (!isNormalized) { normalize(schema); } required = getRequired(schema); problems = {}; addProblem = (key, msg) => { return problems[realKey(key)] = msg; }; walk = (curr, key, currSchema) => { var i, isStrict, item, len, newKey, newSchema; delete required[key]; if (~ignore.indexOf(key)) { return true; } if (currSchema == null) { return false; } if (curr == null) { return true; } if (!isValid(curr, currSchema)) { addProblem(key, getTypeError(curr, currSchema)); } if (_is.array(curr)) { newSchema = schema[newKey = getKey(key, "_item")]; if (newSchema != null) { for (i = 0, len = curr.length; i < len; i++) { item = curr[i]; walk(item, newKey, newSchema); } } } else if (_is.object(curr)) { isStrict = currSchema.strict; iterate(curr, (k, item) => { if (!walk(item, (newKey = getKey(key, k)), schema[newKey]) && isStrict) { return addProblem(newKey, "unexpected"); } else if (!isStrict) { return walk(item, (newKey = getKey(key, "_item")), schema[newKey]); } }); } return true; }; strict = schema.__strict; if (strict == null) { strict = true; } walk(obj, "", { _types: [_is.object], strict: strict }); iterate(required, (k) => { return addProblem(k, "missing"); }); if ((keys = Object.keys(problems)).length > 0) { return reject(keys.sort().map((key) => { return `'${key}' is ${problems[key]}`; })); } else { return resolve(); } }); }; module.exports.getAdder = (schema) => { normalize(schema); return (newSchema, merge) => { var k, k3, ref, v, v2, v3; ref = normalize(newSchema); for (k in ref) { v = ref[k]; if (merge && (v2 = schema[k])) { for (k3 in v) { v3 = v[k3]; v2[k3] = v3; } } else { schema[k] = v; } } return schema; }; }; module.exports.setDefaults = (obj, schema, {concat, ignore = []} = {}) => { return iterate(schema, (k, v) => { var def, i, item, len, parent, prop, results, val; if (((def = v.default) != null) && !~ignore.indexOf(k)) { ({parent, prop} = k.split("$").reduce(((acc, curr) => { var val; val = acc.parent = acc.parent[acc.prop]; if (val == null) { throw new Error(`couldn't set default value on ${realKey(k)}`); } acc.prop = curr; return acc; }), { parent: { 1: obj }, prop: 1 })); if ((val = parent[prop]) == null) { return parent[prop] = def; } else if (concat && Array.isArray(val) && Array.isArray(def)) { results = []; for (i = 0, len = def.length; i < len; i++) { item = def[i]; if (!~val.indexOf(item)) { results.push(val.push(item)); } else { results.push(void 0); } } return results; } } }); }; module.exports.toDoc = (schema, type) => { var concat, getIndent, ignore, indent, indention, keys, lines, parent, push; lines = ["```js", "module.exports = {"]; indention = " "; indent = 1; getIndent = () => { return indention.repeat(indent); }; normalize(schema); delete schema.__strict; keys = Object.keys(schema); if (keys.length < 5) { lines.push("\n // …"); } ({push} = Array.prototype); concat = (arr) => { return push.apply(lines, arr); }; ignore = []; parent = ""; iterate(schema, (k, v) => { var children, def, desc, dyn, dynName, dynamic, getTypes, i, ind, len, names, ref, required, tmpval, typeAbove, val; if (~ignore.indexOf(k)) { return; } // end of block if (parent && !k.startsWith(parent + "$")) { parent = ""; indent--; lines.push(""); lines.push(getIndent() + "},"); } ind = getIndent(); names = getTypeNames(v.types); getTypes = (long, schem) => { var _n, types; if (schem) { _n = getTypeNames(schem.types); } else { _n = names; } types = _n.length === 1 ? _n[0] : "[" + _n.join(", ") + "]"; if (long) { types = _n.length === 1 ? "type: " + types : "types: " + types; } return types; }; if (v._default == null) { def = v.default; } if (def == null) { def = null; } def = JSON.stringify(def) + ","; typeAbove = def.length > 20; if (~names.indexOf("Object") || ~names.indexOf("Array")) { dynamic = []; children = keys.filter((key) => { if (key.startsWith(k + "$")) { if (key.startsWith(k + "$_item")) { dynamic.push(key); return false; } return true; } return false; }); if (children.length > 0) { if (def === "{},") { def = "{"; typeAbove = true; parent = k; indent++; } } } //else if ~names.indexOf("Object") // newLine lines.push(""); // description above if ((desc = (ref = v.desc) != null ? ref.split("\n") : void 0) != null) { concat(desc.map((str) => { return ind + "// " + str; })); } required = v.required ? "(required) " : ""; if (typeAbove) { // type above lines.push(ind + "// " + required + getTypes(true)); } if (v._default) { // default above when _default is present lines.push(ind + "// Default: " + v._default); } // dynamic above if ((dynamic != null ? dynamic.length : void 0) > 0) { for (i = 0, len = dynamic.length; i < len; i++) { dyn = dynamic[i]; tmpval = schema[dyn]; ignore.push(dyn); dynName = "$" + realKey(dyn.replace(k + "$_item", "item")); lines.push(ind + `// ${dynName} (` + getTypes(false, tmpval) + ") " + (tmpval.desc || "")); } } if (parent) { // value k = k.replace(parent + "$", ""); } val = ind + realKey(k) + ": " + def; if (!typeAbove) { val += " // " + required + getTypes(false); } return lines.push(val); }); lines.push("\n // …\n"); lines.push("}"); lines.push("```"); return lines.join("\n"); };