Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

stash.js

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stash.js - npm Package Compare versions

Comparing version 0.0.2 to 1.0.0

examples/facebook.js

5

bower.json
{
"name": "stash.js",
"version": "0.0.2",
"version": "1.0.0",
"authors": [

@@ -25,3 +25,6 @@ "Tadeu Zagallo <tadeuzagallo@gmail.com>"

"chai": "~1.9.1"
},
"dependencies": {
"bluebird": "~1.2.4"
}
}

21

package.json
{
"name": "stash.js",
"version": "0.0.2",
"version": "1.0.0",
"description": "Multilayer Cache Manager for JavaScript",
"main": "src/stash.js",
"scripts": {
"test": "mocha spec"
"test": "mocha -- test/*_test.js test/*/*_test.js test/*/*/*_test.js"
},

@@ -27,3 +27,20 @@ "repository": {

"mocha": "~1.18.2"
},
"dependencies": {
"bluebird": "~1.2.4"
},
"testling": {
"harness": "mocha-bdd",
"files": ["test/test_helper.js", "test/*_test.js", "test/*/*_test.js", "test/*/*/*_test.js"],
"browsers": [
"ie/9..latest",
"chrome/22..latest",
"firefox/16..latest",
"safari/5..latest",
"opera/11.0..latest",
"iphone/5..latest",
"ipad/5..latest",
"android-browser/4..latest"
]
}
}

@@ -1,10 +0,16 @@

