verso-db 0.1.4 → 0.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.
Files changed (110) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +81 -49
  3. package/dist/BinaryHeap.d.ts +16 -5
  4. package/dist/BinaryHeap.d.ts.map +1 -1
  5. package/dist/BinaryHeap.js +138 -0
  6. package/dist/BinaryHeap.js.map +1 -0
  7. package/dist/Collection.d.ts +98 -17
  8. package/dist/Collection.d.ts.map +1 -1
  9. package/dist/Collection.js +1186 -0
  10. package/dist/Collection.js.map +1 -0
  11. package/dist/HNSWIndex.d.ts +170 -15
  12. package/dist/HNSWIndex.d.ts.map +1 -1
  13. package/dist/HNSWIndex.js +2818 -0
  14. package/dist/HNSWIndex.js.map +1 -0
  15. package/dist/MaxBinaryHeap.d.ts +2 -60
  16. package/dist/MaxBinaryHeap.d.ts.map +1 -1
  17. package/dist/MaxBinaryHeap.js +5 -0
  18. package/dist/MaxBinaryHeap.js.map +1 -0
  19. package/dist/SearchWorker.d.ts +104 -0
  20. package/dist/SearchWorker.d.ts.map +1 -0
  21. package/dist/SearchWorker.js +573 -0
  22. package/dist/SearchWorker.js.map +1 -0
  23. package/dist/VectorDB.d.ts +19 -5
  24. package/dist/VectorDB.d.ts.map +1 -1
  25. package/dist/VectorDB.js +246 -0
  26. package/dist/VectorDB.js.map +1 -0
  27. package/dist/WorkerPool.d.ts +92 -0
  28. package/dist/WorkerPool.d.ts.map +1 -0
  29. package/dist/WorkerPool.js +266 -0
  30. package/dist/WorkerPool.js.map +1 -0
  31. package/dist/backends/JsDistanceBackend.d.ts +3 -20
  32. package/dist/backends/JsDistanceBackend.d.ts.map +1 -1
  33. package/dist/backends/JsDistanceBackend.js +163 -0
  34. package/dist/backends/JsDistanceBackend.js.map +1 -0
  35. package/dist/encoding/DeltaEncoder.d.ts +2 -2
  36. package/dist/encoding/DeltaEncoder.d.ts.map +1 -1
  37. package/dist/encoding/DeltaEncoder.js +199 -0
  38. package/dist/encoding/DeltaEncoder.js.map +1 -0
  39. package/dist/errors.js +97 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/index.d.ts +16 -17
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +61 -3419
  44. package/dist/index.js.map +1 -0
  45. package/dist/presets.d.ts +9 -9
  46. package/dist/presets.d.ts.map +1 -1
  47. package/dist/presets.js +205 -0
  48. package/dist/presets.js.map +1 -0
  49. package/dist/quantization/ScalarQuantizer.d.ts +10 -34
  50. package/dist/quantization/ScalarQuantizer.d.ts.map +1 -1
  51. package/dist/quantization/ScalarQuantizer.js +346 -0
  52. package/dist/quantization/ScalarQuantizer.js.map +1 -0
  53. package/dist/storage/BatchWriter.d.ts.map +1 -1
  54. package/dist/storage/BatchWriter.js +351 -0
  55. package/dist/storage/BatchWriter.js.map +1 -0
  56. package/dist/storage/BunStorageBackend.d.ts +12 -5
  57. package/dist/storage/BunStorageBackend.d.ts.map +1 -1
  58. package/dist/storage/BunStorageBackend.js +182 -0
  59. package/dist/storage/BunStorageBackend.js.map +1 -0
  60. package/dist/storage/MemoryBackend.d.ts.map +1 -1
  61. package/dist/storage/MemoryBackend.js +109 -0
  62. package/dist/storage/MemoryBackend.js.map +1 -0
  63. package/dist/storage/OPFSBackend.d.ts +9 -1
  64. package/dist/storage/OPFSBackend.d.ts.map +1 -1
  65. package/dist/storage/OPFSBackend.js +325 -0
  66. package/dist/storage/OPFSBackend.js.map +1 -0
  67. package/dist/storage/StorageBackend.d.ts +1 -1
  68. package/dist/storage/StorageBackend.js +12 -0
  69. package/dist/storage/StorageBackend.js.map +1 -0
  70. package/dist/storage/WriteAheadLog.d.ts +15 -11
  71. package/dist/storage/WriteAheadLog.d.ts.map +1 -1
  72. package/dist/storage/WriteAheadLog.js +321 -0
  73. package/dist/storage/WriteAheadLog.js.map +1 -0
  74. package/dist/storage/createStorageBackend.d.ts +4 -0
  75. package/dist/storage/createStorageBackend.d.ts.map +1 -1
  76. package/dist/storage/createStorageBackend.js +119 -0
  77. package/dist/storage/createStorageBackend.js.map +1 -0
  78. package/dist/storage/index.d.ts +3 -3
  79. package/dist/storage/index.js +33 -0
  80. package/dist/storage/index.js.map +1 -0
  81. package/dist/storage/nodeFsRuntime.d.ts +14 -0
  82. package/dist/storage/nodeFsRuntime.d.ts.map +1 -0
  83. package/dist/storage/nodeFsRuntime.js +105 -0
  84. package/dist/storage/nodeFsRuntime.js.map +1 -0
  85. package/package.json +47 -23
  86. package/dist/Storage.d.ts +0 -54
  87. package/dist/Storage.d.ts.map +0 -1
  88. package/dist/backends/DistanceBackend.d.ts +0 -5
  89. package/dist/backends/DistanceBackend.d.ts.map +0 -1
  90. package/src/BinaryHeap.ts +0 -131
  91. package/src/Collection.ts +0 -695
  92. package/src/HNSWIndex.ts +0 -1839
  93. package/src/MaxBinaryHeap.ts +0 -175
  94. package/src/Storage.ts +0 -435
  95. package/src/VectorDB.ts +0 -109
  96. package/src/backends/DistanceBackend.ts +0 -17
  97. package/src/backends/JsDistanceBackend.ts +0 -227
  98. package/src/encoding/DeltaEncoder.ts +0 -217
  99. package/src/errors.ts +0 -110
  100. package/src/index.ts +0 -138
  101. package/src/presets.ts +0 -229
  102. package/src/quantization/ScalarQuantizer.ts +0 -383
  103. package/src/storage/BatchWriter.ts +0 -336
  104. package/src/storage/BunStorageBackend.ts +0 -161
  105. package/src/storage/MemoryBackend.ts +0 -120
  106. package/src/storage/OPFSBackend.ts +0 -250
  107. package/src/storage/StorageBackend.ts +0 -74
  108. package/src/storage/WriteAheadLog.ts +0 -326
  109. package/src/storage/createStorageBackend.ts +0 -137
  110. package/src/storage/index.ts +0 -53
