function keyblade (obj, opts) {
  opts = Object.assign({
    message: _defaultMessage,
    logBeforeThrow: true,
    ignore: []
  }, opts)
  opts.ignore = (opts.ignore && Array.isArray(opts.ignore)) ? opts.ignore : []

  return new Proxy(obj, {
    get (target, propKey, receiver) {
      const useGetter = Reflect.has(target, propKey, receiver) || _isReserved(propKey, opts.ignore)
      if (useGetter) {
        return Reflect.get(target, propKey, receiver)
      }

      // Leave symbols alone.
      if (typeof propKey === 'symbol') {
        return Reflect.get(target, propKey, receiver)
      }

      const message = opts.message(propKey)
      if (opts.logBeforeThrow) {
        if (typeof opts.logBeforeThrow === 'function') {
          opts.logBeforeThrow(message, propKey)
        } else {
          console.error(message)
        }
      }

      throw new UndefinedKeyError(message)
    }
  })
}
function keyblade (obj, opts) {
  opts = Object.assign({
    message: _defaultMessage,
    logBeforeThrow: true,
    ignore: []
  }, opts)
  opts.ignore = (opts.ignore && Array.isArray(opts.ignore)) ? opts.ignore : []

  return new Proxy(obj, {
    get (target, propKey, receiver) {
      const useGetter = Reflect.has(target, propKey, receiver) || _isReserved(propKey, opts.ignore)
      if (useGetter) {
        return Reflect.get(target, propKey, receiver)
      }

      // Leave symbols alone.
      if (typeof propKey === 'symbol') {
        return Reflect.get(target, propKey, receiver)
      }

      const message = opts.message(propKey)
      if (opts.logBeforeThrow) {
        if (typeof opts.logBeforeThrow === 'function') {
          opts.logBeforeThrow(message, propKey)
        } else {
          console.error(message)
        }
      }

      throw new UndefinedKeyError(message)
    }
  })
}
function keyblade ( obj , opts ) { opts = Object . assign ( { message : _defaultMessage , logBeforeThrow : true , ignore : [ ] } , opts ) opts . ignore = ( opts . ignore && Array . isArray ( opts . ignore ) ) ? opts . ignore : [ ] return new Proxy ( obj , { get ( target , propKey , receiver ) { const useGetter = Reflect . has ( target , propKey , receiver ) || _isReserved ( propKey , opts . ignore ) if ( useGetter ) { return Reflect . get ( target , propKey , receiver ) } // Leave symbols alone. if ( typeof propKey === 'symbol' ) { return Reflect . get ( target , propKey , receiver ) } const message = opts . message ( propKey ) if ( opts . logBeforeThrow ) { if ( typeof opts . logBeforeThrow === 'function' ) { opts . logBeforeThrow ( message , propKey ) } else { console . error ( message ) } } throw new UndefinedKeyError ( message ) } } ) }
Protects the given object by wrapping it in a Proxy.

@param  {object} obj
The object to wrap.

@param  {(string) => string} opts.message
Optional function used to construct the error message.
Will get the key passed as the only argument.

@param {string[]} ignore
Fields to ignore.

@param {bool|Function(message: string, key: string)}
If specified, and is a function, is invoked before throwing.
If specified, and is truthy, `console.error` before throwing.

@return {Proxy<object>}
Protects the given object by wrapping it in a Proxy .