UNPKG

@v4fire/core

Version:
166 lines 4.13 kB
'use strict'; require('../lib/core'); const path = require('path'), isPathEqual = require('path-equal').pathEqual; const fs = require('fs-extra'); const { env } = process; const origin = Symbol('Original function'); class Config { constructor() { this.src = {}; this.envs = {}; this.roots = []; this.client = []; this.server = []; } extend(...args) { return Object.mixin({ deep: true, withProto: true, concatArrays: Array.union }, ...args); } expand(config = this) { const blacklist = Object.assign(Object.create(null), { extend: true, expand: true, createConfig: true, hash: true }); const reduce = (from, to) => { Object.forEach(from, (el, key) => { if (blacklist[key]) { return; } if (Object.isFunction(el)) { if (!el.length) { try { to[key] = el.call(from); } catch {} } } else if (Object.isDictionary(el)) { to[key] = {}; to[key] = reduce(el, to[key]); } else if (Object.isArray(el)) { to[key] = []; to[key] = reduce(el, to[key]); } else { to[key] = el; } }); return to; }; return reduce(config, {}); } hash({ data, alg = 'md5', length } = {}) { const objectHash = require('node-object-hash'), val = objectHash().hash({ config: this.expand(), ...data }, { alg }); if (length) { return val.slice(0, length); } return val; } createConfig({ dirs, envs, mod }, opts) { const activeDir = dirs[0], isActiveConfig = isPathEqual(path.join(process.cwd(), 'config'), activeDir); if (envs) { this.extend(env, envs, Object.fastClone(env)); } function setProto(obj, proto, link = []) { Object.forEach(obj, (el, key) => { if (!el || typeof el !== 'object') { return; } key = [...link, key]; const parent = Object.get(proto, key); if (parent && el !== parent) { Object.setPrototypeOf(el, parent); } setProto(el, proto, key); }); } const modObj = mod ? include(mod, activeDir) : undefined, proto = modObj || Object.getPrototypeOf(opts); setProto(opts, proto); Object.setPrototypeOf(opts, proto); const config = this.extend(Object.create(proto), opts), p = this.getSrcMap(activeDir); ['roots'].concat(dirs.slice(1)).forEach((nm, i) => { let src; if (i) { if ({ client: true, server: true }[nm]) { const s = p.pzlr; src = path.join(p.src, (nm === 'client' ? s.blockDir : s.serverDir) || ''); } else { src = p.src; } } else { src = p.root; } config.src[nm] = (this.src[nm] || []).union(src); }); function bindObjCtx(obj) { Object.forEach(obj, { propsToIterate: 'all' }, (el, key) => { if (Object.isFunction(el)) { if (isPathEqual(path.join(process.cwd(), 'config'), activeDir)) { const o = el[origin] || el, ctx = Object.assign(Object.create({ config }), obj); el[origin] = o; obj[key] = Object.assign(o.bind(ctx), { [origin]: o }); } } else { obj[key] = el; if (el && typeof el === 'object') { bindObjCtx(el); } } }); } if (isActiveConfig) { bindObjCtx(config); } if (envs) { Object.keys(envs).forEach(nm => { config.envs[nm] = env[nm]; }); } config.hash = this.hash; config.extend = this.extend; config.expand = this.expand; return config; } getSrcMap(dir) { const root = path.join(dir, '../'), pzlr = fs.readJSONSync(path.join(root, '.pzlrrc')); return { pzlr, root, src: path.join(root, pzlr.sourceDir) }; } } module.exports = new Config();