UNPKG

persistnsync

Version:

Zustand middleware to easily persist and sync Zustand state between tabs and windows

132 lines (131 loc) 5.77 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.persistNSync = void 0; exports.clearStorage = clearStorage; var DEFAULT_INIT_DELAY = 100; function getItem(options) { var cookies = document.cookie.split("; "); var cookie = cookies.find(function (c) { return c.startsWith(options.name); }); return (localStorage.getItem(options.name) || sessionStorage.getItem(options.name) || (cookie === null || cookie === void 0 ? void 0 : cookie.split("=")[1])); } function setItem(options, value) { var storage = options.storage; if (storage === "cookies") { document.cookie = "".concat(options.name, "=").concat(value, "; max-age=31536000; SameSite=Strict;"); } if (storage === "sessionStorage") sessionStorage.setItem(options.name, value); else localStorage.setItem(options.name, value); } function clearStorage(name, storage) { switch (storage || "localStorage") { case "localStorage": localStorage.removeItem(name); break; case "sessionStorage": sessionStorage.removeItem(name); break; case "cookies": document.cookie = "".concat(name, "=;expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=Strict;"); break; default: } } var persistNSync = function (stateCreator, options) { return function (set, get, store) { /** avoid error during serverside render */ if (!globalThis.localStorage) return stateCreator(set, get, store); if (!options.storage) options.storage = "localStorage"; /** timeout 0 is enough. timeout 100 is added to avoid server and client render content mismatch error */ var delay = options.initDelay === undefined ? DEFAULT_INIT_DELAY : options.initDelay; setTimeout(function () { var initialState = get(); var savedState = getItem(options); if (savedState) set(__assign(__assign({}, initialState), JSON.parse(savedState))); }, delay); var set_ = function (newStateOrPartialOrFunction, replace) { var prevState = get(); // @ts-expect-error -- Zustand v5 introduced stricter type checking set(newStateOrPartialOrFunction, replace); var newState = get(); saveAndSync({ newState: newState, prevState: prevState, options: options }); }; window.addEventListener("storage", function (e) { if (e.key === options.name) set(__assign(__assign({}, get()), JSON.parse(e.newValue || "{}"))); }); return stateCreator(set_, get, store); }; }; exports.persistNSync = persistNSync; /** Encapsulate cache in closure */ var getKeysToPersistAndSyncMemoised = (function () { var persistAndSyncKeysCache = {}; var getKeysToPersistAndSync = function (keys, options) { var exclude = options.exclude, include = options.include; var keysToInlcude = (include === null || include === void 0 ? void 0 : include.length) ? keys.filter(function (key) { return matchPatternOrKey(key, include); }) : keys; var keysToPersistAndSync = keysToInlcude.filter(function (key) { return !matchPatternOrKey(key, exclude || []); }); return keysToPersistAndSync; }; return function (keys, options) { var cacheKey = JSON.stringify({ options: options, keys: keys }); if (!persistAndSyncKeysCache[cacheKey]) persistAndSyncKeysCache[cacheKey] = getKeysToPersistAndSync(keys, options); return persistAndSyncKeysCache[cacheKey]; }; })(); function matchPatternOrKey(key, patterns) { for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) { var patternOrKey = patterns_1[_i]; if (typeof patternOrKey === "string" && key === patternOrKey) return true; else if (patternOrKey instanceof RegExp && patternOrKey.test(key)) return true; } return false; } function saveAndSync(_a) { var _b, _c; var newState = _a.newState, prevState = _a.prevState, options = _a.options; if (newState.__persistNSyncOptions) { var prevStorage = ((_b = prevState.__persistNSyncOptions) === null || _b === void 0 ? void 0 : _b.storage) || options.storage; var newStorage = ((_c = newState.__persistNSyncOptions) === null || _c === void 0 ? void 0 : _c.storage) || options.storage; if (prevStorage !== newStorage) { var name_1 = prevState.__persistNSyncOptions.name || options.name; clearStorage(name_1, prevStorage); } Object.assign(options, newState.__persistNSyncOptions); } /** temporarily support `regExpToIgnore` */ if (!options.exclude) options.exclude = []; if (options.regExpToIgnore) options.exclude.push(options.regExpToIgnore); /** end of temporarily support `regExpToIgnore` */ var keysToPersistAndSync = getKeysToPersistAndSyncMemoised(Object.keys(newState), options); if (keysToPersistAndSync.length === 0) return; var stateToStore = {}; keysToPersistAndSync .filter(function (key) { return prevState[key] !== newState[key]; }) // using only shallow equality .forEach(function (key) { return (stateToStore[key] = newState[key]); }); if (Object.keys(stateToStore).length) setItem(options, JSON.stringify(stateToStore)); }