persistReducer.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. "use strict";
  2. exports.__esModule = true;
  3. exports.default = persistReducer;
  4. var _constants = require("./constants");
  5. var _autoMergeLevel = _interopRequireDefault(require("./stateReconciler/autoMergeLevel1"));
  6. var _createPersistoid = _interopRequireDefault(require("./createPersistoid"));
  7. var _getStoredState = _interopRequireDefault(require("./getStoredState"));
  8. var _purgeStoredState = _interopRequireDefault(require("./purgeStoredState"));
  9. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  10. function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
  11. function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
  12. 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; }
  13. function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
  14. function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
  15. var DEFAULT_TIMEOUT = 5000;
  16. /*
  17. @TODO add validation / handling for:
  18. - persisting a reducer which has nested _persist
  19. - handling actions that fire before reydrate is called
  20. */
  21. function persistReducer(config, baseReducer) {
  22. if (process.env.NODE_ENV !== 'production') {
  23. if (!config) throw new Error('config is required for persistReducer');
  24. if (!config.key) throw new Error('key is required in persistor config');
  25. if (!config.storage) throw new Error("redux-persist: config.storage is required. Try using one of the provided storage engines `import storage from 'redux-persist/lib/storage'`");
  26. }
  27. var version = config.version !== undefined ? config.version : _constants.DEFAULT_VERSION;
  28. var debug = config.debug || false;
  29. var stateReconciler = config.stateReconciler === undefined ? _autoMergeLevel.default : config.stateReconciler;
  30. var getStoredState = config.getStoredState || _getStoredState.default;
  31. var timeout = config.timeout !== undefined ? config.timeout : DEFAULT_TIMEOUT;
  32. var _persistoid = null;
  33. var _purge = false;
  34. var _paused = true;
  35. var conditionalUpdate = function conditionalUpdate(state) {
  36. // update the persistoid only if we are rehydrated and not paused
  37. state._persist.rehydrated && _persistoid && !_paused && _persistoid.update(state);
  38. return state;
  39. };
  40. return function (state, action) {
  41. var _ref = state || {},
  42. _persist = _ref._persist,
  43. rest = _objectWithoutProperties(_ref, ["_persist"]); // $FlowIgnore need to update State type
  44. var restState = rest;
  45. if (action.type === _constants.PERSIST) {
  46. var _sealed = false;
  47. var _rehydrate = function _rehydrate(payload, err) {
  48. // dev warning if we are already sealed
  49. if (process.env.NODE_ENV !== 'production' && _sealed) console.error("redux-persist: rehydrate for \"".concat(config.key, "\" called after timeout."), payload, err); // only rehydrate if we are not already sealed
  50. if (!_sealed) {
  51. action.rehydrate(config.key, payload, err);
  52. _sealed = true;
  53. }
  54. };
  55. timeout && setTimeout(function () {
  56. !_sealed && _rehydrate(undefined, new Error("redux-persist: persist timed out for persist key \"".concat(config.key, "\"")));
  57. }, timeout); // @NOTE PERSIST resumes if paused.
  58. _paused = false; // @NOTE only ever create persistoid once, ensure we call it at least once, even if _persist has already been set
  59. if (!_persistoid) _persistoid = (0, _createPersistoid.default)(config); // @NOTE PERSIST can be called multiple times, noop after the first
  60. if (_persist) {
  61. // We still need to call the base reducer because there might be nested
  62. // uses of persistReducer which need to be aware of the PERSIST action
  63. return _objectSpread({}, baseReducer(restState, action), {
  64. _persist: _persist
  65. });
  66. }
  67. if (typeof action.rehydrate !== 'function' || typeof action.register !== 'function') throw new Error('redux-persist: either rehydrate or register is not a function on the PERSIST action. This can happen if the action is being replayed. This is an unexplored use case, please open an issue and we will figure out a resolution.');
  68. action.register(config.key);
  69. getStoredState(config).then(function (restoredState) {
  70. var migrate = config.migrate || function (s, v) {
  71. return Promise.resolve(s);
  72. };
  73. migrate(restoredState, version).then(function (migratedState) {
  74. _rehydrate(migratedState);
  75. }, function (migrateErr) {
  76. if (process.env.NODE_ENV !== 'production' && migrateErr) console.error('redux-persist: migration error', migrateErr);
  77. _rehydrate(undefined, migrateErr);
  78. });
  79. }, function (err) {
  80. _rehydrate(undefined, err);
  81. });
  82. return _objectSpread({}, baseReducer(restState, action), {
  83. _persist: {
  84. version: version,
  85. rehydrated: false
  86. }
  87. });
  88. } else if (action.type === _constants.PURGE) {
  89. _purge = true;
  90. action.result((0, _purgeStoredState.default)(config));
  91. return _objectSpread({}, baseReducer(restState, action), {
  92. _persist: _persist
  93. });
  94. } else if (action.type === _constants.FLUSH) {
  95. action.result(_persistoid && _persistoid.flush());
  96. return _objectSpread({}, baseReducer(restState, action), {
  97. _persist: _persist
  98. });
  99. } else if (action.type === _constants.PAUSE) {
  100. _paused = true;
  101. } else if (action.type === _constants.REHYDRATE) {
  102. // noop on restState if purging
  103. if (_purge) return _objectSpread({}, restState, {
  104. _persist: _objectSpread({}, _persist, {
  105. rehydrated: true
  106. }) // @NOTE if key does not match, will continue to default else below
  107. });
  108. if (action.key === config.key) {
  109. var reducedState = baseReducer(restState, action);
  110. var inboundState = action.payload; // only reconcile state if stateReconciler and inboundState are both defined
  111. var reconciledRest = stateReconciler !== false && inboundState !== undefined ? stateReconciler(inboundState, state, reducedState, config) : reducedState;
  112. var _newState = _objectSpread({}, reconciledRest, {
  113. _persist: _objectSpread({}, _persist, {
  114. rehydrated: true
  115. })
  116. });
  117. return conditionalUpdate(_newState);
  118. }
  119. } // if we have not already handled PERSIST, straight passthrough
  120. if (!_persist) return baseReducer(state, action); // run base reducer:
  121. // is state modified ? return original : return updated
  122. var newState = baseReducer(restState, action);
  123. if (newState === restState) return state;
  124. return conditionalUpdate(_objectSpread({}, newState, {
  125. _persist: _persist
  126. }));
  127. };
  128. }