/
config-manager.ts
104 lines (90 loc) 路 2.76 KB
/
config-manager.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import pako from 'pako'
import { getDefaultConfig, AppConfig } from '@/app-config'
import { mergeConfig } from '@/app-config/merge-config'
import { storage } from './browser-api'
import { Observable } from 'rxjs/Observable'
import { from } from 'rxjs/observable/from'
import { concat } from 'rxjs/observable/concat'
import { map } from 'rxjs/operators/map'
import { fromEventPattern } from 'rxjs/observable/fromEventPattern'
export interface StorageChanged<T> {
newValue: T,
oldValue?: T,
}
export interface AppConfigChanged {
newConfig: AppConfig,
oldConfig?: AppConfig,
}
/** Compressed config data */
interface AppConfigCompressed {
/** version */
v: 1
/** data */
d: string
}
function deflate (config: AppConfig): AppConfigCompressed {
return {
v: 1,
d: pako.deflate(JSON.stringify(config), { to: 'string' })
}
}
function inflate (config: AppConfig | AppConfigCompressed): AppConfig
function inflate (config: undefined): undefined
function inflate (config?: AppConfig | AppConfigCompressed): AppConfig | undefined
function inflate (config?: AppConfig | AppConfigCompressed): AppConfig | undefined {
if (config && config['v'] === 1) {
return JSON.parse(pako.inflate((config as AppConfigCompressed).d, { to: 'string' }))
}
return config as AppConfig
}
export async function initConfig (): Promise<AppConfig> {
let baseconfig = await getConfig()
baseconfig = baseconfig && baseconfig.version
? mergeConfig(baseconfig)
: getDefaultConfig()
await updateConfig(baseconfig)
return baseconfig
}
export async function resetConfig () {
const baseconfig = getDefaultConfig()
await updateConfig(baseconfig)
return baseconfig
}
export async function getConfig (): Promise<AppConfig> {
const { baseconfig } = await storage.sync.get<{
baseconfig: AppConfig
}>('baseconfig')
return inflate(baseconfig || getDefaultConfig())
}
export function updateConfig (baseconfig: AppConfig): Promise<void> {
return storage.sync.set({ baseconfig: deflate(baseconfig) })
}
/**
* Listen to config changes
*/
export async function addConfigListener (
cb: (changes: AppConfigChanged) => any
) {
storage.sync.addListener(changes => {
if (changes.baseconfig) {
const {
newValue,
oldValue,
} = (changes as { baseconfig: StorageChanged<AppConfigCompressed> }).baseconfig
if (newValue) {
cb({ newConfig: inflate(newValue), oldConfig: inflate(oldValue) })
}
}
})
}
/**
* Get config and create a stream listening to config change
*/
export function createConfigStream (): Observable<AppConfig> {
return concat(
from(getConfig()),
fromEventPattern<[AppConfigChanged] | AppConfigChanged>(addConfigListener as any).pipe(
map(args => (Array.isArray(args) ? args[0] : args).newConfig),
),
)
}