forked from sheepzh/time-tracker-4-browser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsite-database.ts
More file actions
141 lines (125 loc) · 4.39 KB
/
Copy pathsite-database.ts
File metadata and controls
141 lines (125 loc) · 4.39 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
* Copyright (c) 2021 Hengyang Zhang
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
import { toMap } from '@util/array'
import { CATE_NOT_SET_ID } from "@util/site"
import BaseDatabase from "./common/base-database"
import { REMAIN_WORD_PREFIX } from "./common/constant"
type _Entry = {
/**
* Alias
*/
a?: string
/**
* Icon url
*/
i?: string
/**
* Category ID
*/
c?: number
/**
* Count run time
*/
r?: boolean
}
const DB_KEY_PREFIX = REMAIN_WORD_PREFIX + 'SITE_'
const HOST_KEY_PREFIX = DB_KEY_PREFIX + 'h'
const VIRTUAL_KEY_PREFIX = DB_KEY_PREFIX + 'v'
const MERGED_FLAG = 'm'
function cvt2Key({ host, type }: tt4b.site.SiteKey): string {
switch (type) {
case 'virtual': return VIRTUAL_KEY_PREFIX + host
case 'merged': return HOST_KEY_PREFIX + MERGED_FLAG + host
case 'normal': return HOST_KEY_PREFIX + '_' + host
}
}
function cvt2SiteKey(key: string): tt4b.site.SiteKey {
if (key.startsWith(VIRTUAL_KEY_PREFIX)) {
return {
host: key.substring(VIRTUAL_KEY_PREFIX.length),
type: 'virtual',
}
} else if (key.startsWith(HOST_KEY_PREFIX)) {
return {
host: key.substring(HOST_KEY_PREFIX.length + 1),
type: key.charAt(HOST_KEY_PREFIX.length) === MERGED_FLAG ? 'merged' : 'normal',
}
} else {
// Can't go there
return { host: key, type: 'normal' }
}
}
function cvt2Entry({ alias, iconUrl, cate, run }: tt4b.site.SiteInfo): _Entry {
const entry: _Entry = { i: iconUrl }
alias && (entry.a = alias)
cate && (entry.c = cate)
run && (entry.r = true)
entry.i = iconUrl
return entry
}
function cvt2SiteInfo(key: tt4b.site.SiteKey, entry: _Entry | undefined): tt4b.site.SiteInfo {
const { a, i, c, r } = entry ?? {}
const siteInfo: tt4b.site.SiteInfo = { ...key }
siteInfo.alias = a
siteInfo.cate = c ?? CATE_NOT_SET_ID
siteInfo.iconUrl = i
siteInfo.run = !!r
return siteInfo
}
function buildFilter(condition?: tt4b.site.Query): (site: tt4b.site.SiteInfo) => boolean {
const { fuzzyQuery, cateIds, types } = condition || {}
let cateFilter = typeof cateIds === 'number' ? [cateIds] : (cateIds?.length ? cateIds : undefined)
let typeFilter = typeof types === 'string' ? [types] : (types?.length ? types : undefined)
return site => {
const { host: siteHost, alias: siteAlias, cate, type } = site || {}
if (fuzzyQuery && !(siteHost?.includes(fuzzyQuery) || siteAlias?.includes(fuzzyQuery))) return false
if (cateFilter && (!cateFilter.includes(cate ?? CATE_NOT_SET_ID) || type !== 'normal')) return false
if (typeFilter && !typeFilter.includes(type)) return false
return true
}
}
class SiteDatabase extends BaseDatabase {
async select(condition?: tt4b.site.Query): Promise<tt4b.site.SiteInfo[]> {
const filter = buildFilter(condition)
const data = await this.storage.get()
return Object.entries(data)
.filter(([key]) => key.startsWith(DB_KEY_PREFIX))
.map(([key, value]) => cvt2SiteInfo(cvt2SiteKey(key), value as _Entry))
.filter(filter)
}
/**
* Get by key
*
* @returns site info, or undefined
*/
async get(key: tt4b.site.SiteKey): Promise<tt4b.site.SiteInfo | undefined> {
const entry = await this.storage.getOne<_Entry>(cvt2Key(key))
return entry && cvt2SiteInfo(key, entry)
}
async getBatch(keys: tt4b.site.SiteKey[]): Promise<tt4b.site.SiteInfo[]> {
const result = await this.storage.get(keys.map(cvt2Key))
return Object.entries(result)
.map(([key, value]) => cvt2SiteInfo(cvt2SiteKey(key), value as _Entry))
}
async save(...sites: tt4b.site.SiteInfo[]): Promise<void> {
if (!sites.length) return
const toSet = toMap(sites, cvt2Key, cvt2Entry)
await this.storage.set(toSet)
}
async remove(siteKeys: tt4b.site.SiteKey[]): Promise<void> {
if (!siteKeys.length) return
const keys = siteKeys.map(cvt2Key)
await this.storage.remove(keys)
}
async exist(siteKey: tt4b.site.SiteKey): Promise<boolean> {
const key = cvt2Key(siteKey)
const entry = await this.storage.getOne<_Entry>(key)
return !!entry
}
}
const siteDatabase = new SiteDatabase()
export default siteDatabase