@lodestar/db 1.35.0-dev.83de5b8dea → 1.35.0-dev.8689cc3545

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstractPrefixedRepository.d.ts","sourceRoot":"","sources":["../src/abstractPrefixedRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstractRepository.d.ts","sourceRoot":"","sources":["../src/abstractRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../src/const.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,gBAAgB,IAAgB,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/controller/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAC,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAC,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAC,wBAAwB,EAAC,MAAM,cAAc,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/controller/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,wBAAwB,EAAC,MAAM,cAAc,CAAC;AAEtD,uDAAuD;AACvD,MAAM,MAAM,EAAE,GAAG,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,EAAE,CAAC,EAAE,CAAC,CAAC;IACP,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,EAAE,CAAC,EAAE,CAAC,CAAC;IACP,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,kBAAkB;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,QAAQ,CAAC,CAAC,EAAE,CAAC;IAC5B,GAAG,EAAE,CAAC,CAAC;IACP,KAAK,EAAE,CAAC,CAAC;CACV;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,EAAE,CAAC;IAGtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB,iDAAiD;IACjD,UAAU,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAIpD,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAEhE,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAIhD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAIxD,UAAU,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IACtD,IAAI,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAE5C,YAAY,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAE9C,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;CAC7D"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"level.d.ts","sourceRoot":"","sources":["../../src/controller/level.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/controller/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE1D,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACrC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACvC,UAAU,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACtC,YAAY,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACxC,WAAW,EAAE,KAAK,CAAC;IACnB,qBAAqB,EAAE,SAAS,CAAC;CAClC,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,IAAI,CAAC;AAEzB;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAiBhG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAEhF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAE9D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE9D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodestar/db",
3
- "version": "1.35.0-dev.83de5b8dea",
3
+ "version": "1.35.0-dev.8689cc3545",
4
4
  "description": "DB modules of Lodestar",
5
5
  "author": "ChainSafe Systems",
6
6
  "homepage": "https://github.com/ChainSafe/lodestar#readme",
@@ -20,11 +20,9 @@
20
20
  },
21
21
  "types": "./lib/index.d.ts",
22
22
  "files": [
23
- "lib/**/*.d.ts",
24
- "lib/**/*.js",
25
- "lib/**/*.js.map",
26
- "*.d.ts",
27
- "*.js"
23
+ "src",
24
+ "lib",
25
+ "!**/*.tsbuildinfo"
28
26
  ],
29
27
  "scripts": {
30
28
  "clean": "rm -rf lib && rm -f *.tsbuildinfo",
@@ -42,13 +40,13 @@
42
40
  },
43
41
  "dependencies": {
44
42
  "@chainsafe/ssz": "^1.2.2",
45
- "@lodestar/config": "1.35.0-dev.83de5b8dea",
46
- "@lodestar/utils": "1.35.0-dev.83de5b8dea",
43
+ "@lodestar/config": "1.35.0-dev.8689cc3545",
44
+ "@lodestar/utils": "1.35.0-dev.8689cc3545",
47
45
  "classic-level": "^1.4.1",
48
46
  "it-all": "^3.0.4"
49
47
  },
50
48
  "devDependencies": {
51
- "@lodestar/logger": "1.35.0-dev.83de5b8dea"
49
+ "@lodestar/logger": "1.35.0-dev.8689cc3545"
52
50
  },
53
- "gitHead": "0d98b47561f58f1bc043a0546455518ca29750bf"
51
+ "gitHead": "449ee7fae124e34a70536ffec343c7447830e2e6"
54
52
  }
