Instantly share code, notes, and snippets.
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save japboy/11452097 to your computer and use it in GitHub Desktop.
My fundamental cookie manager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var _ = require('underscore'); | |
var dotProp = require('dot-prop'); | |
var global = global || window, doc = global.document, nav = global.navigator; | |
var RE = global.RegExp, J = global.JSON, decode = global.decodeURIComponent, encode = global.encodeURIComponent; | |
var escapedKey = function (key) { | |
return encode(key).replace(/[\-\.\+\*]/g, '\\$&'); | |
}; | |
var reKey = function (_escapedKey) { | |
return new RE('(?:(?:^|.*;)\\s*' + _escapedKey + '\\s*\\=\\s*([^;]*).*$)|^.*$'); | |
}; | |
/** | |
* Fundamental cookie reader and writer | |
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie | |
* @see https://gist.github.com/cou929/7869555 | |
*/ | |
exports.cookie = { | |
/** | |
* Get the value of specified key | |
* @param {String} key Key string | |
* @returns {String|Null} Value string for specified key | |
*/ | |
getItem: function (key) { | |
if (!_.isString(key)) return null; | |
return decode(doc.cookie.replace(reKey(escapedKey(key)), "$1")) || null; | |
}, | |
/** | |
* Create or update the pair of key and value | |
* @param {String} key Key string | |
* @param {String} val Value string | |
* @param {Number|String|Date} end Seconds for `max-age` or date string/object for `expires` | |
* @param {String} path Target path affected by this cookie | |
* @param {String} domain Target domain name affected by this cookie | |
* @param {Boolean} secure Flag to transmit this cookie only by HTTPS | |
* @returns {Boolean} Flag whether the process completes successfully or not | |
*/ | |
setItem: function (key, val, end, path, domain, secure) { | |
if (!key || /^(?:expires|max\-age|path|domain|secure)$/i.test(key)) return false; | |
var expires = ''; | |
if (end) { | |
switch (end.constructor) { | |
case Number: | |
expires = (Infinity === end) ? '; expires=Tue, 19 Jan 2038 03:14:07 GMT' : '; max-age=' + end; | |
break; | |
case String: | |
expires = '; expires=' + end; | |
break; | |
case Date: | |
expires = '; expires=' + end.toUTCString(); | |
break; | |
} | |
} | |
doc.cookie = encode(key) + '=' + encode(val) + expires + (_.isString(domain) ? '; domain=' + domain : '') + (_.isString(path) ? '; path=' + path : '') + (secure ? '; secure' : ''); | |
return true; | |
}, | |
/** | |
* Check whether the key exists or not | |
* @param {String} key Key string | |
* @returns {Boolean} Flag for the existence | |
*/ | |
hasItem: function (key) { | |
if (!_.isString(key)) return false; | |
return reKey(escapedKey(key)).test(doc.cookie); | |
}, | |
/** | |
* Remove the pair of key and value by making them expire | |
* @param {String} key Key string | |
* @param {String} path Target path affected by this cookie | |
* @param {String} domain Target domain name affected by this cookie | |
* @returns {Boolean} Flag whether the process completes successfully or not | |
*/ | |
removeItem: function (key, path, domain) { | |
if (!this.hasItem(key)) return false; | |
doc.cookie = encode(key) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + (_.isString(domain) ? '; domain=' + domain : '') + (_.isString(path) ? '; path=' + path : ''); | |
return true; | |
}, | |
/** | |
* Return an array of existing keys | |
* @returns {Array} List of existing keys | |
*/ | |
keys: function () { | |
var keys = doc.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '').split(/\s*(?:\=[^;]*)?;\s*/); | |
return _.map(keys, decode); | |
}, | |
/** | |
* Clear all the cookie | |
*/ | |
clear: function () { | |
_.each(this.keys(), function (key) { | |
this.removeItem(key); | |
}); | |
}, | |
/** | |
* Return the total length of cookie | |
* @returns {Number} Total length (bytes) | |
*/ | |
size: function () { | |
return doc.cookie.length; | |
} | |
}; | |
/** | |
* Namespace based cookie manager | |
* @class | |
* @see https://gist.github.com/cou929/7869555 | |
*/ | |
exports.CookieManager = (function () { | |
function CookieManager (rootKey, opts_) { | |
this.maxSize = 4000; | |
this.rootKey = rootKey; | |
var opts = _.isObject(opts_) ? opts_ : {}; | |
this.end = opts.end || undefined; | |
this.path = opts.path || undefined; | |
this.domain = opts.domain || undefined; | |
this.secure = opts.secure || undefined; | |
this.exceeded = _.bind(this.exceeded, this); | |
this.getRoot = _.bind(this.getRoot, this); | |
this.setRoot = _.bind(this.setRoot, this); | |
this.getItem = _.bind(this.getItem, this); | |
this.setItem = _.bind(this.setItem, this); | |
this.removeItem = _.bind(this.removeItem, this); | |
this.clear = _.bind(this.clear, this); | |
} | |
var proto = CookieManager.prototype; | |
proto.exceeded = function (value) { | |
var stringifiedValue = _.isObject(value) ? J.stringify(value) : value; | |
var currentSize = exports.cookie.size() + stringifiedValue.length; | |
if (this.maxSize > currentSize) return false; | |
return true; | |
}; | |
proto.getRoot = function () { | |
var data = J.parse(exports.cookie.getItem(this.rootKey)); | |
return _.isObject(data) ? data : {}; | |
}; | |
proto.setRoot = function (data) { | |
return exports.cookie.setItem(this.rootKey, J.stringify(data), this.end, this.path, this.domain, this.secure); | |
}; | |
proto.getItem = function (path) { | |
var stringifiedData = exports.cookie.getItem(this.rootKey); | |
var data = J.parse(stringifiedData); | |
return dotProp.get(data, path); | |
}; | |
proto.setItem = function (path, value) { | |
if (this.exceeded(value)) throw new Error('Exceeded the limit of cookie size.'); | |
var data = this.getRoot(); | |
dotProp.set(data, path, value); | |
return this.setRoot(data); | |
}; | |
proto.removeItem = function (path) { | |
var data = this.getRoot(); | |
dotProp.set(data, path, null); | |
return this.setRoot(data); | |
}; | |
proto.clear = function () { | |
return exports.cookie.removeItem(this.rootKey); | |
}; | |
return CookieManager; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment