You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.1 KiB
131 lines
3.1 KiB
2 years ago
|
// @flow
|
||
|
|
||
|
import type {
|
||
|
Persistor,
|
||
|
PersistConfig,
|
||
|
PersistorOptions,
|
||
|
PersistorState,
|
||
|
MigrationManifest,
|
||
|
RehydrateAction,
|
||
|
RehydrateErrorType,
|
||
|
} from './types'
|
||
|
|
||
|
import { createStore } from 'redux'
|
||
|
import { FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE } from './constants'
|
||
|
|
||
|
type PendingRehydrate = [Object, RehydrateErrorType, PersistConfig]
|
||
|
type Persist = <R>(PersistConfig, MigrationManifest) => R => R
|
||
|
type CreatePersistor = Object => void
|
||
|
type BoostrappedCb = () => any
|
||
|
|
||
|
const initialState: PersistorState = {
|
||
|
registry: [],
|
||
|
bootstrapped: false,
|
||
|
}
|
||
|
|
||
|
const persistorReducer = (state = initialState, action) => {
|
||
|
switch (action.type) {
|
||
|
case REGISTER:
|
||
|
return { ...state, registry: [...state.registry, action.key] }
|
||
|
case REHYDRATE:
|
||
|
let firstIndex = state.registry.indexOf(action.key)
|
||
|
let registry = [...state.registry]
|
||
|
registry.splice(firstIndex, 1)
|
||
|
return { ...state, registry, bootstrapped: registry.length === 0 }
|
||
|
default:
|
||
|
return state
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export default function persistStore(
|
||
|
store: Object,
|
||
|
options?: ?PersistorOptions,
|
||
|
cb?: BoostrappedCb
|
||
|
): Persistor {
|
||
|
// help catch incorrect usage of passing PersistConfig in as PersistorOptions
|
||
|
if (process.env.NODE_ENV !== 'production') {
|
||
|
let optionsToTest: Object = options || {}
|
||
|
let bannedKeys = [
|
||
|
'blacklist',
|
||
|
'whitelist',
|
||
|
'transforms',
|
||
|
'storage',
|
||
|
'keyPrefix',
|
||
|
'migrate',
|
||
|
]
|
||
|
bannedKeys.forEach(k => {
|
||
|
if (!!optionsToTest[k])
|
||
|
console.error(
|
||
|
`redux-persist: invalid option passed to persistStore: "${k}". You may be incorrectly passing persistConfig into persistStore, whereas it should be passed into persistReducer.`
|
||
|
)
|
||
|
})
|
||
|
}
|
||
|
let boostrappedCb = cb || false
|
||
|
|
||
|
let _pStore = createStore(
|
||
|
persistorReducer,
|
||
|
initialState,
|
||
|
options && options.enhancer ? options.enhancer : undefined
|
||
|
)
|
||
|
let register = (key: string) => {
|
||
|
_pStore.dispatch({
|
||
|
type: REGISTER,
|
||
|
key,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
let rehydrate = (key: string, payload: Object, err: any) => {
|
||
|
let rehydrateAction = {
|
||
|
type: REHYDRATE,
|
||
|
payload,
|
||
|
err,
|
||
|
key,
|
||
|
}
|
||
|
// dispatch to `store` to rehydrate and `persistor` to track result
|
||
|
store.dispatch(rehydrateAction)
|
||
|
_pStore.dispatch(rehydrateAction)
|
||
|
if (boostrappedCb && persistor.getState().bootstrapped) {
|
||
|
boostrappedCb()
|
||
|
boostrappedCb = false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let persistor: Persistor = {
|
||
|
..._pStore,
|
||
|
purge: () => {
|
||
|
let results = []
|
||
|
store.dispatch({
|
||
|
type: PURGE,
|
||
|
result: purgeResult => {
|
||
|
results.push(purgeResult)
|
||
|
},
|
||
|
})
|
||
|
return Promise.all(results)
|
||
|
},
|
||
|
flush: () => {
|
||
|
let results = []
|
||
|
store.dispatch({
|
||
|
type: FLUSH,
|
||
|
result: flushResult => {
|
||
|
results.push(flushResult)
|
||
|
},
|
||
|
})
|
||
|
return Promise.all(results)
|
||
|
},
|
||
|
pause: () => {
|
||
|
store.dispatch({
|
||
|
type: PAUSE,
|
||
|
})
|
||
|
},
|
||
|
persist: () => {
|
||
|
store.dispatch({ type: PERSIST, register, rehydrate })
|
||
|
},
|
||
|
}
|
||
|
|
||
|
if (!(options && options.manualPersist)){
|
||
|
persistor.persist()
|
||
|
}
|
||
|
|
||
|
return persistor
|
||
|
}
|