@aztec/kv-store 5.0.0-private.20260319 → 5.0.0-rc.2
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 +8 -1
- 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/indexeddb/index.js +1 -1
- package/dest/interfaces/array_test_suite.d.ts +1 -1
- package/dest/interfaces/array_test_suite.d.ts.map +1 -1
- package/dest/interfaces/array_test_suite.js +33 -34
- package/dest/interfaces/index.d.ts +2 -2
- package/dest/interfaces/index.d.ts.map +1 -1
- package/dest/interfaces/map_test_suite.d.ts +1 -1
- package/dest/interfaces/map_test_suite.d.ts.map +1 -1
- package/dest/interfaces/map_test_suite.js +32 -33
- package/dest/interfaces/multi_map_test_suite.d.ts +1 -1
- package/dest/interfaces/multi_map_test_suite.d.ts.map +1 -1
- package/dest/interfaces/multi_map_test_suite.js +68 -69
- package/dest/interfaces/set_test_suite.d.ts +1 -1
- package/dest/interfaces/set_test_suite.d.ts.map +1 -1
- package/dest/interfaces/set_test_suite.js +13 -14
- package/dest/interfaces/singleton_test_suite.d.ts +1 -1
- package/dest/interfaces/singleton_test_suite.d.ts.map +1 -1
- package/dest/interfaces/singleton_test_suite.js +6 -7
- package/dest/lmdb/index.js +2 -2
- package/dest/lmdb-v2/factory.d.ts +28 -3
- package/dest/lmdb-v2/factory.d.ts.map +1 -1
- package/dest/lmdb-v2/factory.js +61 -10
- package/dest/lmdb-v2/read_transaction.js +21 -19
- package/dest/lmdb-v2/store.d.ts +2 -2
- package/dest/lmdb-v2/store.d.ts.map +1 -1
- package/dest/lmdb-v2/store.js +4 -4
- 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 +27 -0
- package/dest/sqlite-opfs/errors.d.ts.map +1 -0
- package/dest/sqlite-opfs/errors.js +34 -0
- package/dest/sqlite-opfs/index.d.ts +16 -0
- package/dest/sqlite-opfs/index.d.ts.map +1 -0
- package/dest/sqlite-opfs/index.js +22 -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/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/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 +79 -0
- package/dest/sqlite-opfs/store.d.ts.map +1 -0
- package/dest/sqlite-opfs/store.js +281 -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 +248 -0
- package/dest/stores/l2_tips_store.d.ts +7 -13
- package/dest/stores/l2_tips_store.d.ts.map +1 -1
- package/dest/stores/l2_tips_store.js +24 -43
- package/package.json +22 -19
- package/src/bench/shared_map_bench.ts +111 -0
- package/src/indexeddb/index.ts +1 -1
- package/src/interfaces/array_test_suite.ts +33 -35
- package/src/interfaces/index.ts +1 -1
- package/src/interfaces/map_test_suite.ts +32 -34
- package/src/interfaces/multi_map_test_suite.ts +65 -67
- package/src/interfaces/set_test_suite.ts +13 -15
- package/src/interfaces/singleton_test_suite.ts +6 -8
- package/src/lmdb/index.ts +2 -2
- package/src/lmdb-v2/factory.ts +79 -9
- package/src/lmdb-v2/read_transaction.ts +23 -23
- package/src/lmdb-v2/store.ts +4 -2
- package/src/sqlite-opfs/array.ts +124 -0
- package/src/sqlite-opfs/errors.ts +44 -0
- package/src/sqlite-opfs/index.ts +39 -0
- package/src/sqlite-opfs/internal/ordered-binary-browser.js +465 -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/set.ts +29 -0
- package/src/sqlite-opfs/singleton.ts +48 -0
- package/src/sqlite-opfs/store.ts +296 -0
- package/src/sqlite-opfs/worker.ts +230 -0
- package/src/stores/l2_tips_store.ts +20 -41
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { toArray } from '@aztec/foundation/iterable';
|
|
2
|
-
import { expect } from 'chai';
|
|
3
2
|
import { isSyncStore } from './utils.js';
|
|
4
3
|
export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
5
4
|
describe(testName, ()=>{
|
|
@@ -36,62 +35,62 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
36
35
|
it('should be able to set and get values', async ()=>{
|
|
37
36
|
await multiMap.set('foo', 'bar');
|
|
38
37
|
await multiMap.set('baz', 'qux');
|
|
39
|
-
expect(await get('foo')).
|
|
40
|
-
expect(await get('baz')).
|
|
41
|
-
expect(await get('quux')).
|
|
38
|
+
expect(await get('foo')).toBe('bar');
|
|
39
|
+
expect(await get('baz')).toBe('qux');
|
|
40
|
+
expect(await get('quux')).toBe(undefined);
|
|
42
41
|
});
|
|
43
42
|
it('should be able to set values if they do not exist', async ()=>{
|
|
44
|
-
expect(await multiMap.setIfNotExists('foo', 'bar')).
|
|
45
|
-
expect(await multiMap.setIfNotExists('foo', 'baz')).
|
|
46
|
-
expect(await get('foo')).
|
|
43
|
+
expect(await multiMap.setIfNotExists('foo', 'bar')).toBe(true);
|
|
44
|
+
expect(await multiMap.setIfNotExists('foo', 'baz')).toBe(false);
|
|
45
|
+
expect(await get('foo')).toBe('bar');
|
|
47
46
|
});
|
|
48
47
|
it('should be able to delete values', async ()=>{
|
|
49
48
|
await multiMap.set('foo', 'bar');
|
|
50
49
|
await multiMap.set('baz', 'qux');
|
|
51
50
|
await multiMap.delete('foo');
|
|
52
|
-
expect(await get('foo')).
|
|
53
|
-
expect(await get('baz')).
|
|
51
|
+
expect(await get('foo')).toBe(undefined);
|
|
52
|
+
expect(await get('baz')).toBe('qux');
|
|
54
53
|
});
|
|
55
54
|
it('should be able to get size of the map', async ()=>{
|
|
56
55
|
await multiMap.set('foo', 'bar');
|
|
57
|
-
expect(await size()).
|
|
56
|
+
expect(await size()).toBe(1);
|
|
58
57
|
await multiMap.set('baz', 'qux');
|
|
59
|
-
expect(await size()).
|
|
58
|
+
expect(await size()).toBe(2);
|
|
60
59
|
await multiMap.delete('foo');
|
|
61
|
-
expect(await size()).
|
|
60
|
+
expect(await size()).toBe(1);
|
|
62
61
|
});
|
|
63
62
|
it('returns 0 for empty multimap size', async ()=>{
|
|
64
|
-
expect(await size()).
|
|
63
|
+
expect(await size()).toBe(0);
|
|
65
64
|
});
|
|
66
65
|
it('calculates size correctly with multiple values per key', async ()=>{
|
|
67
|
-
expect(await size()).
|
|
66
|
+
expect(await size()).toBe(0);
|
|
68
67
|
// Add multiple values for same key
|
|
69
68
|
await multiMap.set('key1', 'value1');
|
|
70
|
-
expect(await size()).
|
|
69
|
+
expect(await size()).toBe(1);
|
|
71
70
|
await multiMap.set('key1', 'value2');
|
|
72
|
-
expect(await size()).
|
|
71
|
+
expect(await size()).toBe(2);
|
|
73
72
|
await multiMap.set('key1', 'value3');
|
|
74
|
-
expect(await size()).
|
|
73
|
+
expect(await size()).toBe(3);
|
|
75
74
|
// Add values for different key
|
|
76
75
|
await multiMap.set('key2', 'value4');
|
|
77
|
-
expect(await size()).
|
|
76
|
+
expect(await size()).toBe(4);
|
|
78
77
|
// Delete one value from key1
|
|
79
78
|
await multiMap.deleteValue('key1', 'value2');
|
|
80
|
-
expect(await size()).
|
|
79
|
+
expect(await size()).toBe(3);
|
|
81
80
|
// Delete entire key
|
|
82
81
|
await multiMap.delete('key1');
|
|
83
|
-
expect(await size()).
|
|
82
|
+
expect(await size()).toBe(1);
|
|
84
83
|
// Delete last key
|
|
85
84
|
await multiMap.delete('key2');
|
|
86
|
-
expect(await size()).
|
|
85
|
+
expect(await size()).toBe(0);
|
|
87
86
|
});
|
|
88
87
|
it('should be able to iterate over entries when there are no keys', async ()=>{
|
|
89
|
-
expect(await entries()).
|
|
88
|
+
expect(await entries()).toEqual([]);
|
|
90
89
|
});
|
|
91
90
|
it('should be able to iterate over entries', async ()=>{
|
|
92
91
|
await multiMap.set('foo', 'bar');
|
|
93
92
|
await multiMap.set('baz', 'qux');
|
|
94
|
-
expect(await entries()).
|
|
93
|
+
expect(await entries()).toEqual([
|
|
95
94
|
[
|
|
96
95
|
'baz',
|
|
97
96
|
'qux'
|
|
@@ -105,7 +104,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
105
104
|
it('should be able to iterate over values', async ()=>{
|
|
106
105
|
await multiMap.set('foo', 'bar');
|
|
107
106
|
await multiMap.set('baz', 'quux');
|
|
108
|
-
expect(await values()).
|
|
107
|
+
expect(await values()).toEqual([
|
|
109
108
|
'quux',
|
|
110
109
|
'bar'
|
|
111
110
|
]);
|
|
@@ -113,7 +112,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
113
112
|
it('should be able to iterate over keys', async ()=>{
|
|
114
113
|
await multiMap.set('foo', 'bar');
|
|
115
114
|
await multiMap.set('baz', 'qux');
|
|
116
|
-
expect(await keys()).
|
|
115
|
+
expect(await keys()).toEqual([
|
|
117
116
|
'baz',
|
|
118
117
|
'foo'
|
|
119
118
|
]);
|
|
@@ -121,7 +120,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
121
120
|
it('should be able to get multiple values for a single key', async ()=>{
|
|
122
121
|
await multiMap.set('foo', 'bar');
|
|
123
122
|
await multiMap.set('foo', 'baz');
|
|
124
|
-
expect(await getValues('foo')).
|
|
123
|
+
expect(await getValues('foo')).toEqual([
|
|
125
124
|
'bar',
|
|
126
125
|
'baz'
|
|
127
126
|
]);
|
|
@@ -129,7 +128,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
129
128
|
it('should ignore multiple identical values', async ()=>{
|
|
130
129
|
await multiMap.set('foo', 'bar');
|
|
131
130
|
await multiMap.set('foo', 'bar');
|
|
132
|
-
expect(await getValues('foo')).
|
|
131
|
+
expect(await getValues('foo')).toEqual([
|
|
133
132
|
'bar'
|
|
134
133
|
]);
|
|
135
134
|
});
|
|
@@ -138,7 +137,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
138
137
|
await multiMap.set('foo', '2');
|
|
139
138
|
await multiMap.set('foo', '3');
|
|
140
139
|
await multiMap.deleteValue('foo', '2');
|
|
141
|
-
expect(await getValues('foo')).
|
|
140
|
+
expect(await getValues('foo')).toEqual([
|
|
142
141
|
'1',
|
|
143
142
|
'3'
|
|
144
143
|
]);
|
|
@@ -147,25 +146,25 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
147
146
|
await multiMap.set('foo', '1');
|
|
148
147
|
await multiMap.set('foo', '2');
|
|
149
148
|
await multiMap.set('foo', '3');
|
|
150
|
-
expect(await size()).
|
|
149
|
+
expect(await size()).toBe(3);
|
|
151
150
|
await multiMap.set('bar', '1');
|
|
152
151
|
await multiMap.set('bar', '2');
|
|
153
152
|
await multiMap.set('bar', '3');
|
|
154
|
-
expect(await size()).
|
|
153
|
+
expect(await size()).toBe(6);
|
|
155
154
|
await multiMap.deleteValue('foo', '2');
|
|
156
|
-
expect(await size()).
|
|
155
|
+
expect(await size()).toBe(5);
|
|
157
156
|
});
|
|
158
157
|
it('should be able to delete the last and first values for a key', async ()=>{
|
|
159
158
|
await multiMap.set('foo', '1');
|
|
160
159
|
await multiMap.set('foo', '2');
|
|
161
160
|
await multiMap.set('foo', '3');
|
|
162
161
|
await multiMap.deleteValue('foo', '1');
|
|
163
|
-
expect(await getValues('foo')).
|
|
162
|
+
expect(await getValues('foo')).toEqual([
|
|
164
163
|
'2',
|
|
165
164
|
'3'
|
|
166
165
|
]);
|
|
167
166
|
await multiMap.deleteValue('foo', '3');
|
|
168
|
-
expect(await getValues('foo')).
|
|
167
|
+
expect(await getValues('foo')).toEqual([
|
|
169
168
|
'2'
|
|
170
169
|
]);
|
|
171
170
|
});
|
|
@@ -176,7 +175,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
176
175
|
await multiMap.deleteValue('foo', '1');
|
|
177
176
|
await multiMap.deleteValue('foo', '3');
|
|
178
177
|
await multiMap.deleteValue('foo', '2');
|
|
179
|
-
expect(await getValues('foo')).
|
|
178
|
+
expect(await getValues('foo')).toEqual([]);
|
|
180
179
|
});
|
|
181
180
|
it('should be able to insert after deletion', async ()=>{
|
|
182
181
|
await multiMap.set('foo', '1');
|
|
@@ -184,14 +183,14 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
184
183
|
await multiMap.set('foo', '3');
|
|
185
184
|
await multiMap.deleteValue('foo', '2');
|
|
186
185
|
await multiMap.set('foo', 'bar');
|
|
187
|
-
expect(await getValues('foo')).
|
|
186
|
+
expect(await getValues('foo')).toEqual([
|
|
188
187
|
'1',
|
|
189
188
|
'3',
|
|
190
189
|
'bar'
|
|
191
190
|
]);
|
|
192
191
|
// Delete the just-added entry
|
|
193
192
|
await multiMap.deleteValue('foo', 'bar');
|
|
194
|
-
expect(await getValues('foo')).
|
|
193
|
+
expect(await getValues('foo')).toEqual([
|
|
195
194
|
'1',
|
|
196
195
|
'3'
|
|
197
196
|
]);
|
|
@@ -200,7 +199,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
200
199
|
// LMDB and IndexedDB behave differently here, the former ordering by value and the latter by insertion. This is
|
|
201
200
|
// fine because there is no expectation for values in a multimap to be ordered.
|
|
202
201
|
const values = (await getValues('foo')).sort((a, b)=>a.localeCompare(b));
|
|
203
|
-
expect(values).
|
|
202
|
+
expect(values).toEqual([
|
|
204
203
|
'1',
|
|
205
204
|
'2',
|
|
206
205
|
'3'
|
|
@@ -212,7 +211,7 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
212
211
|
// Insert some more
|
|
213
212
|
await multiMap.set('foo', 'baz');
|
|
214
213
|
await multiMap.set('foo', 'qux');
|
|
215
|
-
expect(await getValues('foo')).
|
|
214
|
+
expect(await getValues('foo')).toEqual([
|
|
216
215
|
'baz',
|
|
217
216
|
'qux'
|
|
218
217
|
]);
|
|
@@ -225,19 +224,19 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
225
224
|
expect(await keys({
|
|
226
225
|
start: 'b',
|
|
227
226
|
end: 'c'
|
|
228
|
-
})).
|
|
227
|
+
})).toEqual([
|
|
229
228
|
'b'
|
|
230
229
|
]);
|
|
231
230
|
expect(await keys({
|
|
232
231
|
start: 'b'
|
|
233
|
-
})).
|
|
232
|
+
})).toEqual([
|
|
234
233
|
'b',
|
|
235
234
|
'c',
|
|
236
235
|
'd'
|
|
237
236
|
]);
|
|
238
237
|
expect(await keys({
|
|
239
238
|
end: 'c'
|
|
240
|
-
})).
|
|
239
|
+
})).toEqual([
|
|
241
240
|
'a',
|
|
242
241
|
'b'
|
|
243
242
|
]);
|
|
@@ -245,86 +244,86 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
245
244
|
start: 'b',
|
|
246
245
|
end: 'c',
|
|
247
246
|
reverse: true
|
|
248
|
-
})).
|
|
247
|
+
})).toEqual([
|
|
249
248
|
'c'
|
|
250
249
|
]);
|
|
251
250
|
expect(await keys({
|
|
252
251
|
start: 'b',
|
|
253
252
|
limit: 1
|
|
254
|
-
})).
|
|
253
|
+
})).toEqual([
|
|
255
254
|
'b'
|
|
256
255
|
]);
|
|
257
256
|
expect(await keys({
|
|
258
257
|
start: 'b',
|
|
259
258
|
reverse: true
|
|
260
|
-
})).
|
|
259
|
+
})).toEqual([
|
|
261
260
|
'd',
|
|
262
261
|
'c'
|
|
263
262
|
]);
|
|
264
263
|
expect(await keys({
|
|
265
264
|
end: 'b',
|
|
266
265
|
reverse: true
|
|
267
|
-
})).
|
|
266
|
+
})).toEqual([
|
|
268
267
|
'b',
|
|
269
268
|
'a'
|
|
270
269
|
]);
|
|
271
270
|
});
|
|
272
271
|
it('returns 0 for missing key', async ()=>{
|
|
273
|
-
expect(await getValueCount('missing')).
|
|
272
|
+
expect(await getValueCount('missing')).toBe(0);
|
|
274
273
|
});
|
|
275
274
|
it('counts a single value', async ()=>{
|
|
276
275
|
await multiMap.set('foo', 'bar');
|
|
277
|
-
expect(await getValueCount('foo')).
|
|
276
|
+
expect(await getValueCount('foo')).toBe(1);
|
|
278
277
|
});
|
|
279
278
|
it('counts multiple distinct values for same key', async ()=>{
|
|
280
279
|
await multiMap.set('foo', 'bar');
|
|
281
280
|
await multiMap.set('foo', 'baz');
|
|
282
281
|
await multiMap.set('foo', 'qux');
|
|
283
|
-
expect(await getValueCount('foo')).
|
|
282
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
284
283
|
});
|
|
285
284
|
it('does not increase count for duplicate inserts', async ()=>{
|
|
286
285
|
await multiMap.set('foo', 'bar');
|
|
287
286
|
await multiMap.set('foo', 'bar');
|
|
288
287
|
await multiMap.set('foo', 'baz');
|
|
289
288
|
await multiMap.set('foo', 'baz');
|
|
290
|
-
expect(await getValueCount('foo')).
|
|
291
|
-
expect(await getValues('foo')).
|
|
289
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
290
|
+
expect((await getValues('foo')).sort()).toEqual([
|
|
292
291
|
'bar',
|
|
293
292
|
'baz'
|
|
294
|
-
]);
|
|
293
|
+
].sort());
|
|
295
294
|
});
|
|
296
295
|
it('decrements when deleting a single value', async ()=>{
|
|
297
296
|
await multiMap.set('foo', '1');
|
|
298
297
|
await multiMap.set('foo', '2');
|
|
299
298
|
await multiMap.set('foo', '3');
|
|
300
|
-
expect(await getValueCount('foo')).
|
|
299
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
301
300
|
await multiMap.deleteValue('foo', '2');
|
|
302
|
-
expect(await getValueCount('foo')).
|
|
303
|
-
expect(await getValues('foo')).
|
|
301
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
302
|
+
expect((await getValues('foo')).sort()).toEqual([
|
|
304
303
|
'1',
|
|
305
304
|
'3'
|
|
306
|
-
]);
|
|
305
|
+
].sort());
|
|
307
306
|
});
|
|
308
307
|
it('does not change count when deleting a non-existent value', async ()=>{
|
|
309
308
|
await multiMap.set('foo', '1');
|
|
310
309
|
await multiMap.set('foo', '3');
|
|
311
|
-
expect(await getValueCount('foo')).
|
|
310
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
312
311
|
await multiMap.deleteValue('foo', '2');
|
|
313
|
-
expect(await getValueCount('foo')).
|
|
312
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
314
313
|
});
|
|
315
314
|
it('clears all values when deleting a key', async ()=>{
|
|
316
315
|
await multiMap.set('foo', 'bar');
|
|
317
316
|
await multiMap.set('foo', 'baz');
|
|
318
|
-
expect(await getValueCount('foo')).
|
|
317
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
319
318
|
await multiMap.delete('foo');
|
|
320
|
-
expect(await getValueCount('foo')).
|
|
321
|
-
expect(await getValues('foo')).
|
|
319
|
+
expect(await getValueCount('foo')).toBe(0);
|
|
320
|
+
expect(await getValues('foo')).toEqual([]);
|
|
322
321
|
});
|
|
323
322
|
it('count equals enumerated values length', async ()=>{
|
|
324
323
|
await multiMap.set('foo', '1');
|
|
325
324
|
await multiMap.set('foo', '2');
|
|
326
325
|
const vals = await getValues('foo');
|
|
327
|
-
expect(await getValueCount('foo')).
|
|
326
|
+
expect(await getValueCount('foo')).toBe(vals.length);
|
|
328
327
|
});
|
|
329
328
|
it('sum of per-key counts equals total size', async ()=>{
|
|
330
329
|
await multiMap.set('foo', '1');
|
|
@@ -336,29 +335,29 @@ export function describeAztecMultiMap(testName, getStore, forceAsync = false) {
|
|
|
336
335
|
const uniqueKeys = Array.from(new Set(allKeys));
|
|
337
336
|
const counts = await Promise.all(uniqueKeys.map((k)=>getValueCount(k)));
|
|
338
337
|
const sum = counts.reduce((s, n)=>s + n, 0);
|
|
339
|
-
expect(sum).
|
|
338
|
+
expect(sum).toBe(await size());
|
|
340
339
|
});
|
|
341
340
|
it('supports sparse slots: delete middle, reinsert new, count remains correct', async ()=>{
|
|
342
341
|
await multiMap.set('foo', '1');
|
|
343
342
|
await multiMap.set('foo', '2');
|
|
344
343
|
await multiMap.set('foo', '3');
|
|
345
|
-
expect(await getValueCount('foo')).
|
|
344
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
346
345
|
await multiMap.deleteValue('foo', '2');
|
|
347
|
-
expect(await getValueCount('foo')).
|
|
346
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
348
347
|
await multiMap.set('foo', '4');
|
|
349
|
-
expect(await getValueCount('foo')).
|
|
350
|
-
expect(await getValues('foo')).
|
|
348
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
349
|
+
expect((await getValues('foo')).sort()).toEqual([
|
|
351
350
|
'1',
|
|
352
351
|
'3',
|
|
353
352
|
'4'
|
|
354
|
-
]);
|
|
353
|
+
].sort());
|
|
355
354
|
});
|
|
356
355
|
it('multiple keys are independent', async ()=>{
|
|
357
356
|
await multiMap.set('foo', '1');
|
|
358
357
|
await multiMap.set('foo', '2');
|
|
359
358
|
await multiMap.set('bar', '3');
|
|
360
|
-
expect(await getValueCount('foo')).
|
|
361
|
-
expect(await getValueCount('bar')).
|
|
359
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
360
|
+
expect(await getValueCount('bar')).toBe(1);
|
|
362
361
|
});
|
|
363
362
|
});
|
|
364
363
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
2
2
|
export declare function describeAztecSet(testName: string, getStore: () => AztecKVStore | Promise<AztecAsyncKVStore>, forceAsync?: boolean): void;
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0X3Rlc3Rfc3VpdGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnRlcmZhY2VzL3NldF90ZXN0X3N1aXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLFlBQVksRUFBRSxNQUFNLFlBQVksQ0FBQztBQUdsRSx3QkFBZ0IsZ0JBQWdCLENBQzlCLFFBQVEsRUFBRSxNQUFNLEVBQ2hCLFFBQVEsRUFBRSxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsRUFDekQsVUFBVSxHQUFFLE9BQWUsUUFvRTVCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set_test_suite.d.ts","sourceRoot":"","sources":["../../src/interfaces/set_test_suite.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"set_test_suite.d.ts","sourceRoot":"","sources":["../../src/interfaces/set_test_suite.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlE,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC,EACzD,UAAU,GAAE,OAAe,QAoE5B"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { toArray } from '@aztec/foundation/iterable';
|
|
2
|
-
import { expect } from 'chai';
|
|
3
2
|
import { isSyncStore } from './utils.js';
|
|
4
3
|
export function describeAztecSet(testName, getStore, forceAsync = false) {
|
|
5
4
|
describe(testName, ()=>{
|
|
@@ -21,21 +20,21 @@ export function describeAztecSet(testName, getStore, forceAsync = false) {
|
|
|
21
20
|
it('should be able to set and get values', async ()=>{
|
|
22
21
|
await set.add('foo');
|
|
23
22
|
await set.add('baz');
|
|
24
|
-
expect(await has('foo')).
|
|
25
|
-
expect(await has('baz')).
|
|
26
|
-
expect(await has('bar')).
|
|
23
|
+
expect(await has('foo')).toBe(true);
|
|
24
|
+
expect(await has('baz')).toBe(true);
|
|
25
|
+
expect(await has('bar')).toBe(false);
|
|
27
26
|
});
|
|
28
27
|
it('should be able to delete values', async ()=>{
|
|
29
28
|
await set.add('foo');
|
|
30
29
|
await set.add('baz');
|
|
31
30
|
await set.delete('foo');
|
|
32
|
-
expect(await has('foo')).
|
|
33
|
-
expect(await has('baz')).
|
|
31
|
+
expect(await has('foo')).toBe(false);
|
|
32
|
+
expect(await has('baz')).toBe(true);
|
|
34
33
|
});
|
|
35
34
|
it('should be able to iterate over entries', async ()=>{
|
|
36
35
|
await set.add('baz');
|
|
37
36
|
await set.add('foo');
|
|
38
|
-
expect(await entries()).
|
|
37
|
+
expect(await entries()).toEqual([
|
|
39
38
|
'baz',
|
|
40
39
|
'foo'
|
|
41
40
|
]);
|
|
@@ -48,19 +47,19 @@ export function describeAztecSet(testName, getStore, forceAsync = false) {
|
|
|
48
47
|
expect(await entries({
|
|
49
48
|
start: 'b',
|
|
50
49
|
end: 'c'
|
|
51
|
-
})).
|
|
50
|
+
})).toEqual([
|
|
52
51
|
'b'
|
|
53
52
|
]);
|
|
54
53
|
expect(await entries({
|
|
55
54
|
start: 'b'
|
|
56
|
-
})).
|
|
55
|
+
})).toEqual([
|
|
57
56
|
'b',
|
|
58
57
|
'c',
|
|
59
58
|
'd'
|
|
60
59
|
]);
|
|
61
60
|
expect(await entries({
|
|
62
61
|
end: 'c'
|
|
63
|
-
})).
|
|
62
|
+
})).toEqual([
|
|
64
63
|
'a',
|
|
65
64
|
'b'
|
|
66
65
|
]);
|
|
@@ -68,26 +67,26 @@ export function describeAztecSet(testName, getStore, forceAsync = false) {
|
|
|
68
67
|
start: 'b',
|
|
69
68
|
end: 'c',
|
|
70
69
|
reverse: true
|
|
71
|
-
})).
|
|
70
|
+
})).toEqual([
|
|
72
71
|
'c'
|
|
73
72
|
]);
|
|
74
73
|
expect(await entries({
|
|
75
74
|
start: 'b',
|
|
76
75
|
limit: 1
|
|
77
|
-
})).
|
|
76
|
+
})).toEqual([
|
|
78
77
|
'b'
|
|
79
78
|
]);
|
|
80
79
|
expect(await entries({
|
|
81
80
|
start: 'b',
|
|
82
81
|
reverse: true
|
|
83
|
-
})).
|
|
82
|
+
})).toEqual([
|
|
84
83
|
'd',
|
|
85
84
|
'c'
|
|
86
85
|
]);
|
|
87
86
|
expect(await entries({
|
|
88
87
|
end: 'b',
|
|
89
88
|
reverse: true
|
|
90
|
-
})).
|
|
89
|
+
})).toEqual([
|
|
91
90
|
'b',
|
|
92
91
|
'a'
|
|
93
92
|
]);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
2
2
|
export declare function describeAztecSingleton(testName: string, getStore: () => AztecKVStore | Promise<AztecAsyncKVStore>, forceAsync?: boolean): void;
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2luZ2xldG9uX3Rlc3Rfc3VpdGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnRlcmZhY2VzL3NpbmdsZXRvbl90ZXN0X3N1aXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLFlBQVksRUFBRSxNQUFNLFlBQVksQ0FBQztBQUdsRSx3QkFBZ0Isc0JBQXNCLENBQ3BDLFFBQVEsRUFBRSxNQUFNLEVBQ2hCLFFBQVEsRUFBRSxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsRUFDekQsVUFBVSxHQUFFLE9BQWUsUUFvQzVCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleton_test_suite.d.ts","sourceRoot":"","sources":["../../src/interfaces/singleton_test_suite.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"singleton_test_suite.d.ts","sourceRoot":"","sources":["../../src/interfaces/singleton_test_suite.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlE,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC,EACzD,UAAU,GAAE,OAAe,QAoC5B"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { expect } from 'chai';
|
|
2
1
|
import { isSyncStore } from './utils.js';
|
|
3
2
|
export function describeAztecSingleton(testName, getStore, forceAsync = false) {
|
|
4
3
|
describe(testName, ()=>{
|
|
@@ -15,16 +14,16 @@ export function describeAztecSingleton(testName, getStore, forceAsync = false) {
|
|
|
15
14
|
return isSyncStore(store) && !forceAsync ? singleton.get() : await singleton.getAsync();
|
|
16
15
|
}
|
|
17
16
|
it('returns undefined if the value is not set', async ()=>{
|
|
18
|
-
expect(await get()).
|
|
17
|
+
expect(await get()).toBe(undefined);
|
|
19
18
|
});
|
|
20
19
|
it('should be able to set and get values', async ()=>{
|
|
21
|
-
expect(await singleton.set('foo')).
|
|
22
|
-
expect(await get()).
|
|
20
|
+
expect(await singleton.set('foo')).toBe(true);
|
|
21
|
+
expect(await get()).toBe('foo');
|
|
23
22
|
});
|
|
24
23
|
it('overwrites the value if it is set again', async ()=>{
|
|
25
|
-
expect(await singleton.set('foo')).
|
|
26
|
-
expect(await singleton.set('bar')).
|
|
27
|
-
expect(await get()).
|
|
24
|
+
expect(await singleton.set('foo')).toBe(true);
|
|
25
|
+
expect(await singleton.set('bar')).toBe(true);
|
|
26
|
+
expect(await get()).toBe('bar');
|
|
28
27
|
});
|
|
29
28
|
});
|
|
30
29
|
}
|
package/dest/lmdb/index.js
CHANGED
|
@@ -10,8 +10,8 @@ export function createStore(name, config, schemaVersion = undefined, log = creat
|
|
|
10
10
|
}
|
|
11
11
|
log.info(dataDirectory ? `Creating ${name} data store at directory ${dataDirectory} with map size ${config.dataStoreMapSizeKb} KB` : `Creating ${name} ephemeral data store with map size ${config.dataStoreMapSizeKb} KB`);
|
|
12
12
|
const store = AztecLmdbStore.open(dataDirectory, config.dataStoreMapSizeKb, false);
|
|
13
|
-
if (config.
|
|
14
|
-
return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.
|
|
13
|
+
if (config.rollupAddress) {
|
|
14
|
+
return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.rollupAddress, log);
|
|
15
15
|
}
|
|
16
16
|
return store;
|
|
17
17
|
}
|
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
3
|
+
import { type SchemaVersionMismatchPolicy } from '@aztec/stdlib/database-version/manager';
|
|
3
4
|
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
4
5
|
import { AztecLMDBStoreV2 } from './store.js';
|
|
5
|
-
|
|
6
|
-
export
|
|
6
|
+
/** Optional versioning hooks for persistent LMDB stores. */
|
|
7
|
+
export type CreateStoreOptions = {
|
|
8
|
+
onUpgrade?: (dataDir: string, currentVersion: number, latestVersion: number) => Promise<void>;
|
|
9
|
+
schemaVersionMismatchPolicy?: SchemaVersionMismatchPolicy;
|
|
10
|
+
};
|
|
11
|
+
export declare function createStore(name: string, schemaVersion: number, config: DataStoreConfig, bindings?: LoggerBindings, options?: CreateStoreOptions): Promise<AztecLMDBStoreV2>;
|
|
12
|
+
/**
|
|
13
|
+
* Open a persistent on-disk store rooted in OS tmpdir. Caller chooses whether to
|
|
14
|
+
* auto-remove the directory on close. Uses standard durable LMDB flags (fsync on
|
|
15
|
+
* every commit) — for full in-memory / NOSYNC semantics use `openEphemeralStore`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function openTmpStore(name: string, cleanupTmpDir?: boolean, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
18
|
+
/**
|
|
19
|
+
* Open a fully-ephemeral store: a fresh tmpdir backing file, LMDB opened with
|
|
20
|
+
* MDB_NOSYNC | MDB_NOMETASYNC (no fsync, kernel-only writeback), and the directory
|
|
21
|
+
* unconditionally removed on close. Intended for tests and worker-local scratch
|
|
22
|
+
* stores where durability is explicitly not desired.
|
|
23
|
+
*/
|
|
24
|
+
export declare function openEphemeralStore(name: string, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
7
25
|
export declare function openStoreAt(dataDir: string, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
26
|
+
/**
|
|
27
|
+
* Open a fully-ephemeral store seeded from an existing `data.mdb` file. Creates a fresh tmpdir,
|
|
28
|
+
* copies `srcDataMdbPath` into it as `data.mdb`, opens with MDB_NOSYNC | MDB_NOMETASYNC, and
|
|
29
|
+
* removes the tmpdir on close. Intended for worker clones of a main-thread-built store — the
|
|
30
|
+
* source file is never written to.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cloneEphemeralStoreFrom(srcDataMdbPath: string, name: string, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
8
33
|
export declare function openVersionedStoreAt(dataDirectory: string, schemaVersion: number, rollupAddress: EthAddress, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xtZGItdjIvZmFjdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxFQUFFLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBQzFFLE9BQU8sRUFBMEIsS0FBSywyQkFBMkIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2xILE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBTTlELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUk5Qyw0REFBNEQ7QUFDNUQsTUFBTSxNQUFNLGtCQUFrQixHQUFHO0lBQy9CLFNBQVMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlGLDJCQUEyQixDQUFDLEVBQUUsMkJBQTJCLENBQUM7Q0FDM0QsQ0FBQztBQUVGLHdCQUFzQixXQUFXLENBQy9CLElBQUksRUFBRSxNQUFNLEVBQ1osYUFBYSxFQUFFLE1BQU0sRUFDckIsTUFBTSxFQUFFLGVBQWUsRUFDdkIsUUFBUSxDQUFDLEVBQUUsY0FBYyxFQUN6QixPQUFPLEdBQUUsa0JBQXVCLEdBQy9CLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQWdDM0I7QUFFRDs7OztHQUlHO0FBQ0gsd0JBQXNCLFlBQVksQ0FDaEMsSUFBSSxFQUFFLE1BQU0sRUFDWixhQUFhLEdBQUUsT0FBYyxFQUM3QixXQUFXLFNBQXFCLEVBQ2hDLFVBQVUsU0FBYyxFQUN4QixRQUFRLENBQUMsRUFBRSxjQUFjLEdBQ3hCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQW9CM0I7QUFFRDs7Ozs7R0FLRztBQUNILHdCQUFzQixrQkFBa0IsQ0FDdEMsSUFBSSxFQUFFLE1BQU0sRUFDWixXQUFXLFNBQXFCLEVBQ2hDLFVBQVUsU0FBYyxFQUN4QixRQUFRLENBQUMsRUFBRSxjQUFjLEdBQ3hCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQWUzQjtBQUVELHdCQUFzQixXQUFXLENBQy9CLE9BQU8sRUFBRSxNQUFNLEVBQ2YsV0FBVyxTQUFxQixFQUNoQyxVQUFVLFNBQWMsRUFDeEIsUUFBUSxDQUFDLEVBQUUsY0FBYyxHQUN4QixPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FJM0I7QUFFRDs7Ozs7R0FLRztBQUNILHdCQUFzQix1QkFBdUIsQ0FDM0MsY0FBYyxFQUFFLE1BQU0sRUFDdEIsSUFBSSxFQUFFLE1BQU0sRUFDWixXQUFXLFNBQXFCLEVBQ2hDLFVBQVUsU0FBYyxFQUN4QixRQUFRLENBQUMsRUFBRSxjQUFjLEdBQ3hCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQWdCM0I7QUFFRCx3QkFBc0Isb0JBQW9CLENBQ3hDLGFBQWEsRUFBRSxNQUFNLEVBQ3JCLGFBQWEsRUFBRSxNQUFNLEVBQ3JCLGFBQWEsRUFBRSxVQUFVLEVBQ3pCLFdBQVcsU0FBcUIsRUFDaEMsVUFBVSxTQUFjLEVBQ3hCLFFBQVEsQ0FBQyxFQUFFLGNBQWMsR0FDeEIsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBVTNCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAA0B,KAAK,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAM9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI9C,4DAA4D;AAC5D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;CAC3D,CAAC;AAEF,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,eAAe,EACvB,QAAQ,CAAC,EAAE,cAAc,EACzB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CAgC3B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,aAAa,GAAE,OAAc,EAC7B,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAe3B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAI3B;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAgB3B;AAED,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,UAAU,EACzB,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAU3B"}
|