-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSettingsStore.ts
More file actions
126 lines (109 loc) · 3.24 KB
/
SettingsStore.ts
File metadata and controls
126 lines (109 loc) · 3.24 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { EventEmitter } from "../utils/EventEmitter"
export type DataStoreResource = 'dataStore' | 'userDataStore'
const joinPath = (...parts: Array<string>) =>
parts.map(part =>
part
.replace(/^\/+/, '')
.replace(/\/+$/, '')
).join('/')
export type BaseSettingsStoreInput = {
engine: any, // TODO: Proper typings
resource: DataStoreResource,
namespace: string,
item: string,
defaults: any
}
export class SettingsStore {
engine: any
resource: DataStoreResource
dataStoreId: string
settings: Record<string,any>
eventEmitter = new EventEmitter()
constructor({
engine,
resource,
namespace,
item,
defaults = {}
}: BaseSettingsStoreInput) {
this.engine = engine
this.resource = resource
this.dataStoreId = joinPath(namespace, item)
this.settings = defaults
}
async initialize() {
await this.refresh()
}
async create() {
await this.engine.mutate({
resource: `${this.resource}/${this.dataStoreId}`,
type: 'create',
data: this.settings
})
}
async refresh() {
const prevSettings = this.settings;
try {
const newSettings = await this.engine.query({
settings: {
resource: this.resource,
id: this.dataStoreId,
}
})
this.settings = newSettings.settings
} catch (e) {
if (e.details?.status === 404) {
await this.create()
} else {
throw e;
}
}
Object.keys(prevSettings).forEach(key => {
if (prevSettings[key] !== this.settings[key]) {
this.eventEmitter.emit(`change ${key}`, this.settings[key])
}
})
this.eventEmitter.emit('change', this.settings)
}
get(key: string) {
return this.settings[key]
}
async set(key: string, value: any) {
const prevSettings = this.settings
const newSettings = {
...this.settings,
[key]: value
}
if (typeof value === 'undefined') {
delete newSettings[key]
}
this.settings = newSettings
this.eventEmitter.emit(`change ${key}`, value)
this.eventEmitter.emit('change', this.settings)
try {
await this.engine.mutate({
resource: this.resource,
type: 'update',
id: this.dataStoreId,
data: this.settings
})
} catch (e) {
this.settings = prevSettings
this.eventEmitter.emit(`change ${key}`, this.get(key))
this.eventEmitter.emit('change', this.settings)
throw e
}
}
subscribeAll(callback: Function) {
this.eventEmitter.on('change', callback)
}
subscribe(key: string, callback: Function) {
this.eventEmitter.on(`change ${key}`, callback)
}
unsubscribeAll(callback: Function) {
this.eventEmitter.off('change', callback)
}
unsubscribe(key: string, callback: Function) {
this.eventEmitter.off(`change ${key}`, callback)
}
}