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.
130 lines
3.1 KiB
130 lines
3.1 KiB
// @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 |
|
}
|
|
|