package/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ # [0.2.0](https://github.com/briansunter/verso/compare/v0.1.5...v0.2.0) (2026-03-15)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * comprehensive codebase audit - fix bugs, improve error handling, remove dead code ([3a95681](https://github.com/briansunter/verso/commit/3a95681365477b0a000a78beeebf95a6269bd90c))
7
+
8
+
9
+ ### Features
10
+
11
+ * gracefully skip browser smoke test when Playwright unavailable in CI ([55bf0fd](https://github.com/briansunter/verso/commit/55bf0fd238b15263860fdd2c914910efd565323d))
12
+ * worker parallelism with SharedArrayBuffer, quantized search, and parallel build ([ccdf9b3](https://github.com/briansunter/verso/commit/ccdf9b32d6bd0f0840a1799b6866e006a62fcbd3))
13
+
14
+ ## [0.1.5](https://github.com/briansunter/verso/compare/v0.1.4...v0.1.5) (2026-02-28)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * audit round 2 — 7 fixes, 31 tests added (377 total) ([6098253](https://github.com/briansunter/verso/commit/6098253e7193d5af4d827abada8699dc9b8f3c55))
20
+ * audit round 3 — 17 fixes, 111 tests added (488 total) ([2eb0c69](https://github.com/briansunter/verso/commit/2eb0c69751f2fe87f84ba128aad019b979e205fd))
21
+ * audit round 4 — 14 fixes, 43 tests added (531 total) ([5078dde](https://github.com/briansunter/verso/commit/5078dde36cf5a7bb0467539eb471814c4881c3f7))
22
+ * audit round 5 — ID exhaustion guards, input validation, deterministic ordering, benchmark fixes (607 total tests) ([b22d54c](https://github.com/briansunter/verso/commit/b22d54c359e328d76a0fd4658093411e5faccf0b))
23
+ * comprehensive codebase audit — 12 bugs fixed, 69 tests added ([7479626](https://github.com/briansunter/verso/commit/7479626ee020952f56746914152c242b80e7c4f9))
24
+ * quantized search respects explicit efSearch, benchmark fixes ([07ad671](https://github.com/briansunter/verso/commit/07ad6718d4af44a7e5bd4470dd3e23c921e19532))
25
+
1
26
  ## [0.1.4](https://github.com/briansunter/verso/compare/v0.1.3...v0.1.4) (2025-12-29)
2
27
 
3
28
 
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Verso
2
2
 
3
- High-performance vector search with HNSW indexing for Bun and Browser.
3
+ High-performance vector search with HNSW indexing for Bun, Node.js, and Browser.
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/verso.svg)](https://www.npmjs.com/package/verso)
5
+ [![npm version](https://img.shields.io/npm/v/verso-db.svg)](https://www.npmjs.com/package/verso-db)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
8
  ## Performance
@@ -18,7 +18,7 @@ High-performance vector search with HNSW indexing for Bun and Browser.
18
18
  - **HNSW Algorithm** - Hierarchical Navigable Small World for fast approximate nearest neighbor search
19
19
  - **Multiple Distance Metrics** - Cosine similarity, Euclidean, dot product
20
20
  - **Int8 Quantization** - 4x memory reduction with minimal recall loss
21
- - **Multi-Platform** - Bun (file system) and Browser (OPFS)
21
+ - **Multi-Platform** - Bun/Node.js (file system) and Browser (OPFS)
22
22
  - **Parameter Presets** - Pre-tuned configurations for different use cases
23
23
  - **Batch Queries** - Efficient batch processing for throughput
24
24
  - **Metadata Filtering** - MongoDB-style query operators
@@ -27,19 +27,19 @@ High-performance vector search with HNSW indexing for Bun and Browser.
27
27
 
28
28
  ```bash
29
29
  # Bun
30
- bun add verso
30
+ bun add verso-db
31
31
 
32
- # npm
33
- npm install verso
32
+ # npm / Node.js
33
+ npm install verso-db
34
34
  ```
35
35
 
36
36
  ## Quick Start
37
37
 
38
38
  ```typescript
39
- import { VectorDB, getRecommendedPreset } from 'verso';
39
+ import { VectorDB, getRecommendedPreset } from 'verso-db';
40
40
 
41
41
  // Create database
42
- const db = new VectorDB();
42
+ const db = new VectorDB({ storagePath: './my_vectors' });
43
43
 
44
44
  // Get recommended parameters for your vector dimensions
45
45
  const preset = getRecommendedPreset(768);
@@ -74,8 +74,12 @@ const results = await collection.query({
74
74
  efSearch: preset.efSearch
75
75
  });
76
76
 
77
- console.log(results);
78
- // [{ id: 'doc1', score: 0.99, metadata: { title: 'Document 1', ... } }, ...]
77
+ console.log(results.ids); // ['doc1', 'doc2', 'doc3']
78
+ console.log(results.distances); // [0.01, 0.05, 0.12]
79
+ console.log(results.metadata); // [{ title: 'Document 1', ... }, ...]
80
+
81
+ // Optional: release resources explicitly
82
+ await db.close();
79
83
  ```
80
84
 
81
85
  ## API Reference
@@ -85,7 +89,7 @@ console.log(results);
85
89
  Main database class for managing collections.
86
90
 
87
91
  ```typescript
88
- const db = new VectorDB();
92
+ const db = new VectorDB({ storagePath: './vectors' });
89
93
 
90
94
  // Create collection
91
95
  const collection = await db.createCollection('name', {
@@ -95,7 +99,7 @@ const collection = await db.createCollection('name', {
95
99
  efConstruction: 200 // Build-time search depth
96
100
  });
97
101
 
98
- // Get existing collection
102
+ // Get existing collection (returns undefined if not found)
99
103
  const collection = await db.getCollection('name');
100
104
 
101
105
  // List collections
@@ -103,6 +107,9 @@ const names = await db.listCollections();
103
107
 
104
108
  // Delete collection
105
109
  await db.deleteCollection('name');
110
+
111
+ // Close database
112
+ await db.close();
106
113
  ```
107
114
 
108
115
  ### Collection
@@ -110,31 +117,47 @@ await db.deleteCollection('name');
110
117
  ```typescript
111
118
  // Add vectors
112
119
  await collection.add({
113
- ids: string[],
114
- vectors: Float32Array[],
115
- metadata?: object[]
120
+ ids: ['id1', 'id2'],
121
+ vectors: [new Float32Array([...]), new Float32Array([...])],
122
+ metadata: [{ key: 'value' }, { key: 'value' }] // optional
116
123
  });
117
124
 
118
- // Query
125
+ // Upsert vectors (update existing, add new)
126
+ await collection.upsert({
127
+ ids: ['id1', 'id3'], // id1 updated, id3 added
128
+ vectors: [new Float32Array([...]), new Float32Array([...])],
129
+ metadata: [{ key: 'new_value' }, { key: 'value' }]
130
+ });
131
+
132
+ // Query — returns { ids: string[], distances: number[], metadata: object[] }
119
133
  const results = await collection.query({
120
- queryVector: Float32Array,
121
- k: number,
122
- efSearch?: number,
123
- filter?: FilterExpression
134
+ queryVector: new Float32Array([...]),
135
+ k: 10,
136
+ efSearch: 200, // optional
137
+ filter: { category: 'tech' } // optional
124
138
  });
125
139
 
126
140
  // Batch query
127
- const batchResults = await collection.queryBatch({
128
- queryVectors: Float32Array[],
129
- k: number,
130
- efSearch?: number
131
- });
141
+ const batchResults = await collection.queryBatch([
142
+ { queryVector: vec1, k: 10 },
143
+ { queryVector: vec2, k: 5, filter: { type: 'article' } }
144
+ ]);
132
145
 
133
- // Delete vectors
134
- await collection.delete(ids: string[]);
146
+ // Delete a single vector
147
+ await collection.delete('id1');
135
148
 
136
- // Get collection info
137
- const info = await collection.info();
149
+ // Delete multiple vectors
150
+ await collection.deleteBatch(['id1', 'id2']);
151
+
152
+ // Check existence
153
+ collection.has('id1'); // true if active (not deleted)
154
+ collection.count(); // number of active vectors
155
+
156
+ // Flush pending writes when using Collection directly
157
+ await collection.flush();
158
+
159
+ // Compact — permanently remove deleted vectors and reclaim space
160
+ await collection.compact();
138
161
  ```
139
162
 
140
163
  ### Metadata Filtering
@@ -156,23 +179,23 @@ Supported operators: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`
156
179
  ### Parameter Presets
157
180
 
158
181
  ```typescript
159
- import { getRecommendedPreset, getRAGPreset, PRESETS } from 'verso';
182
+ import { getRecommendedPreset, getRAGPreset, PRESETS } from 'verso-db';
160
183
 
161
184
  // Automatic preset based on dimensions
162
185
  const preset = getRecommendedPreset(768);
163
186
 
164
- // RAG-optimized preset (high recall)
165
- const ragPreset = getRAGPreset(768);
166
-
167
- // Available presets
168
- PRESETS.LOW_DIM // <= 128 dimensions
169
- PRESETS.MEDIUM_DIM // 256-512 dimensions
170
- PRESETS.HIGH_DIM // 768+ dimensions
171
- PRESETS.VERY_HIGH_DIM // 1024+ dimensions
172
- PRESETS.SMALL_DATASET // < 10k vectors
173
- PRESETS.LARGE_DATASET // 100k+ vectors
174
- PRESETS.MAX_RECALL // Prioritize accuracy
175
- PRESETS.LOW_LATENCY // Prioritize speed
187
+ // RAG-optimized preset (high recall) by embedding model name
188
+ const ragPreset = getRAGPreset('text-embedding-3-large');
189
+
190
+ // Named presets (accessed by string key)
191
+ PRESETS['low-dim'] // <= 128 dimensions
192
+ PRESETS['medium-dim'] // 256-512 dimensions
193
+ PRESETS['high-dim'] // 768+ dimensions
194
+ PRESETS['very-high-dim'] // 1536+ dimensions
195
+ PRESETS['small-dataset'] // < 10k vectors
196
+ PRESETS['large-dataset'] // 100k+ vectors
197
+ PRESETS['max-recall'] // Prioritize accuracy
198
+ PRESETS['low-latency'] // Prioritize speed
176
199
  ```
177
200
 
178
201
  ### Int8 Quantization
@@ -180,7 +203,7 @@ PRESETS.LOW_LATENCY // Prioritize speed
180
203
  Reduce memory usage by 4x with minimal recall loss:
181
204
 
182
205
  ```typescript
183
- import { ScalarQuantizer, QuantizedVectorStore } from 'verso';
206
+ import { ScalarQuantizer, QuantizedVectorStore } from 'verso-db';
184
207
 
185
208
  // Create quantizer
186
209
  const quantizer = new ScalarQuantizer(768);
@@ -191,10 +214,10 @@ quantizer.train(sampleVectors);
191
214
  // Quantize vectors
192
215
  const quantized = quantizer.quantize(vector);
193
216
 
194
- // Use with QuantizedVectorStore for integrated search
217
+ // Use QuantizedVectorStore for compact in-memory storage
195
218
  const store = new QuantizedVectorStore(768);
196
- store.add(ids, vectors);
197
- const results = store.search(queryVector, k);
219
+ store.addVectors(sampleVectors);
220
+ console.log(store.size(), store.memoryUsage());
198
221
  ```
199
222
 
200
223
  ## Storage Backends
@@ -203,16 +226,16 @@ Verso automatically selects the appropriate storage backend:
203
226
 
204
227
  | Environment | Backend | Storage |
205
228
  |-------------|---------|---------|
206
- | Bun | `BunStorageBackend` | File system |
229
+ | Bun / Node.js | `BunStorageBackend` | File system |
207
230
  | Browser | `OPFSBackend` | Origin Private File System |
208
231
  | Fallback | `MemoryBackend` | In-memory (no persistence) |
209
232
 
210
233
  ```typescript
211
- import { createStorageBackend, getRecommendedStorageType } from 'verso';
234
+ import { createStorageBackend, getRecommendedStorageType } from 'verso-db';
212
235
 
213
236
  // Automatic detection
214
237
  const backend = await createStorageBackend({
215
- basePath: './vectors'
238
+ path: './vectors'
216
239
  });
217
240
 
218
241
  // Check available types
@@ -245,6 +268,15 @@ bun run build
245
268
 
246
269
  # Run benchmarks
247
270
  bun run bench
271
+
272
+ # Recall benchmark
273
+ bun run benchmark:recall
274
+
275
+ # Storage benchmark
276
+ bun run benchmark:storage
277
+
278
+ # Comprehensive benchmark suite
279
+ bun run benchmark:comprehensive
248
280
  ```
249
281
 
250
282
  ## License
@@ -3,18 +3,20 @@ export declare class BinaryHeap {
3
3
  private dists;
4
4
  private _size;
5
5
  private capacity;
6
- private lastPoppedValue;
7
- constructor(capacity: number);
6
+ private readonly isMaxHeap;
7
+ constructor(capacity: number, isMaxHeap?: boolean);
8
8
  /**
9
9
  * Push an element onto the heap.
10
- * When at capacity, simply returns without adding (caller manages bounds).
11
- * This is the correct behavior for HNSW candidate exploration.
10
+ * Auto-grows when at capacity to avoid silently dropping elements.
12
11
  */
13
12
  push(id: number, dist: number): void;
13
+ /**
14
+ * Double the heap capacity when full.
15
+ */
16
+ private grow;
14
17
  pop(): number;
15
18
  peek(): number;
16
19
  peekValue(): number;
17
- getLastPoppedValue(): number;
18
20
  size(): number;
19
21
  clear(): void;
20
22
  isEmpty(): boolean;
@@ -22,4 +24,13 @@ export declare class BinaryHeap {
22
24
  private heapifyUp;
23
25
  private heapifyDown;
24
26
  }
27
+ /**
28
+ * MaxBinaryHeap - A max-heap for HNSW result tracking.
29
+ *
30
+ * Keeps the FURTHEST element at the top, allowing O(log n) eviction
31
+ * of the worst result when a better one is found.
32
+ */
33
+ export declare class MaxBinaryHeap extends BinaryHeap {
34
+ constructor(capacity: number);
35
+ }
25
36
  //# sourceMappingURL=BinaryHeap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BinaryHeap.d.ts","sourceRoot":"","sources":["../src/BinaryHeap.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAa;gBAExB,QAAQ,EAAE,MAAM;IAO5B;;;;OAIG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAapC,GAAG,IAAI,MAAM;IAcb,IAAI,IAAI,MAAM;IAId,SAAS,IAAI,MAAM;IAInB,kBAAkB,IAAI,MAAM;IAI5B,IAAI,IAAI,MAAM;IAId,KAAK,IAAI,IAAI;IAIb,OAAO,IAAI,OAAO;IAIlB,WAAW,IAAI,MAAM;IAIrB,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,WAAW;CAiCpB"}
1
+ {"version":3,"file":"BinaryHeap.d.ts","sourceRoot":"","sources":["../src/BinaryHeap.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;gBAExB,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,OAAe;IAQxD;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAWpC;;OAEG;IACH,OAAO,CAAC,IAAI;IAWZ,GAAG,IAAI,MAAM;IAab,IAAI,IAAI,MAAM;IAId,SAAS,IAAI,MAAM;IAKnB,IAAI,IAAI,MAAM;IAId,KAAK,IAAI,IAAI;IAIb,OAAO,IAAI,OAAO;IAIlB,WAAW,IAAI,MAAM;IAIrB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,WAAW;CAkCpB;AAED;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,UAAU;gBAC/B,QAAQ,EAAE,MAAM;CAG7B"}
@@ -0,0 +1,138 @@
1
+ export class BinaryHeap {
2
+ ids;
3
+ dists;
4
+ _size;
5
+ capacity;
6
+ isMaxHeap;
7
+ constructor(capacity, isMaxHeap = false) {
8
+ this.capacity = capacity;
9
+ this.isMaxHeap = isMaxHeap;
10
+ this.ids = new Uint32Array(capacity);
11
+ this.dists = new Float32Array(capacity);
12
+ this._size = 0;
13
+ }
14
+ /**
15
+ * Push an element onto the heap.
16
+ * Auto-grows when at capacity to avoid silently dropping elements.
17
+ */
18
+ push(id, dist) {
19
+ if (this._size >= this.capacity) {
20
+ this.grow();
21
+ }
22
+ this.ids[this._size] = id;
23
+ this.dists[this._size] = dist;
24
+ this._size++;
25
+ this.heapifyUp(this._size - 1);
26
+ }
27
+ /**
28
+ * Double the heap capacity when full.
29
+ */
30
+ grow() {
31
+ const newCapacity = Math.max(this.capacity * 2, 16);
32
+ const newIds = new Uint32Array(newCapacity);
33
+ const newDists = new Float32Array(newCapacity);
34
+ newIds.set(this.ids);
35
+ newDists.set(this.dists);
36
+ this.ids = newIds;
37
+ this.dists = newDists;
38
+ this.capacity = newCapacity;
39
+ }
40
+ pop() {
41
+ if (this._size === 0)
42
+ return -1;
43
+ const result = this.ids[0];
44
+ this._size--;
45
+ if (this._size > 0) {
46
+ this.ids[0] = this.ids[this._size];
47
+ this.dists[0] = this.dists[this._size];
48
+ this.heapifyDown(0);
49
+ }
50
+ return result;
51
+ }
52
+ peek() {
53
+ return this._size > 0 ? this.ids[0] : -1;
54
+ }
55
+ peekValue() {
56
+ if (this._size > 0)
57
+ return this.dists[0];
58
+ return this.isMaxHeap ? -Infinity : Infinity;
59
+ }
60
+ size() {
61
+ return this._size;
62
+ }
63
+ clear() {
64
+ this._size = 0;
65
+ }
66
+ isEmpty() {
67
+ return this._size === 0;
68
+ }
69
+ getCapacity() {
70
+ return this.capacity;
71
+ }
72
+ heapifyUp(index) {
73
+ // Cache array references to avoid repeated property lookups
74
+ const ids = this.ids;
75
+ const dists = this.dists;
76
+ const isMax = this.isMaxHeap;
77
+ while (index > 0) {
78
+ // Use bitwise shift for faster integer division
79
+ const parentIndex = (index - 1) >> 1;
80
+ if (isMax ? dists[parentIndex] >= dists[index] : dists[parentIndex] <= dists[index])
81
+ break;
82
+ // Inline swap for performance
83
+ const tmpId = ids[index];
84
+ ids[index] = ids[parentIndex];
85
+ ids[parentIndex] = tmpId;
86
+ const tmpDist = dists[index];
87
+ dists[index] = dists[parentIndex];
88
+ dists[parentIndex] = tmpDist;
89
+ index = parentIndex;
90
+ }
91
+ }
92
+ heapifyDown(index) {
93
+ // Cache array references to avoid repeated property lookups
94
+ const ids = this.ids;
95
+ const dists = this.dists;
96
+ const size = this._size;
97
+ const isMax = this.isMaxHeap;
98
+ while (true) {
99
+ const leftChild = (index << 1) + 1; // 2 * index + 1
100
+ const rightChild = leftChild + 1; // 2 * index + 2
101
+ let best = index;
102
+ if (isMax) {
103
+ if (leftChild < size && dists[leftChild] > dists[best])
104
+ best = leftChild;
105
+ if (rightChild < size && dists[rightChild] > dists[best])
106
+ best = rightChild;
107
+ }
108
+ else {
109
+ if (leftChild < size && dists[leftChild] < dists[best])
110
+ best = leftChild;
111
+ if (rightChild < size && dists[rightChild] < dists[best])
112
+ best = rightChild;
113
+ }
114
+ if (best === index)
115
+ break;
116
+ // Inline swap for performance
117
+ const tmpId = ids[index];
118
+ ids[index] = ids[best];
119
+ ids[best] = tmpId;
120
+ const tmpDist = dists[index];
121
+ dists[index] = dists[best];
122
+ dists[best] = tmpDist;
123
+ index = best;
124
+ }
125
+ }
126
+ }
127
+ /**
128
+ * MaxBinaryHeap - A max-heap for HNSW result tracking.
129
+ *
130
+ * Keeps the FURTHEST element at the top, allowing O(log n) eviction
131
+ * of the worst result when a better one is found.
132
+ */
133
+ export class MaxBinaryHeap extends BinaryHeap {
134
+ constructor(capacity) {
135
+ super(capacity, true);
136
+ }
137
+ }
138
+ //# sourceMappingURL=BinaryHeap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryHeap.js","sourceRoot":"","sources":["../src/BinaryHeap.ts"],"names":[],"mappings":"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"}