forked from sheepzh/time-tracker-4-browser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmerge-rule-database.ts
More file actions
97 lines (80 loc) · 2.87 KB
/
merge-rule-database.ts
File metadata and controls
97 lines (80 loc) · 2.87 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
/**
* Copyright (c) 2021 Hengyang Zhang
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
import { isRecord } from '@util/guard'
import { createArrayGuard, createObjectGuard, createRecordGuard, createUnionGuard, isInt, isString } from 'typescript-guard'
import BaseDatabase from "./common/base-database"
import { REMAIN_WORD_PREFIX } from "./common/constant"
import { extractNamespace, isLegacyVersion } from './common/migratable'
import type { BrowserMigratable } from './types'
const DB_KEY = REMAIN_WORD_PREFIX + 'MERGE_RULES'
type MergeRuleSet = { [key: string]: string | number }
const isMergeValue = createUnionGuard(isString, isInt)
const isMergeRuleSet = createRecordGuard(isMergeValue)
const isMergeRule = createObjectGuard<timer.merge.Rule>({
origin: isString,
merged: isMergeValue,
})
/**
* Rules to merge host
*
* @since 0.1.2
*/
class MergeRuleDatabase extends BaseDatabase implements BrowserMigratable<'__merge__'> {
namespace: '__merge__' = '__merge__'
async refresh(): Promise<MergeRuleSet> {
const result = await this.storage.getOne<MergeRuleSet>(DB_KEY)
return result || {}
}
private update(data: MergeRuleSet): Promise<void> {
return this.setByKey(DB_KEY, data)
}
async selectAll(): Promise<timer.merge.Rule[]> {
const set = await this.refresh()
return Object.entries(set)
.map(([origin, merged]) => ({ origin, merged } satisfies timer.merge.Rule))
}
async remove(origin: string): Promise<void> {
const set = await this.refresh()
delete set[origin]
await this.update(set)
}
/**
* Add to the db
*/
async add(...toAdd: timer.merge.Rule[]): Promise<void> {
const set = await this.refresh()
// Not rewrite
toAdd.forEach(({ origin, merged }) => set[origin] = set[origin] ?? merged)
await this.update(set)
}
async importData(data: unknown): Promise<void> {
if (isLegacyVersion(data)) {
return this.importLegacyData(data)
}
const rules = extractNamespace(data, this.namespace, createArrayGuard(isMergeRule)) ?? []
await this.add(...rules)
}
/**
* @deprecated Only for legacy version
*/
private async importLegacyData(data: unknown): Promise<void> {
if (!isRecord(data)) return
const toMigrate = data[DB_KEY]
if (!isMergeRuleSet(toMigrate)) return
const exist = await this.refresh()
Object.entries(toMigrate satisfies MergeRuleSet)
// Not rewrite
.filter(([key]) => !exist[key])
.forEach(([key, value]) => exist[key] = value)
await this.update(exist)
}
exportData(): Promise<timer.merge.Rule[]> {
return this.selectAll()
}
}
const mergeRuleDatabase = new MergeRuleDatabase()
export default mergeRuleDatabase