123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- import { KEY_PREFIX, REHYDRATE } from './constants';
- // @TODO remove once flow < 0.63 support is no longer required.
- export default function createPersistoid(config) {
- // defaults
- var blacklist = config.blacklist || null;
- var whitelist = config.whitelist || null;
- var transforms = config.transforms || [];
- var throttle = config.throttle || 0;
- var storageKey = "".concat(config.keyPrefix !== undefined ? config.keyPrefix : KEY_PREFIX).concat(config.key);
- var storage = config.storage;
- var serialize;
- if (config.serialize === false) {
- serialize = function serialize(x) {
- return x;
- };
- } else if (typeof config.serialize === 'function') {
- serialize = config.serialize;
- } else {
- serialize = defaultSerialize;
- }
- var writeFailHandler = config.writeFailHandler || null; // initialize stateful values
- var lastState = {};
- var stagedState = {};
- var keysToProcess = [];
- var timeIterator = null;
- var writePromise = null;
- var update = function update(state) {
- // add any changed keys to the queue
- Object.keys(state).forEach(function (key) {
- if (!passWhitelistBlacklist(key)) return; // is keyspace ignored? noop
- if (lastState[key] === state[key]) return; // value unchanged? noop
- if (keysToProcess.indexOf(key) !== -1) return; // is key already queued? noop
- keysToProcess.push(key); // add key to queue
- }); //if any key is missing in the new state which was present in the lastState,
- //add it for processing too
- Object.keys(lastState).forEach(function (key) {
- if (state[key] === undefined && passWhitelistBlacklist(key) && keysToProcess.indexOf(key) === -1 && lastState[key] !== undefined) {
- keysToProcess.push(key);
- }
- }); // start the time iterator if not running (read: throttle)
- if (timeIterator === null) {
- timeIterator = setInterval(processNextKey, throttle);
- }
- lastState = state;
- };
- function processNextKey() {
- if (keysToProcess.length === 0) {
- if (timeIterator) clearInterval(timeIterator);
- timeIterator = null;
- return;
- }
- var key = keysToProcess.shift();
- var endState = transforms.reduce(function (subState, transformer) {
- return transformer.in(subState, key, lastState);
- }, lastState[key]);
- if (endState !== undefined) {
- try {
- stagedState[key] = serialize(endState);
- } catch (err) {
- console.error('redux-persist/createPersistoid: error serializing state', err);
- }
- } else {
- //if the endState is undefined, no need to persist the existing serialized content
- delete stagedState[key];
- }
- if (keysToProcess.length === 0) {
- writeStagedState();
- }
- }
- function writeStagedState() {
- // cleanup any removed keys just before write.
- Object.keys(stagedState).forEach(function (key) {
- if (lastState[key] === undefined) {
- delete stagedState[key];
- }
- });
- writePromise = storage.setItem(storageKey, serialize(stagedState)).catch(onWriteFail);
- }
- function passWhitelistBlacklist(key) {
- if (whitelist && whitelist.indexOf(key) === -1 && key !== '_persist') return false;
- if (blacklist && blacklist.indexOf(key) !== -1) return false;
- return true;
- }
- function onWriteFail(err) {
- // @TODO add fail handlers (typically storage full)
- if (writeFailHandler) writeFailHandler(err);
- if (err && process.env.NODE_ENV !== 'production') {
- console.error('Error storing data', err);
- }
- }
- var flush = function flush() {
- while (keysToProcess.length !== 0) {
- processNextKey();
- }
- return writePromise || Promise.resolve();
- }; // return `persistoid`
- return {
- update: update,
- flush: flush
- };
- } // @NOTE in the future this may be exposed via config
- function defaultSerialize(data) {
- return JSON.stringify(data);
- }
|