@frostpillar/frostpillar-btree 0.2.5 → 0.2.6
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-JA.md +33 -2
- package/README.md +33 -2
- package/dist/InMemoryBTree.d.ts +33 -0
- package/dist/btree/autoScale.d.ts +1 -0
- package/dist/btree/node-ops.d.ts +15 -0
- package/dist/btree/rangeQuery.d.ts +1 -0
- package/dist/btree/types.d.ts +12 -26
- package/dist/{chunk-CZFRT2NN.js → chunk-OWHENPGJ.js} +255 -198
- package/dist/concurrency/ConcurrentInMemoryBTree.d.ts +20 -16
- package/dist/concurrency/helpers.d.ts +8 -2
- package/dist/concurrency/types.d.ts +14 -1
- package/dist/concurrency/writeOps.d.ts +48 -0
- package/dist/core.cjs +255 -198
- package/dist/core.js +1 -1
- package/dist/errors.d.ts +3 -0
- package/dist/frostpillar-btree-core.min.js +1 -1
- package/dist/frostpillar-btree.min.js +1 -1
- package/dist/index.cjs +531 -299
- package/dist/index.js +277 -102
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
DEFAULT_MAX_LEAF_ENTRIES,
|
|
7
7
|
InMemoryBTree,
|
|
8
8
|
computeAutoScaleTier
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OWHENPGJ.js";
|
|
10
10
|
|
|
11
11
|
// src/concurrency/helpers.ts
|
|
12
12
|
var DEFAULT_MAX_RETRIES = 16;
|
|
@@ -30,51 +30,79 @@ var assertNeverMutation = (mutation) => {
|
|
|
30
30
|
`Unsupported mutation type from shared store: ${String(unknownMutation.type)}`
|
|
31
31
|
);
|
|
32
32
|
};
|
|
33
|
+
var validatePutManyEntries = (entries) => {
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
if (typeof entry !== "object" || entry === null || !("key" in entry) || !("value" in entry)) {
|
|
36
|
+
throw new BTreeConcurrencyError("Malformed putMany mutation: each entry must have key and value.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var validateInitMutation = (m, expectedConfigFingerprint) => {
|
|
41
|
+
if (typeof m.configFingerprint !== "string") {
|
|
42
|
+
throw new BTreeConcurrencyError("Malformed init mutation: missing configFingerprint.");
|
|
43
|
+
}
|
|
44
|
+
if (expectedConfigFingerprint !== void 0 && m.configFingerprint !== expectedConfigFingerprint) {
|
|
45
|
+
throw new BTreeConcurrencyError(
|
|
46
|
+
"Config mismatch: store peers must share identical tree config."
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var validateSingleMutation = (m, expectedConfigFingerprint) => {
|
|
51
|
+
switch (m.type) {
|
|
52
|
+
case "init":
|
|
53
|
+
validateInitMutation(m, expectedConfigFingerprint);
|
|
54
|
+
break;
|
|
55
|
+
case "put":
|
|
56
|
+
if (!("key" in m) || !("value" in m)) {
|
|
57
|
+
throw new BTreeConcurrencyError("Malformed put mutation: missing key or value.");
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
case "remove":
|
|
61
|
+
if (!("key" in m)) {
|
|
62
|
+
throw new BTreeConcurrencyError("Malformed remove mutation: missing key.");
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
case "removeById":
|
|
66
|
+
if (!("entryId" in m)) {
|
|
67
|
+
throw new BTreeConcurrencyError("Malformed removeById mutation: missing entryId.");
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
case "updateById":
|
|
71
|
+
if (!("entryId" in m) || !("value" in m)) {
|
|
72
|
+
throw new BTreeConcurrencyError("Malformed updateById mutation: missing entryId or value.");
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
case "popFirst":
|
|
76
|
+
case "popLast":
|
|
77
|
+
break;
|
|
78
|
+
case "putMany":
|
|
79
|
+
if (!("entries" in m) || !Array.isArray(m.entries)) {
|
|
80
|
+
throw new BTreeConcurrencyError("Malformed putMany mutation: missing entries array.");
|
|
81
|
+
}
|
|
82
|
+
validatePutManyEntries(m.entries);
|
|
83
|
+
break;
|
|
84
|
+
case "deleteRange":
|
|
85
|
+
if (!("startKey" in m) || !("endKey" in m)) {
|
|
86
|
+
throw new BTreeConcurrencyError("Malformed deleteRange mutation: missing startKey or endKey.");
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
case "clear":
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
throw new BTreeConcurrencyError(
|
|
93
|
+
`Unsupported mutation type from shared store: ${String(m.type)}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
33
97
|
var validateMutationBatch = (mutations, expectedConfigFingerprint) => {
|
|
34
98
|
for (const mutation of mutations) {
|
|
35
99
|
if (typeof mutation !== "object" || mutation === null) {
|
|
36
100
|
throw new BTreeConcurrencyError("Malformed mutation: expected an object.");
|
|
37
101
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
throw new BTreeConcurrencyError("Malformed init mutation: missing configFingerprint.");
|
|
43
|
-
}
|
|
44
|
-
if (expectedConfigFingerprint !== void 0 && m.configFingerprint !== expectedConfigFingerprint) {
|
|
45
|
-
throw new BTreeConcurrencyError(
|
|
46
|
-
"Config mismatch: store peers must share identical tree config."
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
break;
|
|
50
|
-
case "put":
|
|
51
|
-
if (!("key" in m) || !("value" in m)) {
|
|
52
|
-
throw new BTreeConcurrencyError("Malformed put mutation: missing key or value.");
|
|
53
|
-
}
|
|
54
|
-
break;
|
|
55
|
-
case "remove":
|
|
56
|
-
if (!("key" in m)) {
|
|
57
|
-
throw new BTreeConcurrencyError("Malformed remove mutation: missing key.");
|
|
58
|
-
}
|
|
59
|
-
break;
|
|
60
|
-
case "removeById":
|
|
61
|
-
if (!("entryId" in m)) {
|
|
62
|
-
throw new BTreeConcurrencyError("Malformed removeById mutation: missing entryId.");
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
case "updateById":
|
|
66
|
-
if (!("entryId" in m) || !("value" in m)) {
|
|
67
|
-
throw new BTreeConcurrencyError("Malformed updateById mutation: missing entryId or value.");
|
|
68
|
-
}
|
|
69
|
-
break;
|
|
70
|
-
case "popFirst":
|
|
71
|
-
case "popLast":
|
|
72
|
-
break;
|
|
73
|
-
default:
|
|
74
|
-
throw new BTreeConcurrencyError(
|
|
75
|
-
`Unsupported mutation type from shared store: ${String(m.type)}`
|
|
76
|
-
);
|
|
77
|
-
}
|
|
102
|
+
validateSingleMutation(
|
|
103
|
+
mutation,
|
|
104
|
+
expectedConfigFingerprint
|
|
105
|
+
);
|
|
78
106
|
}
|
|
79
107
|
};
|
|
80
108
|
var normalizeMaxRetries = (value) => {
|
|
@@ -135,10 +163,110 @@ function assertAppendVersionContract(expectedVersion, appendResult) {
|
|
|
135
163
|
}
|
|
136
164
|
}
|
|
137
165
|
|
|
166
|
+
// src/concurrency/writeOps.ts
|
|
167
|
+
var applyMutationLocal = (tree, mutation, onInit) => {
|
|
168
|
+
switch (mutation.type) {
|
|
169
|
+
case "init":
|
|
170
|
+
onInit();
|
|
171
|
+
return null;
|
|
172
|
+
case "put":
|
|
173
|
+
return tree.put(mutation.key, mutation.value);
|
|
174
|
+
case "putMany":
|
|
175
|
+
return tree.putMany(mutation.entries);
|
|
176
|
+
case "remove":
|
|
177
|
+
return tree.remove(mutation.key);
|
|
178
|
+
case "removeById":
|
|
179
|
+
return tree.removeById(mutation.entryId);
|
|
180
|
+
case "updateById":
|
|
181
|
+
return tree.updateById(mutation.entryId, mutation.value);
|
|
182
|
+
case "popFirst":
|
|
183
|
+
return tree.popFirst();
|
|
184
|
+
case "popLast":
|
|
185
|
+
return tree.popLast();
|
|
186
|
+
case "deleteRange":
|
|
187
|
+
return tree.deleteRange(mutation.startKey, mutation.endKey, mutation.options);
|
|
188
|
+
case "clear":
|
|
189
|
+
tree.clear();
|
|
190
|
+
return null;
|
|
191
|
+
default:
|
|
192
|
+
return assertNeverMutation(mutation);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
var createPutEvaluator = (duplicateKeys, key, value) => {
|
|
196
|
+
return (tree) => {
|
|
197
|
+
if (duplicateKeys === "reject" && tree.hasKey(key)) {
|
|
198
|
+
throw new BTreeValidationError("Duplicate key rejected.");
|
|
199
|
+
}
|
|
200
|
+
return { type: "put", key, value };
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
var createRemoveEvaluator = (key) => {
|
|
204
|
+
return (tree) => {
|
|
205
|
+
return tree.hasKey(key) ? { type: "remove", key } : null;
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
var createRemoveByIdEvaluator = (entryId) => {
|
|
209
|
+
return (tree) => {
|
|
210
|
+
return tree.peekById(entryId) !== null ? { type: "removeById", entryId } : null;
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
var createUpdateByIdEvaluator = (entryId, value) => {
|
|
214
|
+
return (tree) => {
|
|
215
|
+
return tree.peekById(entryId) !== null ? { type: "updateById", entryId, value } : null;
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
var createPopFirstEvaluator = () => {
|
|
219
|
+
return (tree) => {
|
|
220
|
+
return tree.peekFirst() !== null ? { type: "popFirst" } : null;
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
var createPopLastEvaluator = () => {
|
|
224
|
+
return (tree) => {
|
|
225
|
+
return tree.peekLast() !== null ? { type: "popLast" } : null;
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
var createPutManyEvaluator = (entries, duplicateKeys, compareKeys) => {
|
|
229
|
+
return (tree) => {
|
|
230
|
+
const strictlyAscending = duplicateKeys !== "allow";
|
|
231
|
+
for (let i = 1; i < entries.length; i += 1) {
|
|
232
|
+
const cmp = compareKeys(entries[i - 1].key, entries[i].key);
|
|
233
|
+
if (cmp > 0) {
|
|
234
|
+
throw new BTreeValidationError("putMany: entries not in ascending order.");
|
|
235
|
+
}
|
|
236
|
+
if (strictlyAscending && cmp === 0) {
|
|
237
|
+
throw new BTreeValidationError(
|
|
238
|
+
duplicateKeys === "reject" ? "putMany: duplicate key rejected." : "putMany: equal keys not allowed in strict mode."
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (duplicateKeys === "reject") {
|
|
243
|
+
for (const entry of entries) {
|
|
244
|
+
if (tree.hasKey(entry.key)) {
|
|
245
|
+
throw new BTreeValidationError("Duplicate key rejected.");
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return { type: "putMany", entries };
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
var createDeleteRangeEvaluator = (startKey, endKey, options) => {
|
|
253
|
+
return (tree) => {
|
|
254
|
+
const count = tree.count(startKey, endKey, options);
|
|
255
|
+
if (count === 0) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
return { type: "deleteRange", startKey, endKey, options };
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
var createClearEvaluator = () => {
|
|
262
|
+
return () => ({ type: "clear" });
|
|
263
|
+
};
|
|
264
|
+
|
|
138
265
|
// src/concurrency/ConcurrentInMemoryBTree.ts
|
|
139
266
|
var ConcurrentInMemoryBTree = class {
|
|
140
267
|
constructor(config) {
|
|
141
268
|
this.store = config.store;
|
|
269
|
+
this.compareKeys = config.compareKeys;
|
|
142
270
|
this.maxRetries = normalizeMaxRetries(config.maxRetries);
|
|
143
271
|
this.maxSyncMutationsPerBatch = normalizeMaxSyncMutationsPerBatch(
|
|
144
272
|
config.maxSyncMutationsPerBatch
|
|
@@ -157,6 +285,7 @@ var ConcurrentInMemoryBTree = class {
|
|
|
157
285
|
this.currentVersion = 0n;
|
|
158
286
|
this.operationQueue = Promise.resolve();
|
|
159
287
|
this.initSeen = false;
|
|
288
|
+
this.corrupted = false;
|
|
160
289
|
}
|
|
161
290
|
async sync() {
|
|
162
291
|
await this.runExclusive(async () => {
|
|
@@ -180,34 +309,30 @@ var ConcurrentInMemoryBTree = class {
|
|
|
180
309
|
return;
|
|
181
310
|
}
|
|
182
311
|
validateMutationBatch(log.mutations, this.configFingerprint);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return this.tree.remove(mutation.key);
|
|
197
|
-
case "removeById":
|
|
198
|
-
return this.tree.removeById(mutation.entryId);
|
|
199
|
-
case "updateById":
|
|
200
|
-
return this.tree.updateById(mutation.entryId, mutation.value);
|
|
201
|
-
case "popFirst":
|
|
202
|
-
return this.tree.popFirst();
|
|
203
|
-
case "popLast":
|
|
204
|
-
return this.tree.popLast();
|
|
205
|
-
default:
|
|
206
|
-
return assertNeverMutation(mutation);
|
|
312
|
+
try {
|
|
313
|
+
for (const mutation of log.mutations) {
|
|
314
|
+
applyMutationLocal(this.tree, mutation, () => {
|
|
315
|
+
this.initSeen = true;
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
this.currentVersion = log.version;
|
|
319
|
+
} catch (error) {
|
|
320
|
+
this.corrupted = true;
|
|
321
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
322
|
+
throw new BTreeConcurrencyError(
|
|
323
|
+
`Replay failure: instance is permanently corrupted. Discard and create a new instance. Cause: ${cause}`
|
|
324
|
+
);
|
|
207
325
|
}
|
|
208
326
|
}
|
|
209
327
|
runExclusive(operation) {
|
|
210
|
-
const run = async () =>
|
|
328
|
+
const run = async () => {
|
|
329
|
+
if (this.corrupted) {
|
|
330
|
+
throw new BTreeConcurrencyError(
|
|
331
|
+
"Instance is permanently corrupted. Discard and create a new instance."
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
return operation();
|
|
335
|
+
};
|
|
211
336
|
const result = this.operationQueue.then(run, run);
|
|
212
337
|
this.operationQueue = result.then(
|
|
213
338
|
() => void 0,
|
|
@@ -235,13 +360,29 @@ var ConcurrentInMemoryBTree = class {
|
|
|
235
360
|
const appendResult = await this.store.append(expectedVersion, mutations);
|
|
236
361
|
assertAppendVersionContract(expectedVersion, appendResult);
|
|
237
362
|
if (appendResult.applied) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
363
|
+
try {
|
|
364
|
+
for (const m of mutations) {
|
|
365
|
+
if (m === mutation) break;
|
|
366
|
+
applyMutationLocal(this.tree, m, () => {
|
|
367
|
+
this.initSeen = true;
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
const localResult = applyMutationLocal(
|
|
371
|
+
this.tree,
|
|
372
|
+
mutation,
|
|
373
|
+
() => {
|
|
374
|
+
this.initSeen = true;
|
|
375
|
+
}
|
|
376
|
+
);
|
|
377
|
+
this.currentVersion = appendResult.version;
|
|
378
|
+
return localResult;
|
|
379
|
+
} catch (error) {
|
|
380
|
+
this.corrupted = true;
|
|
381
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
382
|
+
throw new BTreeConcurrencyError(
|
|
383
|
+
`Local apply failure after successful append: instance is permanently corrupted. Discard and create a new instance. Cause: ${cause}`
|
|
384
|
+
);
|
|
241
385
|
}
|
|
242
|
-
const localResult = this.applyMutationLocal(mutation);
|
|
243
|
-
this.currentVersion = appendResult.version;
|
|
244
|
-
return localResult;
|
|
245
386
|
}
|
|
246
387
|
}
|
|
247
388
|
throw new BTreeConcurrencyError(
|
|
@@ -251,47 +392,56 @@ var ConcurrentInMemoryBTree = class {
|
|
|
251
392
|
async put(key, value) {
|
|
252
393
|
return this.runExclusive(async () => {
|
|
253
394
|
return this.appendMutationAndApplyUnlocked(
|
|
254
|
-
(
|
|
255
|
-
if (this.duplicateKeys === "reject" && tree.hasKey(key)) {
|
|
256
|
-
throw new BTreeValidationError("Duplicate key rejected.");
|
|
257
|
-
}
|
|
258
|
-
return { type: "put", key, value };
|
|
259
|
-
}
|
|
395
|
+
createPutEvaluator(this.duplicateKeys, key, value)
|
|
260
396
|
);
|
|
261
397
|
});
|
|
262
398
|
}
|
|
263
399
|
async remove(key) {
|
|
264
400
|
return this.runExclusive(async () => {
|
|
265
|
-
return this.appendMutationAndApplyUnlocked(
|
|
266
|
-
(tree) => {
|
|
267
|
-
return tree.hasKey(key) ? { type: "remove", key } : null;
|
|
268
|
-
}
|
|
269
|
-
);
|
|
401
|
+
return this.appendMutationAndApplyUnlocked(createRemoveEvaluator(key));
|
|
270
402
|
});
|
|
271
403
|
}
|
|
272
404
|
async removeById(entryId) {
|
|
273
405
|
return this.runExclusive(async () => {
|
|
274
|
-
return this.appendMutationAndApplyUnlocked(
|
|
275
|
-
(tree) => {
|
|
276
|
-
return tree.peekById(entryId) !== null ? { type: "removeById", entryId } : null;
|
|
277
|
-
}
|
|
278
|
-
);
|
|
406
|
+
return this.appendMutationAndApplyUnlocked(createRemoveByIdEvaluator(entryId));
|
|
279
407
|
});
|
|
280
408
|
}
|
|
281
409
|
async updateById(entryId, value) {
|
|
410
|
+
return this.runExclusive(async () => {
|
|
411
|
+
return this.appendMutationAndApplyUnlocked(createUpdateByIdEvaluator(entryId, value));
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
async popFirst() {
|
|
415
|
+
return this.runExclusive(async () => {
|
|
416
|
+
return this.appendMutationAndApplyUnlocked(createPopFirstEvaluator());
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
async popLast() {
|
|
420
|
+
return this.runExclusive(async () => {
|
|
421
|
+
return this.appendMutationAndApplyUnlocked(createPopLastEvaluator());
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
async putMany(entries) {
|
|
425
|
+
if (entries.length === 0) {
|
|
426
|
+
return [];
|
|
427
|
+
}
|
|
282
428
|
return this.runExclusive(async () => {
|
|
283
429
|
return this.appendMutationAndApplyUnlocked(
|
|
284
|
-
(
|
|
285
|
-
return tree.peekById(entryId) !== null ? { type: "updateById", entryId, value } : null;
|
|
286
|
-
}
|
|
430
|
+
createPutManyEvaluator(entries, this.duplicateKeys, this.compareKeys)
|
|
287
431
|
);
|
|
288
432
|
});
|
|
289
433
|
}
|
|
290
|
-
async
|
|
434
|
+
async deleteRange(startKey, endKey, options) {
|
|
291
435
|
return this.runExclusive(async () => {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
436
|
+
const result = await this.appendMutationAndApplyUnlocked(
|
|
437
|
+
createDeleteRangeEvaluator(startKey, endKey, options)
|
|
438
|
+
);
|
|
439
|
+
return result ?? 0;
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
async clear() {
|
|
443
|
+
await this.runExclusive(async () => {
|
|
444
|
+
await this.appendMutationAndApplyUnlocked(createClearEvaluator());
|
|
295
445
|
});
|
|
296
446
|
}
|
|
297
447
|
async get(key) {
|
|
@@ -327,13 +477,6 @@ var ConcurrentInMemoryBTree = class {
|
|
|
327
477
|
async peekLast() {
|
|
328
478
|
return this.readOp((tree) => tree.peekLast());
|
|
329
479
|
}
|
|
330
|
-
async popLast() {
|
|
331
|
-
return this.runExclusive(async () => {
|
|
332
|
-
return this.appendMutationAndApplyUnlocked((tree) => {
|
|
333
|
-
return tree.peekLast() !== null ? { type: "popLast" } : null;
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
480
|
async peekById(entryId) {
|
|
338
481
|
return this.readOp((tree) => tree.peekById(entryId));
|
|
339
482
|
}
|
|
@@ -349,6 +492,38 @@ var ConcurrentInMemoryBTree = class {
|
|
|
349
492
|
async getPairOrNextLower(key) {
|
|
350
493
|
return this.readOp((tree) => tree.getPairOrNextLower(key));
|
|
351
494
|
}
|
|
495
|
+
async entries() {
|
|
496
|
+
return this.readOp((tree) => Array.from(tree.entries()));
|
|
497
|
+
}
|
|
498
|
+
async entriesReversed() {
|
|
499
|
+
return this.readOp((tree) => Array.from(tree.entriesReversed()));
|
|
500
|
+
}
|
|
501
|
+
async keys() {
|
|
502
|
+
return this.readOp((tree) => Array.from(tree.keys()));
|
|
503
|
+
}
|
|
504
|
+
async values() {
|
|
505
|
+
return this.readOp((tree) => Array.from(tree.values()));
|
|
506
|
+
}
|
|
507
|
+
async forEach(callback) {
|
|
508
|
+
await this.readOp((tree) => {
|
|
509
|
+
tree.forEach(callback);
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
async *[Symbol.asyncIterator]() {
|
|
513
|
+
const all = await this.entries();
|
|
514
|
+
for (const entry of all) {
|
|
515
|
+
yield entry;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async clone() {
|
|
519
|
+
return this.readOp((tree) => tree.clone());
|
|
520
|
+
}
|
|
521
|
+
async toJSON() {
|
|
522
|
+
return this.readOp((tree) => tree.toJSON());
|
|
523
|
+
}
|
|
524
|
+
static fromJSON(json, compareKeys) {
|
|
525
|
+
return InMemoryBTree.fromJSON(json, compareKeys);
|
|
526
|
+
}
|
|
352
527
|
};
|
|
353
528
|
export {
|
|
354
529
|
BTreeConcurrencyError,
|
package/package.json
CHANGED