| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | 'use strict'class FiggyPudding {  constructor (specs, opts, providers) {    this.__specs = specs || {}    Object.keys(this.__specs).forEach(alias => {      if (typeof this.__specs[alias] === 'string') {        const key = this.__specs[alias]        const realSpec = this.__specs[key]        if (realSpec) {          const aliasArr = realSpec.aliases || []          aliasArr.push(alias, key)          realSpec.aliases = [...(new Set(aliasArr))]          this.__specs[alias] = realSpec        } else {          throw new Error(`Alias refers to invalid key: ${key} -> ${alias}`)        }      }    })    this.__opts = opts || {}    this.__providers = reverse((providers).filter(      x => x != null && typeof x === 'object'    ))    this.__isFiggyPudding = true  }  get (key) {    return pudGet(this, key, true)  }  get [Symbol.toStringTag] () { return 'FiggyPudding' }  forEach (fn, thisArg = this) {    for (let [key, value] of this.entries()) {      fn.call(thisArg, value, key, this)    }  }  toJSON () {    const obj = {}    this.forEach((val, key) => {      obj[key] = val    })    return obj  }  * entries (_matcher) {    for (let key of Object.keys(this.__specs)) {      yield [key, this.get(key)]    }    const matcher = _matcher || this.__opts.other    if (matcher) {      const seen = new Set()      for (let p of this.__providers) {        const iter = p.entries ? p.entries(matcher) : entries(p)        for (let [key, val] of iter) {          if (matcher(key) && !seen.has(key)) {            seen.add(key)            yield [key, val]          }        }      }    }  }  * [Symbol.iterator] () {    for (let [key, value] of this.entries()) {      yield [key, value]    }  }  * keys () {    for (let [key] of this.entries()) {      yield key    }  }  * values () {    for (let [, value] of this.entries()) {      yield value    }  }  concat (...moreConfig) {    return new Proxy(new FiggyPudding(      this.__specs,      this.__opts,      reverse(this.__providers).concat(moreConfig)    ), proxyHandler)  }}try {  const util = require('util')  FiggyPudding.prototype[util.inspect.custom] = function (depth, opts) {    return (      this[Symbol.toStringTag] + ' '    ) + util.inspect(this.toJSON(), opts)  }} catch (e) {}function BadKeyError (key) {  throw Object.assign(new Error(    `invalid config key requested: ${key}`  ), {code: 'EBADKEY'})}function pudGet (pud, key, validate) {  let spec = pud.__specs[key]  if (validate && !spec && (!pud.__opts.other || !pud.__opts.other(key))) {    BadKeyError(key)  } else {    if (!spec) { spec = {} }    let ret    for (let p of pud.__providers) {      ret = tryGet(key, p)      if (ret === undefined && spec.aliases && spec.aliases.length) {        for (let alias of spec.aliases) {          if (alias === key) { continue }          ret = tryGet(alias, p)          if (ret !== undefined) {            break          }        }      }      if (ret !== undefined) {        break      }    }    if (ret === undefined && spec.default !== undefined) {      if (typeof spec.default === 'function') {        return spec.default(pud)      } else {        return spec.default      }    } else {      return ret    }  }}function tryGet (key, p) {  let ret  if (p.__isFiggyPudding) {    ret = pudGet(p, key, false)  } else if (typeof p.get === 'function') {    ret = p.get(key)  } else {    ret = p[key]  }  return ret}const proxyHandler = {  has (obj, prop) {    return prop in obj.__specs && pudGet(obj, prop, false) !== undefined  },  ownKeys (obj) {    return Object.keys(obj.__specs)  },  get (obj, prop) {    if (      typeof prop === 'symbol' ||      prop.slice(0, 2) === '__' ||      prop in FiggyPudding.prototype    ) {      return obj[prop]    }    return obj.get(prop)  },  set (obj, prop, value) {    if (      typeof prop === 'symbol' ||      prop.slice(0, 2) === '__'    ) {      obj[prop] = value      return true    } else {      throw new Error('figgyPudding options cannot be modified. Use .concat() instead.')    }  },  deleteProperty () {    throw new Error('figgyPudding options cannot be deleted. Use .concat() and shadow them instead.')  }}module.exports = figgyPuddingfunction figgyPudding (specs, opts) {  function factory (...providers) {    return new Proxy(new FiggyPudding(      specs,      opts,      providers    ), proxyHandler)  }  return factory}function reverse (arr) {  const ret = []  arr.forEach(x => ret.unshift(x))  return ret}function entries (obj) {  return Object.keys(obj).map(k => [k, obj[k]])}
 |