UNPKG

@squirrel-forge/ui-util

Version:

A collection of utilities, classes, functions and abstracts made for the browser and babel compatible.

180 lines (167 loc) 5.5 kB
/** * Requires */ import { EventDispatcher } from '../Events/EventDispatcher.js'; import { Exception } from '../Error/Exception.js'; import { isEmpty } from '../Var/isEmpty.js'; import { isPojo } from '../Object/isPojo.js'; /** * Cookie manager exception * @class * @extends Exception */ class CookieManagerException extends Exception {} /** * Cookie manager */ export class CookieManager extends EventDispatcher { /** * Parse cookies string * @param {string} str - Cookies string * @return {Object.<string, string>} - Cookie name:value map */ static parseCookies( str ) { const cookies = {}; const raw = str.split( ';' ); for ( let i = 0; i < raw.length; i++ ) { const { name, value } = this.parseCookie( raw[ i ] ); cookies[ name ] = value; } return cookies; } /** * Parse cookie string * @param {string} str - Cookie string * @return {{name: string, value: string}} - Cookie data */ static parseCookie( str ) { const parts = str.trim().split( '=' ); return { name : parts[ 0 ], value : parts[ 1 ] }; } /** * Jar cookies string * @type {string} */ #jar = ''; /** * Jar cookies object * @type {Object.<string, string>} */ #cookies = {}; /** * Constructor * @constructor * @param {null|console} debug - Console or alike object to show debugging */ constructor( debug ) { super( document, null, debug ); this.refreshJar(); } /** * Refresh cookie jar * @return {void} */ refreshJar() { if ( document.cookie === this.#jar ) return; this.#cookies = this.constructor.parseCookies( document.cookie ); this.#jar = document.cookie; this.dispatchEvent( 'cookies.refreshed', { cookies : this.#cookies } ); } /** * Set cookie * @param {string} name - Cookie name * @param {string|number} value - Cookie value * @param {('day'|'hr'|'min'|'sec')} mode - Expire mode * @param {null|number|Date} expire - Expire date/offset * @param {null|number} maxage - Max age in seconds * @param {null|string} path - Cookie path * @param {('lax'|'strict'|'none')} samesite - Same site restriction * @param {boolean} secure - Secure connection only * @param {null|string} domain - Cookie domain * @return {{name: string, value: string}} - Cookie value */ set( name, value, { mode = 'day', expire = null, maxage = null, path = '/', samesite = 'strict', secure = true, domain = null, } = {} ) { if ( isEmpty( name ) || isEmpty( value ) ) { throw new CookieManagerException( 'First two arguments, name and value must be set' ); } const unset = expire === -1000; const cookie = { name, value }; const parts = [ `${name}=${encodeURIComponent( value )}`, `Domain=${domain || window.location.hostname}`, ]; if ( expire ) { if ( !( expire instanceof Date ) ) { if ( typeof expire !== 'number' ) { throw new CookieManagerException( 'Expire must be a number' ); } const modes = { day : 24 * 60 * 60 * 1000, hr : 60 * 60 * 1000, min : 60 * 1000, sec : 1000, }; if ( typeof modes[ mode ] === 'undefined' ) { throw new CookieManagerException( 'Expire mode must be one of (day|hr|min|sec)' ); } const d = new Date(); d.setTime( d.getTime() + expire * modes[ mode ] ); expire = d; } if ( !( expire instanceof Date ) ) { throw new CookieManagerException( 'Expire must be a date or number' ); } parts.push( `Expires=${expire.toUTCString()}` ); } else if ( maxage ) { if ( typeof maxage !== 'number' ) { throw new CookieManagerException( 'MaxAge must be a number (seconds)' ); } parts.push( `MaxAge=${maxage}` ); } if ( path ) parts.push( `Path=${path}` ); if ( samesite ) parts.push( `SameSite=${samesite}` ); if ( secure ) parts.push( 'Secure' ); document.cookie = parts.join( '; ' ); this.dispatchEvent( 'cookie.' + ( unset ? 'unset' : 'set' ), { cookie } ); this.refreshJar(); return cookie; } /** * Remove cookie * @param {string} name - Cookie name * @param {null|Object} options - Setter options * @return {void} */ remove( name, options = null ) { if ( !this.has( name ) ) return; if ( !isPojo( options ) ) options = {}; options.expire = -1000; options.maxage = null; this.set( name, '', options ); } /** * Get cookie value * @param {string} name - Cookie name * @return {*|null} - Cookie value */ get( name ) { if ( this.#cookies[ name ] ) return this.#cookies[ name ]; return null; } /** * Check if a cookie name exists * @param {string} name - Cookie name * @return {boolean} - Exists state */ has( name ) { return typeof this.#cookies[ name ] !== 'undefined'; } }