serializable-bptree 8.1.6 → 8.2.0

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 CHANGED
@@ -7,7 +7,7 @@
7
7
  This is a B+tree that's totally okay with duplicate values. If you need to keep track of the B+ tree's state, don't just leave it in memory - make sure you write it down.
8
8
 
9
9
  ```typescript
10
- import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'fs'
10
+ import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs'
11
11
  import {
12
12
  BPTreeSync,
13
13
  SerializeStrategySync,
@@ -91,6 +91,8 @@ Additionally, this library supports asynchronous operations and rule-based query
91
91
 
92
92
  ```bash
93
93
  npm i serializable-bptree
94
+ # or
95
+ npx jsr add @izure/serializable-bptree
94
96
  ```
95
97
 
96
98
  ```typescript
@@ -156,7 +158,7 @@ const others = candidates.filter((c) => driver.tree !== c.tree)
156
158
  // 2. Execute query using the selected driver
157
159
  let keys = driver.tree.keys(driver.condition)
158
160
  for (const { tree, condition } of others) {
159
- keys = tree.keys(condition, keys)
161
+ keys = tree.keys(condition, { filterValues: keys })
160
162
  }
161
163
 
162
164
  console.log('Found: ', keys)
@@ -343,6 +343,30 @@ var MVCCTransaction = class {
343
343
  deleted
344
344
  };
345
345
  }
346
+ /**
347
+ * Checks for conflicts among multiple transactions.
348
+ * A conflict occurs if two or more transactions modify (write or delete) the same key.
349
+ * @param transactions Array of transactions to check.
350
+ * @returns An array of keys that are in conflict.
351
+ */
352
+ static CheckConflicts(transactions) {
353
+ const modifiedKeys = /* @__PURE__ */ new Map();
354
+ const conflicts = /* @__PURE__ */ new Set();
355
+ for (const tx of transactions) {
356
+ const txModified = /* @__PURE__ */ new Set([
357
+ ...tx.writeBuffer.keys(),
358
+ ...tx.deleteBuffer
359
+ ]);
360
+ for (const key of txModified) {
361
+ const count = modifiedKeys.get(key) ?? 0;
362
+ if (count > 0) {
363
+ conflicts.add(key);
364
+ }
365
+ modifiedKeys.set(key, count + 1);
366
+ }
367
+ }
368
+ return Array.from(conflicts);
369
+ }
346
370
  /**
347
371
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
348
372
  * Root transactions call this after commit to reclaim memory.
@@ -1632,6 +1656,15 @@ var BPTreeTransaction = class _BPTreeTransaction {
1632
1656
  }
1633
1657
  return best;
1634
1658
  }
1659
+ /**
1660
+ * Checks for conflicts between multiple transactions.
1661
+ *
1662
+ * @param transactions Array of BPTreeTransaction instances to check
1663
+ * @returns An array of keys that are in conflict. Empty array if no conflicts.
1664
+ */
1665
+ static CheckConflicts(transactions) {
1666
+ return MVCCTransaction.CheckConflicts(transactions.map((tx) => tx.mvcc));
1667
+ }
1635
1668
  /**
1636
1669
  * Returns the ID of the root node.
1637
1670
  * @returns The root node ID.
@@ -2084,11 +2117,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2084
2117
  const { root, order } = head;
2085
2118
  this.strategy.head = head;
2086
2119
  this.order = order;
2087
- this._writeHead({
2088
- root,
2089
- order: this.order,
2090
- data: this.strategy.head.data
2091
- });
2120
+ this.rootId = root;
2092
2121
  }
2093
2122
  if (this.order < 3) {
2094
2123
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -2125,17 +2154,24 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2125
2154
  }
2126
2155
  return void 0;
2127
2156
  }
2128
- *keysStream(condition, filterValues, limit, order = "asc") {
2129
- const stream = this.whereStream(condition, limit, order);
2157
+ *keysStream(condition, options) {
2158
+ const { filterValues, limit, order = "asc" } = options ?? {};
2159
+ const stream = this.whereStream(condition, options);
2130
2160
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2161
+ let count = 0;
2131
2162
  for (const [key] of stream) {
2132
2163
  if (intersection && !intersection.has(key)) {
2133
2164
  continue;
2134
2165
  }
2135
2166
  yield key;
2167
+ count++;
2168
+ if (limit !== void 0 && count >= limit) {
2169
+ break;
2170
+ }
2136
2171
  }
2137
2172
  }
2138
- *whereStream(condition, limit, order = "asc") {
2173
+ *whereStream(condition, options) {
2174
+ const { filterValues, limit, order = "asc" } = options ?? {};
2139
2175
  const driverKey = this.getDriverKey(condition);
2140
2176
  if (!driverKey) return;
2141
2177
  const value = condition[driverKey];
@@ -2158,8 +2194,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2158
2194
  earlyTerminate
2159
2195
  );
2160
2196
  let count = 0;
2197
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2161
2198
  for (const pair of generator) {
2162
2199
  const [k, v] = pair;
2200
+ if (intersection && !intersection.has(k)) {
2201
+ continue;
2202
+ }
2163
2203
  let isMatch = true;
2164
2204
  for (const key in condition) {
2165
2205
  if (key === driverKey) continue;
@@ -2179,16 +2219,16 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2179
2219
  }
2180
2220
  }
2181
2221
  }
2182
- keys(condition, filterValues, order = "asc") {
2222
+ keys(condition, options) {
2183
2223
  const set = /* @__PURE__ */ new Set();
