You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
5.6 KiB
261 lines
5.6 KiB
'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;
|
|
|