123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import { KEY_PREFIX, REHYDRATE } from './constants'
- import type { Persistoid, PersistConfig, Transform } from './types'
- type IntervalID = any
- export default function createPersistoid(config: PersistConfig): Persistoid {
-
- const blacklist: ?Array<string> = config.blacklist || null
- const whitelist: ?Array<string> = config.whitelist || null
- const transforms = config.transforms || []
- const throttle = config.throttle || 0
- const storageKey = `${
- config.keyPrefix !== undefined ? config.keyPrefix : KEY_PREFIX
- }${config.key}`
- const storage = config.storage
- let serialize
- if (config.serialize === false) {
- serialize = x => x
- } else if (typeof config.serialize === 'function') {
- serialize = config.serialize
- } else {
- serialize = defaultSerialize
- }
- const writeFailHandler = config.writeFailHandler || null
-
- let lastState = {}
- let stagedState = {}
- let keysToProcess = []
- let timeIterator: ?IntervalID = null
- let writePromise = null
- const update = (state: Object) => {
-
- Object.keys(state).forEach(key => {
- if (!passWhitelistBlacklist(key)) return
- if (lastState[key] === state[key]) return
- if (keysToProcess.indexOf(key) !== -1) return
- keysToProcess.push(key)
- })
-
-
- Object.keys(lastState).forEach(key => {
- if (
- state[key] === undefined &&
- passWhitelistBlacklist(key) &&
- keysToProcess.indexOf(key) === -1 &&
- lastState[key] !== undefined
- ) {
- keysToProcess.push(key)
- }
- })
-
- if (timeIterator === null) {
- timeIterator = setInterval(processNextKey, throttle)
- }
- lastState = state
- }
- function processNextKey() {
- if (keysToProcess.length === 0) {
- if (timeIterator) clearInterval(timeIterator)
- timeIterator = null
- return
- }
- let key = keysToProcess.shift()
- let endState = transforms.reduce((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 {
-
- delete stagedState[key]
- }
- if (keysToProcess.length === 0) {
- writeStagedState()
- }
- }
- function writeStagedState() {
-
- Object.keys(stagedState).forEach(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) {
-
- if (writeFailHandler) writeFailHandler(err)
- if (err && process.env.NODE_ENV !== 'production') {
- console.error('Error storing data', err)
- }
- }
- const flush = () => {
- while (keysToProcess.length !== 0) {
- processNextKey()
- }
- return writePromise || Promise.resolve()
- }
-
- return {
- update,
- flush,
- }
- }
- function defaultSerialize(data) {
- return JSON.stringify(data)
- }
|