zustand-persist
Version:
persist and rehydrate redux stores
295 lines (277 loc) • 11.4 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var React = require('react');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(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);
};
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
var LoadManager = /** @class */ (function () {
function LoadManager() {
this.onAllLoadedCallback = function () { };
this.loadStatusRecord = {};
}
LoadManager.prototype.register = function (key) {
this.loadStatusRecord[key] = false;
};
LoadManager.prototype.isLoaded = function (key) {
return this.loadStatusRecord[key];
};
LoadManager.prototype.onAllLoaded = function (callback) {
this.onAllLoadedCallback = callback;
};
LoadManager.prototype.setLoaded = function (key) {
this.loadStatusRecord[key] = true;
if (Object.values(this.loadStatusRecord).every(Boolean)) {
this.onAllLoadedCallback();
}
};
return LoadManager;
}());
var cachedLoadManager;
function getLoadManager() {
if (!cachedLoadManager) {
cachedLoadManager = new LoadManager();
}
return cachedLoadManager;
}
function PersistGate(props) {
var _this = this;
var children = props.children, _a = props.loading, loading = _a === void 0 ? false : _a, onBeforeLift = props.onBeforeLift;
var _b = React.useState(false), isReady = _b[0], setIsReady = _b[1];
getLoadManager().onAllLoaded(function () { return __awaiter(_this, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = onBeforeLift;
if (!_a) return [3 /*break*/, 2];
return [4 /*yield*/, onBeforeLift()];
case 1:
_a = (_b.sent());
_b.label = 2;
case 2:
setIsReady(true);
return [2 /*return*/];
}
});
}); });
return React__default['default'].createElement(React__default['default'].Fragment, null, isReady ? children : loading);
}
function parseJson(text) {
try {
return JSON.parse(text || '{}');
}
catch (error) {
return undefined;
}
}
var _rootKey = 'root';
var _storage;
function configureKeeper(option) {
_storage = option.storage;
_rootKey = (option === null || option === void 0 ? void 0 : option.rootKey) || _rootKey;
}
function getItem(key) {
return __awaiter(this, void 0, void 0, function () {
var draft;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getRoot()];
case 1:
draft = _a.sent();
return [2 /*return*/, draft[key]];
}
});
});
}
var isRemovingRoot = false;
function setItem(key, value) {
return __awaiter(this, void 0, void 0, function () {
var draft;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getRoot()];
case 1:
draft = _a.sent();
draft[key] = value;
if (isRemovingRoot) {
return [2 /*return*/];
}
_cachedRoot = draft;
return [4 /*yield*/, _storage.setItem(_rootKey, JSON.stringify(draft))];
case 2:
_a.sent();
return [2 /*return*/];
}
});
});
}
var _cachedRoot = null;
function getRoot() {
return __awaiter(this, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (_cachedRoot) {
return [2 /*return*/, _cachedRoot];
}
_a = parseJson;
return [4 /*yield*/, _storage.getItem(_rootKey)];
case 1:
_cachedRoot = _a.apply(void 0, [_b.sent()]);
return [2 /*return*/, _cachedRoot];
}
});
});
}
function removeRoot() {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
isRemovingRoot = true;
return [4 /*yield*/, _storage.removeItem(_rootKey)];
case 1:
_a.sent();
_cachedRoot = undefined;
isRemovingRoot = false;
return [2 /*return*/];
}
});
});
}
function reconcile(state, option) {
var _a = option || {}, allowlist = _a.allowlist, denylist = _a.denylist;
if (allowlist) {
return Object.entries(state).reduce(function (prev, _a) {
var _b;
var eachKey = _a[0], value = _a[1];
return allowlist.includes(eachKey)
? __assign(__assign({}, prev), (_b = {}, _b[eachKey] = value, _b)) : prev;
}, {});
}
else if (denylist) {
return Object.entries(state).reduce(function (prev, _a) {
var _b;
var eachKey = _a[0], value = _a[1];
return !denylist.includes(eachKey)
? __assign(__assign({}, prev), (_b = {}, _b[eachKey] = value, _b)) : prev;
}, {});
}
return state;
}
function configurePersist(option) {
var _this = this;
configureKeeper(option);
var loadManager = getLoadManager();
function hydrate(key, set, get) {
return __awaiter(this, void 0, void 0, function () {
var saveState, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!!loadManager.isLoaded(key)) return [3 /*break*/, 2];
_a = parseJson;
return [4 /*yield*/, getItem(key)];
case 1:
saveState = _a.apply(void 0, [_b.sent()]);
if (saveState) {
set(__assign(__assign({}, get()), saveState));
}
loadManager.setLoaded(key);
_b.label = 2;
case 2: return [2 /*return*/];
}
});
});
}
var persist = function (option, fn) { return function (set, get, api) {
var key = option.key, allowlist = option.allowlist, denylist = option.denylist;
loadManager.register(key);
hydrate(key, set, get);
return fn(function (payload) { return __awaiter(_this, void 0, void 0, function () {
var state;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
set(payload);
state = reconcile(get(), { allowlist: allowlist, denylist: denylist });
return [4 /*yield*/, setItem(key, JSON.stringify(state))];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); }, get, api);
}; };
function purge() {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, removeRoot()];
});
});
}
return {
persist: persist,
purge: purge,
};
}
exports.PersistGate = PersistGate;
exports.configurePersist = configurePersist;