# Stash.js #
# Stash.js [![Build Status](https://travis-ci.org/tadeuzagallo/stash.js.svg?branch=master)](https://travis-ci.org/tadeuzagallo/stash.js) [![Code Climate](https://codeclimate.com/github/tadeuzagallo/stash.js.png)](https://codeclimate.com/github/tadeuzagallo/stash.js) #
Inspired by the [php library](https://github.com/tedivm/Stash), Stash makes it easier to save your data on multiple layers of cache.
Inspired by the [php library](https://github.com/tedivm/Stash), Stash makes it easier to save your data on multiple layers of cache
## Usage ##
You can install it via [bower](http://bower.io/)
You can either install via [npm](https://www.npmjs.org)
```javascript
$ npm install stash.js
```
Or via [bower](http://bower.io/)
```
$ bower install stash

@@ -17,16 +23,35 @@ ```

*Syntax Updated:* in order to add new drivers, I had to replace the old sync syntax, the new one is based on promises, and it now depends on [bluebird](https://github.com/petkaantonov/bluebird)
```javascript
// Initialize a stash pool
var stash = new Stash.Pool();
var item = stash.getItem('my/key/path');
var data = item.get();
if (item.isMiss()) {
item.lock(); // Check invalidation options to see how it affects lock behavior
// Short version -- with Promise
data = ...
stash.get('my/key/path').catch(function (err) {
// Data is either inexistent or expired
return slowFuncThatReturnsPromise().then(this.save);
});
item.set(data, cacheDuration);
}
// Long Version (stash.get does all of it internally)
var item = stash.getItem('my/key/path');
item.get().then(function (data) {
item.isMiss().then(function (missed) {
if (missed) {
item.lock(); // Async lock
actuallyFetchData(function (data) {
item.set(data);
callback(data);
});
} else {
callback(data);
}
});
});
```
You can run the node.js samples on the `examples` folder to see a really basic demo
### Managing drivers ###

@@ -37,3 +62,3 @@

var localStorage = new Stash.Drivers.LocalStorage('my-custom-namespace');
var pool = new Stash.Pool([ephemeral, localStorage]); // It read on this order, and writes in reverse order
var pool = new Stash.Pool([ephemeral, localStorage]); // It reads on this order, and writes in reverse order
```

@@ -62,3 +87,3 @@

* Add more drivers
* Suporte Node.js as well
* ~~Suporte Node.js as well~~ Add Node.js exclusive drivers
* Maybe a jQuery plugin to integrate with ajax calls

@@ -65,0 +90,0 @@

@@ -1,4 +0,10 @@

(function (exports) {
var Stash = exports.Stash || {};
(function (global) {
var Stash = global.Stash || {};
var isNode = typeof require !== 'undefined';
var Promise = global.Promise;
if (isNode) {
Promise = require('bluebird');
}
Stash.Item = (function () {

@@ -8,2 +14,7 @@ function Item(key, pool) {

this.pool = pool;
this.save = (function (that) {
return function () {
that.save.apply(that, arguments);
};
})(this);

@@ -19,25 +30,25 @@ this._unload_();

Item.prototype._unload_ = function () {
this._loaded_ = false;
this.value = null;
this.expiration = false;
this.locked = false;
}
this.locked = undefined;
};
Item.prototype._load_ = function () {
if (!this._loaded_) {
this._loaded_ = true;
var that = this;
Item.prototype._load_ = function (callback) {
var that = this;
var value = this.pool.drivers.reduce(function (a, b) {
return a || b.get(that.key);
}, false);
return new Promise(function (resolve, reject) {
that.pool.drivers.forEach(function (d) {
d.get(that.key).then(resolve);
});
});
};
if (value) {
this.value = value.value;
this.expiration = value.expiration;
this.locked = value.locked;
}
}
Item.prototype._write_ = function (callback) {
var that = this;
return this;
return new Promise(function (resolve, reject) {
that.pool.drivers.reverse().forEach(function (d) {
d.put(that.key, that.value, that.expiration).then(resolve);
});
});
};

@@ -56,43 +67,85 @@

Item.prototype._write_ = function () {
Item.prototype.get = function (cachePolicy, policyData) {
var that = this;
this.pool.drivers.reverse().forEach(function (driver) {
driver.put(that.key, that.value, that.expiration, that.locked);
});
};
Item.prototype.get = function (cachePolicy, policyData) {
this.cachePolicy = cachePolicy || Stash.Item.SP_NONE;
this.policyData = policyData;
if (cachePolicy & Stash.Item.SP_VALUE && this.locked) {
return policyData;
function load(resolve) {
that._load_().then(function (data) {
if (data) {
that.value = data.value;
that.expiration = data.expiration;
data = typeof data.value === 'undefined' ? null : data.value;
}
resolve(data);
});
}
return this._load_().value;
return new Promise(function (resolve, reject) {
if (that.cachePolicy & Stash.Item.SP_VALUE) {
that.isLocked().then(function (locked) {
if (locked) {
resolve(that.policyData);
} else {
load(resolve);
}
});
} else {
load(resolve);
}
});
};
// alias for better syntax on Pool#get
Item.prototype.save = function (value) {
this.set(value);
return value;
};
Item.prototype.set = function (value, expiration) {
if (typeof expiration === 'function') {
callback = expiration;
expiration = null;
}
this._unload_();
this.expiration = Item._calculateExpiration_(expiration);
this.locked = false;
this.value = value;
this._write_();
this.unlock();
return this._write_();
};
Item.prototype.isMiss = function () {
this._load_();
Item.prototype.isMiss = function (callback) {
var that = this;
if (this.locked && this.cachePolicy & Stash.Item.SP_OLD) {
return false;
} else if (!this.locked &&
this.cachePolicy & Stash.Item.SP_PRECOMPUTE &&
this.policyData * 1000 >= this.expiration - Date.now()) {
return true;
var isMissed = function (locked, resolve) {
var miss;
if (locked && (that.cachePolicy & Stash.Item.SP_OLD)) {
miss = false;
} else if (!locked &&
(that.cachePolicy & Stash.Item.SP_PRECOMPUTE) &&
that.policyData * 1000 >= that.expiration - Date.now()) {
miss = true;
} else {
miss = that.value === null ||
typeof(that.expiration) === 'number' &&
that.expiration < Date.now();
}
resolve(miss);
}
return typeof(this.expiration) === 'number' && this.expiration < Date.now();
return new Promise(function (resolve, reject) {
if (that.locked !== undefined) {
isMissed(that.locked, resolve);
} else {
that.isLocked().then(function (locked) {
isMissed(locked, resolve);
});
}
});
};

@@ -102,7 +155,8 @@

var that = this;
this._unload_();
this.pool.drivers.forEach(function (driver) {
driver.delete(that.key);
return new Promise(function (resolve, reject) {
that.pool.drivers.forEach(function (driver) {
driver.delete(that.key).then(resolve);
});
});

@@ -112,7 +166,47 @@ };

Item.prototype.lock = function () {
this._load_();
if (this.locked === true) {
return Promise.cast(this.locked);
}
this.locked = true;
this._write_();
var that = this;
return new Promise(function (resolve, reject) {
that.pool.drivers.forEach(function (d) {
d.lock(that.key).then(resolve);
});
});
};
Item.prototype.isLocked = function () {
if (this.locked !== undefined) {
return Promise.cast(this.locked);
}
var that = this;
return new Promise(function (resolve, reject) {
that.pool.drivers.forEach(function (d) {
d.isLocked(that.key).then(function (locked) {
that.locked = locked;
resolve(locked);
});
});
});
};
Item.prototype.unlock = function () {
if (this.locked === false) {
return Promise.cast();
}
this.locked = false;
var that = this;
return new Promise(function (resolve, reject) {
that.pool.drivers.forEach(function (d) {
d.unlock(that.key).then(resolve);
});
});
}
return Item;

@@ -133,3 +227,3 @@ })();

Pool.prototype.getItem = function (key) {
item = new Stash.Item(key, this);
var item = new Stash.Item(key, this);

@@ -145,2 +239,19 @@ return item;

Pool.prototype.get = function (key) {
var item = this.getItem(key);
return new Promise(function (resolve, reject) {
item.get().then(function (data) {
item.isMiss().then(function (missed) {
if (missed) {
item.lock();
reject('Cache is missing');
} else {
resolve(data);
}
});
});
}).bind(item);
};
return Pool;

@@ -151,25 +262,20 @@ })();

Stash.Drivers.Utils = {
validateValue: function (value) {
if (!JSON.stringify(value)) {
assemble: function (value, expiration) {
if (typeof value === 'function') {
throw new TypeError('Only serializables values can be cached');
}
},
assemble: function (value, expiration, locked) {
Stash.Drivers.Utils.validateValue(value);
return { value: value, expiration: expiration, locked: locked || false };
return JSON.stringify({ value: value, expiration: expiration });
},
cd: function (cache, key) {
if (!key) {
return cache;
key: function (namespace, key) {
if (key instanceof Array) {
key.unshift(namespace);
return key.filter(String).join('/');
} else {
key = key.toString()
.trim()
.replace(/^\/+/g, '')
.replace(/\/+$/g, '');
return namespace + '/' + key;
}
return key.split('/').reduce(function (cache, folder) {
if (!cache[folder]) {
cache[folder] = { __stash_value__: null };
}
cache = cache[folder];
return cache;
}, cache);
}

@@ -179,32 +285,58 @@ };

Stash.Drivers.Ephemeral = (function () {
function Ephemeral () {
this._cache_ = {};
}
var cache = {};
function Ephemeral () {}
Ephemeral.prototype.get = function (key) {
var cache = Stash.Drivers.Utils.cd(this._cache_, key);
key = Stash.Drivers.Utils.key('', key);
var data = typeof cache[key] === 'undefined' ? null : cache[key];
return cache.__stash_value__ || null;
if (data) {
data = JSON.parse(data);
}
return Promise.cast(data);
};
Ephemeral.prototype.put = function (key, value, expiration, locked) {
Ephemeral.prototype.put = function (key, value, expiration) {
key = Stash.Drivers.Utils.key('', key);
var data = Stash.Drivers.Utils.assemble(value, expiration);
cache[key] = data;
return Promise.cast();
};
var cache = Stash.Drivers.Utils.cd(this._cache_, key);
Ephemeral.prototype.delete = function (key) {
key = Stash.Drivers.Utils.key('', key);
var length = key.length;
cache.__stash_value__ = Stash.Drivers.Utils.assemble(value, expiration, locked);
Object.keys(cache).forEach(function (_key) {
if (_key.substr(0, length) === key) {
cache[_key] = null;
}
});
cache[key] = null;
return Promise.cast();
};
Ephemeral.prototype.delete = function (key) {
var key = key.split('/');
var last = key.pop();
var cache = Stash.Drivers.Utils.cd(this._cache_, key.join('/'));
Ephemeral.prototype.flush = function () {
cache = {};
return Promise.cast();
};
cache[last] = null;
Ephemeral.prototype.lock = function (key) {
var key = Stash.Drivers.Utils.key('', key) + '_lock';
cache[key] = 1;
return Promise.cast();
};
Ephemeral.prototype.flush = function () {
this._cache_ = {};
Ephemeral.prototype.isLocked = function (key) {
key = Stash.Drivers.Utils.key('', key) + '_lock';
return Promise.cast(Boolean(cache[key]));
}
Ephemeral.prototype.parent = Ephemeral.prototype;
Ephemeral.prototype.unlock = function (key) {
key = Stash.Drivers.Utils.key('', key) + '_lock';
cache[key] = null;
return Promise.cast();
};

@@ -217,44 +349,75 @@ return Ephemeral;

this.namespace = namespace || 'stash';
this._loadCache_();
}
LocalStorage.prototype = new Stash.Drivers.Ephemeral();
LocalStorage.prototype.get = function (key) {
key = Stash.Drivers.Utils.key(this.namespace, key);
var data = localStorage.getItem(key);
if (data) {
data = JSON.parse(data);
}
LocalStorage.prototype._loadCache_ = function () {
this._cache_ = {};
return Promise.cast(data);
}
if (typeof(localStorage) !== 'undefined') {
var saved = localStorage.getItem(this.namespace);
LocalStorage.prototype.put = function (key, value, expiration) {
key = Stash.Drivers.Utils.key(this.namespace, key);
var data = Stash.Drivers.Utils.assemble(value, expiration);
if (saved) {
this._cache_ = JSON.parse(saved);
return this.putRaw(key, data);
};
LocalStorage.prototype.putRaw = function (key, value) {
localStorage.setItem(key, value);
return Promise.cast();
}
LocalStorage.prototype.delete = function (key) {
key = Stash.Drivers.Utils.key(this.namespace, key);
var length = key.length;
for (var i = 0, l = localStorage.length; i < l; i++) {
var _key = localStorage.key(i);
if (_key && _key.substr(0, length) === key) {
localStorage.removeItem(_key);
}
}
};
LocalStorage.prototype._commit_ = function () {
if (typeof(localStorage) !== 'undefined') {
localStorage.setItem(this.namespace, JSON.stringify(this._cache_));
}
localStorage.removeItem(key);
return Promise.cast();
};
LocalStorage.prototype.put = function (key, value, expiration, locked) {
this.parent.put.apply(this, arguments);
this._commit_();
LocalStorage.prototype.flush = function () {
return this.delete('');
};
LocalStorage.prototype.delete = function (key) {
this.parent.delete.apply(this, arguments);
this._commit_();
LocalStorage.prototype.lock = function (key) {
key = Stash.Drivers.Utils.key(this.namespace, key) + '_lock';
return this.putRaw(key, 1);
};
LocalStorage.prototype.flush = function () {
this.parent.flush.apply(this, arguments);
this._commit_();
LocalStorage.prototype.isLocked = function (key) {
var that = this;
return new Promise(function (resolve, reject) {
that.get(key + '_lock').then(function (data) {
resolve(Boolean(data));
});
});
};
LocalStorage.prototype.unlock = function (key) {
key = Stash.Drivers.Utils.key(this.namespace, key) + '_lock';
localStorage.removeItem(key);
return Promise.cast();
}
return LocalStorage;
})();
exports.Stash = Stash;
})(typeof(window) === 'undefined' ? module.exports : window);
if (isNode) {
module.exports = Stash;
} else {
global.Stash = Stash;
}
})(this);

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc