@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 CHANGED
@@ -437,6 +437,8 @@ copy.put(99, 'new');
437
437
  tree.hasKey(99); // false -- 元のツリーには影響しない
438
438
  ```
439
439
 
440
+ 注意: `EntryId` の値はクローン内で再割り当てされます — 元のツリーの ID はクローンに対して有効ではありません。
441
+
440
442
  **`toJSON()` / `fromJSON()`** -- ツリーをシリアライズ・復元します。
441
443
 
442
444
  ```ts
@@ -756,6 +758,23 @@ try {
756
758
 
757
759
  ---
758
760
 
761
+ #### 共有ストアのセキュリティ前提
762
+
763
+ `ConcurrentInMemoryBTree` は共有ストアが**信頼されている**ことを前提としています。悪意を持って細工されたミューテーションペイロードや、異常に大きなペイロードに対する防御機能はありません。
764
+
765
+ **信頼境界:**
766
+ - ストアはあなたのアプリケーションの管理下にあること。
767
+ - 同一ストアを共有するすべてのインスタンスは同一の設定を使用すること(最初の書き込み時に `init` ミューテーションの設定フィンガープリントで検証されますが、リプレイバッチに `init` が含まれている場合に限ります)。
768
+ - ミューテーションはリプレイ前に構造的に検証されますが、セマンティックな正確性(キー型の整合性など)は呼び出し側の責任です。
769
+
770
+ **共有・マルチテナントデプロイメントにおける堅牢化の推奨事項:**
771
+ - 認可レイヤーなしに `append` や `getLogEntriesSince` を信頼されていないクライアントに公開しないこと。
772
+ - 格納するミューテーションペイロードのサイズ制限をストアレベルで適用してから `ConcurrentInMemoryBTree` に渡すこと。
773
+ - `maxSyncMutationsPerBatch` を使用して、1回の sync 呼び出しで適用するミューテーション数を制限すること(デフォルト:100,000)。
774
+ - リプレイ失敗により `sync()` が `BTreeConcurrencyError` をスローした場合、インスタンスは永続的に汚染されます。そのインスタンスを破棄し、新しいインスタンスを作成してください。
775
+
776
+ ---
777
+
759
778
  ## API リファレンス
760
779
 
761
780
  ### InMemoryBTree
@@ -805,18 +824,21 @@ new InMemoryBTree<TKey, TValue>(config: InMemoryBTreeConfig<TKey>)
805
824
 
806
825
  ### ConcurrentInMemoryBTree
807
826
 
808
- `InMemoryBTree` メソッドのサブセットを `Promise` を返す非同期版として提供します。書き込みは shared store を介して協調し、`readMode` が `'strong'`(デフォルト)の場合は読み取り前に同期します。`readMode` が `'local'` の場合、読み取りは同期なしでローカルツリーに対して実行されます。`putMany`・`deleteRange`・イテレータ・`clear`・`clone`・`toJSON`/`fromJSON` は現在未対応です。
827
+ `InMemoryBTree` メソッドを `Promise` を返す非同期版として提供します。書き込みは shared store を介して協調し、`readMode` が `'strong'`(デフォルト)の場合は読み取り前に同期します。`readMode` が `'local'` の場合、読み取りは同期なしでローカルツリーに対して実行されます。
809
828
 
810
829
  | メソッド | シグネチャ | 説明 |
811
830
  | -------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------- |
812
831
  | `sync` | `() => Promise<void>` | shared store の最新ログを取得して適用する。 |
813
832
  | `put` | `(key: TKey, value: TValue) => Promise<EntryId>` | 楽観的並行制御で挿入する。 |
833
+ | `putMany` | `(entries: readonly { key: TKey; value: TValue }[]) => Promise<EntryId[]>` | 楽観的並行制御で一括挿入する。 |
814
834
  | `remove` | `(key: TKey) => Promise<BTreeEntry<TKey, TValue> \| null>` | 指定キーに一致する最初のエントリを削除する。 |
815
835
  | `removeById` | `(entryId: EntryId) => Promise<BTreeEntry<TKey, TValue> \| null>` | ID でエントリを削除する。 |
816
836
  | `peekById` | `(entryId: EntryId) => Promise<BTreeEntry<TKey, TValue> \| null>` | ID でエントリを参照する(事前に同期)。 |
817
837
  | `updateById` | `(entryId: EntryId, value: TValue) => Promise<BTreeEntry<TKey, TValue> \| null>` | 楽観的並行制御で ID のエントリ値を更新する。 |
818
838
  | `popFirst` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | 最小キーのエントリを削除して返す。 |
819
839
  | `popLast` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | 最大キーのエントリを削除して返す。 |
840
+ | `deleteRange` | `(startKey: TKey, endKey: TKey, options?: RangeBounds) => Promise<number>` | 楽観的並行制御で範囲内のエントリを削除する。 |
841
+ | `clear` | `() => Promise<void>` | 楽観的並行制御で全エントリを削除する。 |
820
842
  | `peekFirst` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | 最小キーのエントリを返す(事前に同期)。 |
821
843
  | `peekLast` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | 最大キーのエントリを返す(事前に同期)。 |
822
844
  | `findFirst` | `(key: TKey) => Promise<BTreeEntry<TKey, TValue> \| null>` | キーに一致する最初のエントリを返す(事前に同期)。 |
@@ -828,10 +850,19 @@ new InMemoryBTree<TKey, TValue>(config: InMemoryBTreeConfig<TKey>)
828
850
  | `nextHigherKey` | `(key: TKey) => Promise<TKey \| null>` | 指定キーより大きい次のキー(事前に同期)。 |
829
851
  | `nextLowerKey` | `(key: TKey) => Promise<TKey \| null>` | 指定キーより小さい次のキー(事前に同期)。 |
830
852
  | `getPairOrNextLower` | `(key: TKey) => Promise<BTreeEntry<TKey, TValue> \| null>` | 一致または次に小さいエントリ(事前に同期)。 |
853
+ | `entries` | `() => Promise<BTreeEntry<TKey, TValue>[]>` | 全エントリを配列で返す(事前に同期)。 |
854
+ | `entriesReversed` | `() => Promise<BTreeEntry<TKey, TValue>[]>` | 全エントリを逆順で配列として返す(事前に同期)。 |
855
+ | `keys` | `() => Promise<TKey[]>` | 全キーを配列で返す(事前に同期)。 |
856
+ | `values` | `() => Promise<TValue[]>` | 全値を配列で返す(事前に同期)。 |
857
+ | `forEach` | `(callback: (entry: BTreeEntry<TKey, TValue>) => void) => Promise<void>` | 全エントリを反復する(事前に同期)。 |
831
858
  | `snapshot` | `() => Promise<BTreeEntry<TKey, TValue>[]>` | 全エントリを返す(事前に同期)。 |
832
859
  | `size` | `() => Promise<number>` | エントリ数を返す(事前に同期)。 |
833
860
  | `getStats` | `() => Promise<BTreeStats>` | 構造統計を返す(事前に同期)。 |
834
861
  | `assertInvariants` | `() => Promise<void>` | 構造的な整合性を検証する(事前に同期)。 |
862
+ | `clone` | `() => Promise<InMemoryBTree<TKey, TValue>>` | 独立したローカルコピーを返す(事前に同期)。 |
863
+ | `toJSON` | `() => Promise<BTreeJSON<TKey, TValue>>` | JSON にシリアライズする(事前に同期)。 |
864
+ | `fromJSON` (static) | `(json: BTreeJSON<TKey, TValue>, compareKeys: KeyComparator<TKey>) => InMemoryBTree<TKey, TValue>` | JSON からデシリアライズする(ローカルツリーを返す)。 |
865
+ | `[Symbol.asyncIterator]` | `() => AsyncIterableIterator<BTreeEntry<TKey, TValue>>` | 全エントリを非同期反復する(事前に同期)。 |
835
866
 
836
867
  **コンストラクタ:**
837
868
 
@@ -855,7 +886,7 @@ new ConcurrentInMemoryBTree<TKey, TValue>(config: ConcurrentInMemoryBTreeConfig<
855
886
  | `ConcurrentInMemoryBTreeConfig<TKey, TValue>` | `InMemoryBTreeConfig<TKey>` を拡張し、`store: SharedTreeStore<TKey, TValue>`、`maxRetries?: number`、`maxSyncMutationsPerBatch?: number`、`readMode?: ReadMode` を追加。 |
856
887
  | `SharedTreeStore<TKey, TValue>` | `getLogEntriesSince(version)` と `append(expectedVersion, mutations)` を持つインターフェース。 |
857
888
  | `SharedTreeLog<TKey, TValue>` | `{ version: bigint; mutations: BTreeMutation<TKey, TValue>[] }` |
858
- | `BTreeMutation<TKey, TValue>` | 判別共用体: `init`、`put`、`remove`、`removeById`、`updateById`、`popFirst`、`popLast`。 |
889
+ | `BTreeMutation<TKey, TValue>` | 判別共用体: `init`、`put`、`putMany`、`remove`、`removeById`、`updateById`、`popFirst`、`popLast`、`deleteRange`、`clear`。 |
859
890
  | `BTreeValidationError` | コンパレータや設定の違反でスローされるエラー。 |
860
891
  | `BTreeInvariantError` | ツリー構造の整合性違反でスローされるエラー。 |
861
892
  | `BTreeConcurrencyError` | 並行処理コンフリクトやストア契約違反でスローされるエラー。 |
package/README.md CHANGED
@@ -437,6 +437,8 @@ copy.put(99, 'new');
437
437
  tree.hasKey(99); // false — original is unaffected
438
438
  ```
439
439
 
440
+ Note: `EntryId` values are reassigned in the clone — IDs from the source tree are not valid for the clone.
441
+
440
442
  **`toJSON()` / `fromJSON()`** -- serialize and reconstruct:
441
443
 
442
444
  ```ts
@@ -756,6 +758,23 @@ try {
756
758
 
757
759
  ---
758
760
 
761
+ #### Shared Store Security Assumptions
762
+
763
+ `ConcurrentInMemoryBTree` assumes the shared store is **trusted**. It does not defend against a store that returns maliciously crafted or arbitrarily large mutation payloads.
764
+
765
+ **Trust boundary:**
766
+ - The store is under your control or the control of your application.
767
+ - All instances sharing a store must use identical configuration (enforced via config fingerprint on the first write, but only when an `init` mutation is present in the replayed batch).
768
+ - Mutations are structurally validated before replay, but semantic correctness (e.g., key type consistency) is the caller's responsibility.
769
+
770
+ **Hardening recommendations for shared or multi-tenant deployments:**
771
+ - Do not expose `append` or `getLogEntriesSince` to untrusted clients without an authorization layer.
772
+ - Apply size limits to stored mutation payloads at the store level before they reach `ConcurrentInMemoryBTree`.
773
+ - Use `maxSyncMutationsPerBatch` to cap the number of mutations applied per sync call (default: 100,000).
774
+ - If a `sync()` throws `BTreeConcurrencyError` due to a replay failure, the instance is permanently poisoned. Discard it and create a new one.
775
+
776
+ ---
777
+
759
778
  ## API Reference
760
779
 
761
780
  ### InMemoryBTree
@@ -805,18 +824,21 @@ new InMemoryBTree<TKey, TValue>(config: InMemoryBTreeConfig<TKey>)
805
824
 
806
825
  ### ConcurrentInMemoryBTree
807
826
 
808
- Exposes a subset of `InMemoryBTree` methods as async equivalents returning `Promise`. Writes coordinate through the shared store; reads sync before returning when `readMode` is `'strong'` (the default). When `readMode` is `'local'`, reads execute against the local tree without syncing. Methods such as `putMany`, iterators, `clear`, `clone`, `deleteRange`, and `toJSON`/`fromJSON` are not yet available on the concurrent wrapper.
827
+ Exposes `InMemoryBTree` methods as async equivalents returning `Promise`. Writes coordinate through the shared store; reads sync before returning when `readMode` is `'strong'` (the default). When `readMode` is `'local'`, reads execute against the local tree without syncing.
809
828
 
810
829
  | Method | Signature | Description |
811
830
  | -------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
812
831
  | `sync` | `() => Promise<void>` | Fetch and apply the latest log entries from the shared store. |
813
832
  | `put` | `(key: TKey, value: TValue) => Promise<EntryId>` | Insert with optimistic concurrency. |
833
+ | `putMany` | `(entries: readonly { key: TKey; value: TValue }[]) => Promise<EntryId[]>` | Batch insert with optimistic concurrency. |
814
834
  | `remove` | `(key: TKey) => Promise<BTreeEntry<TKey, TValue> \| null>` | Remove the first matching entry by key. |
815
835
  | `removeById` | `(entryId: EntryId) => Promise<BTreeEntry<TKey, TValue> \| null>` | Remove a specific entry by ID. |
816
836
  | `peekById` | `(entryId: EntryId) => Promise<BTreeEntry<TKey, TValue> \| null>` | Look up an entry by ID (syncs first). |
817
837
  | `updateById` | `(entryId: EntryId, value: TValue) => Promise<BTreeEntry<TKey, TValue> \| null>` | Update an entry by ID with optimistic concurrency. |
818
838
  | `popFirst` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | Remove and return the smallest entry. |
819
839
  | `popLast` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | Remove and return the largest entry. |
840
+ | `deleteRange` | `(startKey: TKey, endKey: TKey, options?: RangeBounds) => Promise<number>` | Delete entries in range with optimistic concurrency. |
841
+ | `clear` | `() => Promise<void>` | Remove all entries with optimistic concurrency. |
820
842
  | `peekFirst` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | Return the smallest entry (syncs first). |
821
843
  | `peekLast` | `() => Promise<BTreeEntry<TKey, TValue> \| null>` | Return the largest entry (syncs first). |
822
844
  | `findFirst` | `(key: TKey) => Promise<BTreeEntry<TKey, TValue> \| null>` | Return the first entry matching key (syncs first). |
@@ -828,10 +850,19 @@ Exposes a subset of `InMemoryBTree` methods as async equivalents returning `Prom
828
850
  | `nextHigherKey` | `(key: TKey) => Promise<TKey \| null>` | Next key strictly greater (syncs first). |
829
851
  | `nextLowerKey` | `(key: TKey) => Promise<TKey \| null>` | Next key strictly less (syncs first). |
830
852
  | `getPairOrNextLower` | `(key: TKey) => Promise<BTreeEntry<TKey, TValue> \| null>` | Exact match or next lower (syncs first). |
853
+ | `entries` | `() => Promise<BTreeEntry<TKey, TValue>[]>` | Return all entries as array (syncs first). |
854
+ | `entriesReversed` | `() => Promise<BTreeEntry<TKey, TValue>[]>` | Return all entries in reverse as array (syncs first). |
855
+ | `keys` | `() => Promise<TKey[]>` | Return all keys as array (syncs first). |
856
+ | `values` | `() => Promise<TValue[]>` | Return all values as array (syncs first). |
857
+ | `forEach` | `(callback: (entry: BTreeEntry<TKey, TValue>) => void) => Promise<void>` | Iterate all entries (syncs first). |
831
858
  | `snapshot` | `() => Promise<BTreeEntry<TKey, TValue>[]>` | Return all entries (syncs first). |
832
859
  | `size` | `() => Promise<number>` | Return entry count (syncs first). |
833
860
  | `getStats` | `() => Promise<BTreeStats>` | Return structural statistics (syncs first). |
834
861
  | `assertInvariants` | `() => Promise<void>` | Assert structural integrity (syncs first). |
862
+ | `clone` | `() => Promise<InMemoryBTree<TKey, TValue>>` | Return an independent local copy (syncs first). |
863
+ | `toJSON` | `() => Promise<BTreeJSON<TKey, TValue>>` | Serialize to JSON (syncs first). |
864
+ | `fromJSON` (static) | `(json: BTreeJSON<TKey, TValue>, compareKeys: KeyComparator<TKey>) => InMemoryBTree<TKey, TValue>` | Deserialize from JSON (returns local tree). |
865
+ | `[Symbol.asyncIterator]` | `() => AsyncIterableIterator<BTreeEntry<TKey, TValue>>` | Async iteration over all entries (syncs first). |
835
866
 
836
867
  **Constructor:**
837
868
 
@@ -855,7 +886,7 @@ new ConcurrentInMemoryBTree<TKey, TValue>(config: ConcurrentInMemoryBTreeConfig<
855
886
  | `ConcurrentInMemoryBTreeConfig<TKey, TValue>` | Extends `InMemoryBTreeConfig<TKey>` with `store: SharedTreeStore<TKey, TValue>`, `maxRetries?: number`, `maxSyncMutationsPerBatch?: number`, and `readMode?: ReadMode`. |
856
887
  | `SharedTreeStore<TKey, TValue>` | Interface with `getLogEntriesSince(version)` and `append(expectedVersion, mutations)`. |
857
888
  | `SharedTreeLog<TKey, TValue>` | `{ version: bigint; mutations: BTreeMutation<TKey, TValue>[] }` |
858
- | `BTreeMutation<TKey, TValue>` | Discriminated union: `init`, `put`, `remove`, `removeById`, `updateById`, `popFirst`, `popLast`. |
889
+ | `BTreeMutation<TKey, TValue>` | Discriminated union: `init`, `put`, `putMany`, `remove`, `removeById`, `updateById`, `popFirst`, `popLast`, `deleteRange`, `clear`. |
859
890
  | `BTreeValidationError` | Error thrown for comparator or config violations. |
860
891
  | `BTreeInvariantError` | Error thrown for tree structural integrity violations. |
861
892
  | `BTreeConcurrencyError` | Error thrown for concurrency conflicts or store contract violations. |
@@ -22,11 +22,37 @@ export declare class InMemoryBTree<TKey, TValue> {
22
22
  get(key: TKey): TValue | null;
23
23
  hasKey(key: TKey): boolean;
24
24
  findFirst(key: TKey): BTreeEntry<TKey, TValue> | null;
25
+ /**
26
+ * Returns the last entry whose key matches `key`, or `null` if not found.
27
+ * Useful when `duplicateKeys` is `'allow'` and multiple entries share the same key.
28
+ */
25
29
  findLast(key: TKey): BTreeEntry<TKey, TValue> | null;
30
+ /**
31
+ * Returns the smallest key in the tree that is strictly greater than `key`,
32
+ * or `null` if no such key exists.
33
+ */
26
34
  nextHigherKey(key: TKey): TKey | null;
35
+ /**
36
+ * Returns the largest key in the tree that is strictly less than `key`,
37
+ * or `null` if no such key exists.
38
+ */
27
39
  nextLowerKey(key: TKey): TKey | null;
40
+ /**
41
+ * Returns the entry for `key` if it exists; otherwise returns the entry with
42
+ * the largest key strictly less than `key`. Returns `null` when the tree is
43
+ * empty or every key is greater than `key`.
44
+ */
28
45
  getPairOrNextLower(key: TKey): BTreeEntry<TKey, TValue> | null;
46
+ /**
47
+ * Returns the number of entries whose keys fall within [`startKey`, `endKey`].
48
+ * Pass `options` to make either bound exclusive.
49
+ */
29
50
  count(startKey: TKey, endKey: TKey, options?: RangeBounds): number;
51
+ /**
52
+ * Deletes all entries whose keys fall within [`startKey`, `endKey`].
53
+ * Pass `options` to make either bound exclusive.
54
+ * @returns The number of entries deleted.
55
+ */
30
56
  deleteRange(startKey: TKey, endKey: TKey, options?: RangeBounds): number;
31
57
  range(startKey: TKey, endKey: TKey, options?: RangeBounds): BTreeEntry<TKey, TValue>[];
32
58
  entries(): IterableIterator<BTreeEntry<TKey, TValue>>;
@@ -36,6 +62,13 @@ export declare class InMemoryBTree<TKey, TValue> {
36
62
  [Symbol.iterator](): IterableIterator<BTreeEntry<TKey, TValue>>;
37
63
  forEach(callback: (entry: BTreeEntry<TKey, TValue>) => void, thisArg?: unknown): void;
38
64
  snapshot(): BTreeEntry<TKey, TValue>[];
65
+ /**
66
+ * Returns a structurally independent `InMemoryBTree` with identical
67
+ * configuration and entries. The tree structure (nodes, links, entry IDs)
68
+ * is fully independent, but stored key and value references are shared
69
+ * with the source tree.
70
+ * Note: `EntryId` values are reassigned in the clone — IDs from the source tree are not valid for the clone.
71
+ */
39
72
  clone(): InMemoryBTree<TKey, TValue>;
40
73
  toJSON(): BTreeJSON<TKey, TValue>;
41
74
  static fromJSON<TKey, TValue>(json: BTreeJSON<TKey, TValue>, compareKeys: KeyComparator<TKey>): InMemoryBTree<TKey, TValue>;
@@ -1,4 +1,5 @@
1
1
  import { type BTreeState, type InMemoryBTreeConfig } from './types.js';
2
+ export declare const minOccupancy: (max: number) => number;
2
3
  export declare const computeAutoScaleTier: (entryCount: number) => {
3
4
  readonly maxLeaf: number;
4
5
  readonly maxBranch: number;
@@ -0,0 +1,15 @@
1
+ import type { BranchNode, BTreeNode, LeafEntry, LeafNode, NodeKey } from './types.js';
2
+ export declare const createLeafNode: <TKey, TValue>(entries: LeafEntry<TKey, TValue>[], parent: BranchNode<TKey, TValue> | null) => LeafNode<TKey, TValue>;
3
+ export declare const createBranchNode: <TKey, TValue>(children: BTreeNode<TKey, TValue>[], parent: BranchNode<TKey, TValue> | null) => BranchNode<TKey, TValue>;
4
+ export declare const leafEntryCount: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => number;
5
+ export declare const leafEntryAt: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, i: number) => LeafEntry<TKey, TValue>;
6
+ export declare const leafShiftEntry: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => LeafEntry<TKey, TValue> | undefined;
7
+ export declare const leafPopEntry: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => LeafEntry<TKey, TValue> | undefined;
8
+ export declare const leafUnshiftEntry: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, entry: LeafEntry<TKey, TValue>) => void;
9
+ export declare const leafRemoveAt: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, logicalIndex: number) => void;
10
+ export declare const leafInsertAt: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, logicalIndex: number, entry: LeafEntry<TKey, TValue>) => void;
11
+ export declare const leafCompact: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => void;
12
+ export declare const branchCompact: <TKey, TValue>(branch: BranchNode<TKey, TValue>) => void;
13
+ export declare const branchChildCount: <TKey, TValue>(branch: BranchNode<TKey, TValue>) => number;
14
+ export declare const branchInsertAt: <TKey, TValue>(branch: BranchNode<TKey, TValue>, logicalIndex: number, child: BTreeNode<TKey, TValue>, key: NodeKey<TKey>) => void;
15
+ export declare const branchRemoveAt: <TKey, TValue>(branch: BranchNode<TKey, TValue>, physIndex: number) => void;
@@ -1,3 +1,4 @@
1
1
  import { type BTreeEntry, type BTreeState, type RangeBounds } from './types.js';
2
+ export declare function isEmptyRange<TKey>(compare: (a: TKey, b: TKey) => number, startKey: TKey, endKey: TKey, options?: RangeBounds): boolean;
2
3
  export declare const countRangeEntries: <TKey, TValue>(state: BTreeState<TKey, TValue>, startKey: TKey, endKey: TKey, options?: RangeBounds) => number;
3
4
  export declare const rangeQueryEntries: <TKey, TValue>(state: BTreeState<TKey, TValue>, startKey: TKey, endKey: TKey, options?: RangeBounds) => BTreeEntry<TKey, TValue>[];
@@ -6,8 +6,14 @@ export declare const NODE_LEAF: 0;
6
6
  export declare const NODE_BRANCH: 1;
7
7
  export type KeyComparator<TKey> = (left: TKey, right: TKey) => number;
8
8
  export type DuplicateKeyPolicy = 'allow' | 'reject' | 'replace';
9
+ /**
10
+ * Defines the inclusivity of the lower and upper bounds for a key range scan.
11
+ * Both bounds default to `'inclusive'` when omitted.
12
+ */
9
13
  export interface RangeBounds {
14
+ /** Lower bound type. Defaults to `'inclusive'` when omitted. */
10
15
  lowerBound?: 'inclusive' | 'exclusive';
16
+ /** Upper bound type. Defaults to `'inclusive'` when omitted. */
11
17
  upperBound?: 'inclusive' | 'exclusive';
12
18
  }
13
19
  export declare const normalizeDuplicateKeyPolicy: (value: DuplicateKeyPolicy | undefined) => DuplicateKeyPolicy;
@@ -29,6 +35,11 @@ export interface LeafEntry<TKey, TValue> {
29
35
  key: TKey;
30
36
  value: TValue;
31
37
  }
38
+ /**
39
+ * Shallow-copies a `LeafEntry` into a plain `BTreeEntry` for safe public API return.
40
+ * Prevents callers from holding a reference that mutates when `updateById` is called.
41
+ */
42
+ export declare const toPublicEntry: <TKey, TValue>(entry: LeafEntry<TKey, TValue>) => BTreeEntry<TKey, TValue>;
32
43
  export interface LeafNode<TKey, TValue> {
33
44
  kind: typeof NODE_LEAF;
34
45
  entries: LeafEntry<TKey, TValue>[];
@@ -85,29 +96,4 @@ export interface BTreeStats {
85
96
  export declare const isLeafNode: <TKey, TValue>(node: BTreeNode<TKey, TValue>) => node is LeafNode<TKey, TValue>;
86
97
  export declare const writeMinKeyTo: <TKey, TValue>(node: BTreeNode<TKey, TValue>, target: NodeKey<TKey>) => boolean;
87
98
  export declare const normalizeNodeCapacity: (value: number | undefined, field: string, defaultValue: number) => number;
88
- export declare const createLeafNode: <TKey, TValue>(entries: LeafEntry<TKey, TValue>[], parent: BranchNode<TKey, TValue> | null) => LeafNode<TKey, TValue>;
89
- export declare const createBranchNode: <TKey, TValue>(children: BTreeNode<TKey, TValue>[], parent: BranchNode<TKey, TValue> | null) => BranchNode<TKey, TValue>;
90
- /** Number of logical entries in the leaf */
91
- export declare const leafEntryCount: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => number;
92
- /** Get logical entry at index i (0-based from the logical start) */
93
- export declare const leafEntryAt: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, i: number) => LeafEntry<TKey, TValue>;
94
- /** Remove and return the first logical entry. O(1) amortized — increments offset and compacts when dead slots reach half. */
95
- export declare const leafShiftEntry: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => LeafEntry<TKey, TValue> | undefined;
96
- /** Remove and return the last logical entry. O(1) — pops from the backing array tail. */
97
- export declare const leafPopEntry: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => LeafEntry<TKey, TValue> | undefined;
98
- /** Prepend entry to logical start. Falls back to unshift if no gap, otherwise fills gap. */
99
- export declare const leafUnshiftEntry: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, entry: LeafEntry<TKey, TValue>) => void;
100
- /** Remove logical entry at index. Shifts the smaller side to halve average cost. */
101
- export declare const leafRemoveAt: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, logicalIndex: number) => void;
102
- /** Insert entry at logical index. Uses entryOffset gap when inserting in the first half. */
103
- export declare const leafInsertAt: <TKey, TValue>(leaf: LeafNode<TKey, TValue>, logicalIndex: number, entry: LeafEntry<TKey, TValue>) => void;
104
- /** Compact the backing array — remove dead slots before entryOffset. Call before splits/merges. */
105
- export declare const leafCompact: <TKey, TValue>(leaf: LeafNode<TKey, TValue>) => void;
106
- /** Compact branch arrays — remove dead slots before childOffset, keeping a small gap. */
107
- export declare const branchCompact: <TKey, TValue>(branch: BranchNode<TKey, TValue>) => void;
108
- /** Number of logical children in the branch. */
109
- export declare const branchChildCount: <TKey, TValue>(branch: BranchNode<TKey, TValue>) => number;
110
- /** Insert a child at a logical index. Shifts the smaller side to halve average cost. */
111
- export declare const branchInsertAt: <TKey, TValue>(branch: BranchNode<TKey, TValue>, logicalIndex: number, child: BTreeNode<TKey, TValue>, key: NodeKey<TKey>) => void;
112
- /** Remove a child at a physical index. Shifts the smaller side. */
113
- export declare const branchRemoveAt: <TKey, TValue>(branch: BranchNode<TKey, TValue>, physIndex: number) => void;
99
+ export { createLeafNode, createBranchNode, leafEntryCount, leafEntryAt, leafShiftEntry, leafPopEntry, leafUnshiftEntry, leafRemoveAt, leafInsertAt, leafCompact, branchCompact, branchChildCount, branchInsertAt, branchRemoveAt, } from './node-ops.js';