2184
- for (const key of this.keysStream(condition, filterValues, void 0, order)) {
2224
+ for (const key of this.keysStream(condition, options)) {
2185
2225
  set.add(key);
2186
2226
  }
2187
2227
  return set;
2188
2228
  }
2189
- where(condition, order = "asc") {
2229
+ where(condition, options) {
2190
2230
  const map = /* @__PURE__ */ new Map();
2191
- for (const [key, value] of this.whereStream(condition, void 0, order)) {
2231
+ for (const [key, value] of this.whereStream(condition, options)) {
2192
2232
  map.set(key, value);
2193
2233
  }
2194
2234
  return map;
@@ -2414,6 +2454,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2414
2454
  return node;
2415
2455
  }
2416
2456
  delete(key, value) {
2457
+ if (value === void 0) {
2458
+ value = this.get(key);
2459
+ }
2460
+ if (value === void 0) {
2461
+ return;
2462
+ }
2417
2463
  let node = this.insertableNodeByPrimary(value);
2418
2464
  let found = false;
2419
2465
  while (true) {
@@ -2865,14 +2911,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2865
2911
  next,
2866
2912
  prev
2867
2913
  };
2868
- const head = await this._readHead();
2869
- if (head) {
2870
- await this._writeHead({
2871
- root: head.root,
2872
- order: head.order,
2873
- data: this.strategy.head.data
2874
- });
2875
- }
2876
2914
  await this.mvcc.create(id, node);
2877
2915
  return node;
2878
2916
  }
@@ -3165,11 +3203,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3165
3203
  const { root, order } = head;
3166
3204
  this.strategy.head = head;
3167
3205
  this.order = order;
3168
- await this._writeHead({
3169
- root,
3170
- order: this.order,
3171
- data: this.strategy.head.data
3172
- });
3206
+ this.rootId = root;
3173
3207
  }
3174
3208
  if (this.order < 3) {
3175
3209
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -3206,17 +3240,24 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3206
3240
  }
3207
3241
  return void 0;
3208
3242
  }
