-
Notifications
You must be signed in to change notification settings - Fork 16
/
base.ts
144 lines (118 loc) · 3.64 KB
/
base.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
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
142
143
144
import drain from 'it-drain'
import filter from 'it-filter'
import sort from 'it-sort'
import take from 'it-take'
import type { Batch, Datastore, Key, KeyQuery, Pair, Query } from 'interface-datastore'
import type { AbortOptions, Await, AwaitIterable } from 'interface-store'
export class BaseDatastore implements Datastore {
put (key: Key, val: Uint8Array, options?: AbortOptions): Await<Key> {
return Promise.reject(new Error('.put is not implemented'))
}
get (key: Key, options?: AbortOptions): Await<Uint8Array> {
return Promise.reject(new Error('.get is not implemented'))
}
has (key: Key, options?: AbortOptions): Await<boolean> {
return Promise.reject(new Error('.has is not implemented'))
}
delete (key: Key, options?: AbortOptions): Await<void> {
return Promise.reject(new Error('.delete is not implemented'))
}
async * putMany (source: AwaitIterable<Pair>, options: AbortOptions = {}): AwaitIterable<Key> {
for await (const { key, value } of source) {
await this.put(key, value, options)
yield key
}
}
async * getMany (source: AwaitIterable<Key>, options: AbortOptions = {}): AwaitIterable<Pair> {
for await (const key of source) {
yield {
key,
value: await this.get(key, options)
}
}
}
async * deleteMany (source: AwaitIterable<Key>, options: AbortOptions = {}): AwaitIterable<Key> {
for await (const key of source) {
await this.delete(key, options)
yield key
}
}
batch (): Batch {
let puts: Pair[] = []
let dels: Key[] = []
return {
put (key, value) {
puts.push({ key, value })
},
delete (key) {
dels.push(key)
},
commit: async (options) => {
await drain(this.putMany(puts, options))
puts = []
await drain(this.deleteMany(dels, options))
dels = []
}
}
}
/**
* Extending classes should override `query` or implement this method
*/
// eslint-disable-next-line require-yield
async * _all (q: Query, options?: AbortOptions): AwaitIterable<Pair> {
throw new Error('._all is not implemented')
}
/**
* Extending classes should override `queryKeys` or implement this method
*/
// eslint-disable-next-line require-yield
async * _allKeys (q: KeyQuery, options?: AbortOptions): AwaitIterable<Key> {
throw new Error('._allKeys is not implemented')
}
query (q: Query, options?: AbortOptions): AwaitIterable<Pair> {
let it = this._all(q, options)
if (q.prefix != null) {
const prefix = q.prefix
it = filter(it, (e) => e.key.toString().startsWith(prefix))
}
if (Array.isArray(q.filters)) {
it = q.filters.reduce((it, f) => filter(it, f), it)
}
if (Array.isArray(q.orders)) {
it = q.orders.reduce((it, f) => sort(it, f), it)
}
if (q.offset != null) {
let i = 0
const offset = q.offset
it = filter(it, () => i++ >= offset)
}
if (q.limit != null) {
it = take(it, q.limit)
}
return it
}
queryKeys (q: KeyQuery, options?: AbortOptions): AwaitIterable<Key> {
let it = this._allKeys(q, options)
if (q.prefix != null) {
const prefix = q.prefix
it = filter(it, (key) =>
key.toString().startsWith(prefix)
)
}
if (Array.isArray(q.filters)) {
it = q.filters.reduce((it, f) => filter(it, f), it)
}
if (Array.isArray(q.orders)) {
it = q.orders.reduce((it, f) => sort(it, f), it)
}
if (q.offset != null) {
const offset = q.offset
let i = 0
it = filter(it, () => i++ >= offset)
}
if (q.limit != null) {
it = take(it, q.limit)
}
return it
}
}