1
- import { Key } from 'interface-datastore'
1
+ import { Batch , Key , KeyQuery , Pair , Query } from 'interface-datastore'
2
2
import { BaseDatastore , Errors } from 'datastore-core'
3
3
import filter from 'it-filter'
4
4
import map from 'it-map'
5
5
import take from 'it-take'
6
6
import sort from 'it-sort'
7
7
import { Level } from 'level'
8
+ import type { DatabaseOptions , OpenOptions , IteratorOptions } from 'level'
8
9
9
- /**
10
- * @typedef {import('interface-datastore').Datastore } Datastore
11
- * @typedef {import('interface-datastore').Pair } Pair
12
- * @typedef {import('interface-datastore').Batch } Batch
13
- * @typedef {import('interface-datastore').Query } Query
14
- * @typedef {import('interface-datastore').KeyQuery } KeyQuery
15
- * @typedef {import('interface-datastore').Options } QueryOptions
16
- * @typedef {import('abstract-level').AbstractLevel<any, string, Uint8Array> } LevelDb
17
- */
10
+ interface BatchPut {
11
+ type : 'put'
12
+ key : string
13
+ value : Uint8Array
14
+ }
15
+
16
+ interface BatchDel {
17
+ type : 'del'
18
+ key : string
19
+ }
20
+
21
+ type BatchOp = BatchPut | BatchDel
18
22
19
23
/**
20
24
* A datastore backed by leveldb
21
25
*/
22
26
export class LevelDatastore extends BaseDatastore {
23
- /**
24
- * @param {string | LevelDb } path
25
- * @param {import('level').DatabaseOptions<string, Uint8Array> & import('level').OpenOptions } [opts]
26
- */
27
- constructor ( path , opts = { } ) {
27
+ public db : Level < string , Uint8Array >
28
+ private readonly opts : OpenOptions
29
+
30
+ constructor ( path : string | Level < string , Uint8Array > , opts : DatabaseOptions < string , Uint8Array > & OpenOptions = { } ) {
28
31
super ( )
29
32
30
- /** @type {LevelDb } */
31
33
this . db = typeof path === 'string'
32
34
? new Level ( path , {
33
35
...opts ,
@@ -36,91 +38,77 @@ export class LevelDatastore extends BaseDatastore {
36
38
} )
37
39
: path
38
40
39
- /** @type {import('level').OpenOptions } */
40
41
this . opts = {
41
42
createIfMissing : true ,
42
43
compression : false , // same default as go
43
44
...opts
44
45
}
45
46
}
46
47
47
- async open ( ) {
48
+ async open ( ) : Promise < void > {
48
49
try {
49
50
await this . db . open ( this . opts )
50
- } catch ( /** @type { any } */ err ) {
51
+ } catch ( err : any ) {
51
52
throw Errors . dbOpenFailedError ( err )
52
53
}
53
54
}
54
55
55
- /**
56
- * @param {Key } key
57
- * @param {Uint8Array } value
58
- */
59
- async put ( key , value ) {
56
+ async put ( key : Key , value : Uint8Array ) : Promise < void > {
60
57
try {
61
58
await this . db . put ( key . toString ( ) , value )
62
- } catch ( /** @type { any } */ err ) {
59
+ } catch ( err : any ) {
63
60
throw Errors . dbWriteFailedError ( err )
64
61
}
65
62
}
66
63
67
- /**
68
- * @param {Key } key
69
- * @returns {Promise<Uint8Array> }
70
- */
71
- async get ( key ) {
64
+ async get ( key : Key ) : Promise < Uint8Array > {
72
65
let data
73
66
try {
74
67
data = await this . db . get ( key . toString ( ) )
75
- } catch ( /** @type {any } */ err ) {
76
- if ( err . notFound ) throw Errors . notFoundError ( err )
68
+ } catch ( err : any ) {
69
+ if ( err . notFound != null ) {
70
+ throw Errors . notFoundError ( err )
71
+ }
72
+
77
73
throw Errors . dbWriteFailedError ( err )
78
74
}
79
75
return data
80
76
}
81
77
82
- /**
83
- * @param {Key } key
84
- * @returns {Promise<boolean> }
85
- */
86
- async has ( key ) {
78
+ async has ( key : Key ) : Promise < boolean > {
87
79
try {
88
80
await this . db . get ( key . toString ( ) )
89
- } catch ( /** @type {any } */ err ) {
90
- if ( err . notFound ) return false
81
+ } catch ( err : any ) {
82
+ if ( err . notFound != null ) {
83
+ return false
84
+ }
85
+
91
86
throw err
92
87
}
93
88
return true
94
89
}
95
90
96
- /**
97
- * @param {Key } key
98
- * @returns {Promise<void> }
99
- */
100
- async delete ( key ) {
91
+ async delete ( key : Key ) : Promise < void > {
101
92
try {
102
93
await this . db . del ( key . toString ( ) )
103
- } catch ( /** @type { any } */ err ) {
94
+ } catch ( err : any ) {
104
95
throw Errors . dbDeleteFailedError ( err )
105
96
}
106
97
}
107
98
108
- close ( ) {
109
- return this . db && this . db . close ( )
99
+ async close ( ) : Promise < void > {
100
+ await this . db . close ( )
110
101
}
111
102
112
- /**
113
- * @returns {Batch }
114
- */
115
- batch ( ) {
116
- /** @type {Array<{ type: 'put', key: string, value: Uint8Array; } | { type: 'del', key: string }> } */
117
- const ops = [ ]
103
+ batch ( ) : Batch {
104
+ const ops : BatchOp [ ] = [ ]
105
+
118
106
return {
119
107
put : ( key , value ) => {
120
108
ops . push ( {
121
109
type : 'put' ,
122
110
key : key . toString ( ) ,
123
- value : value
111
+ value
124
112
} )
125
113
} ,
126
114
delete : ( key ) => {
@@ -129,16 +117,17 @@ export class LevelDatastore extends BaseDatastore {
129
117
key : key . toString ( )
130
118
} )
131
119
} ,
132
- commit : ( ) => {
133
- return this . db . batch ( ops )
120
+ commit : async ( ) => {
121
+ if ( this . db . batch == null ) {
122
+ throw new Error ( 'Batch operations unsupported by underlying Level' )
123
+ }
124
+
125
+ await this . db . batch ( ops )
134
126
}
135
127
}
136
128
}
137
129
138
- /**
139
- * @param {Query } q
140
- */
141
- query ( q ) {
130
+ query ( q : Query ) : AsyncIterable < Pair > {
142
131
let it = this . _query ( {
143
132
values : true ,
144
133
prefix : q . prefix
@@ -153,22 +142,19 @@ export class LevelDatastore extends BaseDatastore {
153
142
}
154
143
155
144
const { offset, limit } = q
156
- if ( offset ) {
145
+ if ( offset != null ) {
157
146
let i = 0
158
147
it = filter ( it , ( ) => i ++ >= offset )
159
148
}
160
149
161
- if ( limit ) {
150
+ if ( limit != null ) {
162
151
it = take ( it , limit )
163
152
}
164
153
165
154
return it
166
155
}
167
156
168
- /**
169
- * @param {KeyQuery } q
170
- */
171
- queryKeys ( q ) {
157
+ queryKeys ( q : KeyQuery ) : AsyncIterable < Key > {
172
158
let it = map ( this . _query ( {
173
159
values : false ,
174
160
prefix : q . prefix
@@ -183,27 +169,20 @@ export class LevelDatastore extends BaseDatastore {
183
169
}
184
170
185
171
const { offset, limit } = q
186
- if ( offset ) {
172
+ if ( offset != null ) {
187
173
let i = 0
188
174
it = filter ( it , ( ) => i ++ >= offset )
189
175
}
190
176
191
- if ( limit ) {
177
+ if ( limit != null ) {
192
178
it = take ( it , limit )
193
179
}
194
180
195
181
return it
196
182
}
197
183
198
- /**
199
- * @param {object } opts
200
- * @param {boolean } opts.values
201
- * @param {string } [opts.prefix]
202
- * @returns {AsyncIterable<Pair> }
203
- */
204
- _query ( opts ) {
205
- /** @type {import('level').IteratorOptions<string, Uint8Array> } */
206
- const iteratorOpts = {
184
+ _query ( opts : { values : boolean , prefix ?: string } ) : AsyncIterable < Pair > {
185
+ const iteratorOpts : IteratorOptions < string , Uint8Array > = {
207
186
keys : true ,
208
187
keyEncoding : 'buffer' ,
209
188
values : opts . values
@@ -220,7 +199,7 @@ export class LevelDatastore extends BaseDatastore {
220
199
221
200
const iterator = this . db . iterator ( iteratorOpts )
222
201
223
- if ( iterator [ Symbol . asyncIterator ] ) {
202
+ if ( iterator [ Symbol . asyncIterator ] != null ) {
224
203
return levelIteratorToIterator ( iterator )
225
204
}
226
205
@@ -234,47 +213,45 @@ export class LevelDatastore extends BaseDatastore {
234
213
}
235
214
}
236
215
237
- /**
238
- * @param {import('level').Iterator<LevelDb, string, Uint8Array> } li - Level iterator
239
- * @returns {AsyncIterable<Pair> }
240
- */
241
- async function * levelIteratorToIterator ( li ) {
216
+ async function * levelIteratorToIterator ( li : AsyncIterable < [ string , Uint8Array ] > & { close : ( ) => Promise < void > } ) : AsyncIterable < Pair > {
242
217
for await ( const [ key , value ] of li ) {
243
218
yield { key : new Key ( key , false ) , value }
244
219
}
245
220
246
221
await li . close ( )
247
222
}
248
223
249
- /**
250
- * @typedef {object } LevelIterator
251
- * @property {(cb: (err: Error, key: string | Uint8Array | null, value: any)=> void)=>void } next
252
- * @property {(cb: (err: Error) => void) => void } end
253
- */
224
+ interface OldLevelIterator {
225
+ next : ( cb : ( err : Error , key : string | Uint8Array | null , value : any ) => void ) => void
226
+ end : ( cb : ( err : Error ) => void ) => void
227
+ }
254
228
255
- /**
256
- * @param {LevelIterator } li - Level iterator
257
- * @returns {AsyncIterable<Pair> }
258
- */
259
- function oldLevelIteratorToIterator ( li ) {
229
+ function oldLevelIteratorToIterator ( li : OldLevelIterator ) : AsyncIterable < Pair > {
260
230
return {
261
231
[ Symbol . asyncIterator ] ( ) {
262
232
return {
263
- next : ( ) => new Promise ( ( resolve , reject ) => {
233
+ next : async ( ) => await new Promise ( ( resolve , reject ) => {
264
234
li . next ( ( err , key , value ) => {
265
- if ( err ) return reject ( err )
235
+ if ( err != null ) {
236
+ reject ( err ) ; return
237
+ }
266
238
if ( key == null ) {
267
- return li . end ( err => {
268
- if ( err ) return reject ( err )
239
+ li . end ( err => {
240
+ if ( err != null ) {
241
+ reject ( err )
242
+ return
243
+ }
269
244
resolve ( { done : true , value : undefined } )
270
- } )
245
+ } ) ; return
271
246
}
272
247
resolve ( { done : false , value : { key : new Key ( key , false ) , value } } )
273
248
} )
274
249
} ) ,
275
- return : ( ) => new Promise ( ( resolve , reject ) => {
250
+ return : async ( ) => await new Promise ( ( resolve , reject ) => {
276
251
li . end ( err => {
277
- if ( err ) return reject ( err )
252
+ if ( err != null ) {
253
+ reject ( err ) ; return
254
+ }
278
255
resolve ( { done : true , value : undefined } )
279
256
} )
280
257
} )
0 commit comments