| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 | 'use strict';var isObject = require('isobject');var Emitter = require('component-emitter');var visit = require('collection-visit');var toPath = require('to-object-path');var union = require('union-value');var del = require('unset-value');var get = require('get-value');var has = require('has-value');var set = require('set-value');/** * Create a `Cache` constructor that when instantiated will * store values on the given `prop`. * * ```js * var Cache = require('cache-base').namespace('data'); * var cache = new Cache(); * * cache.set('foo', 'bar'); * //=> {data: {foo: 'bar'}} * ``` * @param {String} `prop` The property name to use for storing values. * @return {Function} Returns a custom `Cache` constructor * @api public */function namespace(prop) {  /**   * Create a new `Cache`. Internally the `Cache` constructor is created using   * the `namespace` function, with `cache` defined as the storage object.   *   * ```js   * var app = new Cache();   * ```   * @param {Object} `cache` Optionally pass an object to initialize with.   * @constructor   * @api public   */  function Cache(cache) {    if (prop) {      this[prop] = {};    }    if (cache) {      this.set(cache);    }  }  /**   * Inherit Emitter   */  Emitter(Cache.prototype);  /**   * Assign `value` to `key`. Also emits `set` with   * the key and value.   *   * ```js   * app.on('set', function(key, val) {   *   // do something when `set` is emitted   * });   *   * app.set(key, value);   *   * // also takes an object or array   * app.set({name: 'Halle'});   * app.set([{foo: 'bar'}, {baz: 'quux'}]);   * console.log(app);   * //=> {name: 'Halle', foo: 'bar', baz: 'quux'}   * ```   *   * @name .set   * @emits `set` with `key` and `value` as arguments.   * @param {String} `key`   * @param {any} `value`   * @return {Object} Returns the instance for chaining.   * @api public   */  Cache.prototype.set = function(key, val) {    if (Array.isArray(key) && arguments.length === 2) {      key = toPath(key);    }    if (isObject(key) || Array.isArray(key)) {      this.visit('set', key);    } else {      set(prop ? this[prop] : this, key, val);      this.emit('set', key, val);    }    return this;  };  /**   * Union `array` to `key`. Also emits `set` with   * the key and value.   *   * ```js   * app.union('a.b', ['foo']);   * app.union('a.b', ['bar']);   * console.log(app.get('a'));   * //=> {b: ['foo', 'bar']}   * ```   * @name .union   * @param {String} `key`   * @param {any} `value`   * @return {Object} Returns the instance for chaining.   * @api public   */  Cache.prototype.union = function(key, val) {    if (Array.isArray(key) && arguments.length === 2) {      key = toPath(key);    }    var ctx = prop ? this[prop] : this;    union(ctx, key, arrayify(val));    this.emit('union', val);    return this;  };  /**   * Return the value of `key`. Dot notation may be used   * to get [nested property values][get-value].   *   * ```js   * app.set('a.b.c', 'd');   * app.get('a.b');   * //=> {c: 'd'}   *   * app.get(['a', 'b']);   * //=> {c: 'd'}   * ```   *   * @name .get   * @emits `get` with `key` and `value` as arguments.   * @param {String} `key` The name of the property to get. Dot-notation may be used.   * @return {any} Returns the value of `key`   * @api public   */  Cache.prototype.get = function(key) {    key = toPath(arguments);    var ctx = prop ? this[prop] : this;    var val = get(ctx, key);    this.emit('get', key, val);    return val;  };  /**   * Return true if app has a stored value for `key`,   * false only if value is `undefined`.   *   * ```js   * app.set('foo', 'bar');   * app.has('foo');   * //=> true   * ```   *   * @name .has   * @emits `has` with `key` and true or false as arguments.   * @param {String} `key`   * @return {Boolean}   * @api public   */  Cache.prototype.has = function(key) {    key = toPath(arguments);    var ctx = prop ? this[prop] : this;    var val = get(ctx, key);    var has = typeof val !== 'undefined';    this.emit('has', key, has);    return has;  };  /**   * Delete one or more properties from the instance.   *   * ```js   * app.del(); // delete all   * // or   * app.del('foo');   * // or   * app.del(['foo', 'bar']);   * ```   * @name .del   * @emits `del` with the `key` as the only argument.   * @param {String|Array} `key` Property name or array of property names.   * @return {Object} Returns the instance for chaining.   * @api public   */  Cache.prototype.del = function(key) {    if (Array.isArray(key)) {      this.visit('del', key);    } else {      del(prop ? this[prop] : this, key);      this.emit('del', key);    }    return this;  };  /**   * Reset the entire cache to an empty object.   *   * ```js   * app.clear();   * ```   * @api public   */  Cache.prototype.clear = function() {    if (prop) {      this[prop] = {};    }  };  /**   * Visit `method` over the properties in the given object, or map   * visit over the object-elements in an array.   *   * @name .visit   * @param {String} `method` The name of the `base` method to call.   * @param {Object|Array} `val` The object or array to iterate over.   * @return {Object} Returns the instance for chaining.   * @api public   */  Cache.prototype.visit = function(method, val) {    visit(this, method, val);    return this;  };  return Cache;}/** * Cast val to an array */function arrayify(val) {  return val ? (Array.isArray(val) ? val : [val]) : [];}/** * Expose `Cache` */module.exports = namespace();/** * Expose `Cache.namespace` */module.exports.namespace = namespace;
 |