UNPKG

ra-core

Version:

Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React

202 lines 7.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStorage = exports.localStorageStore = void 0; var RA_STORE = 'RaStore'; // localStorage isn't available in incognito mode. We need to detect it var testLocalStorage = function () { // eslint-disable-next-line eqeqeq if (typeof window === 'undefined' || window.localStorage == undefined) { return false; } try { window.localStorage.setItem('test', 'test'); window.localStorage.removeItem('test'); return true; } catch (e) { return false; } }; var localStorageAvailable = testLocalStorage(); /** * Store using localStorage, or memory storage in incognito mode * * @example * * import { localStorageStore } from 'react-admin'; * * const App = () => ( * <Admin store={localStorageStore()}> * ... * </Admin> * ); */ var localStorageStore = function (version, appKey) { if (version === void 0) { version = '1'; } if (appKey === void 0) { appKey = ''; } var prefix = "".concat(RA_STORE).concat(appKey); var prefixLength = prefix.length; var subscriptions = {}; var publish = function (key, value) { Object.keys(subscriptions).forEach(function (id) { if (!subscriptions[id]) return; // may happen if a component unmounts after a first subscriber was notified if (subscriptions[id].key === key) { subscriptions[id].callback(value); } }); }; // Whenever the local storage changes in another document, look for matching subscribers. // This allows to synchronize state across tabs var onLocalStorageChange = function (event) { var _a; if (((_a = event.key) === null || _a === void 0 ? void 0 : _a.substring(0, prefixLength)) !== prefix) { return; } var key = event.key.substring(prefixLength + 1); var value = event.newValue ? tryParse(event.newValue) : undefined; Object.keys(subscriptions).forEach(function (id) { if (!subscriptions[id]) return; // may happen if a component unmounts after a first subscriber was notified if (subscriptions[id].key === key) { if (value === null) { // an event with a null value is sent when the key is deleted. // to enable default value, we need to call setValue(undefined) instead of setValue(null) subscriptions[id].callback(undefined); } else { subscriptions[id].callback(value == null ? undefined : value); } } }); }; return { setup: function () { if (localStorageAvailable) { var storedVersion = (0, exports.getStorage)().getItem("".concat(prefix, ".version")); if (storedVersion && storedVersion !== version) { var storage_1 = (0, exports.getStorage)(); Object.keys(storage_1).forEach(function (key) { if (key.startsWith(prefix)) { storage_1.removeItem(key); } }); } (0, exports.getStorage)().setItem("".concat(prefix, ".version"), version); window.addEventListener('storage', onLocalStorageChange); } }, teardown: function () { if (localStorageAvailable) { window.removeEventListener('storage', onLocalStorageChange); } }, getItem: function (key, defaultValue) { var valueFromStorage = (0, exports.getStorage)().getItem("".concat(prefix, ".").concat(key)); return valueFromStorage == null ? defaultValue : tryParse(valueFromStorage); }, setItem: function (key, value) { if (value === undefined) { (0, exports.getStorage)().removeItem("".concat(prefix, ".").concat(key)); } else { (0, exports.getStorage)().setItem("".concat(prefix, ".").concat(key), JSON.stringify(value)); } publish(key, value); }, removeItem: function (key) { (0, exports.getStorage)().removeItem("".concat(prefix, ".").concat(key)); publish(key, undefined); }, removeItems: function (keyPrefix) { var storage = (0, exports.getStorage)(); Object.keys(storage).forEach(function (key) { if (key.startsWith("".concat(prefix, ".").concat(keyPrefix))) { storage.removeItem(key); var publishKey = key.substring(prefixLength + 1); publish(publishKey, undefined); } }); }, reset: function () { var storage = (0, exports.getStorage)(); Object.keys(storage).forEach(function (key) { if (key.startsWith(prefix)) { storage.removeItem(key); var publishKey = key.substring(prefixLength + 1); publish(publishKey, undefined); } }); }, subscribe: function (key, callback) { var id = Math.random().toString(); subscriptions[id] = { key: key, callback: callback, }; return function () { delete subscriptions[id]; }; }, }; }; exports.localStorageStore = localStorageStore; var tryParse = function (value) { try { return JSON.parse(value); } catch (e) { return value; } }; var LocalStorageShim = /** @class */ (function () { function LocalStorageShim() { this.valuesMap = new Map(); } LocalStorageShim.prototype.getItem = function (key) { if (this.valuesMap.has(key)) { return String(this.valuesMap.get(key)); } return null; }; LocalStorageShim.prototype.setItem = function (key, value) { this.valuesMap.set(key, value); }; LocalStorageShim.prototype.removeItem = function (key) { this.valuesMap.delete(key); }; LocalStorageShim.prototype.removeItems = function (keyPrefix) { var _this = this; this.valuesMap.forEach(function (value, key) { if (key.startsWith(keyPrefix)) { _this.valuesMap.delete(key); } }); }; LocalStorageShim.prototype.clear = function () { this.valuesMap.clear(); }; LocalStorageShim.prototype.key = function (i) { if (arguments.length === 0) { throw new TypeError("Failed to execute 'key' on 'Storage': 1 argument required, but only 0 present."); // this is a TypeError implemented on Chrome, Firefox throws Not enough arguments to Storage.key. } var arr = Array.from(this.valuesMap.keys()); return arr[i]; }; Object.defineProperty(LocalStorageShim.prototype, "length", { get: function () { return this.valuesMap.size; }, enumerable: false, configurable: true }); return LocalStorageShim; }()); var memoryStorage = new LocalStorageShim(); var getStorage = function () { return localStorageAvailable ? window.localStorage : memoryStorage; }; exports.getStorage = getStorage; //# sourceMappingURL=localStorageStore.js.map