UNPKG

@planjs/mobx-persist

Version:
349 lines (285 loc) 9.36 kB
'use strict'; var serializr = require('serializr'); var _typeof = require('@babel/runtime/helpers/typeof'); var mobx = require('mobx'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var _typeof__default = /*#__PURE__*/_interopDefaultLegacy(_typeof); function _walk(v) { if (_typeof__default["default"](v) === 'object' && v) Object.keys(v).map(function (k) { return _walk(v[k]); }); return v; } function _default() { return serializr.custom(_walk, function (v) { return v; }); } var types = { object: function object(s) { return s ? serializr.object(s) : _default(); }, list: function list(s) { return serializr.list(this.object(s)); }, map: function map(s) { return serializr.map(this.object(s)); } }; function persistObject(target, schema) { var model = createModel(schema); serializr.setDefaultModelSchema(target, model); return target; } function createModel(params) { var schema = {}; Object.keys(params).forEach(function (key) { if (_typeof__default["default"](params[key]) === 'object') { if (params[key].type in types) { if (_typeof__default["default"](params[key].schema) === 'object') { schema[key] = types[params[key].type](createModel(params[key].schema)); } else { schema[key] = types[params[key].type](params[key].schema); } } } else if (params[key] === true) { schema[key] = true; } }); return serializr.createSimpleSchema(schema); } function persist() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var a = args[0], b = args[1]; if (a in types) { return serializr.serializable(types[a](b)); } if (args.length === 1) { return function (target) { return persistObject(target, a); }; } // eslint-disable-next-line prefer-spread return serializr.serializable.apply(null, args); } /** * Basic Storage */ var IStorage = /** @class */ function () { function IStorage() {} IStorage.prototype.getItem = function (key) { throw new Error('IStorage has to implement `getItem` method'); }; IStorage.prototype.removeItem = function (key) { throw new Error('IStorage has to implement `removeItem` method'); }; IStorage.prototype.setItem = function (key, value) { throw new Error('IStorage has to implement `setItem` method'); }; IStorage.prototype.clear = function () { throw new Error('IStorage has to implement `clear` method'); }; IStorage.prototype.onChange = function (key, newValue, oldValue) {}; return IStorage; }(); function mergeObservables(target, source, keys) { var t = target; var s = source; if (_typeof__default["default"](t) === 'object' && _typeof__default["default"](s) === 'object') { for (var key in t) { if (t[key] && _typeof__default["default"](t[key]) === 'object' && _typeof__default["default"](s[key]) === 'object') { if (mobx.isObservableMap(t[key])) t[key].merge(s[key]);else if (mobx.isObservableArray(t[key])) t[key].replace(s[key]);else if (mobx.isObservableObject(t[key])) t[key] = mergeObservables(t[key], s[key]); } else if (s[key] !== undefined) { t[key] = s[key]; } } } return t; } /*! ***************************************************************************** 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. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var LocalStorage = /** @class */ function (_super) { __extends(LocalStorage, _super); function LocalStorage() { var _this = _super.call(this) || this; try { window.addEventListener('storage', function (ev) { var _a; (_a = _this.onChange) === null || _a === void 0 ? void 0 : _a.call(_this, ev.key, ev.newValue, ev.oldValue); }); } catch (e) { console.error('[mobx-persist] LocalStorage error', e); } return _this; } LocalStorage.prototype.getItem = function (key) { return new Promise(function (resolve, reject) { try { var value = window.localStorage.getItem(key); resolve(value); } catch (err) { reject(err); } }); }; LocalStorage.prototype.removeItem = function (key) { return new Promise(function (resolve, reject) { try { window.localStorage.removeItem(key); resolve(null); } catch (err) { reject(err); } }); }; LocalStorage.prototype.setItem = function (key, value) { return new Promise(function (resolve, reject) { try { window.localStorage.setItem(key, value); resolve(null); } catch (err) { reject(err); } }); }; LocalStorage.prototype.clear = function () { return new Promise(function (resolve, reject) { try { window.localStorage.clear(); resolve(null); } catch (err) { reject(err); } }); }; LocalStorage.prototype.onChange = function (key, newVal, oldVal) {}; return LocalStorage; }(IStorage); /** * Create hydrate function * @param opts {CreateHydrateOptions} */ function create(opts) { if (opts === void 0) { opts = {}; } var _a = opts.storage, storage = _a === void 0 ? new LocalStorage() : _a, _b = opts.jsonify, jsonify = _b === void 0 ? true : _b, _c = opts.debounce, debounce = _c === void 0 ? 0 : _c, _d = opts.sync, sync = _d === void 0 ? true : _d; if (!(storage instanceof IStorage)) { throw new Error('storage has to implement `IStorage` all method'); } return function hydrate( /** * persist key */ key, /** * mobx store */ store, initialState, customArgs) { if (initialState === void 0) { initialState = {}; } if (customArgs === void 0) { customArgs = {}; } var schema = serializr.getDefaultModelSchema(store); if (!schema) { var logError_1 = function logError_1() { console.error('[mobx-persist] No cacheable value'); }; var promise_1 = Promise.resolve(store); promise_1.rehydrate = function () { logError_1(); return promise_1; }; promise_1.clear = logError_1; promise_1.dispose = logError_1; logError_1(); return promise_1; } function hydration() { var promise = storage.getItem(key).then(function (d) { return !jsonify ? d : JSON.parse(d); }).then(mobx.action("[mobx-persist " + key + "] LOAD_DATA", function (persisted) { if (persisted && _typeof__default["default"](persisted) === 'object') { serializr.update(schema, store, persisted, function (err) { if (err) { console.error('[mobx-persist] Mobx update error', err); } }, customArgs); } mergeObservables(store, initialState); return store; })); promise.rehydrate = hydration; // Multiple tab sync state if (sync) { var timer_1; storage.onChange = function (changeKey) { if (changeKey === key) { console.warn("[mobx-persist] change key " + changeKey); timer_1 && clearTimeout(timer_1); // If it keeps changing to prevent call stack overflow timer_1 = setTimeout(function () { promise.rehydrate(); timer_1 = null; }, debounce || 0); } }; } return promise; } var result = hydration(); result.clear = function () { storage.removeItem(key); }; result.dispose = mobx.reaction(function () { return serializr.serialize(schema, store); }, function (data) { return storage.setItem(key, !jsonify ? data : JSON.stringify(data)); }, { delay: debounce }); return result; }; } exports.IStorage = IStorage; exports.create = create; exports.persist = persist; //# sourceMappingURL=index.cjs.js.map