koekiemonster
Version:
Browser and Nodejs compatible cookie interface
159 lines (138 loc) • 3.7 kB
JavaScript
;
/**
* Cookie creation interface.
*
* @param {Object} doc Reference to the document.
* @returns {Object} Session storage inspired API.
* @public
*/
module.exports = function bake(doc, options){
var str = 'string'; // Reduce bytes by caching str.
var decode = decodeURIComponent; // Reduce lookups by smaller names.
var encode = encodeURIComponent; // Same as above.
//
// We want to provide a sane out of the box DX, and the most common use
// case would be loading cookies from the browser's `document.cookie`
// location. So when no document is provided, we should attempt to
// default to that without breaking any native environment.
//
if (!doc) {
doc = 'undefined' !== typeof document && str === typeof document.cookie
? document
: {};
}
if (!options) options = {};
if (typeof doc === str) doc = { cookie: doc };
else if (typeof doc.cookie !== str) doc.cookie = '';
/**
* Regular Expression that is used to split cookies into individual items.
*
* @type {RegExp}
* @private
*/
var splitter = /;\s*/;
/**
* Date used to removed cookies.
*
* @type {String}
* @private
*/
var remove = new Date(0).toUTCString();
/**
* Read out all the cookies.
*
* @returns {Array}
* @private
*/
function read() {
return options.read
? options.read()
: doc.cookie.split(splitter);
}
/**
* Write a new cookie.
*
* @param {String} cookie Cookie value.
* @param {Object} meta Additional cookie information.
* @returns {String}
* @private
*/
function write(cookie, meta) {
return options.write
? options.write(cookie, meta)
: (doc.cookie = cookie);
}
/**
* Get the contents of a cookie.
*
* @param {String} key Name of the cookie we want to fetch.
* @returns {String|Undefined} Result of the cookie or nothing.
* @public
*/
function getItem(key) {
var cookies = read();
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
var index = cookie.indexOf('=');
var name = decode(cookie.slice(0, index));
if (name === key) return decode(cookie.slice(index + 1));
}
}
/**
* Set a new cookie.
*
* @param {String} key Name of the cookie.
* @param {String} value Data for the cookie.
* @param {Object} opts Options for the cookie setting.
* @returns {String} Cookie.
* @public
*/
function setItem(key, value, opts) {
if (typeof key !== str || typeof value !== str) return false;
if (!opts) opts = {};
value = encode(value);
key = encode(key);
var cookie = key + '=' + value;
if ('expires' in opts) cookie += '; expires=' + opts.expires;
if ('path' in opts) cookie += '; path=' + opts.path;
if ('domain' in opts) cookie += '; domain=' + opts.domain;
if (opts.secure) cookie += '; secure';
return write(cookie, {
remove: opts.expires === remove,
value: value,
opts: opts,
key: key
});
}
/**
* Remove a cookie.
*
* @param {String} key Name of the cookie.
* @param {Object} opts Options for the cookie setting.
* @returns {Undefined} Void.
* @public
*/
function removeItem(key, opts) {
if (!opts) opts = {};
opts.expires = remove;
return setItem(key, '', opts);
}
/**
* Clear all cookies.
*
* @returns {Undefined} Void.
* @public
*/
function clear() {
var cookies = read();
for (var i = 0; i < cookies.length; i++) {
removeItem(decode(cookies[i].split('=')[0]));
}
}
return {
removeItem: removeItem,
getItem: getItem,
setItem: setItem,
clear: clear
};
};