| '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 = figgyPudding | 
| function 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]]) | 
| } |