3209
- async *keysStream(condition, filterValues, limit, order = "asc") {
3210
- const stream = this.whereStream(condition, limit, order);
3243
+ async *keysStream(condition, options) {
3244
+ const { filterValues, limit, order = "asc" } = options ?? {};
3245
+ const stream = this.whereStream(condition, options);
3211
3246
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3247
+ let count = 0;
3212
3248
  for await (const [key] of stream) {
3213
3249
  if (intersection && !intersection.has(key)) {
3214
3250
  continue;
3215
3251
  }
3216
3252
  yield key;
3253
+ count++;
3254
+ if (limit !== void 0 && count >= limit) {
3255
+ break;
3256
+ }
3217
3257
  }
3218
3258
  }
3219
- async *whereStream(condition, limit, order = "asc") {
3259
+ async *whereStream(condition, options) {
3260
+ const { filterValues, limit, order = "asc" } = options ?? {};
3220
3261
  const driverKey = this.getDriverKey(condition);
3221
3262
  if (!driverKey) return;
3222
3263
  const value = condition[driverKey];
@@ -3239,8 +3280,12 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3239
3280
  earlyTerminate
3240
3281
  );
3241
3282
  let count = 0;
3283
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3242
3284
  for await (const pair of generator) {
3243
3285
  const [k, v] = pair;
3286
+ if (intersection && !intersection.has(k)) {
3287
+ continue;
3288
+ }
3244
3289
  let isMatch = true;
3245
3290
  for (const key in condition) {
3246
3291
  if (key === driverKey) continue;
@@ -3260,16 +3305,16 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3260
3305
  }
3261
3306
  }
3262
3307
  }
3263
- async keys(condition, filterValues, order = "asc") {
3308
+ async keys(condition, options) {
3264
3309
  const set = /* @__PURE__ */ new Set();
3265
- for await (const key of this.keysStream(condition, filterValues, void 0, order)) {
3310
+ for await (const key of this.keysStream(condition, options)) {
3266
3311
  set.add(key);
3267
3312
  }
3268
3313
  return set;
3269
3314
  }
3270
- async where(condition, order = "asc") {
3315
+ async where(condition, options) {
3271
3316
  const map = /* @__PURE__ */ new Map();
3272
- for await (const [key, value] of this.whereStream(condition, void 0, order)) {
3317
+ for await (const [key, value] of this.whereStream(condition, options)) {
3273
3318
  map.set(key, value);
3274
3319
  }
3275
3320
  return map;
@@ -3498,6 +3543,12 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3498
3543
  }
3499
3544
  async delete(key, value) {
3500
3545
  return this.writeLock(0, async () => {
3546
+ if (value === void 0) {
3547
+ value = await this.get(key);
3548
+ }
3549
+ if (value === void 0) {
3550
+ return;
3551
+ }
3501
3552
  let node = await this.insertableNodeByPrimary(value);
3502
3553
  let found = false;
3503
3554
  while (true) {
@@ -307,6 +307,30 @@ var MVCCTransaction = class {
307
307
  deleted
308
308
  };
309
309
  }
310
+ /**
311
+ * Checks for conflicts among multiple transactions.
312
+ * A conflict occurs if two or more transactions modify (write or delete) the same key.
313
+ * @param transactions Array of transactions to check.
314
+ * @returns An array of keys that are in conflict.
315
+ */
316
+ static CheckConflicts(transactions) {
317
+ const modifiedKeys = /* @__PURE__ */ new Map();
318
+ const conflicts = /* @__PURE__ */ new Set();
319
+ for (const tx of transactions) {
320
+ const txModified = /* @__PURE__ */ new Set([
321
+ ...tx.writeBuffer.keys(),
322
+ ...tx.deleteBuffer
323
+ ]);
324
+ for (const key of txModified) {
325
+ const count = modifiedKeys.get(key) ?? 0;
326
+ if (count > 0) {
327
+ conflicts.add(key);
328
+ }
329
+ modifiedKeys.set(key, count + 1);
330
+ }
331
+ }
332
+ return Array.from(conflicts);
333
+ }
310
334
  /**
311
335
  * Cleans up both deletedCache and versionIndex based on minActiveVersion.
312
336
  * Root transactions call this after commit to reclaim memory.
@@ -1596,6 +1620,15 @@ var BPTreeTransaction = class _BPTreeTransaction {
1596
1620
  }
1597
1621
  return best;
1598
1622
  }
1623
+ /**
1624
+ * Checks for conflicts between multiple transactions.
1625
+ *
1626
+ * @param transactions Array of BPTreeTransaction instances to check
1627
+ * @returns An array of keys that are in conflict. Empty array if no conflicts.
1628
+ */
1629
+ static CheckConflicts(transactions) {
1630
+ return MVCCTransaction.CheckConflicts(transactions.map((tx) => tx.mvcc));
1631
+ }
1599
1632
  /**
1600
1633
  * Returns the ID of the root node.
1601
1634
  * @returns The root node ID.
@@ -2048,11 +2081,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2048
2081
  const { root, order } = head;
2049
2082
  this.strategy.head = head;
2050
2083
  this.order = order;
2051
- this._writeHead({
2052
- root,
2053
- order: this.order,
2054
- data: this.strategy.head.data
2055
- });
2084
+ this.rootId = root;
2056
2085
  }
2057
2086
  if (this.order < 3) {
2058
2087
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -2089,17 +2118,24 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2089
2118
  }
2090
2119
  return void 0;
2091
2120
  }
2092
- *keysStream(condition, filterValues, limit, order = "asc") {
2093
- const stream = this.whereStream(condition, limit, order);
2121
+ *keysStream(condition, options) {
2122
+ const { filterValues, limit, order = "asc" } = options ?? {};
2123
+ const stream = this.whereStream(condition, options);
2094
2124
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2125
+ let count = 0;
2095
2126
  for (const [key] of stream) {
2096
2127
  if (intersection && !intersection.has(key)) {
2097
2128
  continue;
2098
2129
  }
2099
2130
  yield key;
2131
+ count++;
2132
+ if (limit !== void 0 && count >= limit) {
2133
+ break;
2134
+ }
2100
2135
  }
2101
2136
  }
2102
- *whereStream(condition, limit, order = "asc") {
2137
+ *whereStream(condition, options) {
2138
+ const { filterValues, limit, order = "asc" } = options ?? {};
2103
2139
  const driverKey = this.getDriverKey(condition);
2104
2140
  if (!driverKey) return;
2105
2141
  const value = condition[driverKey];
@@ -2122,8 +2158,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2122
2158
  earlyTerminate
2123
2159
  );
2124
2160
  let count = 0;
2161
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
2125
2162
  for (const pair of generator) {
2126
2163
  const [k, v] = pair;
2164
+ if (intersection && !intersection.has(k)) {
2165
+ continue;
2166
+ }
2127
2167
  let isMatch = true;
2128
2168
  for (const key in condition) {
2129
2169
  if (key === driverKey) continue;
@@ -2143,16 +2183,16 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2143
2183
  }
2144
2184
  }
2145
2185
  }
2146
- keys(condition, filterValues, order = "asc") {
2186
+ keys(condition, options) {
2147
2187
  const set = /* @__PURE__ */ new Set();
2148
- for (const key of this.keysStream(condition, filterValues, void 0, order)) {
2188
+ for (const key of this.keysStream(condition, options)) {
2149
2189
  set.add(key);
2150
2190
  }
2151
2191
  return set;
2152
2192
  }
2153
- where(condition, order = "asc") {
2193
+ where(condition, options) {
2154
2194
  const map = /* @__PURE__ */ new Map();
2155
- for (const [key, value] of this.whereStream(condition, void 0, order)) {
2195
+ for (const [key, value] of this.whereStream(condition, options)) {
2156
2196
  map.set(key, value);
2157
2197
  }
2158
2198
  return map;
@@ -2378,6 +2418,12 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
2378
2418
  return node;
2379
2419
  }
2380
2420
  delete(key, value) {
2421
+ if (value === void 0) {
2422
+ value = this.get(key);
2423
+ }
2424
+ if (value === void 0) {
2425
+ return;
2426
+ }
2381
2427
  let node = this.insertableNodeByPrimary(value);
2382
2428
  let found = false;
2383
2429
  while (true) {
@@ -2829,14 +2875,6 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
2829
2875
  next,
2830
2876
  prev
2831
2877
  };
2832
- const head = await this._readHead();
2833
- if (head) {
2834
- await this._writeHead({
2835
- root: head.root,
2836
- order: head.order,
2837
- data: this.strategy.head.data
2838
- });
2839
- }
2840
2878
  await this.mvcc.create(id, node);
2841
2879
  return node;
2842
2880
  }
@@ -3129,11 +3167,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3129
3167
  const { root, order } = head;
3130
3168
  this.strategy.head = head;
3131
3169
  this.order = order;
3132
- await this._writeHead({
3133
- root,
3134
- order: this.order,
3135
- data: this.strategy.head.data
3136
- });
3170
+ this.rootId = root;
3137
3171
  }
3138
3172
  if (this.order < 3) {
3139
3173
  throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
@@ -3170,17 +3204,24 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3170
3204
  }
3171
3205
  return void 0;
3172
3206
  }
3173
- async *keysStream(condition, filterValues, limit, order = "asc") {
3174
- const stream = this.whereStream(condition, limit, order);
3207
+ async *keysStream(condition, options) {
3208
+ const { filterValues, limit, order = "asc" } = options ?? {};
3209
+ const stream = this.whereStream(condition, options);
3175
3210
  const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3211
+ let count = 0;
3176
3212
  for await (const [key] of stream) {
3177
3213
  if (intersection && !intersection.has(key)) {
3178
3214
  continue;
3179
3215
  }
3180
3216
  yield key;
3217
+ count++;
3218
+ if (limit !== void 0 && count >= limit) {
3219
+ break;
3220
+ }
3181
3221
  }
3182
3222
  }
3183
- async *whereStream(condition, limit, order = "asc") {
3223
+ async *whereStream(condition, options) {
3224
+ const { filterValues, limit, order = "asc" } = options ?? {};
3184
3225
  const driverKey = this.getDriverKey(condition);
3185
3226
  if (!driverKey) return;
3186
3227
  const value = condition[driverKey];
@@ -3203,8 +3244,12 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3203
3244
  earlyTerminate
3204
3245
  );
3205
3246
  let count = 0;
3247
+ const intersection = filterValues && filterValues.size > 0 ? filterValues : null;
3206
3248
  for await (const pair of generator) {
3207
3249
  const [k, v] = pair;
3250
+ if (intersection && !intersection.has(k)) {
3251
+ continue;
3252
+ }
3208
3253
  let isMatch = true;
3209
3254
  for (const key in condition) {
3210
3255
  if (key === driverKey) continue;
@@ -3224,16 +3269,16 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3224
3269
  }
3225
3270
  }
3226
3271
  }
3227
- async keys(condition, filterValues, order = "asc") {
3272
+ async keys(condition, options) {
3228
3273
  const set = /* @__PURE__ */ new Set();
3229
- for await (const key of this.keysStream(condition, filterValues, void 0, order)) {
3274
+ for await (const key of this.keysStream(condition, options)) {
3230
3275
  set.add(key);
3231
3276
  }
3232
3277
  return set;
3233
3278
  }
3234
- async where(condition, order = "asc") {
3279
+ async where(condition, options) {
3235
3280
  const map = /* @__PURE__ */ new Map();
3236
- for await (const [key, value] of this.whereStream(condition, void 0, order)) {
3281
+ for await (const [key, value] of this.whereStream(condition, options)) {
3237
3282
  map.set(key, value);
3238
3283
  }
3239
3284
  return map;
@@ -3462,6 +3507,12 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
3462
3507
  }
3463
3508
  async delete(key, value) {
3464
3509
  return this.writeLock(0, async () => {
3510
+ if (value === void 0) {
3511
+ value = await this.get(key);
3512
+ }
3513
+ if (value === void 0) {
3514
+ return;
3515
+ }
3465
3516
  let node = await this.insertableNodeByPrimary(value);
3466
3517
  let found = false;
3467
3518
  while (true) {
@@ -10,5 +10,5 @@ export declare class BPTreeAsync<K, V> extends BPTreeAsyncTransaction<K, V> {
10
10
  */
11
11
  createTransaction(): Promise<BPTreeAsyncTransaction<K, V>>;
12
12
  insert(key: K, value: V): Promise<void>;
13
- delete(key: K, value: V): Promise<void>;
13
+ delete(key: K, value?: V): Promise<void>;
14
14
  }
@@ -10,5 +10,5 @@ export declare class BPTreeSync<K, V> extends BPTreeSyncTransaction<K, V> {
10
10
  */
11
11
  createTransaction(): BPTreeSyncTransaction<K, V>;
12
12
  insert(key: K, value: V): void;
13
- delete(key: K, value: V): void;
13
+ delete(key: K, value?: V): void;
14
14
  }
@@ -1,5 +1,5 @@
1
1
  import type { TransactionEntry, TransactionResult } from 'mvcc-api';
2
- import type { BPTreeCondition, BPTreeConstructorOption, BPTreeUnknownNode, Deferred, BPTreeLeafNode, BPTreeNodeKey, BPTreePair, SerializableData, BPTreeNode, BPTreeMVCC } from '../types';
2
+ import type { BPTreeCondition, BPTreeConstructorOption, BPTreeUnknownNode, Deferred, BPTreeLeafNode, BPTreeNodeKey, BPTreePair, SerializableData, BPTreeNode, BPTreeMVCC, BPTreeSearchOption } from '../types';
3
3
  import { ValueComparator } from './ValueComparator';
4
4
  import { SerializeStrategy } from './SerializeStrategy';
5
5
  export declare abstract class BPTreeTransaction<K, V> {
@@ -55,6 +55,13 @@ export declare abstract class BPTreeTransaction<K, V> {
55
55
  tree: T;
56
56
  condition: BPTreeCondition<unknown>;
57
57
  } | null;
58
+ /**
59
+ * Checks for conflicts between multiple transactions.
60
+ *
61
+ * @param transactions Array of BPTreeTransaction instances to check
62
+ * @returns An array of keys that are in conflict. Empty array if no conflicts.
63
+ */
64
+ static CheckConflicts<K, V>(transactions: BPTreeTransaction<K, V>[]): string[];
58
65
  /**
59
66
  * Returns the ID of the root node.
60
67
  * @returns The root node ID.
@@ -100,28 +107,44 @@ export declare abstract class BPTreeTransaction<K, V> {
100
107
  * This method is used to initialize the stored tree and recover data.
101
108
  * If it is not called, the tree will not function.
102
109
  */
110
+ abstract init(): Deferred<void>;
103
111
  /**
104
- * After creating a tree instance, it must be called.
105
- * This method is used to initialize the stored tree and recover data.
106
- * If it is not called, the tree will not function.
112
+ * Retrieves the value associated with the given key.
113
+ * @param key The key to search for.
114
+ * @returns A Deferred that resolves to the value if found, or undefined if not found.
107
115
  */
108
- abstract init(): Deferred<void>;
116
+ abstract get(key: K): Deferred<V | undefined>;
117
+ /**
118
+ * Returns a generator that yields keys satisfying the given condition.
119
+ * This is a memory-efficient way to iterate through keys when dealing with large result sets.
120
+ * @param condition The search condition (e.g., gt, lt, equal, like).
121
+ * @param options Search options including filterValues, limit, and order.
122
+ * @returns An async or synchronous generator yielding keys of type K.
123
+ */
124
+ abstract keysStream(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): AsyncGenerator<K> | Generator<K>;
125
+ /**
126
+ * Returns a generator that yields [key, value] pairs satisfying the given condition.
127
+ * This is a memory-efficient way to iterate through pairs when dealing with large result sets.
128
+ * @param condition The search condition (e.g., gt, lt, equal, like).
129
+ * @param options Search options including filterValues, limit, and order.
130
+ * @returns An async or synchronous generator yielding [K, V] tuples.
131
+ */
132
+ abstract whereStream(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): AsyncGenerator<[K, V]> | Generator<[K, V]>;
109
133
  /**
110
134
  * It searches for a key within the tree. The result is returned as an array sorted in ascending order based on the value.
111
135
  * The result is key set instance, and you can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
112
136
  * This method operates much faster than first searching with `where` and then retrieving only the key list.
113
137
  * @param condition You can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
114
- * @param filterValues The `Set` containing values to check for intersection.
115
- * Returns a `Set` containing values that are common to both the input `Set` and the intersection `Set`.
116
- * If this parameter is not provided, it searches for all keys inserted into the tree.
138
+ * @param options Search options including filterValues, limit, and order.
117
139
  */
118
- abstract keys(condition: BPTreeCondition<V>, filterValues?: Set<K>): Deferred<Set<K>>;
140
+ abstract keys(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Deferred<Set<K>>;
119
141
  /**
120
142
  * It searches for a value within the tree. The result is returned as an array sorted in ascending order based on the value.
121
143
  * The result includes the key and value attributes, and you can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
122
144
  * @param condition You can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
145
+ * @param options Search options including filterValues, limit, and order.
123
146
  */
124
- abstract where(condition: BPTreeCondition<V>): Deferred<BPTreePair<K, V>>;
147
+ abstract where(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Deferred<BPTreePair<K, V>>;
125
148
  /**
126
149
  * You enter the key and value as a pair. You can later search for the pair by value.
127
150
  * This data is stored in the tree, sorted in ascending order of value.
@@ -133,8 +156,9 @@ export declare abstract class BPTreeTransaction<K, V> {
133
156
  * Deletes the pair that matches the key and value.
134
157
  * @param key The key of the pair. This key must be unique.
135
158
  * @param value The value of the pair.
159
+ * @warning If the 'value' is not specified, a full scan will be performed to find the value associated with the key, which may lead to performance degradation.
136
160
  */
137
- abstract delete(key: K, value: V): Deferred<void>;
161
+ abstract delete(key: K, value?: V): Deferred<void>;
138
162
  /**
139
163
  * It returns whether there is a value in the tree.
140
164
  * @param key The key value to search for. This key must be unique.
@@ -1,5 +1,5 @@
1
1
  import type { TransactionResult } from 'mvcc-api';
2
- import type { AsyncBPTreeMVCC, BPTreeCondition, BPTreeConstructorOption, BPTreeLeafNode, BPTreeNode, BPTreeNodeKey, BPTreeOrder, BPTreePair, BPTreeUnknownNode, SerializableData, SerializeStrategyHead } from '../types';
2
+ import type { AsyncBPTreeMVCC, BPTreeCondition, BPTreeConstructorOption, BPTreeLeafNode, BPTreeNode, BPTreeNodeKey, BPTreePair, BPTreeUnknownNode, SerializableData, SerializeStrategyHead, BPTreeSearchOption } from '../types';
3
3
  import { Ryoiki } from 'ryoiki';
4
4
  import { BPTreeTransaction } from '../base/BPTreeTransaction';
5
5
  import { SerializeStrategyAsync } from '../SerializeStrategyAsync';
@@ -37,13 +37,13 @@ export declare class BPTreeAsyncTransaction<K, V> extends BPTreeTransaction<K, V
37
37
  protected _initInternal(): Promise<void>;
38
38
  exists(key: K, value: V): Promise<boolean>;
39
39
  get(key: K): Promise<V | undefined>;
40
- keysStream(condition: BPTreeCondition<V>, filterValues?: Set<K>, limit?: number, order?: BPTreeOrder): AsyncGenerator<K>;
41
- whereStream(condition: BPTreeCondition<V>, limit?: number, order?: BPTreeOrder): AsyncGenerator<[K, V]>;
42
- keys(condition: BPTreeCondition<V>, filterValues?: Set<K>, order?: BPTreeOrder): Promise<Set<K>>;
43
- where(condition: BPTreeCondition<V>, order?: BPTreeOrder): Promise<BPTreePair<K, V>>;
40
+ keysStream(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): AsyncGenerator<K>;
41
+ whereStream(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): AsyncGenerator<[K, V]>;
42
+ keys(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Promise<Set<K>>;
43
+ where(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Promise<BPTreePair<K, V>>;
44
44
  insert(key: K, value: V): Promise<void>;
45
45
  protected _deleteEntry(node: BPTreeUnknownNode<K, V>, key: BPTreeNodeKey<K>): Promise<BPTreeUnknownNode<K, V>>;
46
- delete(key: K, value: V): Promise<void>;
46
+ delete(key: K, value?: V): Promise<void>;
47
47
  getHeadData(): Promise<SerializableData>;
48
48
  setHeadData(data: SerializableData): Promise<void>;
49
49
  commit(label?: string): Promise<TransactionResult<string, BPTreeNode<K, V>>>;
@@ -1,5 +1,5 @@
1
1
  import type { TransactionResult } from 'mvcc-api';
2
- import type { BPTreeCondition, BPTreeConstructorOption, BPTreeLeafNode, BPTreeNode, BPTreeNodeKey, BPTreeOrder, BPTreePair, BPTreeUnknownNode, SerializableData, SerializeStrategyHead, SyncBPTreeMVCC } from '../types';
2
+ import type { BPTreeCondition, BPTreeConstructorOption, BPTreeLeafNode, BPTreeNode, BPTreeNodeKey, BPTreePair, BPTreeUnknownNode, SerializableData, SerializeStrategyHead, SyncBPTreeMVCC, BPTreeSearchOption } from '../types';
3
3
  import { BPTreeTransaction } from '../base/BPTreeTransaction';
4
4
  import { SerializeStrategySync } from '../SerializeStrategySync';
5
5
  import { ValueComparator } from '../base/ValueComparator';
@@ -34,13 +34,13 @@ export declare class BPTreeSyncTransaction<K, V> extends BPTreeTransaction<K, V>
34
34
  protected _initInternal(): void;
35
35
  exists(key: K, value: V): boolean;
36
36
  get(key: K): V | undefined;
37
- keysStream(condition: BPTreeCondition<V>, filterValues?: Set<K>, limit?: number, order?: BPTreeOrder): Generator<K>;
38
- whereStream(condition: BPTreeCondition<V>, limit?: number, order?: BPTreeOrder): Generator<[K, V]>;
39
- keys(condition: BPTreeCondition<V>, filterValues?: Set<K>, order?: BPTreeOrder): Set<K>;
40
- where(condition: BPTreeCondition<V>, order?: BPTreeOrder): BPTreePair<K, V>;
37
+ keysStream(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Generator<K>;
38
+ whereStream(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Generator<[K, V]>;
39
+ keys(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Set<K>;
40
+ where(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): BPTreePair<K, V>;
41
41
  insert(key: K, value: V): void;
42
42
  protected _deleteEntry(node: BPTreeUnknownNode<K, V>, key: BPTreeNodeKey<K>): BPTreeUnknownNode<K, V>;
43
- delete(key: K, value: V): void;
43
+ delete(key: K, value?: V): void;
44
44
  getHeadData(): SerializableData;
45
45
  setHeadData(data: SerializableData): void;
46
46
  commit(label?: string): TransactionResult<string, BPTreeNode<K, V>>;
@@ -52,6 +52,11 @@ export type BPTreeCondition<V> = Partial<{
52
52
  * - `'desc'`: Descending order - traverses from right to left
53
53
  */
54
54
  export type BPTreeOrder = 'asc' | 'desc';
55
+ export interface BPTreeSearchOption<K> {
56
+ filterValues?: Set<K>;
57
+ limit?: number;
58
+ order?: BPTreeOrder;
59
+ }
55
60
  export type BPTreePair<K, V> = Map<K, V>;
56
61
  export type BPTreeUnknownNode<K, V> = BPTreeInternalNode<K, V> | BPTreeLeafNode<K, V>;
57
62
  export interface BPTreeConstructorOption {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serializable-bptree",
3
- "version": "8.1.6",
3
+ "version": "8.2.0",
4
4
  "description": "Store the B+tree flexibly, not only in-memory.",
5
5
  "types": "./dist/types/index.d.ts",
6
6
  "main": "./dist/cjs/index.cjs",
@@ -38,13 +38,13 @@
38
38
  "license": "MIT",
39
39
  "devDependencies": {
40
40
  "@types/jest": "^30.0.0",
41
- "esbuild": "^0.27.2",
41
+ "esbuild": "^0.27.3",
42
42
  "jest": "^30.2.0",
43
43
  "ts-jest": "^29.4.6",
44
44
  "typescript": "^5.9.3"
45
45
  },
46
46
  "dependencies": {
47
- "mvcc-api": "^1.3.3",
47
+ "mvcc-api": "^1.3.4",
48
48
  "ryoiki": "^1.2.0"
49
49
  }
50
50
  }