UNPKG

reactant-storage

Version:

A persistence storage plugin for Reactant

489 lines (444 loc) 21 kB
'use strict'; var React = require('react'); var reactantModule = require('reactant-module'); var reduxPersist = require('redux-persist'); /****************************************************************************** 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, SuppressedError, Symbol, Iterator */ 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 __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 __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function __param(paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } } function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); return Constructor; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var PersistGate = /*#__PURE__*/ function (_PureComponent) { _inherits(PersistGate, _PureComponent); function PersistGate() { var _getPrototypeOf2; var _this; _classCallCheck(this, PersistGate); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(PersistGate)).call.apply(_getPrototypeOf2, [this].concat(args))); _defineProperty(_assertThisInitialized(_this), "state", { bootstrapped: false }); _defineProperty(_assertThisInitialized(_this), "_unsubscribe", void 0); _defineProperty(_assertThisInitialized(_this), "handlePersistorState", function () { var persistor = _this.props.persistor; var _persistor$getState = persistor.getState(), bootstrapped = _persistor$getState.bootstrapped; if (bootstrapped) { if (_this.props.onBeforeLift) { Promise.resolve(_this.props.onBeforeLift()).finally(function () { return _this.setState({ bootstrapped: true }); }); } else { _this.setState({ bootstrapped: true }); } _this._unsubscribe && _this._unsubscribe(); } }); return _this; } _createClass(PersistGate, [{ key: "componentDidMount", value: function componentDidMount() { this._unsubscribe = this.props.persistor.subscribe(this.handlePersistorState); this.handlePersistorState(); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this._unsubscribe && this._unsubscribe(); } }, { key: "render", value: function render() { if (process.env.NODE_ENV !== 'production') { if (typeof this.props.children === 'function' && this.props.loading) console.error('redux-persist: PersistGate expects either a function child or loading prop, but not both. The loading prop will be ignored.'); } if (typeof this.props.children === 'function') { return this.props.children(this.state.bootstrapped); } return this.state.bootstrapped ? this.props.children : this.props.loading; } }]); return PersistGate; }(React.PureComponent); _defineProperty(PersistGate, "defaultProps", { children: null, loading: null }); var StorageOptions = Symbol('StorageOptions'); var getRehydrated = function (target) { var _a; var module = target; var state = module[reactantModule.stateKey]; return (_a = state === null || state === void 0 ? void 0 : state._persist) === null || _a === void 0 ? void 0 : _a.rehydrated; }; var ReactantStorage = /** @class */ (function (_super) { __extends(ReactantStorage, _super); function ReactantStorage(options) { var _a; var _this = _super.call(this) || this; _this.blacklist = ['router', 'lastAction']; /** * all modules rehydrated */ _this.rehydrated = false; _this.persistConfig = {}; _this.storageSettingMap = new Map(); _this.middleware = function (store) { return function (next) { return function (_action) { var _a, _b; if (_this[reactantModule.enableAutoComputedKey] && _action.type === reduxPersist.REHYDRATE && _action.key !== 'root') { var target_1 = reactantModule.getRef(_this).modules[_action.key]; var persistStateKeys = (_b = Object.keys((_a = _action.payload) !== null && _a !== void 0 ? _a : {})) !== null && _b !== void 0 ? _b : []; persistStateKeys.forEach(function (persistStateKey) { var _a; if (persistStateKey !== '_persist' && ((_a = target_1[reactantModule.signalMapKey]) === null || _a === void 0 ? void 0 : _a[persistStateKey])) { // need to update the target signal value to the latest hydrated state target_1[reactantModule.signalMapKey][persistStateKey].value = _action.payload[persistStateKey]; } }); } var result = next(_action); return result; }; }; }; /** * manual persist */ _this.manualPersist = false; /** * persistence paused */ _this.paused = false; _this.rehydrateCallbackSet = new Set(); _this.provider = function (props) { var _a, _b; if ((_b = (_a = _this.store) === null || _a === void 0 ? void 0 : _a.getState()._persist) === null || _b === void 0 ? void 0 : _b.rehydrated) return React.createElement(React.Fragment, null, props.children); return (React.createElement(PersistGate, { loading: _this.options.loading || null, persistor: _this.persistor }, props.children)); }; _this.options = __assign(__assign({}, options), { whitelist: (_a = options.whitelist) !== null && _a !== void 0 ? _a : [] }); _this.persistRootConfig = __assign({ key: 'root', // https://github.com/rt2zz/redux-persist/issues/786#issuecomment-421850652 timeout: null }, _this.options); return _this; } /** * set module to storage persistent */ ReactantStorage.prototype.setStorage = function (target, options) { var _this = this; var module = target; if (process.env.NODE_ENV !== 'production') { if (typeof module[reactantModule.nameKey] !== 'string') { throw new Error("Module '".concat(module.constructor.name, "' is invalid for using 'setStorage', the parameter 'options.name' of the decorator '@injectable(options)' that decorates the '").concat(module.constructor.name, "' module must be specified as a string.")); } if (typeof module[reactantModule.stateKey] !== 'object') { throw new Error("Module '".concat(module.constructor.name, "' is invalid for using 'setStorage', the current module does not have any global state that is decorated with '@state'.")); } if (Object.prototype.hasOwnProperty.call(module[reactantModule.stateKey], '_persist')) { throw new Error("Module '".concat(module.constructor.name, "' is invalid for using 'setStorage', the current module should not customize the state with the key '_persist'.")); } } this.storageSettingMap.set(module, function () { var _a; var persistConfig = __assign(__assign({ storage: _this.options.storage }, options), { key: module[reactantModule.identifierKey] }); Object.assign(_this.persistConfig, (_a = {}, _a[module[reactantModule.identifierKey]] = persistConfig, _a)); }); }; /** * get every module rehydrated */ ReactantStorage.prototype.getRehydrated = function (target) { if (!this.storageSettingMap.has(target)) { throw new Error("Module '".concat(target.constructor.name, "' is not set to storage persistent.")); } return getRehydrated(target); }; ReactantStorage.prototype.beforeCombineRootReducers = function (reducers) { var e_1, _a; var _this = this; var _b; (_b = this.beforeCombinePersistReducer) === null || _b === void 0 ? void 0 : _b.call(this); try { for (var _c = __values(this.storageSettingMap), _d = _c.next(); !_d.done; _d = _c.next()) { var _e = __read(_d.value, 2), _ = _e[0], set = _e[1]; set(); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_1) throw e_1.error; } } if (process.env.NODE_ENV !== 'production') { if (reducers._persist) { throw new Error("Storage module conflict with the names of other modules, make sure that no module has a name of '_persist'."); } } Object.keys(reducers).forEach(function (key) { var _a; var isTempIdentifier = /^@@reactant\//.test(key); if (isTempIdentifier) { _this.blacklist.push(key); } var persistConfig = _this.persistConfig[key]; if (persistConfig) { var reducer = reduxPersist.persistReducer(persistConfig, reducers[key]); Object.assign(reducers, (_a = {}, _a[key] = reducer, _a)); } else if (_this.persistRootConfig.blacklist) { // use blacklist mode if (isTempIdentifier) { if (process.env.NODE_ENV !== 'production') { console.warn("For state persistence, The '@injectable({ name })' in the ".concat(key, " module has not been set yet.")); } } } }); return reducers; }; ReactantStorage.prototype.afterCombineRootReducers = function (rootReducer) { return reduxPersist.persistReducer(__assign({ blacklist: __spreadArray(__spreadArray([], __read(Object.keys(this.persistConfig)), false), __read(this.blacklist), false) }, this.persistRootConfig), rootReducer); }; Object.defineProperty(ReactantStorage.prototype, "store", { get: function () { return this[reactantModule.storeKey]; }, enumerable: false, configurable: true }); ReactantStorage.prototype.afterCreateStore = function (store) { var _this = this; this.paused = this.manualPersist; var replaceReducer = store.replaceReducer; // eslint-disable-next-line no-param-reassign store.replaceReducer = function (reducer) { _this.rehydrated = false; replaceReducer(reducer); _this.persistor = reduxPersist.persistStore(store, // TODO: fix type https://github.com/rt2zz/redux-persist/pull/1247 { manualPersist: _this.manualPersist, }, function () { var _a; // after redux-persist action rehydrate _this.rehydrated = true; (_a = _this._onRehydrated) === null || _a === void 0 ? void 0 : _a.call(_this); }); _this._enhancePersistor(); }; this.persistor = reduxPersist.persistStore(store, // TODO: fix type https://github.com/rt2zz/redux-persist/pull/1247 { manualPersist: this.manualPersist, }, function () { var _a; // after redux-persist action rehydrate _this.rehydrated = true; (_a = _this._onRehydrated) === null || _a === void 0 ? void 0 : _a.call(_this); }); this._enhancePersistor(); return store; }; ReactantStorage.prototype._enhancePersistor = function () { var _this = this; if (!this.persistor) { throw new Error("Persistor is not created yet."); } var _a = this.persistor, pause = _a.pause, persist = _a.persist; this.persistor.pause = function () { if (!_this.paused) { _this.paused = true; pause(); } }; this.persistor.persist = function () { if (_this.paused) { _this.paused = false; persist(); } }; }; /** * pauses persistence until persist() is called */ ReactantStorage.prototype.pause = function () { var _a; return (_a = this.persistor) === null || _a === void 0 ? void 0 : _a.pause(); }; /** * resumes persistence */ ReactantStorage.prototype.persist = function () { var _a; return (_a = this.persistor) === null || _a === void 0 ? void 0 : _a.persist(); }; /** * immediately writes all pending state to disk and returns a promise */ ReactantStorage.prototype.flush = function () { var _a; return (_a = this.persistor) === null || _a === void 0 ? void 0 : _a.flush(); }; /** * purges state from disk and returns a promise */ ReactantStorage.prototype.purge = function () { var _a; return (_a = this.persistor) === null || _a === void 0 ? void 0 : _a.purge(); }; ReactantStorage.prototype._onRehydrated = function () { var e_2, _a; if (!this.rehydrateCallbackSet.size) return; var callbacks = Array.from(this.rehydrateCallbackSet); this.rehydrateCallbackSet.clear(); try { for (var callbacks_1 = __values(callbacks), callbacks_1_1 = callbacks_1.next(); !callbacks_1_1.done; callbacks_1_1 = callbacks_1.next()) { var callback = callbacks_1_1.value; callback(); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (callbacks_1_1 && !callbacks_1_1.done && (_a = callbacks_1.return)) _a.call(callbacks_1); } finally { if (e_2) throw e_2.error; } } }; /** * callback when rehydrated */ ReactantStorage.prototype.onRehydrated = function (callback) { if (this.rehydrated) { callback(); } else { this.rehydrateCallbackSet.add(callback); } }; ReactantStorage = __decorate([ reactantModule.injectable(), __param(0, reactantModule.inject(StorageOptions)), __metadata("design:paramtypes", [Object]) ], ReactantStorage); return ReactantStorage; }(reactantModule.PluginModule)); Object.defineProperty(exports, "REHYDRATE", { enumerable: true, get: function () { return reduxPersist.REHYDRATE; } }); exports.Storage = ReactantStorage; exports.StorageOptions = StorageOptions; exports.getRehydrated = getRehydrated;