1+ /**
2+ * @author zhy
3+ * @since 0.4.1
4+ */
5+ import { DomainAlias , DomainSource } from "../entity/dto/domain-alias"
6+ import BaseDatabase from "./common/base-database"
7+ import { REMAIN_WORD_PREFIX } from "./common/constant"
8+
9+ const DB_KEY_PREFIX = REMAIN_WORD_PREFIX + "ALIAS"
10+ const DB_KEY_PREFIX_LENGTH = DB_KEY_PREFIX . length
11+
12+ const SOURCE_PREFIX_MAP : { [ source in DomainSource ] : string } = {
13+ USER : 'u' ,
14+ DETECTED : 'd'
15+ }
16+ const ABBR_MAP = {
17+ 'u' : DomainSource . USER ,
18+ 'd' : DomainSource . DETECTED
19+ }
20+
21+ const generateKey = ( domain : string ) => DB_KEY_PREFIX + domain
22+ const domainOf = ( key : string ) => key . substring ( DB_KEY_PREFIX_LENGTH )
23+ function valueOf ( domain : string , value : string ) : DomainAlias {
24+ const abbr = value . substr ( 0 , 1 )
25+
26+ return {
27+ domain,
28+ source : ABBR_MAP [ abbr ] ,
29+ name : value . substr ( 1 )
30+ }
31+ }
32+
33+ class DomainAliasDatabase extends BaseDatabase {
34+
35+ /**
36+ * Update the alias
37+ */
38+ async update ( toUpdate : DomainAlias ) : Promise < void > {
39+ const { domain, name, source } = toUpdate
40+ const key = generateKey ( domain )
41+ const value = SOURCE_PREFIX_MAP [ source ] + name
42+ if ( source === DomainSource . USER ) {
43+ // Force update
44+ return this . storage . put ( key , value )
45+ }
46+ const existVal = this . storage . getOne ( key )
47+ if ( ! existVal || typeof existVal !== 'string' ) {
48+ // Force update
49+ return this . storage . put ( key , value )
50+ }
51+ const abbr = ( existVal as string ) . substring ( 0 , 1 )
52+ if ( ABBR_MAP [ abbr ] === DomainSource . DETECTED ) {
53+ // Update
54+ return this . storage . put ( key , value )
55+ }
56+ }
57+
58+ async get ( ...domains : string [ ] ) : Promise < { [ host : string ] : DomainAlias } > {
59+ const keys = domains . map ( generateKey )
60+ const items = await this . storage . get ( keys )
61+ const result = { }
62+ Object . entries ( items ) . forEach ( ( [ key , value ] ) => {
63+ const domain = domainOf ( key )
64+ result [ domain ] = valueOf ( domain , value )
65+ } )
66+ return Promise . resolve ( result )
67+ }
68+
69+ async importData ( data : any ) : Promise < void > {
70+ const items = await this . storage . get ( )
71+ const toSave = { }
72+ Object . entries ( data )
73+ . filter ( ( [ key , value ] ) => key . startsWith ( DB_KEY_PREFIX ) && ! ! value && typeof value === 'string' )
74+ . forEach ( ( [ key , value ] ) => toSave [ key ] = this . migrate ( items [ key ] , value as string ) )
75+ await this . storage . set ( toSave )
76+ }
77+
78+ private migrate ( exist : string | undefined , toUpdate : string ) : string {
79+ if ( ! exist ) {
80+ return toUpdate
81+ }
82+ if ( exist . startsWith ( 'u' ) && ! toUpdate . startsWith ( 'u' ) ) {
83+ return exist
84+ }
85+ return toUpdate
86+ }
87+ }
88+
89+ export default DomainAliasDatabase
0 commit comments