@aztec-labs/kv-store 6.0.0-nightly.20260829
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.
- package/README.md +19 -0
- package/dest/bench/shared_map_bench.d.ts +19 -0
- package/dest/bench/shared_map_bench.d.ts.map +1 -0
- package/dest/bench/shared_map_bench.js +91 -0
- package/dest/deprecated/indexeddb/array.d.ts +22 -0
- package/dest/deprecated/indexeddb/array.d.ts.map +1 -0
- package/dest/deprecated/indexeddb/array.js +121 -0
- package/dest/deprecated/indexeddb/index.d.ts +7 -0
- package/dest/deprecated/indexeddb/index.d.ts.map +1 -0
- package/dest/deprecated/indexeddb/index.js +8 -0
- package/dest/deprecated/indexeddb/map.d.ts +38 -0
- package/dest/deprecated/indexeddb/map.d.ts.map +1 -0
- package/dest/deprecated/indexeddb/map.js +121 -0
- package/dest/deprecated/indexeddb/multi_map.d.ts +14 -0
- package/dest/deprecated/indexeddb/multi_map.d.ts.map +1 -0
- package/dest/deprecated/indexeddb/multi_map.js +108 -0
- package/dest/deprecated/indexeddb/set.d.ts +17 -0
- package/dest/deprecated/indexeddb/set.d.ts.map +1 -0
- package/dest/deprecated/indexeddb/set.js +24 -0
- package/dest/deprecated/indexeddb/singleton.d.ts +17 -0
- package/dest/deprecated/indexeddb/singleton.d.ts.map +1 -0
- package/dest/deprecated/indexeddb/singleton.js +41 -0
- package/dest/deprecated/indexeddb/store.d.ts +98 -0
- package/dest/deprecated/indexeddb/store.d.ts.map +1 -0
- package/dest/deprecated/indexeddb/store.js +171 -0
- package/dest/interfaces/array.d.ts +81 -0
- package/dest/interfaces/array.d.ts.map +1 -0
- package/dest/interfaces/array.js +1 -0
- package/dest/interfaces/array_test_suite.d.ts +3 -0
- package/dest/interfaces/array_test_suite.d.ts.map +1 -0
- package/dest/interfaces/array_test_suite.js +103 -0
- package/dest/interfaces/common.d.ts +25 -0
- package/dest/interfaces/common.d.ts.map +1 -0
- package/dest/interfaces/common.js +8 -0
- package/dest/interfaces/counter.d.ts +59 -0
- package/dest/interfaces/counter.d.ts.map +1 -0
- package/dest/interfaces/counter.js +1 -0
- package/dest/interfaces/index.d.ts +10 -0
- package/dest/interfaces/index.d.ts.map +1 -0
- package/dest/interfaces/index.js +8 -0
- package/dest/interfaces/map.d.ts +106 -0
- package/dest/interfaces/map.d.ts.map +1 -0
- package/dest/interfaces/map.js +3 -0
- package/dest/interfaces/map_test_suite.d.ts +3 -0
- package/dest/interfaces/map_test_suite.d.ts.map +1 -0
- package/dest/interfaces/map_test_suite.js +261 -0
- package/dest/interfaces/multi_map.d.ts +41 -0
- package/dest/interfaces/multi_map.d.ts.map +1 -0
- package/dest/interfaces/multi_map.js +3 -0
- package/dest/interfaces/multi_map_test_suite.d.ts +3 -0
- package/dest/interfaces/multi_map_test_suite.d.ts.map +1 -0
- package/dest/interfaces/multi_map_test_suite.js +363 -0
- package/dest/interfaces/set.d.ts +44 -0
- package/dest/interfaces/set.d.ts.map +1 -0
- package/dest/interfaces/set.js +1 -0
- package/dest/interfaces/set_test_suite.d.ts +3 -0
- package/dest/interfaces/set_test_suite.d.ts.map +1 -0
- package/dest/interfaces/set_test_suite.js +95 -0
- package/dest/interfaces/singleton.d.ts +29 -0
- package/dest/interfaces/singleton.d.ts.map +1 -0
- package/dest/interfaces/singleton.js +4 -0
- package/dest/interfaces/singleton_test_suite.d.ts +3 -0
- package/dest/interfaces/singleton_test_suite.d.ts.map +1 -0
- package/dest/interfaces/singleton_test_suite.js +29 -0
- package/dest/interfaces/store.d.ts +120 -0
- package/dest/interfaces/store.d.ts.map +1 -0
- package/dest/interfaces/store.js +1 -0
- package/dest/interfaces/utils.d.ts +18 -0
- package/dest/interfaces/utils.d.ts.map +1 -0
- package/dest/interfaces/utils.js +18 -0
- package/dest/lmdb/array.d.ts +24 -0
- package/dest/lmdb/array.d.ts.map +1 -0
- package/dest/lmdb/array.js +119 -0
- package/dest/lmdb/counter.d.ts +19 -0
- package/dest/lmdb/counter.d.ts.map +1 -0
- package/dest/lmdb/counter.js +50 -0
- package/dest/lmdb/index.d.ts +12 -0
- package/dest/lmdb/index.d.ts.map +1 -0
- package/dest/lmdb/index.js +25 -0
- package/dest/lmdb/map.d.ts +40 -0
- package/dest/lmdb/map.d.ts.map +1 -0
- package/dest/lmdb/map.js +156 -0
- package/dest/lmdb/multi_map.d.ts +13 -0
- package/dest/lmdb/multi_map.d.ts.map +1 -0
- package/dest/lmdb/multi_map.js +44 -0
- package/dest/lmdb/set.d.ts +18 -0
- package/dest/lmdb/set.d.ts.map +1 -0
- package/dest/lmdb/set.js +32 -0
- package/dest/lmdb/singleton.d.ts +14 -0
- package/dest/lmdb/singleton.d.ts.map +1 -0
- package/dest/lmdb/singleton.js +26 -0
- package/dest/lmdb/store.d.ts +94 -0
- package/dest/lmdb/store.d.ts.map +1 -0
- package/dest/lmdb/store.js +200 -0
- package/dest/lmdb-v2/array.d.ts +19 -0
- package/dest/lmdb-v2/array.d.ts.map +1 -0
- package/dest/lmdb-v2/array.js +103 -0
- package/dest/lmdb-v2/factory.d.ts +35 -0
- package/dest/lmdb-v2/factory.d.ts.map +1 -0
- package/dest/lmdb-v2/factory.js +126 -0
- package/dest/lmdb-v2/index.d.ts +3 -0
- package/dest/lmdb-v2/index.d.ts.map +1 -0
- package/dest/lmdb-v2/index.js +2 -0
- package/dest/lmdb-v2/map.d.ts +53 -0
- package/dest/lmdb-v2/map.d.ts.map +1 -0
- package/dest/lmdb-v2/map.js +106 -0
- package/dest/lmdb-v2/message.d.ts +131 -0
- package/dest/lmdb-v2/message.d.ts.map +1 -0
- package/dest/lmdb-v2/message.js +20 -0
- package/dest/lmdb-v2/multi_map.d.ts +52 -0
- package/dest/lmdb-v2/multi_map.d.ts.map +1 -0
- package/dest/lmdb-v2/multi_map.js +123 -0
- package/dest/lmdb-v2/read_transaction.d.ts +16 -0
- package/dest/lmdb-v2/read_transaction.d.ts.map +1 -0
- package/dest/lmdb-v2/read_transaction.js +137 -0
- package/dest/lmdb-v2/set.d.ts +15 -0
- package/dest/lmdb-v2/set.d.ts.map +1 -0
- package/dest/lmdb-v2/set.js +23 -0
- package/dest/lmdb-v2/singleton.d.ts +12 -0
- package/dest/lmdb-v2/singleton.d.ts.map +1 -0
- package/dest/lmdb-v2/singleton.js +31 -0
- package/dest/lmdb-v2/store.d.ts +43 -0
- package/dest/lmdb-v2/store.d.ts.map +1 -0
- package/dest/lmdb-v2/store.js +171 -0
- package/dest/lmdb-v2/tx-helpers.d.ts +6 -0
- package/dest/lmdb-v2/tx-helpers.d.ts.map +1 -0
- package/dest/lmdb-v2/tx-helpers.js +21 -0
- package/dest/lmdb-v2/utils.d.ts +8 -0
- package/dest/lmdb-v2/utils.d.ts.map +1 -0
- package/dest/lmdb-v2/utils.js +32 -0
- package/dest/lmdb-v2/write_transaction.d.ts +17 -0
- package/dest/lmdb-v2/write_transaction.d.ts.map +1 -0
- package/dest/lmdb-v2/write_transaction.js +258 -0
- package/dest/sqlite-opfs/array.d.ts +21 -0
- package/dest/sqlite-opfs/array.d.ts.map +1 -0
- package/dest/sqlite-opfs/array.js +128 -0
- package/dest/sqlite-opfs/errors.d.ts +54 -0
- package/dest/sqlite-opfs/errors.d.ts.map +1 -0
- package/dest/sqlite-opfs/errors.js +77 -0
- package/dest/sqlite-opfs/index.d.ts +14 -0
- package/dest/sqlite-opfs/index.d.ts.map +1 -0
- package/dest/sqlite-opfs/index.js +16 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.d.ts +32 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.d.ts.map +1 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.js +448 -0
- package/dest/sqlite-opfs/manage.d.ts +22 -0
- package/dest/sqlite-opfs/manage.d.ts.map +1 -0
- package/dest/sqlite-opfs/manage.js +38 -0
- package/dest/sqlite-opfs/map.d.ts +35 -0
- package/dest/sqlite-opfs/map.d.ts.map +1 -0
- package/dest/sqlite-opfs/map.js +163 -0
- package/dest/sqlite-opfs/messages.d.ts +66 -0
- package/dest/sqlite-opfs/messages.d.ts.map +1 -0
- package/dest/sqlite-opfs/messages.js +5 -0
- package/dest/sqlite-opfs/multi_map.d.ts +16 -0
- package/dest/sqlite-opfs/multi_map.d.ts.map +1 -0
- package/dest/sqlite-opfs/multi_map.js +67 -0
- package/dest/sqlite-opfs/pool_integrity.d.ts +20 -0
- package/dest/sqlite-opfs/pool_integrity.d.ts.map +1 -0
- package/dest/sqlite-opfs/pool_integrity.js +282 -0
- package/dest/sqlite-opfs/pool_lock.d.ts +8 -0
- package/dest/sqlite-opfs/pool_lock.d.ts.map +1 -0
- package/dest/sqlite-opfs/pool_lock.js +47 -0
- package/dest/sqlite-opfs/set.d.ts +13 -0
- package/dest/sqlite-opfs/set.d.ts.map +1 -0
- package/dest/sqlite-opfs/set.js +19 -0
- package/dest/sqlite-opfs/singleton.d.ts +13 -0
- package/dest/sqlite-opfs/singleton.d.ts.map +1 -0
- package/dest/sqlite-opfs/singleton.js +48 -0
- package/dest/sqlite-opfs/store.d.ts +84 -0
- package/dest/sqlite-opfs/store.d.ts.map +1 -0
- package/dest/sqlite-opfs/store.js +318 -0
- package/dest/sqlite-opfs/worker.d.ts +2 -0
- package/dest/sqlite-opfs/worker.d.ts.map +1 -0
- package/dest/sqlite-opfs/worker.js +275 -0
- package/dest/stores/index.d.ts +3 -0
- package/dest/stores/index.d.ts.map +1 -0
- package/dest/stores/index.js +2 -0
- package/dest/stores/l2_tips_store.d.ts +23 -0
- package/dest/stores/l2_tips_store.d.ts.map +1 -0
- package/dest/stores/l2_tips_store.js +64 -0
- package/dest/utils.d.ts +15 -0
- package/dest/utils.d.ts.map +1 -0
- package/dest/utils.js +59 -0
- package/package.json +108 -0
- package/src/bench/shared_map_bench.ts +111 -0
- package/src/deprecated/indexeddb/array.ts +122 -0
- package/src/deprecated/indexeddb/index.ts +12 -0
- package/src/deprecated/indexeddb/map.ts +137 -0
- package/src/deprecated/indexeddb/multi_map.ts +106 -0
- package/src/deprecated/indexeddb/set.ts +37 -0
- package/src/deprecated/indexeddb/singleton.ts +52 -0
- package/src/deprecated/indexeddb/store.ts +214 -0
- package/src/interfaces/array.ts +92 -0
- package/src/interfaces/array_test_suite.ts +128 -0
- package/src/interfaces/common.ts +31 -0
- package/src/interfaces/counter.ts +65 -0
- package/src/interfaces/index.ts +9 -0
- package/src/interfaces/map.ts +117 -0
- package/src/interfaces/map_test_suite.ts +198 -0
- package/src/interfaces/multi_map.ts +45 -0
- package/src/interfaces/multi_map_test_suite.ts +372 -0
- package/src/interfaces/set.ts +48 -0
- package/src/interfaces/set_test_suite.ts +79 -0
- package/src/interfaces/singleton.ts +29 -0
- package/src/interfaces/singleton_test_suite.ts +44 -0
- package/src/interfaces/store.ts +142 -0
- package/src/interfaces/utils.ts +23 -0
- package/src/lmdb/array.ts +140 -0
- package/src/lmdb/counter.ts +67 -0
- package/src/lmdb/index.ts +41 -0
- package/src/lmdb/map.ts +177 -0
- package/src/lmdb/multi_map.ts +51 -0
- package/src/lmdb/set.ts +45 -0
- package/src/lmdb/singleton.ts +35 -0
- package/src/lmdb/store.ts +242 -0
- package/src/lmdb-v2/array.ts +120 -0
- package/src/lmdb-v2/factory.ts +184 -0
- package/src/lmdb-v2/index.ts +2 -0
- package/src/lmdb-v2/map.ts +136 -0
- package/src/lmdb-v2/message.ts +169 -0
- package/src/lmdb-v2/multi_map.ts +150 -0
- package/src/lmdb-v2/read_transaction.ts +156 -0
- package/src/lmdb-v2/set.ts +33 -0
- package/src/lmdb-v2/singleton.ts +38 -0
- package/src/lmdb-v2/store.ts +220 -0
- package/src/lmdb-v2/tx-helpers.ts +29 -0
- package/src/lmdb-v2/utils.ts +32 -0
- package/src/lmdb-v2/write_transaction.ts +315 -0
- package/src/sqlite-opfs/array.ts +124 -0
- package/src/sqlite-opfs/errors.ts +94 -0
- package/src/sqlite-opfs/index.ts +27 -0
- package/src/sqlite-opfs/internal/ordered-binary-browser.js +465 -0
- package/src/sqlite-opfs/manage.ts +46 -0
- package/src/sqlite-opfs/map.ts +163 -0
- package/src/sqlite-opfs/messages.ts +39 -0
- package/src/sqlite-opfs/multi_map.ts +74 -0
- package/src/sqlite-opfs/pool_integrity.ts +327 -0
- package/src/sqlite-opfs/pool_lock.ts +62 -0
- package/src/sqlite-opfs/set.ts +29 -0
- package/src/sqlite-opfs/singleton.ts +48 -0
- package/src/sqlite-opfs/store.ts +331 -0
- package/src/sqlite-opfs/worker.ts +259 -0
- package/src/stores/index.ts +3 -0
- package/src/stores/l2_tips_store.ts +67 -0
- package/src/utils.ts +98 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { toArray } from '@aztec-labs/foundation/iterable';
|
|
2
|
+
|
|
3
|
+
import type { Range } from './common.js';
|
|
4
|
+
import type { AztecAsyncSet, AztecSet } from './set.js';
|
|
5
|
+
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
6
|
+
import { isSyncStore } from './utils.js';
|
|
7
|
+
|
|
8
|
+
export function describeAztecSet(
|
|
9
|
+
testName: string,
|
|
10
|
+
getStore: () => AztecKVStore | Promise<AztecAsyncKVStore>,
|
|
11
|
+
forceAsync: boolean = false,
|
|
12
|
+
) {
|
|
13
|
+
describe(testName, () => {
|
|
14
|
+
let store: AztecKVStore | AztecAsyncKVStore;
|
|
15
|
+
let set: AztecSet<string> | AztecAsyncSet<string>;
|
|
16
|
+
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
store = await getStore();
|
|
19
|
+
set = store.openSet<string>('test');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(async () => {
|
|
23
|
+
await store.delete();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
async function has(key: string) {
|
|
27
|
+
return isSyncStore(store) && !forceAsync
|
|
28
|
+
? (set as AztecSet<string>).has(key)
|
|
29
|
+
: await (set as AztecAsyncSet<string>).hasAsync(key);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function entries(range?: Range<any>) {
|
|
33
|
+
return isSyncStore(store) && !forceAsync
|
|
34
|
+
? await toArray((set as AztecSet<string>).entries(range))
|
|
35
|
+
: await toArray((set as AztecAsyncSet<string>).entriesAsync(range));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
it('should be able to set and get values', async () => {
|
|
39
|
+
await set.add('foo');
|
|
40
|
+
await set.add('baz');
|
|
41
|
+
|
|
42
|
+
expect(await has('foo')).toBe(true);
|
|
43
|
+
expect(await has('baz')).toBe(true);
|
|
44
|
+
expect(await has('bar')).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should be able to delete values', async () => {
|
|
48
|
+
await set.add('foo');
|
|
49
|
+
await set.add('baz');
|
|
50
|
+
|
|
51
|
+
await set.delete('foo');
|
|
52
|
+
|
|
53
|
+
expect(await has('foo')).toBe(false);
|
|
54
|
+
expect(await has('baz')).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should be able to iterate over entries', async () => {
|
|
58
|
+
await set.add('baz');
|
|
59
|
+
await set.add('foo');
|
|
60
|
+
|
|
61
|
+
expect(await entries()).toEqual(['baz', 'foo']);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('supports range queries', async () => {
|
|
65
|
+
await set.add('a');
|
|
66
|
+
await set.add('b');
|
|
67
|
+
await set.add('c');
|
|
68
|
+
await set.add('d');
|
|
69
|
+
|
|
70
|
+
expect(await entries({ start: 'b', end: 'c' })).toEqual(['b']);
|
|
71
|
+
expect(await entries({ start: 'b' })).toEqual(['b', 'c', 'd']);
|
|
72
|
+
expect(await entries({ end: 'c' })).toEqual(['a', 'b']);
|
|
73
|
+
expect(await entries({ start: 'b', end: 'c', reverse: true })).toEqual(['c']);
|
|
74
|
+
expect(await entries({ start: 'b', limit: 1 })).toEqual(['b']);
|
|
75
|
+
expect(await entries({ start: 'b', reverse: true })).toEqual(['d', 'c']);
|
|
76
|
+
expect(await entries({ end: 'b', reverse: true })).toEqual(['b', 'a']);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a singleton value in the database.
|
|
3
|
+
* Note: The singleton loses type info so it's recommended to serialize to buffer when storing it.
|
|
4
|
+
*/
|
|
5
|
+
interface AztecBaseSingleton<T> {
|
|
6
|
+
/**
|
|
7
|
+
* Sets the value.
|
|
8
|
+
* @param val - The new value
|
|
9
|
+
*/
|
|
10
|
+
set(val: T): Promise<boolean>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Deletes the value.
|
|
14
|
+
*/
|
|
15
|
+
delete(): Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
export interface AztecSingleton<T> extends AztecBaseSingleton<T> {
|
|
18
|
+
/**
|
|
19
|
+
* Gets the value.
|
|
20
|
+
*/
|
|
21
|
+
get(): T | undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AztecAsyncSingleton<T> extends AztecBaseSingleton<T> {
|
|
25
|
+
/**
|
|
26
|
+
* Gets the value.
|
|
27
|
+
*/
|
|
28
|
+
getAsync(): Promise<T | undefined>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AztecAsyncSingleton, AztecSingleton } from './singleton.js';
|
|
2
|
+
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
3
|
+
import { isSyncStore } from './utils.js';
|
|
4
|
+
|
|
5
|
+
export function describeAztecSingleton(
|
|
6
|
+
testName: string,
|
|
7
|
+
getStore: () => AztecKVStore | Promise<AztecAsyncKVStore>,
|
|
8
|
+
forceAsync: boolean = false,
|
|
9
|
+
) {
|
|
10
|
+
describe(testName, () => {
|
|
11
|
+
let store: AztecKVStore | AztecAsyncKVStore;
|
|
12
|
+
let singleton: AztecSingleton<string> | AztecAsyncSingleton<string>;
|
|
13
|
+
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
store = await getStore();
|
|
16
|
+
singleton = store.openSingleton<string>('test');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(async () => {
|
|
20
|
+
await store.delete();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
async function get() {
|
|
24
|
+
return isSyncStore(store) && !forceAsync
|
|
25
|
+
? (singleton as AztecSingleton<string>).get()
|
|
26
|
+
: await (singleton as AztecAsyncSingleton<string>).getAsync();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
it('returns undefined if the value is not set', async () => {
|
|
30
|
+
expect(await get()).toBe(undefined);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should be able to set and get values', async () => {
|
|
34
|
+
expect(await singleton.set('foo')).toBe(true);
|
|
35
|
+
expect(await get()).toBe('foo');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('overwrites the value if it is set again', async () => {
|
|
39
|
+
expect(await singleton.set('foo')).toBe(true);
|
|
40
|
+
expect(await singleton.set('bar')).toBe(true);
|
|
41
|
+
expect(await get()).toBe('bar');
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { AztecArray, AztecAsyncArray } from './array.js';
|
|
2
|
+
import type { Key, StoreSize, Value } from './common.js';
|
|
3
|
+
import type { AztecAsyncCounter, AztecCounter } from './counter.js';
|
|
4
|
+
import type { AztecAsyncMap, AztecMap } from './map.js';
|
|
5
|
+
import type { AztecAsyncMultiMap, AztecMultiMap } from './multi_map.js';
|
|
6
|
+
import type { AztecAsyncSet, AztecSet } from './set.js';
|
|
7
|
+
import type { AztecAsyncSingleton, AztecSingleton } from './singleton.js';
|
|
8
|
+
|
|
9
|
+
/** A key-value store */
|
|
10
|
+
export interface AztecKVStore {
|
|
11
|
+
syncGetters: true;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new map.
|
|
14
|
+
* @param name - The name of the map
|
|
15
|
+
* @returns The map
|
|
16
|
+
*/
|
|
17
|
+
openMap<K extends Key, V extends Value>(name: string): AztecMap<K, V>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new set.
|
|
21
|
+
* @param name - The name of the set
|
|
22
|
+
* @returns The set
|
|
23
|
+
*/
|
|
24
|
+
openSet<K extends Key>(name: string): AztecSet<K>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new multi-map.
|
|
28
|
+
* @param name - The name of the multi-map
|
|
29
|
+
* @returns The multi-map
|
|
30
|
+
*/
|
|
31
|
+
openMultiMap<K extends Key, V extends Value>(name: string): AztecMultiMap<K, V>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new array.
|
|
35
|
+
* @param name - The name of the array
|
|
36
|
+
* @returns The array
|
|
37
|
+
*/
|
|
38
|
+
openArray<T extends Value>(name: string): AztecArray<T>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new singleton.
|
|
42
|
+
* @param name - The name of the singleton
|
|
43
|
+
* @returns The singleton
|
|
44
|
+
*/
|
|
45
|
+
openSingleton<T extends Value>(name: string): AztecSingleton<T>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new count map.
|
|
49
|
+
* @param name - name of the counter
|
|
50
|
+
*/
|
|
51
|
+
openCounter<K extends Key>(name: string): AztecCounter<K>;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Starts a transaction. All calls to read/write data while in a transaction are queued and executed atomically.
|
|
55
|
+
* @param callback - The callback to execute in a transaction
|
|
56
|
+
*/
|
|
57
|
+
transaction<T extends Exclude<any, Promise<any>>>(callback: () => T): Promise<T>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Clears all entries in the store
|
|
61
|
+
*/
|
|
62
|
+
clear(): Promise<void>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Deletes the store
|
|
66
|
+
*/
|
|
67
|
+
delete(): Promise<void>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Estimates the size of the store in bytes.
|
|
71
|
+
*/
|
|
72
|
+
estimateSize(): Promise<StoreSize>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Closes the store
|
|
76
|
+
*/
|
|
77
|
+
close(): Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface AztecAsyncKVStore {
|
|
81
|
+
/**
|
|
82
|
+
* Creates a new map.
|
|
83
|
+
* @param name - The name of the map
|
|
84
|
+
* @returns The map
|
|
85
|
+
*/
|
|
86
|
+
openMap<K extends Key, V extends Value>(name: string): AztecAsyncMap<K, V>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Creates a new set.
|
|
90
|
+
* @param name - The name of the set
|
|
91
|
+
* @returns The set
|
|
92
|
+
*/
|
|
93
|
+
openSet<K extends Key>(name: string): AztecAsyncSet<K>;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Creates a new multi-map.
|
|
97
|
+
* @param name - The name of the multi-map
|
|
98
|
+
* @returns The multi-map
|
|
99
|
+
*/
|
|
100
|
+
openMultiMap<K extends Key, V extends Value>(name: string): AztecAsyncMultiMap<K, V>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Creates a new array.
|
|
104
|
+
* @param name - The name of the array
|
|
105
|
+
* @returns The array
|
|
106
|
+
*/
|
|
107
|
+
openArray<T extends Value>(name: string): AztecAsyncArray<T>;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Creates a new singleton.
|
|
111
|
+
* @param name - The name of the singleton
|
|
112
|
+
* @returns The singleton
|
|
113
|
+
*/
|
|
114
|
+
openSingleton<T extends Value>(name: string): AztecAsyncSingleton<T>;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Creates a new count map.
|
|
118
|
+
* @param name - name of the counter
|
|
119
|
+
*/
|
|
120
|
+
openCounter<K extends Key>(name: string): AztecAsyncCounter<K>;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Starts a transaction. All calls to read/write data while in a transaction are queued and executed atomically.
|
|
124
|
+
* @param callback - The callback to execute in a transaction
|
|
125
|
+
*/
|
|
126
|
+
transactionAsync<T extends Exclude<any, Promise<any>>>(callback: () => Promise<T>): Promise<T>;
|
|
127
|
+
|
|
128
|
+
/** Clears all entries in the store */
|
|
129
|
+
clear(): Promise<void>;
|
|
130
|
+
|
|
131
|
+
/** Deletes the store */
|
|
132
|
+
delete(): Promise<void>;
|
|
133
|
+
|
|
134
|
+
/** Estimates the size of the store in bytes. */
|
|
135
|
+
estimateSize(): Promise<StoreSize>;
|
|
136
|
+
|
|
137
|
+
/** Closes the store */
|
|
138
|
+
close(): Promise<void>;
|
|
139
|
+
|
|
140
|
+
/** Backups the store to the target folder.*/
|
|
141
|
+
backupTo(dstPath: string, compact?: boolean): Promise<void>;
|
|
142
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
export const mockLogger = {
|
|
5
|
+
debug: (msg: string, data: any) => console.log(msg, data),
|
|
6
|
+
info: (msg: string, data: any) => console.log(msg, data),
|
|
7
|
+
warn: (msg: string, data: any) => console.log(msg, data),
|
|
8
|
+
error: (msg: string, data: any) => console.error(msg, data),
|
|
9
|
+
fatal: (msg: string, data: any) => console.error(msg, data),
|
|
10
|
+
silent: (_msg: string, _data: any) => {},
|
|
11
|
+
verbose: (msg: string, data: any) => console.log(msg, data),
|
|
12
|
+
trace: (msg: string, data: any) => console.log(msg, data),
|
|
13
|
+
level: 'trace' as const,
|
|
14
|
+
isLevelEnabled: (_level: string) => true,
|
|
15
|
+
module: 'kv-store:mock-logger',
|
|
16
|
+
createChild: () => mockLogger,
|
|
17
|
+
getBindings: () => ({}),
|
|
18
|
+
};
|
|
19
|
+
/* eslint-enable no-console */
|
|
20
|
+
|
|
21
|
+
export function isSyncStore(store: AztecKVStore | AztecAsyncKVStore): store is AztecAsyncKVStore {
|
|
22
|
+
return (store as AztecKVStore).syncGetters === true;
|
|
23
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { Database, Key } from 'lmdb';
|
|
2
|
+
|
|
3
|
+
import type { AztecArray, AztecAsyncArray } from '../interfaces/array.js';
|
|
4
|
+
import type { Value } from '../interfaces/common.js';
|
|
5
|
+
import { LmdbAztecSingleton } from './singleton.js';
|
|
6
|
+
|
|
7
|
+
/** The shape of a key that stores a value in an array */
|
|
8
|
+
type ArrayIndexSlot = ['array', string, 'slot', number];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* An persistent array backed by LMDB.
|
|
12
|
+
*/
|
|
13
|
+
export class LmdbAztecArray<T extends Value> implements AztecArray<T>, AztecAsyncArray<T> {
|
|
14
|
+
#db: Database<T, ArrayIndexSlot>;
|
|
15
|
+
#name: string;
|
|
16
|
+
#length: LmdbAztecSingleton<number>;
|
|
17
|
+
|
|
18
|
+
constructor(db: Database<unknown, Key>, arrName: string) {
|
|
19
|
+
this.#name = arrName;
|
|
20
|
+
this.#length = new LmdbAztecSingleton(db, `${arrName}:meta:length`);
|
|
21
|
+
this.#db = db as Database<T, ArrayIndexSlot>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get length(): number {
|
|
25
|
+
return this.#length.get() ?? 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
lengthAsync(): Promise<number> {
|
|
29
|
+
return Promise.resolve(this.length);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
push(...vals: T[]): Promise<number> {
|
|
33
|
+
return this.#db.childTransaction(() => {
|
|
34
|
+
let length = this.length;
|
|
35
|
+
for (const val of vals) {
|
|
36
|
+
void this.#db.put(this.#slot(length), val);
|
|
37
|
+
length += 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void this.#length.set(length);
|
|
41
|
+
|
|
42
|
+
return length;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
pop(): Promise<T | undefined> {
|
|
47
|
+
return this.#db.childTransaction(() => {
|
|
48
|
+
const length = this.length;
|
|
49
|
+
if (length === 0) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const slot = this.#slot(length - 1);
|
|
54
|
+
const val = this.#db.get(slot) as T;
|
|
55
|
+
|
|
56
|
+
void this.#db.remove(slot);
|
|
57
|
+
void this.#length.set(length - 1);
|
|
58
|
+
|
|
59
|
+
return val;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
at(index: number): T | undefined {
|
|
64
|
+
if (index < 0) {
|
|
65
|
+
index = this.length + index;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// the Array API only accepts indexes in the range [-this.length, this.length)
|
|
69
|
+
// so if after normalizing the index is still out of range, return undefined
|
|
70
|
+
if (index < 0 || index >= this.length) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return this.#db.get(this.#slot(index));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
atAsync(index: number): Promise<T | undefined> {
|
|
78
|
+
return Promise.resolve(this.at(index));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
setAt(index: number, val: T): Promise<boolean> {
|
|
82
|
+
if (index < 0) {
|
|
83
|
+
index = this.length + index;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (index < 0 || index >= this.length) {
|
|
87
|
+
return Promise.resolve(false);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return this.#db.put(this.#slot(index), val);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
*entries(): IterableIterator<[number, T]> {
|
|
94
|
+
const transaction = this.#db.useReadTransaction();
|
|
95
|
+
try {
|
|
96
|
+
const values = this.#db.getRange({
|
|
97
|
+
start: this.#slot(0),
|
|
98
|
+
limit: this.length,
|
|
99
|
+
transaction,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
for (const { key, value } of values) {
|
|
103
|
+
const index = key[3];
|
|
104
|
+
yield [index, value];
|
|
105
|
+
}
|
|
106
|
+
} finally {
|
|
107
|
+
transaction.done();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async *entriesAsync(): AsyncIterableIterator<[number, T]> {
|
|
112
|
+
for (const [key, value] of this.entries()) {
|
|
113
|
+
yield [key, value];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
*values(): IterableIterator<T> {
|
|
118
|
+
for (const [_, value] of this.entries()) {
|
|
119
|
+
yield value;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async *valuesAsync(): AsyncIterableIterator<T> {
|
|
124
|
+
for (const [_, value] of this.entries()) {
|
|
125
|
+
yield value;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
[Symbol.iterator](): IterableIterator<T> {
|
|
130
|
+
return this.values();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<T> {
|
|
134
|
+
return this.valuesAsync();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#slot(index: number): ArrayIndexSlot {
|
|
138
|
+
return ['array', this.#name, 'slot', index];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Key as BaseKey, Database } from 'lmdb';
|
|
2
|
+
|
|
3
|
+
import type { Key, Range } from '../interfaces/common.js';
|
|
4
|
+
import type { AztecAsyncCounter, AztecCounter } from '../interfaces/counter.js';
|
|
5
|
+
import { LmdbAztecMap } from './map.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A counter implementation backed by LMDB
|
|
9
|
+
*/
|
|
10
|
+
export class LmdbAztecCounter<K extends Key> implements AztecCounter<K>, AztecAsyncCounter<K> {
|
|
11
|
+
#db: Database;
|
|
12
|
+
#name: string;
|
|
13
|
+
#map: LmdbAztecMap<K, number>;
|
|
14
|
+
|
|
15
|
+
constructor(db: Database<unknown, BaseKey>, name: string) {
|
|
16
|
+
this.#db = db;
|
|
17
|
+
this.#name = name;
|
|
18
|
+
this.#map = new LmdbAztecMap(db, name);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async set(key: K, value: number): Promise<void> {
|
|
22
|
+
await this.#map.set(key, value);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
update(key: K, delta = 1): Promise<void> {
|
|
26
|
+
return this.#db.childTransaction(() => {
|
|
27
|
+
const current = this.#map.get(key) ?? 0;
|
|
28
|
+
const next = current + delta;
|
|
29
|
+
|
|
30
|
+
if (next < 0) {
|
|
31
|
+
throw new Error(`Cannot update ${key} in counter ${this.#name} below zero`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (next === 0) {
|
|
35
|
+
void this.#map.delete(key);
|
|
36
|
+
} else {
|
|
37
|
+
// store the key inside the entry because LMDB might return an internal representation
|
|
38
|
+
// of the key when iterating over the database
|
|
39
|
+
void this.#map.set(key, next);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get(key: K): number {
|
|
45
|
+
return this.#map.get(key) ?? 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getAsync(key: K): Promise<number> {
|
|
49
|
+
return Promise.resolve(this.get(key));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
entries(range: Range<K> = {}): IterableIterator<[K, number]> {
|
|
53
|
+
return this.#map.entries(range);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async *entriesAsync(range: Range<K> = {}): AsyncIterableIterator<[K, number]> {
|
|
57
|
+
yield* this.entries(range);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
keys(range: Range<K> = {}): IterableIterator<K> {
|
|
61
|
+
return this.#map.keys(range);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async *keysAsync(range: Range<K> = {}): AsyncIterableIterator<K> {
|
|
65
|
+
yield* this.keys(range);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Logger, createLogger } from '@aztec-labs/foundation/log';
|
|
2
|
+
import type { DataStoreConfig } from '@aztec-labs/stdlib/kv-store';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
import { initStoreForRollupAndSchemaVersion } from '../utils.js';
|
|
6
|
+
import { AztecLmdbStore } from './store.js';
|
|
7
|
+
|
|
8
|
+
export { AztecLmdbStore } from './store.js';
|
|
9
|
+
|
|
10
|
+
export function createStore(
|
|
11
|
+
name: string,
|
|
12
|
+
config: DataStoreConfig,
|
|
13
|
+
schemaVersion: number | undefined = undefined,
|
|
14
|
+
log: Logger = createLogger('kv-store'),
|
|
15
|
+
) {
|
|
16
|
+
let { dataDirectory } = config;
|
|
17
|
+
if (typeof dataDirectory !== 'undefined') {
|
|
18
|
+
dataDirectory = join(dataDirectory, name);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
log.info(
|
|
22
|
+
dataDirectory
|
|
23
|
+
? `Creating ${name} data store at directory ${dataDirectory} with map size ${config.dataStoreMapSizeKb} KB`
|
|
24
|
+
: `Creating ${name} ephemeral data store with map size ${config.dataStoreMapSizeKb} KB`,
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const store = AztecLmdbStore.open(dataDirectory, config.dataStoreMapSizeKb, false);
|
|
28
|
+
if (config.rollupAddress) {
|
|
29
|
+
return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.rollupAddress, log);
|
|
30
|
+
}
|
|
31
|
+
return store;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Opens a temporary store for testing purposes.
|
|
35
|
+
* @param ephemeral - true if the store should only exist in memory and not automatically be flushed to disk. Optional
|
|
36
|
+
* @returns A new store
|
|
37
|
+
*/
|
|
38
|
+
export function openTmpStore(ephemeral: boolean = false): AztecLmdbStore {
|
|
39
|
+
const mapSize = 1024 * 1024 * 10; // 10 GB map size
|
|
40
|
+
return AztecLmdbStore.open(undefined, mapSize, ephemeral);
|
|
41
|
+
}
|