UNPKG

ngx-store

Version:

Angular decorators to automagically keep variables in HTML5 LocalStorage, SessionStorage, cookies; injectable services for managing and listening to data changes and a bit more.

1,061 lines (1,039 loc) 36.7 kB
import { Debugger } from 'ts-debug'; import { filter, delay, map } from 'rxjs/operators'; import merge from 'lodash.merge'; import { Subject, interval, merge as merge$1, fromEvent } from 'rxjs'; import { Injectable, NgModule } from '@angular/core'; const CONFIG_PREFIX = 'NGX-STORE_'; class ConfigHelper { static getItem(key) { return localStorage.getItem(CONFIG_PREFIX + key); } static setItem(key, item) { return localStorage.setItem(CONFIG_PREFIX + key, item); } } const DefaultConfig = { prefix: 'ngx_', previousPrefix: 'angular2ws_', clearType: 'prefix', mutateObjects: true, cookiesScope: '', cookiesCheckInterval: 0, debugMode: false, }; let ConfigFills = {}; const localStoragePrefix = ConfigHelper.getItem('prefix'); if (typeof NGXSTORE_CONFIG === 'object') { ConfigFills = Object.assign({}, NGXSTORE_CONFIG); } if (localStoragePrefix !== undefined && localStoragePrefix !== null) { ConfigFills.previousPrefix = localStoragePrefix; } else if (ConfigFills.previousPrefix === undefined) { ConfigFills.previousPrefix = DefaultConfig.previousPrefix; } // merge default config, deprecated config and global config all together const Config = Object.assign({}, DefaultConfig, ConfigFills); const debug = new Debugger(console, Config.debugMode, '[ngx-store] '); ConfigHelper.setItem('prefix', Config.prefix); const isEqual = require('lodash.isequal'); class Cache { static getCacheFor(cacheCandidate) { let cacheItem = Cache.get(cacheCandidate.key); if (!cacheItem) { cacheItem = new CacheItem(cacheCandidate); debug.log(`Created new CacheItem for ${cacheCandidate.name} for ${cacheItem.utilities[0].utility.getStorageName()}`); Cache.set(cacheItem); return cacheItem; } debug.log(`Loaded prior CacheItem of ${cacheItem.name} for ${cacheCandidate.utilities[0].utility.getStorageName()}`); cacheItem.addTargets(cacheCandidate.targets); cacheItem.addServices(cacheCandidate.services); cacheItem.addUtilities(cacheCandidate.utilities); Cache.set(cacheItem); return cacheItem; } static remove(cacheItem) { return Cache.items.delete(cacheItem.key); } static get(key) { return Cache.items.get(key); } static set(cacheItem) { if (!Cache.get(cacheItem.key)) { debug.log('CacheItem for ' + cacheItem.key, cacheItem); } Cache.items.set(cacheItem.key, cacheItem); } } Cache.items = new Map(); // tslint:disable:only-arrow-functions class CacheItem { constructor(cacheItem) { this.name = ''; this.targets = []; this.services = []; this.utilities = []; this.currentTarget = {}; this.proxy = null; this._key = ''; this.initializedTargets = new Set(); this._key = cacheItem.key; this.name = cacheItem.name; this.addTargets(cacheItem.targets); this.addServices(cacheItem.services); this.addUtilities(cacheItem.utilities); } get key() { return this._key; } saveValue(value, config = {}) { debug.groupCollapsed('CacheItem#saveValue for ' + this.key + ' in ' + this.currentTarget.constructor.name); debug.log('new value: ', value); // if (value === false && this.readValue() === true) debugger; debug.log('previous value: ', this.readValue()); debug.log('targets.length: ', this.targets.length); debug.log('currentTarget:', this.currentTarget); debug.groupEnd(); // prevent overwriting value by initializators if (!this.initializedTargets.has(this.currentTarget)) { this.initializedTargets.add(this.currentTarget); let readValue = this.readValue(); if (config.migrateKey) { this.migrate(config, this.utilities[0].utility); readValue = this.readValue(); } const savedValue = (readValue !== null && readValue !== undefined) ? readValue : value; let proxy = this.getProxy(savedValue, config); proxy = (proxy !== null) ? proxy : value; debug.log('initial value for ' + this.key + ' in ' + this.currentTarget.constructor.name, proxy); this.propagateChange(savedValue); return proxy; } this.propagateChange(value); return this.getProxy(value, config); } getProxy(value, config = {}) { if (value === undefined && this.proxy) { return this.proxy; } // return cached proxy if value hasn't changed value = (value === undefined) ? this.readValue() : value; if (typeof value !== 'object' || value === null) { this.proxy = value; return value; } if ((!Config.mutateObjects && !config.mutate) || config.mutate === false) { return value; } const _self = this; // alias to use in standard function expressions const prototype = Object.assign(new value.constructor(), value.__proto__); prototype.save = function () { _self.saveValue(value, config); }; // TODO set prototype for Array.prototype or something if (Array.isArray(value)) { // handle methods that could change value of array const methodsToOverwrite = [ 'pop', 'push', 'reverse', 'shift', 'unshift', 'splice', 'filter', 'forEach', 'map', 'fill', 'sort', 'copyWithin', ]; for (const method of methodsToOverwrite) { prototype[method] = function () { const readValue = _self.readValue(); // @ts-ignore const result = Array.prototype[method].apply(readValue, arguments); debug.log('Saving value for ' + _self.key + ' by method ' + prototype.constructor.name + '.' + method); _self.saveValue(readValue, config); return result; }; } } Object.setPrototypeOf(value, prototype); this.proxy = value; return value; } readValue(config = {}) { const entry = this.utilities[0]; const value = entry ? entry.utility.get(this.key, entry.config) : null; return (typeof value !== 'object') ? value : JSON.parse(JSON.stringify(this.getProxy(value, entry.config))); } addTargets(targets) { targets.forEach(target => { if (this.targets.indexOf(target) === -1) { if (typeof target === 'object') { // handle Angular Component destruction const originalFunction = target.ngOnDestroy; const _self = this; target.ngOnDestroy = function () { if (typeof originalFunction === 'function') { originalFunction.apply(this, arguments); } target.ngOnDestroy = originalFunction || function () { }; _self.initializedTargets.delete(target); _self.targets = _self.targets.filter(t => t !== target); if (!_self.targets.length) { _self.services.forEach(service => { service.keys = service.keys.filter(key => key !== _self._key); }); _self.resetProxy(); Cache.remove(_self); } debug.groupCollapsed(`${_self.key} OnDestroy handler:`); debug.log('removed target:', target.constructor.name); debug.log('remaining targets:', _self.targets); debug.log('cacheItem:', Cache.get(_self.key)); debug.groupEnd(); }; this.targets.push(target); } } }); } addServices(services) { services.forEach(service => { if (this.services.indexOf(service) === -1) { service.keys.push(this._key); this.services.push(service); } }); } addUtilities(utilityEntries) { utilityEntries.forEach(entry => { if (this.utilities.findIndex(e => e.utility === entry.utility) === -1) { this.utilities.push(entry); entry.utility.set(this.key, this.readValue()); } }); } resetProxy() { this.proxy = null; } propagateChange(value, source) { if (isEqual(value, this.readValue())) { return; } this.utilities.forEach(entry => { const utility = entry.utility; // updating service which the change came from would affect in a cycle if (utility === source) { return; } debug.log(`propagating change on ${this.key} to:`, utility); utility.set(this._key, value, entry.config); }); } migrate(config, utility) { const prefix = (config.prefix || Config.prefix) || ''; const keyExists = (key) => key in utility.getStorage(); const migrateKey = keyExists(prefix + config.migrateKey) ? prefix + config.migrateKey : config.migrateKey; if (!keyExists(migrateKey)) { return; } debug.log('Migrating', migrateKey, 'to', config.key, 'in', utility.getStorageName()); const value = utility.get(migrateKey, Object.assign(Object.assign({}, config), { prefix: '' })); utility.set(this._key, value); utility.remove(migrateKey, { prefix: '' }); } } class NgxStorageEvent { constructor(type, key, storageArea) { this.type = type; this.key = key; this.storageArea = storageArea; this.timeStamp = (Date.now() - NgxStorageEvent.initTimeStamp); this.bubbles = false; this.cancelBubble = false; this.cancelable = false; this.composed = false; this.currentTarget = window; this.defaultPrevented = false; this.eventPhase = 2; this.isTrusted = true; this.path = [window]; this.returnValue = true; this.srcElement = window; this.target = window; this.url = window.location.href; this.isInternal = true; } /** * Methods below exist only to satisfy TypeScript compiler */ // tslint:disable:typedef get initEvent() { return StorageEvent.prototype.initEvent.bind(this); } get preventDefault() { return StorageEvent.prototype.preventDefault.bind(this); } get stopImmediatePropagation() { return StorageEvent.prototype.stopImmediatePropagation.bind(this); } get stopPropagation() { return StorageEvent.prototype.stopPropagation.bind(this); } get composedPath() { return StorageEvent.prototype.composedPath.bind(this); } get AT_TARGET() { return StorageEvent.prototype.AT_TARGET; } get BUBBLING_PHASE() { return StorageEvent.prototype.BUBBLING_PHASE; } get CAPTURING_PHASE() { return StorageEvent.prototype.BUBBLING_PHASE; } } NgxStorageEvent.initTimeStamp = Date.now(); const _get = require('lodash.get'); const _set = require('lodash.set'); const _merge = require('lodash.merge'); class Resource { constructor(service, key) { this.service = service; this.key = key; this._defaultValue = null; this._path = []; this._prefix = Config.prefix; } /** * Returns default value * @returns {T} */ get defaultValue() { return this._defaultValue; } /** * Returns current path as a string * @returns {string} */ get path() { return this.pathString; } /** * Returns currently set prefix * @returns {string} */ get prefix() { return this._prefix || ''; } /** * Returns value taking path into account * @returns {T} */ get value() { return this.considerDefault(this.readValue()); } get fullValue() { return this.considerDefault(this.service.utility.get(this.key, { prefix: this._prefix })); } get pathString() { return this._path.join('.'); } /** * Sets path of object property * @param {string} path * @returns {this} */ setPath(path) { this._path = path.split('.'); return this; } /** * Appends current path * e.g. if path('key') and appendPath('nested'), the path will be "key.nested" * @param {string} path * @returns {this} */ appendPath(path) { this._path.push(path); return this; } /** * Removes last item of path * e.g. if path('key.nested') and truncatePath(), the path will be "key" * @returns {this} */ truncatePath() { this._path.pop(); return this; } /** * Resets set path * @returns {this} */ resetPath() { this._path = []; return this; } /** * Sets prefix * @param {string} prefix * @returns {this} */ setPrefix(prefix) { this._prefix = prefix; return this; } /** * Moves storage item to new key using given prefix * @param {string} prefix * @returns {this} */ changePrefix(prefix) { this.service.utility.set(this.key, this.fullValue, { prefix }); this.service.utility.remove(this.key, { prefix: this._prefix }); return this.setPrefix(prefix); } /** * Sets default value for both reading and saving operations * @param defaultValue * @returns {this} */ setDefaultValue(defaultValue) { this._defaultValue = defaultValue; const value = this.readValue(); if (this.isNullOrUndefined(value)) { this.save(defaultValue); } return this; } /** * Creates or overrides value as a new entry or existing object property depending on path * @param value * @returns {this} */ save(value) { if (this.pathString) { value = _set(this.fullValue, this.pathString, this.considerDefault(value)); } this.service.utility.set(this.key, this.considerDefault(value), { prefix: this._prefix }); return this; } /** * Updates existing object property using current path * @param {T} value * @returns {this} */ update(value) { return this.save(_merge(this.readValue(), value)); } /** * Removes item stored under current key * @returns {this} */ remove() { this.service.utility.remove(this.key); return this; } considerDefault(value) { return this.isNullOrUndefined(value) ? this._defaultValue : value; } isNullOrUndefined(value) { return (value === null || value === undefined); } readValue() { const value = this.service.utility.get(this.key, { prefix: this._prefix }); if (this.pathString) { return _get(value, this.pathString); } return value; } } // const merge = require('lodash.merge'); class WebStorageService { constructor(utility) { this.utility = utility; } /** * Gets keys for stored variables created by ngx-store, * ignores keys that have not been created by decorators and have no prefix at once */ get keys() { // get prefixed key if prefix is defined const prefixKeys = this.utility.keys.filter(key => { if (this.utility.prefix && this.utility.prefix.length) { return key.startsWith(this.utility.prefix); } return true; }); const decoratorKeys = this.constructor.keys; return prefixKeys.concat(decoratorKeys); } get config() { return Config; } get(key) { return this.utility.get(key); } /** * Returns new data Resource for given key exposing builder design pattern * designed for complex nested data structures */ load(key) { return new Resource(this, key); } set(key, value) { return this.utility.set(key, value); } update(key, changes) { const value = this.get(key); if (value !== undefined && typeof value !== 'object') { debug.throw(new Error(`Value stored under "${key}" key is not an object and tried to be updated.`)); return value; } return this.set(key, merge({}, value, changes)); } // TODO return true if item existed and false otherwise (?) remove(key) { return this.utility.remove(key); } observe(key, exactMatch) { return this._changes.pipe(filter((event) => { var _a; if (!key) { return true; } if (exactMatch) { if (Config.prefix && key.startsWith(Config.prefix)) { return event.key === key; } return event.key === Config.prefix + key; } else { return ((_a = event.key) === null || _a === void 0 ? void 0 : _a.indexOf(key)) !== -1; } }), delay(30)); } /** * Clears chosen data from Storage * @param clearType 'prefix' | 'decorators' | 'all' * @param prefixOrClass defines the prefix or class (not its instance) whose decorators should be cleared */ clear(clearType, prefixOrClass) { clearType = clearType || Config.clearType; if (clearType === 'decorators') { let keys = []; if (typeof prefixOrClass === 'object') { keys = this.keys.filter(key => Cache.get(key).targets.includes(prefixOrClass)); debug.log(this.utility.getStorageName() + ' > Removing decorated data from ' + prefixOrClass.constructor.name + ':', keys); } else { keys = this.keys; debug.log(this.utility.getStorageName() + ' > Removing decorated data:', keys); } keys.forEach(key => this.remove(key)); } else if (clearType === 'prefix') { prefixOrClass = prefixOrClass || this.utility.prefix; this.utility.forEach((value, key) => { if (key.startsWith(prefixOrClass)) { this.remove(this.utility.trimPrefix(key)); } }); } else if (clearType === 'all') { this.utility.clear(); } } generateEvent(key, newValue, oldValue) { const type = this.utility.getStorageName().charAt(0).toLowerCase() + this.utility.getStorageName().slice(1); const event = new NgxStorageEvent(type, key, this.utility.getStorage()); event.oldValue = (oldValue !== undefined) ? oldValue : this.get(key); event.newValue = newValue; return event; } mapNativeEvent(ev) { const event = this.generateEvent(ev.key, this.utility.getGettable(ev.newValue), this.utility.getGettable(ev.oldValue)); event.isInternal = false; return event; } } WebStorageService.keys = []; class WebStorageUtility { constructor(storage, prefix = '', previousPrefix) { this._prefix = ''; this._changes = new Subject(); this._storage = storage; this._prefix = prefix; // handle previousPrefix for backward-compatibility and safe config changes below if (prefix === previousPrefix) { return; } if (previousPrefix === null) { return; } if (previousPrefix === undefined) { return; } debug.log(this.getStorageName() + ' > Detected prefix change from ' + previousPrefix + ' to ' + prefix); this.forEach((value, key) => { // ignore config settings when previousPrefix = '' if (key.startsWith(previousPrefix) && !key.startsWith(CONFIG_PREFIX)) { const nameWithoutPrefix = this.trimPrefix(key); this.set(nameWithoutPrefix, this._storage.getItem(key)); if (previousPrefix !== '') { this._storage.removeItem(key); } } }); } get prefix() { return this._prefix; } get changes() { return this._changes.asObservable(); } get keys() { const keys = []; this.forEach((value, key) => keys.push(key)); return keys; } static getSettable(value) { return JSON.stringify(value); } static getGettable(value) { if (value === 'undefined') { return null; } try { return JSON.parse(value); } catch (e) { return value; } } getStorage() { return this._storage; } getStorageKey(key, prefix) { prefix = (typeof prefix === 'string') ? prefix : this.prefix; return `${prefix}${key}`; } getStorageName() { return this._storage.type || ((this._storage === localStorage) ? 'localStorage' : 'sessionStorage'); } get(key, config = {}) { const storageKey = this.getStorageKey(key, config.prefix); const value = this._storage.getItem(storageKey); // TODO return undefined if no key /*if (value === null && !(storageKey in this._storage)) { return undefined; }*/ return this.getGettable(value); } set(key, value, config = {}) { if (value === null || value === undefined) { this.remove(key); return null; } try { const storageKey = this.getStorageKey(key, config.prefix); const storable = this.getSettable(value); this.emitEvent(key, value); this._storage.setItem(storageKey, storable, config.expires); const cacheItem = Cache.get(key); if (cacheItem) { debug.log(`updating following CacheItem from ${this.constructor.name}:`, cacheItem); cacheItem.resetProxy(); cacheItem.propagateChange(value, this); } } catch (error) { console.warn(`[ngx-store] ${this.getStorageName()}: following error occurred while trying to save ${key} =`, value); console.error(error); } return value; } // TODO return true if item existed and false otherwise (?) remove(key, config = {}) { const storageKey = this.getStorageKey(key, config.prefix); this._storage.removeItem(storageKey); const cacheItem = Cache.get(key); if (cacheItem) { cacheItem.resetProxy(); } } clear() { this.emitEvent(null, null, null); this.forEach((value, key) => { if (key.startsWith(CONFIG_PREFIX)) { return; } this.remove(key, { prefix: '' }); }); } forEach(callbackFn) { if (typeof this._storage.forEach === 'function') { return this._storage.forEach((value, key) => { callbackFn(this.getGettable(value), key); }); } Object.keys(this._storage).forEach((key) => { callbackFn(this.getGettable(this._storage[key]), key); }); } getSettable(value) { return WebStorageUtility.getSettable(value); } getGettable(value) { return WebStorageUtility.getGettable(value); } trimPrefix(key) { return key.replace(this.prefix, ''); } emitEvent(key, newValue, oldValue) { const event = new NgxStorageEvent(this.getStorageName(), key, this._storage); event.oldValue = (oldValue !== undefined) ? oldValue : this.get(key); event.newValue = newValue; this._changes.next(event); } } // TODO: in the future use ES6 Proxy to handle indexers class NgxStorage { constructor() { this.externalChanges = new Subject(); } emitEvent(key, newValue, oldValue) { var _a; const event = new NgxStorageEvent(this.type, key, this); event.oldValue = (oldValue !== undefined) ? oldValue : this.getItem(key); event.newValue = newValue; event.isInternal = false; (_a = this.externalChanges) === null || _a === void 0 ? void 0 : _a.next(event); } } class CookiesStorage extends NgxStorage { constructor() { super(); this.cachedCookieString = ''; this.cachedItemsMap = new Map(); this.getAllItems(); if (Config.cookiesCheckInterval) { interval(Config.cookiesCheckInterval) .subscribe(() => { var _a; if (!((_a = this.externalChanges) === null || _a === void 0 ? void 0 : _a.observers.length)) { return; // don't run if there are no set subscriptions } this.getAllItems(); }); } } get type() { return 'cookiesStorage'; } get length() { return this.getAllKeys().length; } key(index) { return this.getAllKeys()[index]; } getItem(key) { return this.getAllItems().get(key); } removeItem(key) { if (typeof document === 'undefined') { return; } let domain = this.resolveDomain(Config.cookiesScope); domain = (domain) ? 'domain=' + domain + ';' : ''; document.cookie = key + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;' + domain; this.cachedItemsMap.delete(key); } /** * @param key * @param value * @param expirationDate passing null affects in lifetime cookie */ setItem(key, value, expirationDate) { if (typeof document === 'undefined') { return; } let domain = this.resolveDomain(Config.cookiesScope); debug.log('Cookies domain:', domain); domain = (domain) ? 'domain=' + domain + ';' : ''; let utcDate = ''; if (expirationDate instanceof Date) { utcDate = expirationDate.toUTCString(); } else if (expirationDate === null) { utcDate = 'Fri, 18 Dec 2099 12:00:00 GMT'; } const expires = utcDate ? '; expires=' + utcDate : ''; const cookie = key + '=' + value + expires + ';path=/;' + domain; debug.log('Cookie`s set instruction:', cookie); this.cachedItemsMap.set(key, value); document.cookie = cookie; } clear() { this.getAllKeys().forEach(key => this.removeItem(key)); } forEach(callbackFn) { return this.getAllItems().forEach((value, key) => callbackFn(value, key)); } getAllKeys() { return Array.from(this.getAllItems().keys()); } // TODO: consider getting cookies from all paths getAllItems() { if (this.cachedCookieString === document.cookie) { // No changes return this.cachedItemsMap; } const map = new Map(); if (typeof document === 'undefined') { return map; } const cookies = document.cookie.split(';'); // tslint:disable-next-line:prefer-for-of for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); const eqPos = cookie.indexOf('='); const key = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; const value = eqPos > -1 ? cookie.substr(eqPos + 1, cookie.length) : cookie; map.set(key, value); } // detect changes and emit events if (this.cachedItemsMap) { map.forEach((value, key) => { let cachedValue = this.cachedItemsMap.get(key); cachedValue = (cachedValue !== undefined) ? cachedValue : null; if (value !== cachedValue) { this.emitEvent(key, WebStorageUtility.getGettable(value), WebStorageUtility.getGettable(cachedValue)); } }); this.cachedItemsMap.forEach((value, key) => { if (!map.has(key)) { this.emitEvent(key, null, WebStorageUtility.getGettable(value)); } }); } this.cachedCookieString = document.cookie; return this.cachedItemsMap = map; } /** * domain.com + path="." = .domain.com * domain.com + path=".sub." = .sub.domain.com * sub.domain.com + path="sub." = sub.domain.com * www.sub.domain.com + path="." = .sub.domain.com * localhost + path=".whatever." = localhost * @param path */ resolveDomain(path) { if (!path) { return ''; } const hostname = document.domain; if ((hostname.match(/\./g) || []).length < 1) { return ''; } const www = (path[0] !== '.' && hostname.indexOf('www.') === 0) ? 'www.' : ''; return www + path + this.getDomain(); } /** * This function determines base domain by setting cookie at the highest level possible * @url http://rossscrivener.co.uk/blog/javascript-get-domain-exclude-subdomain */ getDomain() { let i = 0; let domain = document.domain; const domainParts = domain.split('.'); const s = '_gd' + (new Date()).getTime(); while (i < (domainParts.length - 1) && document.cookie.indexOf(s + '=' + s) === -1) { domain = domainParts.slice(-1 - (++i)).join('.'); document.cookie = s + '=' + s + ';domain=' + domain + ';'; } document.cookie = s + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;domain=' + domain + ';'; return domain; } } const cookiesStorage = new CookiesStorage(); class SharedStorageUtility extends WebStorageUtility { getSettable(value) { return value; } getGettable(value) { return value; } } class SharedStorage extends NgxStorage { constructor() { super(); this.sharedMap = new Map(); delete this.externalChanges; } get type() { return 'sharedStorage'; } get length() { return this.getAllKeys().length; } key(index) { return this.getAllKeys()[index]; } getItem(key) { const value = this.sharedMap.get(key); return (value !== undefined) ? value : null; } removeItem(key) { this.sharedMap.delete(key); } setItem(key, value) { this.sharedMap.set(key, value); } clear() { this.sharedMap.clear(); } forEach(func) { return this.sharedMap.forEach((value, key) => func(value, key)); } getAllKeys() { return Array.from(this.sharedMap.keys()); } } const sharedStorage = new SharedStorage(); const localStorageUtility = new WebStorageUtility(localStorage, Config.prefix, Config.previousPrefix); const sessionStorageUtility = new WebStorageUtility(sessionStorage, Config.prefix, Config.previousPrefix); const cookiesStorageUtility = new WebStorageUtility(cookiesStorage, Config.prefix, Config.previousPrefix); const sharedStorageUtility = new SharedStorageUtility(sharedStorage, Config.prefix, Config.prefix); class LocalStorageService extends WebStorageService { constructor() { super(localStorageUtility); this._changes = merge$1(fromEvent(window, 'storage') .pipe(filter((event) => event.storageArea === localStorage), map((event) => this.mapNativeEvent(event))), localStorageUtility.changes); } } LocalStorageService.keys = []; LocalStorageService.decorators = [ { type: Injectable } ]; LocalStorageService.ctorParameters = () => []; class SessionStorageService extends WebStorageService { constructor() { super(sessionStorageUtility); this._changes = merge$1(fromEvent(window, 'storage') .pipe(filter((event) => event.storageArea === sessionStorage), map((event) => this.mapNativeEvent(event))), sessionStorageUtility.changes); } } SessionStorageService.keys = []; SessionStorageService.decorators = [ { type: Injectable } ]; SessionStorageService.ctorParameters = () => []; class CookiesStorageService extends WebStorageService { constructor() { var _a; super(cookiesStorageUtility); this._changes = !cookiesStorage.externalChanges ? cookiesStorageUtility.changes : merge$1((_a = cookiesStorage.externalChanges) === null || _a === void 0 ? void 0 : _a.asObservable(), cookiesStorageUtility.changes); } set(key, value, expirationDate) { return this.utility.set(key, value, { expires: expirationDate }); } } CookiesStorageService.keys = []; CookiesStorageService.decorators = [ { type: Injectable } ]; CookiesStorageService.ctorParameters = () => []; class SharedStorageService extends WebStorageService { constructor() { super(sharedStorageUtility); this._changes = sharedStorageUtility.changes; } } SharedStorageService.keys = []; SharedStorageService.decorators = [ { type: Injectable } ]; SharedStorageService.ctorParameters = () => []; // tslint:disable:only-arrow-functions function LocalStorage(keyOrConfig, config) { return WebStorage(localStorageUtility, LocalStorageService, keyOrConfig, config); } function SessionStorage(keyOrConfig, config) { return WebStorage(sessionStorageUtility, SessionStorageService, keyOrConfig, config); } function CookieStorage(keyOrConfig, config) { return WebStorage(cookiesStorageUtility, CookiesStorageService, keyOrConfig, config); } function SharedStorage$1(keyOrConfig, config) { return WebStorage(sharedStorageUtility, SharedStorageService, keyOrConfig, config); } function WebStorage(webStorageUtility, service, keyOrConfig, config = {}) { return (target, propertyName) => { let key = ''; if (typeof keyOrConfig === 'object') { key = keyOrConfig.key || ''; config = keyOrConfig; } else if (typeof keyOrConfig === 'string') { key = keyOrConfig; } key = key || config.key || propertyName; let cacheItem = Cache.getCacheFor({ key, name: propertyName, targets: [target], services: [service], utilities: [{ utility: webStorageUtility, config, }], }); Object.defineProperty(target, propertyName, { get: function () { return cacheItem.getProxy(undefined, config); }, set: function (value) { if (!Cache.get(cacheItem.key)) { cacheItem = Cache.getCacheFor(cacheItem); } cacheItem.addTargets([target]); cacheItem.currentTarget = target; cacheItem.saveValue(value, config); }, configurable: true, }); return target; }; } class NgxStoreModule { // methods for future use static forRoot() { return { ngModule: NgxStoreModule, }; } static forChild() { return NgxStoreModule; } } NgxStoreModule.decorators = [ { type: NgModule, args: [{ declarations: [], imports: [], exports: [], providers: [ LocalStorageService, SessionStorageService, CookiesStorageService, SharedStorageService, ], },] } ]; /* * Public API Surface of ngx-store */ /** * Generated bundle index. Do not edit. */ export { CookieStorage, CookiesStorageService as CookieStorageService, CookiesStorageService, LocalStorage, LocalStorageService, Resource as NgxResource, NgxStorageEvent, NgxStoreModule, SessionStorage, SessionStorageService, SharedStorage$1 as SharedStorage, SharedStorageService, SharedStorage$1 as TempStorage, SharedStorageService as TempStorageService, NgxStoreModule as WebStorageModule, WebStorageService, WebStorageUtility as ɵa }; //# sourceMappingURL=ngx-store.js.map