@@ -0,0 +1,244 @@
1
+ import {Type} from "@chainsafe/ssz";
2
+ import {ChainForkConfig} from "@lodestar/config";
3
+ import {BUCKET_LENGTH} from "./const.js";
4
+ import {KeyValue} from "./controller/index.js";
5
+ import {Db, DbReqOpts, FilterOptions} from "./controller/interface.js";
6
+ import {encodeKey} from "./util.js";
7
+
8
+ type Id = Uint8Array | string | number | bigint;
9
+
10
+ /**
11
+ * Repository is a high level kv storage
12
+ * This abstract repository is designed in a way to store items with different prefixed
13
+ * Specially when those prefixed data is not available in the object to be stored
14
+ *
15
+ * By default, SSZ-encoded values,
16
+ */
17
+ export abstract class PrefixedRepository<P, I extends Id, T> {
18
+ private readonly dbReqOpts: DbReqOpts;
19
+ /** Inclusive range for the minimum key for the bucket */
20
+ private readonly minKey: Uint8Array;
21
+ /** Exclusive range for the maximum key for the bucket */
22
+ private readonly maxKey: Uint8Array;
23
+
24
+ protected constructor(
25
+ protected config: ChainForkConfig,
26
+ protected db: Db,
27
+ protected bucket: number,
28
+ protected type: Type<T>,
29
+ private readonly bucketId: string
30
+ ) {
31
+ this.dbReqOpts = {bucketId: this.bucketId};
32
+ this.minKey = encodeKey(bucket, Buffer.alloc(0));
33
+ this.maxKey = encodeKey(bucket + 1, Buffer.alloc(0));
34
+ }
35
+
36
+ abstract encodeKeyRaw(prefix: P, id: I): Uint8Array;
37
+ abstract decodeKeyRaw(raw: Uint8Array): {prefix: P; id: I};
38
+ /**
39
+ * Max key is inclusive
40
+ * */
41
+ abstract getMaxKeyRaw(prefix: P): Uint8Array;
42
+ /**
43
+ * Min key is inclusive
44
+ * */
45
+ abstract getMinKeyRaw(prefix: P): Uint8Array;
46
+
47
+ protected encodeValue(value: T): Uint8Array {
48
+ return this.type.serialize(value);
49
+ }
50
+
51
+ protected decodeValue(data: Uint8Array): T {
52
+ return this.type.deserialize(data);
53
+ }
54
+
55
+ protected wrapKey(raw: Uint8Array): Uint8Array {
56
+ return encodeKey(this.bucket, raw);
57
+ }
58
+
59
+ protected unwrapKey(key: Uint8Array): Uint8Array {
60
+ return key.slice(BUCKET_LENGTH);
61
+ }
62
+
63
+ // The Id can be inferred from the value
64
+ getId(value: T): I {
65
+ return this.type.hashTreeRoot(value) as I;
66
+ }
67
+
68
+ async get(prefix: P, id: I): Promise<T | null> {
69
+ const key = this.wrapKey(this.encodeKeyRaw(prefix, id));
70
+ const v = await this.db.get(key, this.dbReqOpts);
71
+ return v ? this.decodeValue(v) : null;
72
+ }
73
+
74
+ async getMany(prefix: P, ids: I[]): Promise<(T | undefined)[]> {
75
+ const keys = [];
76
+ for (const id of ids) {
77
+ keys.push(this.wrapKey(this.encodeKeyRaw(prefix, id)));
78
+ }
79
+ const values = await this.db.getMany(keys, this.dbReqOpts);
80
+
81
+ const result = [];
82
+ for (const value of values) {
83
+ result.push(value ? this.decodeValue(value) : undefined);
84
+ }
85
+
86
+ return result;
87
+ }
88
+
89
+ async getManyBinary(prefix: P, ids: I[]): Promise<(Uint8Array | undefined)[]> {
90
+ const keys = [];
91
+ for (const id of ids) {
92
+ keys.push(this.wrapKey(this.encodeKeyRaw(prefix, id)));
93
+ }
94
+ return await this.db.getMany(keys, this.dbReqOpts);
95
+ }
96
+
97
+ async getBinary(prefix: P, id: I): Promise<Uint8Array | null> {
98
+ const key = this.wrapKey(this.encodeKeyRaw(prefix, id));
99
+ return await this.db.get(key, this.dbReqOpts);
100
+ }
101
+
102
+ async put(prefix: P, item: T): Promise<void> {
103
+ const id = this.getId(item);
104
+ const key = this.wrapKey(this.encodeKeyRaw(prefix, id));
105
+ await this.db.put(key, this.encodeValue(item), this.dbReqOpts);
106
+ }
107
+
108
+ async putMany(prefix: P, items: T[]): Promise<void> {
109
+ const batch: KeyValue<Uint8Array, Uint8Array>[] = [];
110
+ for (const item of items) {
111
+ const id = this.getId(item);
112
+ const key = this.wrapKey(this.encodeKeyRaw(prefix, id));
113
+ batch.push({key, value: this.encodeValue(item)});
114
+ }
115
+ await this.db.batchPut(batch, this.dbReqOpts);
116
+ }
117
+
118
+ async putBinary(prefix: P, id: I, bytes: Uint8Array): Promise<void> {
119
+ const key = this.wrapKey(this.encodeKeyRaw(prefix, id));
120
+ await this.db.put(key, bytes, this.dbReqOpts);
121
+ }
122
+
123
+ async putManyBinary(prefix: P, items: KeyValue<I, Uint8Array>[]): Promise<void> {
124
+ const batch: KeyValue<Uint8Array, Uint8Array>[] = [];
125
+ for (const {key, value} of items) {
126
+ batch.push({key: this.wrapKey(this.encodeKeyRaw(prefix, key)), value: value});
127
+ }
128
+ await this.db.batchPut(batch, this.dbReqOpts);
129
+ }
130
+
131
+ async delete(prefix: P, id: I): Promise<void> {
132
+ const key = this.wrapKey(this.encodeKeyRaw(prefix, id));
133
+ await this.db.delete(key, this.dbReqOpts);
134
+ }
135
+
136
+ async deleteMany(prefix: P | P[]): Promise<void> {
137
+ const keys: Uint8Array[][] = [];
138
+
139
+ for (const p of Array.isArray(prefix) ? prefix : [prefix]) {
140
+ const prefixedKeys = await this.db.keys({
141
+ gte: this.wrapKey(this.getMinKeyRaw(p)),
142
+ lte: this.wrapKey(this.getMaxKeyRaw(p)),
143
+ bucketId: this.bucketId,
144
+ });
145
+ keys.push(prefixedKeys);
146
+ }
147
+
148
+ await this.db.batchDelete(keys.flat(), this.dbReqOpts);
149
+ }
150
+
151
+ async *valuesStream(prefix: P | P[]): AsyncIterable<T> {
152
+ for (const p of Array.isArray(prefix) ? prefix : [prefix]) {
153
+ for await (const vb of this.db.valuesStream({
154
+ gte: this.wrapKey(this.getMinKeyRaw(p)),
155
+ lte: this.wrapKey(this.getMaxKeyRaw(p)),
156
+ bucketId: this.bucketId,
157
+ })) {
158
+ yield this.decodeValue(vb);
159
+ }
160
+ }
161
+ }
162
+
163
+ async *valuesStreamBinary(prefix: P | P[]): AsyncIterable<{prefix: P; id: I; value: Uint8Array}> {
164
+ for (const p of Array.isArray(prefix) ? prefix : [prefix]) {
165
+ for await (const {key, value} of this.db.entriesStream({
166
+ gte: this.wrapKey(this.getMinKeyRaw(p)),
167
+ lte: this.wrapKey(this.getMaxKeyRaw(p)),
168
+ bucketId: this.bucketId,
169
+ })) {
170
+ const {prefix, id} = this.decodeKeyRaw(this.unwrapKey(key));
171
+
172
+ yield {
173
+ prefix,
174
+ id,
175
+ value,
176
+ };
177
+ }
178
+ }
179
+ }
180
+
181
+ async *entriesStream(prefix: P | P[]): AsyncIterable<{prefix: P; id: I; value: T}> {
182
+ for (const v of Array.isArray(prefix) ? prefix : [prefix]) {
183
+ for await (const {key, value} of this.db.entriesStream({
184
+ gte: this.wrapKey(this.getMinKeyRaw(v)),
185
+ lte: this.wrapKey(this.getMaxKeyRaw(v)),
186
+ bucketId: this.bucketId,
187
+ })) {
188
+ const {prefix, id} = this.decodeKeyRaw(this.unwrapKey(key));
189
+
190
+ yield {
191
+ prefix,
192
+ id,
193
+ value: this.decodeValue(value),
194
+ };
195
+ }
196
+ }
197
+ }
198
+
199
+ async *entriesStreamBinary(prefix: P | P[]): AsyncIterable<{prefix: P; id: I; value: Uint8Array}> {
200
+ for (const v of Array.isArray(prefix) ? prefix : [prefix]) {
201
+ for await (const {key, value} of this.db.entriesStream({
202
+ gte: this.wrapKey(this.getMinKeyRaw(v)),
203
+ lte: this.wrapKey(this.getMaxKeyRaw(v)),
204
+ bucketId: this.bucketId,
205
+ })) {
206
+ const {prefix, id} = this.decodeKeyRaw(this.unwrapKey(key));
207
+
208
+ yield {
209
+ prefix,
210
+ id: id,
211
+ value,
212
+ };
213
+ }
214
+ }
215
+ }
216
+
217
+ async keys(opts?: FilterOptions<{prefix: P; id: I}>): Promise<{prefix: P; id: I}[]> {
218
+ const optsBuff: FilterOptions<Uint8Array> = {
219
+ bucketId: this.bucketId,
220
+ };
221
+
222
+ if (opts?.gte !== undefined) {
223
+ optsBuff.gte = this.wrapKey(this.encodeKeyRaw(opts.gte.prefix, opts.gte.id));
224
+ } else if (opts?.gt !== undefined) {
225
+ optsBuff.gt = this.wrapKey(this.encodeKeyRaw(opts.gt.prefix, opts.gt.id));
226
+ } else {
227
+ optsBuff.gte = this.minKey;
228
+ }
229
+
230
+ if (opts?.lte !== undefined) {
231
+ optsBuff.lte = this.wrapKey(this.encodeKeyRaw(opts.lte.prefix, opts.lte.id));
232
+ } else if (opts?.lt !== undefined) {
233
+ optsBuff.lt = this.wrapKey(this.encodeKeyRaw(opts.lt.prefix, opts.lt.id));
234
+ } else {
235
+ optsBuff.lt = this.maxKey;
236
+ }
237
+
238
+ if (opts?.reverse !== undefined) optsBuff.reverse = opts.reverse;
239
+ if (opts?.limit !== undefined) optsBuff.limit = opts.limit;
240
+
241
+ const data = await this.db.keys(optsBuff);
242
+ return (data ?? []).map((data) => this.decodeKeyRaw(this.unwrapKey(data)));
243
+ }
244
+ }
@@ -0,0 +1,283 @@
1
+ import {Type} from "@chainsafe/ssz";
2
+ import {ChainForkConfig} from "@lodestar/config";
3
+ import {BUCKET_LENGTH} from "./const.js";
4
+ import {FilterOptions, KeyValue} from "./controller/index.js";
5
+ import {Db, DbReqOpts} from "./controller/interface.js";
6
+ import {encodeKey as _encodeKey} from "./util.js";
7
+
8
+ export type Id = Uint8Array | string | number | bigint;
9
+
10
+ /**
11
+ * Repository is a high level kv storage
12
+ * managing a Uint8Array to Uint8Array kv database
13
+ * It translates typed keys and values to Uint8Arrays required by the underlying database
14
+ *
15
+ * By default, SSZ-encoded values,
16
+ * indexed by root
17
+ */
18
+ export abstract class Repository<I extends Id, T> {
19
+ private readonly dbReqOpts: DbReqOpts;
20
+
21
+ private readonly minKey: Uint8Array;
22
+ private readonly maxKey: Uint8Array;
23
+
24
+ protected constructor(
25
+ protected config: ChainForkConfig,
26
+ protected db: Db,
27
+ protected bucket: number,
28
+ protected type: Type<T>,
29
+ protected readonly bucketId: string
30
+ ) {
31
+ this.dbReqOpts = {bucketId: this.bucketId};
32
+ this.minKey = _encodeKey(bucket, Buffer.alloc(0));
33
+ this.maxKey = _encodeKey(bucket + 1, Buffer.alloc(0));
34
+ }
35
+
36
+ encodeValue(value: T): Uint8Array {
37
+ return this.type.serialize(value);
38
+ }
39
+
40
+ decodeValue(data: Uint8Array): T {
41
+ return this.type.deserialize(data);
42
+ }
43
+
44
+ encodeKey(id: I): Uint8Array {
45
+ return _encodeKey(this.bucket, id);
46
+ }
47
+
48
+ decodeKey(key: Uint8Array): I {
49
+ return key.slice(BUCKET_LENGTH) as I;
50
+ }
51
+
52
+ async get(id: I): Promise<T | null> {
53
+ const value = await this.db.get(this.encodeKey(id), this.dbReqOpts);
54
+ if (!value) return null;
55
+ return this.decodeValue(value);
56
+ }
57
+
58
+ async getBinary(id: I): Promise<Uint8Array | null> {
59
+ const value = await this.db.get(this.encodeKey(id), this.dbReqOpts);
60
+ if (!value) return null;
61
+ return value;
62
+ }
63
+
64
+ async has(id: I): Promise<boolean> {
65
+ return (await this.get(id)) !== null;
66
+ }
67
+
68
+ async put(id: I, value: T): Promise<void> {
69
+ await this.db.put(this.encodeKey(id), this.encodeValue(value), this.dbReqOpts);
70
+ }
71
+
72
+ async putBinary(id: I, value: Uint8Array): Promise<void> {
73
+ await this.db.put(this.encodeKey(id), value, this.dbReqOpts);
74
+ }
75
+
76
+ async delete(id: I): Promise<void> {
77
+ await this.db.delete(this.encodeKey(id), this.dbReqOpts);
78
+ }
79
+
80
+ // The Id can be inferred from the value
81
+ getId(value: T): I {
82
+ return this.type.hashTreeRoot(value) as I;
83
+ }
84
+
85
+ async add(value: T): Promise<void> {
86
+ await this.put(this.getId(value), value);
87
+ }
88
+
89
+ async remove(value: T): Promise<void> {
90
+ await this.delete(this.getId(value));
91
+ }
92
+
93
+ async batchPut(items: KeyValue<I, T>[]): Promise<void> {
94
+ if (items.length === 1) {
95
+ return this.put(items[0].key, items[0].value);
96
+ }
97
+
98
+ await this.db.batchPut(
99
+ Array.from({length: items.length}, (_, i) => ({
100
+ key: this.encodeKey(items[i].key),
101
+ value: this.encodeValue(items[i].value),
102
+ })),
103
+ this.dbReqOpts
104
+ );
105
+ }
106
+
107
+ // Similar to batchPut but we support value as Uint8Array
108
+ async batchPutBinary(items: KeyValue<I, Uint8Array>[]): Promise<void> {
109
+ if (items.length === 1) {
110
+ return this.db.put(this.encodeKey(items[0].key), items[0].value, this.dbReqOpts);
111
+ }
112
+
113
+ await this.db.batchPut(
114
+ Array.from({length: items.length}, (_, i) => ({
115
+ key: this.encodeKey(items[i].key),
116
+ value: items[i].value,
117
+ })),
118
+ this.dbReqOpts
119
+ );
120
+ }
121
+
122
+ async batchDelete(ids: I[]): Promise<void> {
123
+ if (ids.length === 1) {
124
+ return this.delete(ids[0]);
125
+ }
126
+
127
+ await this.db.batchDelete(
128
+ Array.from({length: ids.length}, (_, i) => this.encodeKey(ids[i])),
129
+ this.dbReqOpts
130
+ );
131
+ }
132
+
133
+ async batchAdd(values: T[]): Promise<void> {
134
+ // handle single value in batchPut
135
+ await this.batchPut(
136
+ Array.from({length: values.length}, (_, i) => ({
137
+ key: this.getId(values[i]),
138
+ value: values[i],
139
+ }))
140
+ );
141
+ }
142
+
143
+ async batchRemove(values: T[]): Promise<void> {
144
+ // handle single value in batchDelete
145
+ await this.batchDelete(Array.from({length: values.length}, (_ignored, i) => this.getId(values[i])));
146
+ }
147
+
148
+ async keys(opts?: FilterOptions<I>): Promise<I[]> {
149
+ const data = await this.db.keys(this.dbFilterOptions(opts));
150
+ return (data ?? []).map((data) => this.decodeKey(data));
151
+ }
152
+
153
+ async *keysStream(opts?: FilterOptions<I>): AsyncIterable<I> {
154
+ const keysStream = this.db.keysStream(this.dbFilterOptions(opts));
155
+ const decodeKey = this.decodeKey.bind(this);
156
+ for await (const key of keysStream) {
157
+ yield decodeKey(key);
158
+ }
159
+ }
160
+
161
+ async values(opts?: FilterOptions<I>): Promise<T[]> {
162
+ const data = await this.db.values(this.dbFilterOptions(opts));
163
+ return (data ?? []).map((data) => this.decodeValue(data));
164
+ }
165
+
166
+ async *valuesStream(opts?: FilterOptions<I>): AsyncIterable<T> {
167
+ const valuesStream = this.db.valuesStream(this.dbFilterOptions(opts));
168
+ const decodeValue = this.decodeValue.bind(this);
169
+ for await (const value of valuesStream) {
170
+ yield decodeValue(value);
171
+ }
172
+ }
173
+
174
+ async *binaryEntriesStream(opts?: FilterOptions<I>): AsyncIterable<KeyValue<Uint8Array, Uint8Array>> {
175
+ yield* this.db.entriesStream(this.dbFilterOptions(opts));
176
+ }
177
+
178
+ async entries(opts?: FilterOptions<I>): Promise<KeyValue<I, T>[]> {
179
+ const data = await this.db.entries(this.dbFilterOptions(opts));
180
+ return (data ?? []).map((data) => ({
181
+ key: this.decodeKey(data.key),
182
+ value: this.decodeValue(data.value),
183
+ }));
184
+ }
185
+
186
+ async *entriesStream(opts?: FilterOptions<I>): AsyncIterable<KeyValue<I, T>> {
187
+ const entriesStream = this.db.entriesStream(this.dbFilterOptions(opts));
188
+ const decodeKey = this.decodeKey.bind(this);
189
+ const decodeValue = this.decodeValue.bind(this);
190
+ for await (const entry of entriesStream) {
191
+ yield {
192
+ key: decodeKey(entry.key),
193
+ value: decodeValue(entry.value),
194
+ };
195
+ }
196
+ }
197
+
198
+ async firstKey(): Promise<I | null> {
199
+ // Metrics accounted in this.keys()
200
+ const keys = await this.keys({limit: 1, bucketId: this.bucketId});
201
+ if (!keys.length) {
202
+ return null;
203
+ }
204
+ return keys[0];
205
+ }
206
+
207
+ async lastKey(): Promise<I | null> {
208
+ // Metrics accounted in this.keys()
209
+ const keys = await this.keys({limit: 1, reverse: true, bucketId: this.bucketId});
210
+ if (!keys.length) {
211
+ return null;
212
+ }
213
+ return keys[0];
214
+ }
215
+
216
+ async firstValue(): Promise<T | null> {
217
+ // Metrics accounted in this.values()
218
+ const values = await this.values({limit: 1, bucketId: this.bucketId});
219
+ if (!values.length) {
220
+ return null;
221
+ }
222
+ return values[0];
223
+ }
224
+
225
+ async lastValue(): Promise<T | null> {
226
+ // Metrics accounted in this.values()
227
+ const values = await this.values({limit: 1, reverse: true, bucketId: this.bucketId});
228
+ if (!values.length) {
229
+ return null;
230
+ }
231
+ return values[0];
232
+ }
233
+
234
+ async firstEntry(): Promise<KeyValue<I, T> | null> {
235
+ // Metrics accounted in this.entries()
236
+ const entries = await this.entries({limit: 1, bucketId: this.bucketId});
237
+ if (!entries.length) {
238
+ return null;
239
+ }
240
+ return entries[0];
241
+ }
242
+
243
+ async lastEntry(): Promise<KeyValue<I, T> | null> {
244
+ // Metrics accounted in this.entries()
245
+ const entries = await this.entries({limit: 1, reverse: true, bucketId: this.bucketId});
246
+ if (!entries.length) {
247
+ return null;
248
+ }
249
+ return entries[0];
250
+ }
251
+
252
+ /**
253
+ * Transforms opts from I to Uint8Array
254
+ */
255
+ protected dbFilterOptions(opts?: FilterOptions<I>): FilterOptions<Uint8Array> {
256
+ const optsBuff: FilterOptions<Uint8Array> = {
257
+ bucketId: this.bucketId,
258
+ };
259
+
260
+ // Set at least one min key
261
+ if (opts?.lt !== undefined) {
262
+ optsBuff.lt = this.encodeKey(opts.lt);
263
+ } else if (opts?.lte !== undefined) {
264
+ optsBuff.lte = this.encodeKey(opts.lte);
265
+ } else {
266
+ optsBuff.lt = this.maxKey;
267
+ }
268
+
269
+ // Set at least on max key
270
+ if (opts?.gt !== undefined) {
271
+ optsBuff.gt = this.encodeKey(opts.gt);
272
+ } else if (opts?.gte !== undefined) {
273
+ optsBuff.gte = this.encodeKey(opts.gte);
274
+ } else {
275
+ optsBuff.gte = this.minKey;
276
+ }
277
+
278
+ if (opts?.reverse !== undefined) optsBuff.reverse = opts.reverse;
279
+ if (opts?.limit !== undefined) optsBuff.limit = opts.limit;
280
+
281
+ return optsBuff;
282
+ }
283
+ }
package/src/const.ts ADDED
@@ -0,0 +1,2 @@
1
+ export const BUCKET_LENGTH = 1;
2
+ export const DB_PREFIX_LENGTH = BUCKET_LENGTH;
@@ -0,0 +1,3 @@
1
+ export type {DatabaseController, Db, DbReqOpts, FilterOptions, KeyValue} from "./interface.js";
2
+ export {LevelDbController} from "./level.js";
3
+ export type {LevelDbControllerMetrics} from "./metrics.js";
@@ -0,0 +1,62 @@
1
+ import {LevelDbControllerMetrics} from "./metrics.js";
2
+
3
+ /** Shortcut for Uint8Array based DatabaseController */
4
+ export type Db = DatabaseController<Uint8Array, Uint8Array>;
5
+
6
+ export type DatabaseOptions = {
7
+ name: string;
8
+ };
9
+
10
+ export interface FilterOptions<K> {
11
+ gt?: K;
12
+ gte?: K;
13
+ lt?: K;
14
+ lte?: K;
15
+ reverse?: boolean;
16
+ limit?: number;
17
+ /** For metrics */
18
+ bucketId?: string;
19
+ }
20
+
21
+ export type DbReqOpts = {
22
+ /** For metrics */
23
+ bucketId?: string;
24
+ };
25
+
26
+ export interface KeyValue<K, V> {
27
+ key: K;
28
+ value: V;
29
+ }
30
+
31
+ export interface DatabaseController<K, V> {
32
+ // service start / stop
33
+
34
+ close(): Promise<void>;
35
+
36
+ /** To inject metrics after CLI initialization */
37
+ setMetrics(metrics: LevelDbControllerMetrics): void;
38
+
39
+ // Core API
40
+
41
+ get(key: K, opts?: DbReqOpts): Promise<V | null>;
42
+ getMany(key: K[], opts?: DbReqOpts): Promise<(V | undefined)[]>;
43
+
44
+ put(key: K, value: V, opts?: DbReqOpts): Promise<void>;
45
+ delete(key: K, opts?: DbReqOpts): Promise<void>;
46
+
47
+ // Batch operations
48
+
49
+ batchPut(items: KeyValue<K, V>[], opts?: DbReqOpts): Promise<void>;
50
+ batchDelete(keys: K[], opts?: DbReqOpts): Promise<void>;
51
+
52
+ // Iterate over entries
53
+
54
+ keysStream(opts?: FilterOptions<K>): AsyncIterable<K>;
55
+ keys(opts?: FilterOptions<K>): Promise<K[]>;
56
+
57
+ valuesStream(opts?: FilterOptions<K>): AsyncIterable<V>;
58
+ values(opts?: FilterOptions<K>): Promise<V[]>;
59
+
60
+ entriesStream(opts?: FilterOptions<K>): AsyncIterable<KeyValue<K, V>>;
61
+ entries(opts?: FilterOptions<K>): Promise<KeyValue<K, V>[]>;
62
+ }
@@ -0,0 +1,246 @@
1
+ import {ClassicLevel} from "classic-level";
2
+ import {Logger} from "@lodestar/utils";
3
+ import {DatabaseController, DatabaseOptions, DbReqOpts, FilterOptions, KeyValue} from "./interface.js";
4
+ import {LevelDbControllerMetrics} from "./metrics.js";
5
+
6
+ enum Status {
7
+ started = "started",
8
+ closed = "closed",
9
+ }
10
+
11
+ export interface LevelDBOptions extends DatabaseOptions {
12
+ db?: ClassicLevel<Uint8Array, Uint8Array>;
13
+ }
14
+
15
+ export type LevelDbControllerModules = {
16
+ logger: Logger;
17
+ metrics?: LevelDbControllerMetrics | null;
18
+ };
19
+
20
+ const BUCKET_ID_UNKNOWN = "unknown";
21
+
22
+ /** Time between capturing metric for db size, every few minutes is sufficient */
23
+ const DB_SIZE_METRIC_INTERVAL_MS = 5 * 60 * 1000;
24
+
25
+ /**
26
+ * The LevelDB implementation of DB
27
+ */
28
+ export class LevelDbController implements DatabaseController<Uint8Array, Uint8Array> {
29
+ private status = Status.started;
30
+
31
+ private dbSizeMetricInterval?: NodeJS.Timeout;
32
+
33
+ constructor(
34
+ private readonly logger: Logger,
35
+ private readonly db: ClassicLevel<Uint8Array, Uint8Array>,
36
+ private metrics: LevelDbControllerMetrics | null
37
+ ) {
38
+ this.metrics = metrics ?? null;
39
+
40
+ if (this.metrics) {
41
+ this.collectDbSizeMetric();
42
+ }
43
+ }
44
+
45
+ static async create(opts: LevelDBOptions, {metrics, logger}: LevelDbControllerModules): Promise<LevelDbController> {
46
+ const db =
47
+ opts.db ||
48
+ new ClassicLevel(opts.name || "beaconchain", {
49
+ keyEncoding: "binary",
50
+ valueEncoding: "binary",
51
+ multithreading: true,
52
+ });
53
+
54
+ try {
55
+ await db.open();
56
+ } catch (e) {
57
+ if ((e as LevelDbError).cause?.code === "LEVEL_LOCKED") {
58
+ throw new Error("Database already in use by another process");
59
+ }
60
+ throw e;
61
+ }
62
+
63
+ return new LevelDbController(logger, db, metrics ?? null);
64
+ }
65
+
66
+ async close(): Promise<void> {
67
+ if (this.status === Status.closed) return;
68
+ this.status = Status.closed;
69
+
70
+ if (this.dbSizeMetricInterval) {
71
+ clearInterval(this.dbSizeMetricInterval);
72
+ }
73
+
74
+ await this.db.close();
75
+ }
76
+
77
+ /** To inject metrics after CLI initialization */
78
+ setMetrics(metrics: LevelDbControllerMetrics): void {
79
+ if (this.metrics !== null) {
80
+ throw Error("metrics can only be set once");
81
+ }
82
+
83
+ this.metrics = metrics;
84
+ if (this.status === Status.started) {
85
+ this.collectDbSizeMetric();
86
+ }
87
+ }
88
+
89
+ async clear(): Promise<void> {
90
+ await this.db.clear();
91
+ }
92
+
93
+ async get(key: Uint8Array, opts?: DbReqOpts): Promise<Uint8Array | null> {
94
+ try {
95
+ this.metrics?.dbReadReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
96
+ this.metrics?.dbReadItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
97
+ return (await this.db.get(key)) as Uint8Array | null;
98
+ } catch (e) {
99
+ if ((e as LevelDbError).code === "LEVEL_NOT_FOUND") {
100
+ return null;
101
+ }
102
+ throw e;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Return the multiple items in the order of the given keys
108
+ * Will return `null` for the keys which does not exists
109
+ *
110
+ * https://github.com/Level/abstract-level?tab=readme-ov-file#dbgetmanykeys-options
111
+ */
112
+ async getMany(keys: Uint8Array[], opts?: DbReqOpts): Promise<(Uint8Array | undefined)[]> {
113
+ this.metrics?.dbReadReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
114
+ this.metrics?.dbReadItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, keys.length);
115
+ return await this.db.getMany(keys);
116
+ }
117
+
118
+ put(key: Uint8Array, value: Uint8Array, opts?: DbReqOpts): Promise<void> {
119
+ this.metrics?.dbWriteReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
120
+ this.metrics?.dbWriteItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
121
+
122
+ return this.db.put(key, value);
123
+ }
124
+
125
+ delete(key: Uint8Array, opts?: DbReqOpts): Promise<void> {
126
+ this.metrics?.dbWriteReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
127
+ this.metrics?.dbWriteItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
128
+
129
+ return this.db.del(key);
130
+ }
131
+
132
+ batchPut(items: KeyValue<Uint8Array, Uint8Array>[], opts?: DbReqOpts): Promise<void> {
133
+ this.metrics?.dbWriteReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
134
+ this.metrics?.dbWriteItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, items.length);
135
+
136
+ return this.db.batch(items.map((item) => ({type: "put", key: item.key, value: item.value})));
137
+ }
138
+
139
+ batchDelete(keys: Uint8Array[], opts?: DbReqOpts): Promise<void> {
140
+ this.metrics?.dbWriteReq.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, 1);
141
+ this.metrics?.dbWriteItems.inc({bucket: opts?.bucketId ?? BUCKET_ID_UNKNOWN}, keys.length);
142
+
143
+ return this.db.batch(keys.map((key) => ({type: "del", key: key})));
144
+ }
145
+
146
+ keysStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<Uint8Array> {
147
+ return this.metricsIterator(this.db.keys(opts), (key) => key, opts.bucketId ?? BUCKET_ID_UNKNOWN);
148
+ }
149
+
150
+ valuesStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<Uint8Array> {
151
+ return this.metricsIterator(this.db.values(opts), (value) => value, opts.bucketId ?? BUCKET_ID_UNKNOWN);
152
+ }
153
+
154
+ entriesStream(opts: FilterOptions<Uint8Array> = {}): AsyncIterable<KeyValue<Uint8Array, Uint8Array>> {
155
+ return this.metricsIterator(
156
+ this.db.iterator(opts),
157
+ (entry) => ({key: entry[0], value: entry[1]}),
158
+ opts.bucketId ?? BUCKET_ID_UNKNOWN
159
+ );
160
+ }
161
+
162
+ keys(opts: FilterOptions<Uint8Array> = {}): Promise<Uint8Array[]> {
163
+ return this.metricsAll(this.db.keys(opts).all(), opts.bucketId ?? BUCKET_ID_UNKNOWN);
164
+ }
165
+
166
+ values(opts: FilterOptions<Uint8Array> = {}): Promise<Uint8Array[]> {
167
+ return this.metricsAll(this.db.values(opts).all(), opts.bucketId ?? BUCKET_ID_UNKNOWN);
168
+ }
169
+
170
+ async entries(opts: FilterOptions<Uint8Array> = {}): Promise<KeyValue<Uint8Array, Uint8Array>[]> {
171
+ const entries = await this.metricsAll(this.db.iterator(opts).all(), opts.bucketId ?? BUCKET_ID_UNKNOWN);
172
+ return entries.map((entry) => ({key: entry[0], value: entry[1]}));
173
+ }
174
+
175
+ /**
176
+ * Get the approximate number of bytes of file system space used by the range [start..end).
177
+ * The result might not include recently written data.
178
+ */
179
+ approximateSize(start: Uint8Array, end: Uint8Array): Promise<number> {
180
+ return this.db.approximateSize(start, end);
181
+ }
182
+
183
+ /**
184
+ * Manually trigger a database compaction in the range [start..end].
185
+ */
186
+ compactRange(start: Uint8Array, end: Uint8Array): Promise<void> {
187
+ return this.db.compactRange(start, end);
188
+ }
189
+
190
+ /** Capture metrics for db.iterator, db.keys, db.values .all() calls */
191
+ private async metricsAll<T>(promise: Promise<T[]>, bucket: string): Promise<T[]> {
192
+ this.metrics?.dbReadReq.inc({bucket}, 1);
193
+ const items = await promise;
194
+ this.metrics?.dbReadItems.inc({bucket}, items.length);
195
+ return items;
196
+ }
197
+
198
+ /** Capture metrics for db.iterator, db.keys, db.values AsyncIterable calls */
199
+ private async *metricsIterator<T, K>(
200
+ iterator: AsyncIterable<T>,
201
+ getValue: (item: T) => K,
202
+ bucket: string
203
+ ): AsyncIterable<K> {
204
+ this.metrics?.dbReadReq.inc({bucket}, 1);
205
+
206
+ let itemsRead = 0;
207
+
208
+ for await (const item of iterator) {
209
+ // Count metrics after done condition
210
+ itemsRead++;
211
+
212
+ yield getValue(item);
213
+ }
214
+
215
+ this.metrics?.dbReadItems.inc({bucket}, itemsRead);
216
+ }
217
+
218
+ /** Start interval to capture metric for db size */
219
+ private collectDbSizeMetric(): void {
220
+ this.dbSizeMetric();
221
+ this.dbSizeMetricInterval = setInterval(this.dbSizeMetric.bind(this), DB_SIZE_METRIC_INTERVAL_MS);
222
+ }
223
+
224
+ /** Capture metric for db size */
225
+ private dbSizeMetric(): void {
226
+ const timer = this.metrics?.dbApproximateSizeTime.startTimer();
227
+ const minKey = Buffer.from([0x00]);
228
+ const maxKey = Buffer.from([0xff]);
229
+
230
+ this.approximateSize(minKey, maxKey)
231
+ .then((dbSize) => {
232
+ this.metrics?.dbSizeTotal.set(dbSize);
233
+ })
234
+ .catch((e) => {
235
+ this.logger.debug("Error approximating db size", {}, e);
236
+ })
237
+ .finally(timer);
238
+ }
239
+
240
+ static async destroy(location: string): Promise<void> {
241
+ return ClassicLevel.destroy(location);
242
+ }
243
+ }
244
+
245
+ /** From https://www.npmjs.com/package/level */
246
+ type LevelDbError = {code: "LEVEL_NOT_FOUND"; cause?: {code: "LEVEL_LOCKED"}};
@@ -0,0 +1,10 @@
1
+ import {Counter, Gauge, Histogram} from "@lodestar/utils";
2
+
3
+ export type LevelDbControllerMetrics = {
4
+ dbReadReq: Counter<{bucket: string}>;
5
+ dbReadItems: Counter<{bucket: string}>;
6
+ dbWriteReq: Counter<{bucket: string}>;
7
+ dbWriteItems: Counter<{bucket: string}>;
8
+ dbSizeTotal: Gauge;
9
+ dbApproximateSizeTime: Histogram;
10
+ };
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./abstractPrefixedRepository.js";
2
+ export * from "./abstractRepository.js";
3
+ export * from "./const.js";
4
+ export * from "./controller/index.js";
5
+ export * from "./util.js";
package/src/util.ts ADDED
@@ -0,0 +1,50 @@
1
+ import {bytesToInt, intToBytes} from "@lodestar/utils";
2
+ import {BUCKET_LENGTH} from "./const.js";
3
+
4
+ export const uintLen = 8;
5
+
6
+ /**
7
+ * Encode a key for the db write/read, Prepend a bucket to a key
8
+ *
9
+ * The encoding of key is very important step that can cause failure of proper indexing and querying of data
10
+ *
11
+ * We are using LevelDB which have pluggable comparator support, so you can decide how to
12
+ * compare keys. But for NodeJS binding only default comparison algorithm is supported which
13
+ * uses lexicographical comparison of the raw bytes of the keys
14
+ *
15
+ * It is important to use **helpers implemented here** to encode db keys so that key comparison properly work.
16
+ */
17
+ export function encodeKey(bucket: number, key: Uint8Array | string | number | bigint): Uint8Array {
18
+ let buf: Buffer;
19
+ const prefixLength = BUCKET_LENGTH;
20
+ //all keys are writen with prefixLength offet
21
+ if (typeof key === "string") {
22
+ buf = Buffer.alloc(key.length + prefixLength);
23
+ buf.write(key, prefixLength);
24
+ } else if (typeof key === "number" || typeof key === "bigint") {
25
+ buf = Buffer.alloc(uintLen + prefixLength);
26
+ intToBytes(BigInt(key), uintLen, "be").copy(buf, prefixLength);
27
+ } else {
28
+ buf = Buffer.alloc(key.length + prefixLength);
29
+ buf.set(key, prefixLength);
30
+ }
31
+ //bucket prefix on position 0
32
+ buf.set(intToBytes(bucket, BUCKET_LENGTH, "le"), 0);
33
+ return buf;
34
+ }
35
+
36
+ export function encodeNumberForDbKey(value: number, byteSize: number): Uint8Array {
37
+ return intToBytes(value, byteSize, "be");
38
+ }
39
+
40
+ export function decodeNumberForDbKey(value: Uint8Array, byteSize: number): number {
41
+ return bytesToInt(value.slice(0, byteSize), "be");
42
+ }
43
+
44
+ export function encodeStringForDbKey(value: string): Uint8Array {
45
+ return Buffer.from(value, "utf-8");
46
+ }
47
+
48
+ export function decodeStringForDbKey(value: Uint8Array): string {
49
+ return Buffer.from(value).toString("utf8");
50
+ }