@faiss-node/native 0.1.4

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/.env.example ADDED
@@ -0,0 +1,5 @@
1
+ # npm Publishing Token
2
+ # Copy this file to .env and add your npm token
3
+ # DO NOT commit .env to git
4
+
5
+ NPM_TOKEN=your_npm_token_here
package/0.1.1 ADDED
File without changes
package/API.md ADDED
@@ -0,0 +1,416 @@
1
+ # API Reference
2
+
3
+ Complete API documentation for `@faiss-node/native`.
4
+
5
+ ## Table of Contents
6
+
7
+ - [FaissIndex Class](#faissindex-class)
8
+ - [Index Types](#index-types)
9
+ - [Methods](#methods)
10
+ - [Types](#types)
11
+ - [Examples](#examples)
12
+
13
+ ## FaissIndex Class
14
+
15
+ The main class for creating and managing FAISS indexes.
16
+
17
+ ### Constructor
18
+
19
+ ```typescript
20
+ new FaissIndex(config: FaissIndexConfig): FaissIndex
21
+ ```
22
+
23
+ Creates a new FAISS index with the specified configuration.
24
+
25
+ **Parameters:**
26
+
27
+ - `config.type` (string, required): Index type
28
+ - `'FLAT_L2'` - Exact search, brute force
29
+ - `'IVF_FLAT'` - Fast approximate search with clustering
30
+ - `'HNSW'` - State-of-the-art approximate search
31
+ - `config.dims` (number, required): Vector dimensions (must be positive integer)
32
+ - `config.nlist` (number, optional): Number of clusters for IVF_FLAT (default: 100)
33
+ - `config.nprobe` (number, optional): Clusters to search for IVF_FLAT (default: 10)
34
+ - `config.M` (number, optional): Connections per node for HNSW (default: 16)
35
+ - `config.efConstruction` (number, optional): HNSW construction parameter (default: 200)
36
+ - `config.efSearch` (number, optional): HNSW search parameter (default: 50)
37
+
38
+ **Example:**
39
+
40
+ ```javascript
41
+ const index = new FaissIndex({ type: 'HNSW', dims: 768 });
42
+ ```
43
+
44
+ ## Index Types
45
+
46
+ ### FLAT_L2 (IndexFlatL2)
47
+
48
+ Exact search using brute-force L2 distance calculation.
49
+
50
+ **Best for:**
51
+ - Small datasets (< 10k vectors)
52
+ - When 100% recall is required
53
+ - Prototyping and testing
54
+
55
+ **Performance:**
56
+ - Search: O(n) - linear scan
57
+ - Memory: 4 × dims × n bytes
58
+ - Accuracy: 100% recall
59
+
60
+ **Example:**
61
+
62
+ ```javascript
63
+ const index = new FaissIndex({ type: 'FLAT_L2', dims: 128 });
64
+ ```
65
+
66
+ ### IVF_FLAT (IndexIVFFlat)
67
+
68
+ Fast approximate search using inverted file index with flat vectors.
69
+
70
+ **Best for:**
71
+ - Medium datasets (10k - 1M vectors)
72
+ - When 90-95% recall is acceptable
73
+ - Production systems with medium-sized datasets
74
+
75
+ **Performance:**
76
+ - Search: O(nprobe × n/nlist) - much faster than FLAT
77
+ - Memory: Similar to FLAT + cluster overhead
78
+ - Accuracy: ~90-95% recall (configurable)
79
+
80
+ **Requirements:**
81
+ - Must call `train()` before adding vectors
82
+ - Training typically requires 10k-100k sample vectors
83
+
84
+ **Example:**
85
+
86
+ ```javascript
87
+ const index = new FaissIndex({
88
+ type: 'IVF_FLAT',
89
+ dims: 768,
90
+ nlist: 100, // Number of clusters
91
+ nprobe: 10 // Clusters to search
92
+ });
93
+
94
+ // Must train before adding vectors
95
+ await index.train(trainingVectors);
96
+ await index.add(dataVectors);
97
+ ```
98
+
99
+ ### HNSW (IndexHNSW)
100
+
101
+ Hierarchical Navigable Small World graph - state-of-the-art approximate search.
102
+
103
+ **Best for:**
104
+ - Large datasets (> 100k vectors)
105
+ - Best speed/accuracy tradeoff
106
+ - Production systems requiring high performance
107
+
108
+ **Performance:**
109
+ - Search: O(log n) - logarithmic search
110
+ - Memory: ~1.5-2× more than FLAT
111
+ - Accuracy: ~95-99% recall (configurable)
112
+
113
+ **No training required** - ready to use immediately.
114
+
115
+ **Example:**
116
+
117
+ ```javascript
118
+ const index = new FaissIndex({
119
+ type: 'HNSW',
120
+ dims: 1536,
121
+ M: 16, // Connections per node
122
+ efConstruction: 200, // Construction parameter
123
+ efSearch: 50 // Search parameter
124
+ });
125
+ ```
126
+
127
+ ## Methods
128
+
129
+ ### add(vectors: Float32Array): Promise<void>
130
+
131
+ Add vectors to the index. Can add a single vector or a batch of vectors.
132
+
133
+ **Parameters:**
134
+ - `vectors` (Float32Array): Vector data. For batch operations, vectors must be concatenated: `[v1[0..d-1], v2[0..d-1], ...]`
135
+
136
+ **Example:**
137
+
138
+ ```javascript
139
+ // Single vector
140
+ await index.add(new Float32Array([1, 2, 3, 4]));
141
+
142
+ // Batch of 4 vectors (each 4 dimensions)
143
+ await index.add(new Float32Array([
144
+ 1, 0, 0, 0, // Vector 1
145
+ 0, 1, 0, 0, // Vector 2
146
+ 0, 0, 1, 0, // Vector 3
147
+ 0, 0, 0, 1 // Vector 4
148
+ ]));
149
+ ```
150
+
151
+ **Throws:**
152
+ - `Error` if index is disposed
153
+ - `Error` if vector dimensions don't match index dimensions
154
+ - `Error` if IVF_FLAT index is not trained
155
+
156
+ ### search(query: Float32Array, k: number): Promise<SearchResults>
157
+
158
+ Search for k nearest neighbors.
159
+
160
+ **Parameters:**
161
+ - `query` (Float32Array): Query vector (must match index dimensions)
162
+ - `k` (number): Number of nearest neighbors to return
163
+
164
+ **Returns:**
165
+ - `Promise<SearchResults>`: Object containing:
166
+ - `distances` (Float32Array): L2 distances to nearest neighbors
167
+ - `labels` (Int32Array): Indices of nearest neighbors
168
+
169
+ **Example:**
170
+
171
+ ```javascript
172
+ const query = new Float32Array([1, 0, 0, 0]);
173
+ const results = await index.search(query, 5);
174
+
175
+ console.log('Nearest neighbors:', results.labels);
176
+ console.log('Distances:', results.distances);
177
+ ```
178
+
179
+ **Throws:**
180
+ - `Error` if index is disposed
181
+ - `Error` if query dimensions don't match
182
+ - `Error` if k is invalid
183
+
184
+ ### searchBatch(queries: Float32Array, k: number): Promise<SearchResults>
185
+
186
+ Perform batch search for multiple queries efficiently.
187
+
188
+ **Parameters:**
189
+ - `queries` (Float32Array): Query vectors concatenated: `[q1[0..d-1], q2[0..d-1], ...]`
190
+ - `k` (number): Number of nearest neighbors per query
191
+
192
+ **Returns:**
193
+ - `Promise<SearchResults>`: Object containing:
194
+ - `distances` (Float32Array): Shape `[nq * k]` - distances for all queries
195
+ - `labels` (Int32Array): Shape `[nq * k]` - labels for all queries
196
+
197
+ **Example:**
198
+
199
+ ```javascript
200
+ // 3 queries of 4 dimensions each
201
+ const queries = new Float32Array([
202
+ 1, 0, 0, 0, // Query 1
203
+ 0, 1, 0, 0, // Query 2
204
+ 0, 0, 1, 0 // Query 3
205
+ ]);
206
+ const results = await index.searchBatch(queries, 5);
207
+
208
+ // results.distances[0..4] = distances for query 1
209
+ // results.distances[5..9] = distances for query 2
210
+ // results.distances[10..14] = distances for query 3
211
+ ```
212
+
213
+ ### train(vectors: Float32Array): Promise<void>
214
+
215
+ Train an IVF_FLAT index. Required before adding vectors.
216
+
217
+ **Parameters:**
218
+ - `vectors` (Float32Array): Training vectors (typically 10k-100k vectors)
219
+
220
+ **Example:**
221
+
222
+ ```javascript
223
+ const trainingVectors = new Float32Array(/* 10k vectors */);
224
+ await ivfIndex.train(trainingVectors);
225
+ await ivfIndex.add(dataVectors); // Now you can add vectors
226
+ ```
227
+
228
+ **Throws:**
229
+ - `Error` if index is not IVF_FLAT
230
+ - `Error` if index is disposed
231
+
232
+ ### setNprobe(nprobe: number): Promise<void>
233
+
234
+ Set the number of clusters to search for IVF_FLAT indexes.
235
+
236
+ **Parameters:**
237
+ - `nprobe` (number): Number of clusters to search (higher = more accurate, slower)
238
+
239
+ **Example:**
240
+
241
+ ```javascript
242
+ await ivfIndex.setNprobe(20); // Search more clusters
243
+ ```
244
+
245
+ **Throws:**
246
+ - `Error` if index is not IVF_FLAT
247
+ - `Error` if index is disposed
248
+
249
+ ### getStats(): IndexStats
250
+
251
+ Get index statistics.
252
+
253
+ **Returns:**
254
+ - `IndexStats`: Object containing:
255
+ - `ntotal` (number): Total vectors in index
256
+ - `dims` (number): Vector dimensions
257
+ - `isTrained` (boolean): Whether index is trained (IVF only)
258
+ - `type` (string): Index type
259
+
260
+ **Example:**
261
+
262
+ ```javascript
263
+ const stats = index.getStats();
264
+ console.log(`Index has ${stats.ntotal} vectors of ${stats.dims} dimensions`);
265
+ ```
266
+
267
+ ### save(filename: string): Promise<void>
268
+
269
+ Save index to disk.
270
+
271
+ **Parameters:**
272
+ - `filename` (string): File path to save index
273
+
274
+ **Example:**
275
+
276
+ ```javascript
277
+ await index.save('./my-index.faiss');
278
+ ```
279
+
280
+ **Throws:**
281
+ - `Error` if index is disposed
282
+ - `Error` if file cannot be written
283
+
284
+ ### static load(filename: string): Promise<FaissIndex>
285
+
286
+ Load index from disk.
287
+
288
+ **Parameters:**
289
+ - `filename` (string): File path to load index from
290
+
291
+ **Returns:**
292
+ - `Promise<FaissIndex>`: Loaded index instance
293
+
294
+ **Example:**
295
+
296
+ ```javascript
297
+ const index = await FaissIndex.load('./my-index.faiss');
298
+ ```
299
+
300
+ **Throws:**
301
+ - `Error` if file cannot be read
302
+ - `Error` if file is not a valid FAISS index
303
+
304
+ ### toBuffer(): Promise<Buffer>
305
+
306
+ Serialize index to a Node.js Buffer.
307
+
308
+ **Returns:**
309
+ - `Promise<Buffer>`: Serialized index data
310
+
311
+ **Example:**
312
+
313
+ ```javascript
314
+ const buffer = await index.toBuffer();
315
+ // Store in database, send over network, etc.
316
+ ```
317
+
318
+ **Throws:**
319
+ - `Error` if index is disposed
320
+
321
+ ### static fromBuffer(buffer: Buffer): Promise<FaissIndex>
322
+
323
+ Deserialize index from Buffer.
324
+
325
+ **Parameters:**
326
+ - `buffer` (Buffer): Serialized index data
327
+
328
+ **Returns:**
329
+ - `Promise<FaissIndex>`: Deserialized index instance
330
+
331
+ **Example:**
332
+
333
+ ```javascript
334
+ const index = await FaissIndex.fromBuffer(buffer);
335
+ ```
336
+
337
+ **Throws:**
338
+ - `Error` if buffer is not valid FAISS index data
339
+
340
+ ### mergeFrom(otherIndex: FaissIndex): Promise<void>
341
+
342
+ Merge vectors from another index into this index.
343
+
344
+ **Parameters:**
345
+ - `otherIndex` (FaissIndex): Index to merge from
346
+
347
+ **Example:**
348
+
349
+ ```javascript
350
+ const index1 = new FaissIndex({ type: 'FLAT_L2', dims: 128 });
351
+ const index2 = new FaissIndex({ type: 'FLAT_L2', dims: 128 });
352
+
353
+ await index1.add(vectors1);
354
+ await index2.add(vectors2);
355
+
356
+ await index1.mergeFrom(index2); // index1 now contains vectors from both
357
+ // Note: index2 is now empty (FAISS behavior)
358
+ ```
359
+
360
+ **Throws:**
361
+ - `Error` if index is disposed
362
+ - `Error` if otherIndex is disposed
363
+ - `Error` if dimensions don't match
364
+
365
+ ### dispose(): void
366
+
367
+ Explicitly dispose of the index and free resources.
368
+
369
+ **Example:**
370
+
371
+ ```javascript
372
+ index.dispose();
373
+ // Index is now unusable - all operations will throw errors
374
+ ```
375
+
376
+ **Note:** Disposal is automatic on garbage collection, but explicit disposal is recommended for immediate resource cleanup.
377
+
378
+ ## Types
379
+
380
+ ### FaissIndexConfig
381
+
382
+ ```typescript
383
+ interface FaissIndexConfig {
384
+ type: 'FLAT_L2' | 'IVF_FLAT' | 'HNSW';
385
+ dims: number;
386
+ nlist?: number;
387
+ nprobe?: number;
388
+ M?: number;
389
+ efConstruction?: number;
390
+ efSearch?: number;
391
+ }
392
+ ```
393
+
394
+ ### SearchResults
395
+
396
+ ```typescript
397
+ interface SearchResults {
398
+ distances: Float32Array;
399
+ labels: Int32Array;
400
+ }
401
+ ```
402
+
403
+ ### IndexStats
404
+
405
+ ```typescript
406
+ interface IndexStats {
407
+ ntotal: number;
408
+ dims: number;
409
+ isTrained: boolean;
410
+ type: string;
411
+ }
412
+ ```
413
+
414
+ ## Examples
415
+
416
+ See the [README.md](./README.md#examples) for complete usage examples.
@@ -0,0 +1,203 @@
1
+ # Documentation
2
+
3
+ This project uses multiple documentation tools to provide comprehensive documentation for both JavaScript/TypeScript API and C++ native code.
4
+
5
+ ## Documentation Structure
6
+
7
+ - **README.md** - Main project documentation and quick start guide
8
+ - **API.md** - Complete API reference (manually maintained)
9
+ - **docs/api/** - TypeDoc-generated JavaScript/TypeScript API documentation
10
+ - **docs/html/** - Doxygen-generated C++ native code documentation
11
+
12
+ ## Documentation Tools
13
+
14
+ ### 1. TypeDoc (JavaScript/TypeScript API)
15
+
16
+ **Purpose:** Generate API documentation from TypeScript definitions and JSDoc comments.
17
+
18
+ **Configuration:** `typedoc.json`
19
+
20
+ **Generate:**
21
+ ```bash
22
+ npm run docs:js
23
+ ```
24
+
25
+ **Output:** `docs/api/` (HTML documentation)
26
+
27
+ **Features:**
28
+ - Extracts documentation from `types.d.ts` and JSDoc comments
29
+ - Type-safe documentation with full type information
30
+ - Interactive search and navigation
31
+ - Automatically deployed to GitHub Pages
32
+
33
+ ### 2. Doxygen (C++ Native Code)
34
+
35
+ **Purpose:** Generate documentation for C++ native bindings.
36
+
37
+ **Configuration:** `Doxyfile`
38
+
39
+ **Generate:**
40
+ ```bash
41
+ npm run docs:cpp
42
+ ```
43
+
44
+ **Output:** `docs/html/` (HTML documentation)
45
+
46
+ **Features:**
47
+ - Documents C++ classes, functions, and structures
48
+ - Source code browsing
49
+ - Call graphs and dependency diagrams
50
+ - Automatically deployed to GitHub Pages
51
+
52
+ ### 3. Generate All Documentation
53
+
54
+ ```bash
55
+ npm run docs # Generates both TypeDoc and Doxygen docs
56
+ ```
57
+
58
+ ## Automated Documentation
59
+
60
+ ### GitHub Actions (Fully Automatic)
61
+
62
+ Documentation is **automatically generated and deployed** when you push to `main`:
63
+
64
+ - ✅ **Auto-generates** on every push to `main`
65
+ - ✅ **Auto-deploys** to GitHub Pages
66
+ - ✅ **Runs on PRs** to verify docs generate correctly
67
+ - ✅ **Monitors** source files, config files, and README
68
+
69
+ **No manual steps required!** Just push your code and documentation updates automatically.
70
+
71
+ ### Local Development (Watch Mode)
72
+
73
+ For local development with auto-regeneration:
74
+
75
+ ```bash
76
+ # Watch mode (TypeDoc only - regenerates on file changes)
77
+ npm run docs:watch
78
+
79
+ # Or use the auto-docs script (both TypeDoc and Doxygen)
80
+ ./scripts/auto-docs.sh
81
+ ```
82
+
83
+ The auto-docs script watches for changes and regenerates both docs automatically.
84
+
85
+ ### Pre-Publish Hook
86
+
87
+ Documentation is automatically generated before publishing to npm:
88
+
89
+ ```bash
90
+ npm publish # Automatically runs 'npm run docs' first
91
+ ```
92
+
93
+ ## Viewing Documentation
94
+
95
+ ### Local Development
96
+
97
+ **TypeDoc (JavaScript API):**
98
+ ```bash
99
+ npm run docs:serve
100
+ # Visit http://localhost:8000
101
+ ```
102
+
103
+ **Doxygen (C++ Code):**
104
+ ```bash
105
+ npm run docs:serve:cpp
106
+ # Visit http://localhost:8001
107
+ ```
108
+
109
+ ### Online
110
+
111
+ - **JavaScript API Docs:** [GitHub Pages - API](https://anupammaurya6767.github.io/faiss-node-native/api/)
112
+ - **C++ Native Docs:** [GitHub Pages - Native](https://anupammaurya6767.github.io/faiss-node-native/)
113
+
114
+ ## Writing Documentation
115
+
116
+ ### JavaScript/TypeScript
117
+
118
+ Add JSDoc comments to your code:
119
+
120
+ ```javascript
121
+ /**
122
+ * Add vectors to the index
123
+ * @param {Float32Array} vectors - Single vector or batch of vectors
124
+ * @returns {Promise<void>}
125
+ * @example
126
+ * await index.add(new Float32Array([1, 2, 3, 4]));
127
+ */
128
+ async add(vectors) {
129
+ // ...
130
+ }
131
+ ```
132
+
133
+ TypeDoc will automatically extract:
134
+ - Parameter types from TypeScript definitions
135
+ - Return types
136
+ - JSDoc comments
137
+ - Examples
138
+
139
+ ### C++
140
+
141
+ Add Doxygen comments:
142
+
143
+ ```cpp
144
+ /**
145
+ * Add vectors to the index
146
+ * @param vectors Pointer to float array (n * dims elements)
147
+ * @param n Number of vectors
148
+ * @throws std::runtime_error if index is disposed
149
+ */
150
+ void Add(const float* vectors, size_t n);
151
+ ```
152
+
153
+ ## Automated Deployment
154
+
155
+ Both documentation types are automatically deployed to GitHub Pages:
156
+
157
+ - **TypeDoc:** Deployed via `.github/workflows/docs-typedoc.yml`
158
+ - **Doxygen:** Deployed via `.github/workflows/docs.yml`
159
+
160
+ Documentation is updated automatically when:
161
+ - Code is pushed to `main` branch
162
+ - Source files are modified
163
+ - Documentation configuration files are updated
164
+
165
+ ## Best Practices
166
+
167
+ 1. **Keep JSDoc comments up-to-date** - They're the source of truth for API docs
168
+ 2. **Use TypeScript types** - TypeDoc extracts types automatically
169
+ 3. **Add examples** - Use `@example` tags in JSDoc
170
+ 4. **Document parameters** - Use `@param` for all parameters
171
+ 5. **Document return values** - Use `@returns` for return types
172
+ 6. **Document errors** - Use `@throws` for exceptions
173
+
174
+ ## Troubleshooting
175
+
176
+ ### TypeDoc not generating
177
+
178
+ ```bash
179
+ # Install dependencies
180
+ npm install
181
+
182
+ # Check TypeDoc version
183
+ npx typedoc --version
184
+
185
+ # Generate with verbose output
186
+ npx typedoc --verbose
187
+ ```
188
+
189
+ ### Doxygen not generating
190
+
191
+ ```bash
192
+ # Check Doxygen installation
193
+ doxygen --version
194
+
195
+ # Generate with verbose output
196
+ doxygen Doxyfile 2>&1 | head -20
197
+ ```
198
+
199
+ ### Documentation not deploying
200
+
201
+ - Check GitHub Actions workflow runs
202
+ - Verify GitHub Pages is enabled in repository settings
203
+ - Check for errors in workflow logs
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Anupam Maurya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,48 @@
1
+ # Quick Publishing Guide
2
+
3
+ ## 🚀 Publish Your First Package (3 Steps)
4
+
5
+ ### Step 1: Test First (Dry Run)
6
+ ```bash
7
+ npm run publish:dry-run
8
+ ```
9
+ This shows what will be published WITHOUT actually publishing.
10
+
11
+ ### Step 2: Verify Everything Looks Good
12
+ Check the output - should show:
13
+ - ✅ Package name: `@faiss-node/native`
14
+ - ✅ Version: `0.1.0`
15
+ - ✅ Author: Your name
16
+ - ✅ Description: Looks good
17
+ - ✅ Files: Only necessary files (no test/, .github/, etc.)
18
+
19
+ ### Step 3: Publish!
20
+ ```bash
21
+ npm run publish:local
22
+ ```
23
+
24
+ That's it! Your package will be live on npm in a few minutes.
25
+
26
+ ## 📍 After Publishing
27
+
28
+ 1. **Check your package**: https://www.npmjs.com/package/@faiss-node/native
29
+ 2. **Test installation**:
30
+ ```bash
31
+ cd /tmp && mkdir test && cd test
32
+ npm init -y
33
+ npm install @faiss-node/native
34
+ node -e "const { FaissIndex } = require('@faiss-node/native'); console.log('✅ Works!');"
35
+ ```
36
+
37
+ ## ⚠️ Important Notes
38
+
39
+ - **You can't unpublish easily** (only within 72 hours if no one installed it)
40
+ - **Version numbers are permanent** - can't republish same version
41
+ - **Always test with `publish:dry-run` first**
42
+
43
+ ## 🎉 You're Done!
44
+
45
+ Your package is now live! Share it:
46
+ - Twitter/X: "Just published @faiss-node/native - high-performance FAISS bindings for Node.js 🚀"
47
+ - GitHub: Update your profile README
48
+ - Reddit: r/node, r/javascript