@frostpillar/frostpillar-btree 0.2.6 → 0.2.8
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 +95 -73
- package/README.md +96 -74
- package/dist/InMemoryBTree.d.ts +3 -36
- package/dist/btree/autoScale.d.ts +1 -0
- package/dist/btree/entry-lookup.d.ts +8 -0
- package/dist/btree/mutations.d.ts +1 -3
- package/dist/btree/rangeQuery.d.ts +4 -1
- package/dist/btree/rebalance-branch.d.ts +4 -0
- package/dist/btree/rebalance.d.ts +5 -2
- package/dist/btree/serialization.d.ts +3 -1
- package/dist/btree/split.d.ts +3 -0
- package/dist/btree/traversal.d.ts +7 -0
- package/dist/btree/types.d.ts +14 -3
- package/dist/{chunk-OWHENPGJ.js → chunk-OFXDCKLC.js} +663 -395
- package/dist/concurrency/ConcurrentInMemoryBTree.d.ts +3 -14
- package/dist/concurrency/coordinator.d.ts +21 -0
- package/dist/concurrency/syncLogValidation.d.ts +2 -0
- package/dist/core.cjs +663 -395
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/frostpillar-btree-core.min.js +1 -1
- package/dist/frostpillar-btree.min.js +1 -1
- package/dist/index.cjs +856 -545
- package/dist/index.d.ts +1 -1
- package/dist/index.js +190 -147
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { InMemoryBTree } from './InMemoryBTree.js';
|
|
2
|
-
export type { BTreeEntry, BTreeJSON, BTreeStats, DuplicateKeyPolicy, EntryId, InMemoryBTreeConfig, RangeBounds, } from './InMemoryBTree.js';
|
|
2
|
+
export type { BTreeEntry, BTreeJSON, BTreeStats, DeleteRebalancePolicy, DuplicateKeyPolicy, EntryId, InMemoryBTreeConfig, RangeBounds, } from './InMemoryBTree.js';
|
|
3
3
|
export { ConcurrentInMemoryBTree } from './concurrency/index.js';
|
|
4
4
|
export type { BTreeMutation, ConcurrentInMemoryBTreeConfig, ReadMode, SharedTreeLog, SharedTreeStore, } from './concurrency/index.js';
|
|
5
5
|
export { BTreeConcurrencyError, BTreeInvariantError, BTreeValidationError, } from './errors.js';
|
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-OFXDCKLC.js";
|
|
10
10
|
|
|
11
11
|
// src/concurrency/helpers.ts
|
|
12
12
|
var DEFAULT_MAX_RETRIES = 16;
|
|
@@ -33,13 +33,17 @@ var assertNeverMutation = (mutation) => {
|
|
|
33
33
|
var validatePutManyEntries = (entries) => {
|
|
34
34
|
for (const entry of entries) {
|
|
35
35
|
if (typeof entry !== "object" || entry === null || !("key" in entry) || !("value" in entry)) {
|
|
36
|
-
throw new BTreeConcurrencyError(
|
|
36
|
+
throw new BTreeConcurrencyError(
|
|
37
|
+
"Malformed putMany mutation: each entry must have key and value."
|
|
38
|
+
);
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
};
|
|
40
42
|
var validateInitMutation = (m, expectedConfigFingerprint) => {
|
|
41
43
|
if (typeof m.configFingerprint !== "string") {
|
|
42
|
-
throw new BTreeConcurrencyError(
|
|
44
|
+
throw new BTreeConcurrencyError(
|
|
45
|
+
"Malformed init mutation: missing configFingerprint."
|
|
46
|
+
);
|
|
43
47
|
}
|
|
44
48
|
if (expectedConfigFingerprint !== void 0 && m.configFingerprint !== expectedConfigFingerprint) {
|
|
45
49
|
throw new BTreeConcurrencyError(
|
|
@@ -47,45 +51,70 @@ var validateInitMutation = (m, expectedConfigFingerprint) => {
|
|
|
47
51
|
);
|
|
48
52
|
}
|
|
49
53
|
};
|
|
50
|
-
var
|
|
54
|
+
var validateMutationFields = (m) => {
|
|
51
55
|
switch (m.type) {
|
|
52
|
-
case "init":
|
|
53
|
-
validateInitMutation(m, expectedConfigFingerprint);
|
|
54
|
-
break;
|
|
55
56
|
case "put":
|
|
56
57
|
if (!("key" in m) || !("value" in m)) {
|
|
57
|
-
throw new BTreeConcurrencyError(
|
|
58
|
+
throw new BTreeConcurrencyError(
|
|
59
|
+
"Malformed put mutation: missing key or value."
|
|
60
|
+
);
|
|
58
61
|
}
|
|
59
62
|
break;
|
|
60
63
|
case "remove":
|
|
61
64
|
if (!("key" in m)) {
|
|
62
|
-
throw new BTreeConcurrencyError(
|
|
65
|
+
throw new BTreeConcurrencyError(
|
|
66
|
+
"Malformed remove mutation: missing key."
|
|
67
|
+
);
|
|
63
68
|
}
|
|
64
69
|
break;
|
|
65
70
|
case "removeById":
|
|
66
71
|
if (!("entryId" in m)) {
|
|
67
|
-
throw new BTreeConcurrencyError(
|
|
72
|
+
throw new BTreeConcurrencyError(
|
|
73
|
+
"Malformed removeById mutation: missing entryId."
|
|
74
|
+
);
|
|
68
75
|
}
|
|
69
76
|
break;
|
|
70
77
|
case "updateById":
|
|
71
78
|
if (!("entryId" in m) || !("value" in m)) {
|
|
72
|
-
throw new BTreeConcurrencyError(
|
|
79
|
+
throw new BTreeConcurrencyError(
|
|
80
|
+
"Malformed updateById mutation: missing entryId or value."
|
|
81
|
+
);
|
|
73
82
|
}
|
|
74
83
|
break;
|
|
75
|
-
case "popFirst":
|
|
76
|
-
case "popLast":
|
|
77
|
-
break;
|
|
78
84
|
case "putMany":
|
|
79
85
|
if (!("entries" in m) || !Array.isArray(m.entries)) {
|
|
80
|
-
throw new BTreeConcurrencyError(
|
|
86
|
+
throw new BTreeConcurrencyError(
|
|
87
|
+
"Malformed putMany mutation: missing entries array."
|
|
88
|
+
);
|
|
81
89
|
}
|
|
82
90
|
validatePutManyEntries(m.entries);
|
|
83
91
|
break;
|
|
84
92
|
case "deleteRange":
|
|
85
93
|
if (!("startKey" in m) || !("endKey" in m)) {
|
|
86
|
-
throw new BTreeConcurrencyError(
|
|
94
|
+
throw new BTreeConcurrencyError(
|
|
95
|
+
"Malformed deleteRange mutation: missing startKey or endKey."
|
|
96
|
+
);
|
|
87
97
|
}
|
|
88
98
|
break;
|
|
99
|
+
default:
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var validateSingleMutation = (m, expectedConfigFingerprint) => {
|
|
104
|
+
switch (m.type) {
|
|
105
|
+
case "init":
|
|
106
|
+
validateInitMutation(m, expectedConfigFingerprint);
|
|
107
|
+
break;
|
|
108
|
+
case "put":
|
|
109
|
+
case "remove":
|
|
110
|
+
case "removeById":
|
|
111
|
+
case "updateById":
|
|
112
|
+
case "putMany":
|
|
113
|
+
case "deleteRange":
|
|
114
|
+
validateMutationFields(m);
|
|
115
|
+
break;
|
|
116
|
+
case "popFirst":
|
|
117
|
+
case "popLast":
|
|
89
118
|
case "clear":
|
|
90
119
|
break;
|
|
91
120
|
default:
|
|
@@ -97,7 +126,9 @@ var validateSingleMutation = (m, expectedConfigFingerprint) => {
|
|
|
97
126
|
var validateMutationBatch = (mutations, expectedConfigFingerprint) => {
|
|
98
127
|
for (const mutation of mutations) {
|
|
99
128
|
if (typeof mutation !== "object" || mutation === null) {
|
|
100
|
-
throw new BTreeConcurrencyError(
|
|
129
|
+
throw new BTreeConcurrencyError(
|
|
130
|
+
"Malformed mutation: expected an object."
|
|
131
|
+
);
|
|
101
132
|
}
|
|
102
133
|
validateSingleMutation(
|
|
103
134
|
mutation,
|
|
@@ -132,9 +163,7 @@ var normalizeReadMode = (value) => {
|
|
|
132
163
|
return "strong";
|
|
133
164
|
}
|
|
134
165
|
if (value !== "strong" && value !== "local") {
|
|
135
|
-
throw new BTreeConcurrencyError(
|
|
136
|
-
`readMode: must be 'strong' or 'local'.`
|
|
137
|
-
);
|
|
166
|
+
throw new BTreeConcurrencyError(`readMode: must be 'strong' or 'local'.`);
|
|
138
167
|
}
|
|
139
168
|
return value;
|
|
140
169
|
};
|
|
@@ -184,7 +213,11 @@ var applyMutationLocal = (tree, mutation, onInit) => {
|
|
|
184
213
|
case "popLast":
|
|
185
214
|
return tree.popLast();
|
|
186
215
|
case "deleteRange":
|
|
187
|
-
return tree.deleteRange(
|
|
216
|
+
return tree.deleteRange(
|
|
217
|
+
mutation.startKey,
|
|
218
|
+
mutation.endKey,
|
|
219
|
+
mutation.options
|
|
220
|
+
);
|
|
188
221
|
case "clear":
|
|
189
222
|
tree.clear();
|
|
190
223
|
return null;
|
|
@@ -231,7 +264,9 @@ var createPutManyEvaluator = (entries, duplicateKeys, compareKeys) => {
|
|
|
231
264
|
for (let i = 1; i < entries.length; i += 1) {
|
|
232
265
|
const cmp = compareKeys(entries[i - 1].key, entries[i].key);
|
|
233
266
|
if (cmp > 0) {
|
|
234
|
-
throw new BTreeValidationError(
|
|
267
|
+
throw new BTreeValidationError(
|
|
268
|
+
"putMany: entries not in ascending order."
|
|
269
|
+
);
|
|
235
270
|
}
|
|
236
271
|
if (strictlyAscending && cmp === 0) {
|
|
237
272
|
throw new BTreeValidationError(
|
|
@@ -262,59 +297,48 @@ var createClearEvaluator = () => {
|
|
|
262
297
|
return () => ({ type: "clear" });
|
|
263
298
|
};
|
|
264
299
|
|
|
265
|
-
// src/concurrency/
|
|
266
|
-
var
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
300
|
+
// src/concurrency/syncLogValidation.ts
|
|
301
|
+
var validateSyncLog = (log, maxSyncMutationsPerBatch) => {
|
|
302
|
+
if (typeof log.version !== "bigint") {
|
|
303
|
+
throw new BTreeConcurrencyError("Store contract: version must be bigint.");
|
|
304
|
+
}
|
|
305
|
+
if (!Array.isArray(log.mutations)) {
|
|
306
|
+
throw new BTreeConcurrencyError(
|
|
307
|
+
"Store contract: mutations must be an array."
|
|
273
308
|
);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
309
|
+
}
|
|
310
|
+
if (log.mutations.length > maxSyncMutationsPerBatch) {
|
|
311
|
+
throw new BTreeConcurrencyError(
|
|
312
|
+
`Sync batch exceeded limit (${String(maxSyncMutationsPerBatch)}).`
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// src/concurrency/coordinator.ts
|
|
318
|
+
var Coordinator = class {
|
|
319
|
+
constructor(tree, store, maxRetries, maxSyncMutationsPerBatch, configFingerprint, readMode) {
|
|
320
|
+
this.tree = tree;
|
|
321
|
+
this.store = store;
|
|
322
|
+
this.maxRetries = maxRetries;
|
|
323
|
+
this.maxSyncMutationsPerBatch = maxSyncMutationsPerBatch;
|
|
324
|
+
this.configFingerprint = configFingerprint;
|
|
325
|
+
this.readMode = readMode;
|
|
285
326
|
this.currentVersion = 0n;
|
|
286
327
|
this.operationQueue = Promise.resolve();
|
|
287
328
|
this.initSeen = false;
|
|
288
329
|
this.corrupted = false;
|
|
289
330
|
}
|
|
290
|
-
async sync() {
|
|
291
|
-
await this.runExclusive(async () => {
|
|
292
|
-
await this.syncUnlocked();
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
331
|
async syncUnlocked() {
|
|
296
332
|
const log = await this.store.getLogEntriesSince(this.currentVersion);
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
if (!Array.isArray(log.mutations)) {
|
|
301
|
-
throw new BTreeConcurrencyError("Store contract: mutations must be an array.");
|
|
302
|
-
}
|
|
303
|
-
if (log.mutations.length > this.maxSyncMutationsPerBatch) {
|
|
304
|
-
throw new BTreeConcurrencyError(
|
|
305
|
-
`Sync batch exceeded limit (${String(this.maxSyncMutationsPerBatch)}).`
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
if (log.version <= this.currentVersion) {
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
333
|
+
validateSyncLog(log, this.maxSyncMutationsPerBatch);
|
|
334
|
+
if (log.version <= this.currentVersion) return;
|
|
311
335
|
validateMutationBatch(log.mutations, this.configFingerprint);
|
|
312
336
|
try {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
337
|
+
const markInit = () => {
|
|
338
|
+
this.initSeen = true;
|
|
339
|
+
};
|
|
340
|
+
for (const mutation of log.mutations)
|
|
341
|
+
applyMutationLocal(this.tree, mutation, markInit);
|
|
318
342
|
this.currentVersion = log.version;
|
|
319
343
|
} catch (error) {
|
|
320
344
|
this.corrupted = true;
|
|
@@ -326,11 +350,10 @@ var ConcurrentInMemoryBTree = class {
|
|
|
326
350
|
}
|
|
327
351
|
runExclusive(operation) {
|
|
328
352
|
const run = async () => {
|
|
329
|
-
if (this.corrupted)
|
|
353
|
+
if (this.corrupted)
|
|
330
354
|
throw new BTreeConcurrencyError(
|
|
331
355
|
"Instance is permanently corrupted. Discard and create a new instance."
|
|
332
356
|
);
|
|
333
|
-
}
|
|
334
357
|
return operation();
|
|
335
358
|
};
|
|
336
359
|
const result = this.operationQueue.then(run, run);
|
|
@@ -342,40 +365,38 @@ var ConcurrentInMemoryBTree = class {
|
|
|
342
365
|
}
|
|
343
366
|
readOp(fn) {
|
|
344
367
|
return this.runExclusive(async () => {
|
|
345
|
-
if (this.readMode === "strong")
|
|
346
|
-
await this.syncUnlocked();
|
|
347
|
-
}
|
|
368
|
+
if (this.readMode === "strong") await this.syncUnlocked();
|
|
348
369
|
return fn(this.tree);
|
|
349
370
|
});
|
|
350
371
|
}
|
|
351
|
-
async
|
|
372
|
+
async appendAndApply(evaluate) {
|
|
352
373
|
for (let attempt = 0; attempt < this.maxRetries; attempt += 1) {
|
|
353
374
|
await this.syncUnlocked();
|
|
354
375
|
const mutation = evaluate(this.tree);
|
|
355
|
-
if (mutation === null)
|
|
356
|
-
return null;
|
|
357
|
-
}
|
|
376
|
+
if (mutation === null) return null;
|
|
358
377
|
const expectedVersion = this.currentVersion;
|
|
359
|
-
const mutations = this.initSeen ? [mutation] : [
|
|
378
|
+
const mutations = this.initSeen ? [mutation] : [
|
|
379
|
+
{ type: "init", configFingerprint: this.configFingerprint },
|
|
380
|
+
mutation
|
|
381
|
+
];
|
|
360
382
|
const appendResult = await this.store.append(expectedVersion, mutations);
|
|
361
383
|
assertAppendVersionContract(expectedVersion, appendResult);
|
|
362
384
|
if (appendResult.applied) {
|
|
363
385
|
try {
|
|
386
|
+
const markInit = () => {
|
|
387
|
+
this.initSeen = true;
|
|
388
|
+
};
|
|
364
389
|
for (const m of mutations) {
|
|
365
390
|
if (m === mutation) break;
|
|
366
|
-
applyMutationLocal(this.tree, m,
|
|
367
|
-
this.initSeen = true;
|
|
368
|
-
});
|
|
391
|
+
applyMutationLocal(this.tree, m, markInit);
|
|
369
392
|
}
|
|
370
|
-
const
|
|
393
|
+
const result = applyMutationLocal(
|
|
371
394
|
this.tree,
|
|
372
395
|
mutation,
|
|
373
|
-
|
|
374
|
-
this.initSeen = true;
|
|
375
|
-
}
|
|
396
|
+
markInit
|
|
376
397
|
);
|
|
377
398
|
this.currentVersion = appendResult.version;
|
|
378
|
-
return
|
|
399
|
+
return result;
|
|
379
400
|
} catch (error) {
|
|
380
401
|
this.corrupted = true;
|
|
381
402
|
const cause = error instanceof Error ? error.message : String(error);
|
|
@@ -389,137 +410,159 @@ var ConcurrentInMemoryBTree = class {
|
|
|
389
410
|
`Mutation failed after ${String(this.maxRetries)} retries.`
|
|
390
411
|
);
|
|
391
412
|
}
|
|
392
|
-
|
|
393
|
-
return this.runExclusive(async () =>
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
413
|
+
writeOp(evaluator) {
|
|
414
|
+
return this.runExclusive(async () => this.appendAndApply(evaluator));
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
// src/concurrency/ConcurrentInMemoryBTree.ts
|
|
419
|
+
var ConcurrentInMemoryBTree = class {
|
|
420
|
+
constructor(config) {
|
|
421
|
+
this.compareKeys = config.compareKeys;
|
|
422
|
+
this.duplicateKeys = config.duplicateKeys ?? "replace";
|
|
423
|
+
const tree = new InMemoryBTree({
|
|
424
|
+
compareKeys: config.compareKeys,
|
|
425
|
+
maxLeafEntries: config.maxLeafEntries,
|
|
426
|
+
maxBranchChildren: config.maxBranchChildren,
|
|
427
|
+
duplicateKeys: config.duplicateKeys,
|
|
428
|
+
enableEntryIdLookup: config.enableEntryIdLookup,
|
|
429
|
+
autoScale: config.autoScale,
|
|
430
|
+
deleteRebalancePolicy: config.deleteRebalancePolicy
|
|
397
431
|
});
|
|
432
|
+
this.coord = new Coordinator(
|
|
433
|
+
tree,
|
|
434
|
+
config.store,
|
|
435
|
+
normalizeMaxRetries(config.maxRetries),
|
|
436
|
+
normalizeMaxSyncMutationsPerBatch(config.maxSyncMutationsPerBatch),
|
|
437
|
+
computeConfigFingerprint(config),
|
|
438
|
+
normalizeReadMode(config.readMode)
|
|
439
|
+
);
|
|
398
440
|
}
|
|
399
|
-
async
|
|
400
|
-
|
|
401
|
-
|
|
441
|
+
async sync() {
|
|
442
|
+
await this.coord.runExclusive(async () => {
|
|
443
|
+
await this.coord.syncUnlocked();
|
|
402
444
|
});
|
|
403
445
|
}
|
|
404
|
-
async
|
|
405
|
-
return this.runExclusive(async () => {
|
|
406
|
-
|
|
446
|
+
async syncThenRead(fn) {
|
|
447
|
+
return this.coord.runExclusive(async () => {
|
|
448
|
+
await this.coord.syncUnlocked();
|
|
449
|
+
return fn(this.coord.tree);
|
|
407
450
|
});
|
|
408
451
|
}
|
|
452
|
+
async put(key, value) {
|
|
453
|
+
return this.coord.writeOp(
|
|
454
|
+
createPutEvaluator(this.duplicateKeys, key, value)
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
async remove(key) {
|
|
458
|
+
return this.coord.writeOp(createRemoveEvaluator(key));
|
|
459
|
+
}
|
|
460
|
+
async removeById(entryId) {
|
|
461
|
+
return this.coord.writeOp(createRemoveByIdEvaluator(entryId));
|
|
462
|
+
}
|
|
409
463
|
async updateById(entryId, value) {
|
|
410
|
-
return this.
|
|
411
|
-
return this.appendMutationAndApplyUnlocked(createUpdateByIdEvaluator(entryId, value));
|
|
412
|
-
});
|
|
464
|
+
return this.coord.writeOp(createUpdateByIdEvaluator(entryId, value));
|
|
413
465
|
}
|
|
414
466
|
async popFirst() {
|
|
415
|
-
return this.
|
|
416
|
-
return this.appendMutationAndApplyUnlocked(createPopFirstEvaluator());
|
|
417
|
-
});
|
|
467
|
+
return this.coord.writeOp(createPopFirstEvaluator());
|
|
418
468
|
}
|
|
419
469
|
async popLast() {
|
|
420
|
-
return this.
|
|
421
|
-
return this.appendMutationAndApplyUnlocked(createPopLastEvaluator());
|
|
422
|
-
});
|
|
470
|
+
return this.coord.writeOp(createPopLastEvaluator());
|
|
423
471
|
}
|
|
424
472
|
async putMany(entries) {
|
|
425
|
-
if (entries.length === 0)
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
return this.appendMutationAndApplyUnlocked(
|
|
430
|
-
createPutManyEvaluator(entries, this.duplicateKeys, this.compareKeys)
|
|
431
|
-
);
|
|
432
|
-
});
|
|
473
|
+
if (entries.length === 0) return [];
|
|
474
|
+
return this.coord.writeOp(
|
|
475
|
+
createPutManyEvaluator(entries, this.duplicateKeys, this.compareKeys)
|
|
476
|
+
);
|
|
433
477
|
}
|
|
434
478
|
async deleteRange(startKey, endKey, options) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
return result ?? 0;
|
|
440
|
-
});
|
|
479
|
+
const result = await this.coord.writeOp(
|
|
480
|
+
createDeleteRangeEvaluator(startKey, endKey, options)
|
|
481
|
+
);
|
|
482
|
+
return result ?? 0;
|
|
441
483
|
}
|
|
442
484
|
async clear() {
|
|
443
|
-
await this.
|
|
444
|
-
await this.appendMutationAndApplyUnlocked(createClearEvaluator());
|
|
445
|
-
});
|
|
485
|
+
await this.coord.writeOp(createClearEvaluator());
|
|
446
486
|
}
|
|
447
487
|
async get(key) {
|
|
448
|
-
return this.readOp((
|
|
488
|
+
return this.coord.readOp((t) => t.get(key));
|
|
449
489
|
}
|
|
450
490
|
async hasKey(key) {
|
|
451
|
-
return this.readOp((
|
|
491
|
+
return this.coord.readOp((t) => t.hasKey(key));
|
|
452
492
|
}
|
|
453
493
|
async findFirst(key) {
|
|
454
|
-
return this.readOp((
|
|
494
|
+
return this.coord.readOp((t) => t.findFirst(key));
|
|
455
495
|
}
|
|
456
496
|
async findLast(key) {
|
|
457
|
-
return this.readOp((
|
|
497
|
+
return this.coord.readOp((t) => t.findLast(key));
|
|
458
498
|
}
|
|
459
499
|
async range(startKey, endKey, options) {
|
|
460
|
-
return this.readOp((
|
|
500
|
+
return this.coord.readOp((t) => t.range(startKey, endKey, options));
|
|
461
501
|
}
|
|
462
502
|
async snapshot() {
|
|
463
|
-
return this.readOp((
|
|
503
|
+
return this.coord.readOp((t) => t.snapshot());
|
|
464
504
|
}
|
|
465
505
|
async size() {
|
|
466
|
-
return this.readOp((
|
|
506
|
+
return this.coord.readOp((t) => t.size());
|
|
467
507
|
}
|
|
468
508
|
async assertInvariants() {
|
|
469
|
-
await this.readOp((
|
|
509
|
+
await this.coord.readOp((t) => t.assertInvariants());
|
|
470
510
|
}
|
|
471
511
|
async getStats() {
|
|
472
|
-
return this.readOp((
|
|
512
|
+
return this.coord.readOp((t) => t.getStats());
|
|
473
513
|
}
|
|
474
514
|
async peekFirst() {
|
|
475
|
-
return this.readOp((
|
|
515
|
+
return this.coord.readOp((t) => t.peekFirst());
|
|
476
516
|
}
|
|
477
517
|
async peekLast() {
|
|
478
|
-
return this.readOp((
|
|
518
|
+
return this.coord.readOp((t) => t.peekLast());
|
|
479
519
|
}
|
|
480
520
|
async peekById(entryId) {
|
|
481
|
-
return this.readOp((
|
|
521
|
+
return this.coord.readOp((t) => t.peekById(entryId));
|
|
482
522
|
}
|
|
483
523
|
async count(startKey, endKey, options) {
|
|
484
|
-
return this.readOp((
|
|
524
|
+
return this.coord.readOp((t) => t.count(startKey, endKey, options));
|
|
485
525
|
}
|
|
486
526
|
async nextHigherKey(key) {
|
|
487
|
-
return this.readOp((
|
|
527
|
+
return this.coord.readOp((t) => t.nextHigherKey(key));
|
|
488
528
|
}
|
|
489
529
|
async nextLowerKey(key) {
|
|
490
|
-
return this.readOp((
|
|
530
|
+
return this.coord.readOp((t) => t.nextLowerKey(key));
|
|
491
531
|
}
|
|
492
532
|
async getPairOrNextLower(key) {
|
|
493
|
-
return this.readOp((
|
|
533
|
+
return this.coord.readOp((t) => t.getPairOrNextLower(key));
|
|
494
534
|
}
|
|
495
535
|
async entries() {
|
|
496
|
-
return this.readOp((
|
|
536
|
+
return this.coord.readOp((t) => Array.from(t.entries()));
|
|
497
537
|
}
|
|
498
538
|
async entriesReversed() {
|
|
499
|
-
return this.readOp((
|
|
539
|
+
return this.coord.readOp((t) => Array.from(t.entriesReversed()));
|
|
500
540
|
}
|
|
501
541
|
async keys() {
|
|
502
|
-
return this.readOp((
|
|
542
|
+
return this.coord.readOp((t) => Array.from(t.keys()));
|
|
503
543
|
}
|
|
504
544
|
async values() {
|
|
505
|
-
return this.readOp((
|
|
545
|
+
return this.coord.readOp((t) => Array.from(t.values()));
|
|
506
546
|
}
|
|
507
547
|
async forEach(callback) {
|
|
508
|
-
await this.readOp((
|
|
509
|
-
|
|
548
|
+
await this.coord.readOp((t) => {
|
|
549
|
+
t.forEach(callback);
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
async forEachRange(startKey, endKey, callback, options) {
|
|
553
|
+
await this.coord.readOp((t) => {
|
|
554
|
+
t.forEachRange(startKey, endKey, callback, options);
|
|
510
555
|
});
|
|
511
556
|
}
|
|
512
557
|
async *[Symbol.asyncIterator]() {
|
|
513
558
|
const all = await this.entries();
|
|
514
|
-
for (const entry of all)
|
|
515
|
-
yield entry;
|
|
516
|
-
}
|
|
559
|
+
for (const entry of all) yield entry;
|
|
517
560
|
}
|
|
518
561
|
async clone() {
|
|
519
|
-
return this.readOp((
|
|
562
|
+
return this.coord.readOp((t) => t.clone());
|
|
520
563
|
}
|
|
521
564
|
async toJSON() {
|
|
522
|
-
return this.readOp((
|
|
565
|
+
return this.coord.readOp((t) => t.toJSON());
|
|
523
566
|
}
|
|
524
567
|
static fromJSON(json, compareKeys) {
|
|
525
568
|
return InMemoryBTree.fromJSON(json, compareKeys);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frostpillar/frostpillar-btree",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "A tiny, zero-dependency in-memory B+ tree for TypeScript, Node.js, and browser JavaScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Hajime Sano",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@types/node": "^24.0.0",
|
|
51
51
|
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
52
52
|
"@typescript-eslint/parser": "^8.56.1",
|
|
53
|
-
"esbuild": "^0.
|
|
53
|
+
"esbuild": "^0.28.1",
|
|
54
54
|
"eslint": "^10.0.3",
|
|
55
55
|
"eslint-config-prettier": "^10.1.8",
|
|
56
56
|
"prettier": "^3.2.5",
|