-
-
Notifications
You must be signed in to change notification settings - Fork 17
/
index.ts
75 lines (63 loc) · 2.25 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { onSnapshot, applySnapshot, IStateTreeNode } from 'mobx-state-tree'
import AsyncLocalStorage from './asyncLocalStorage'
export interface IArgs {
(name: string, store: IStateTreeNode, options?: IOptions): Promise<void>
}
export interface IOptions {
storage?: any,
jsonify?: boolean,
readonly whitelist?: Array<string>,
readonly blacklist?: Array<string>
}
type StrToAnyMap = {[key: string]: any}
export const persist: IArgs = (name, store, options = {}) => {
let {storage, jsonify = true, whitelist, blacklist} = options
// use AsyncLocalStorage by default (or if localStorage was passed in)
if (
typeof window !== 'undefined' &&
typeof window.localStorage !== 'undefined' &&
(!storage || storage === window.localStorage)
) {
storage = AsyncLocalStorage
}
if (!storage) {
return Promise.reject('localStorage (the default storage engine) is not ' +
'supported in this environment. Please configure a different storage ' +
'engine via the `storage:` option.')
}
const whitelistDict = arrToDict(whitelist)
const blacklistDict = arrToDict(blacklist)
onSnapshot(store, (_snapshot: StrToAnyMap) => {
// need to shallow clone as otherwise properties are non-configurable (https://github.com/agilgur5/mst-persist/pull/21#discussion_r348105595)
const snapshot = { ..._snapshot }
Object.keys(snapshot).forEach((key) => {
if (whitelist && !whitelistDict[key]) {
delete snapshot[key]
}
if (blacklist && blacklistDict[key]) {
delete snapshot[key]
}
})
const data = !jsonify ? snapshot : JSON.stringify(snapshot)
storage.setItem(name, data)
})
return storage.getItem(name)
.then((data: object | string) => {
const snapshot = !isString(data) ? data : JSON.parse(data)
// don't apply falsey (which will error), leave store in initial state
if (!snapshot) { return }
applySnapshot(store, snapshot)
})
}
type StrToBoolMap = {[key: string]: boolean}
function arrToDict (arr?: Array<string>): StrToBoolMap {
if (!arr) { return {} }
return arr.reduce((dict: StrToBoolMap, elem) => {
dict[elem] = true
return dict
}, {})
}
function isString (value: any): value is string {
return typeof value === 'string'
}
export default persist