123 lines
3.5 KiB
TypeScript
123 lines
3.5 KiB
TypeScript
/**
|
|
* Node.js-specific exports for @ruvector/wasm
|
|
*/
|
|
|
|
import type { VectorEntry, SearchResult, DbOptions } from './index';
|
|
|
|
let wasmModule: any = null;
|
|
|
|
/**
|
|
* Initialize WASM module for Node.js
|
|
*/
|
|
async function initWasm() {
|
|
if (!wasmModule) {
|
|
wasmModule = await import('../pkg-node/ruvector_wasm.js');
|
|
}
|
|
return wasmModule;
|
|
}
|
|
|
|
/**
|
|
* VectorDB class for Node.js
|
|
*/
|
|
export class VectorDB {
|
|
private db: any;
|
|
private dimensions: number;
|
|
|
|
constructor(options: DbOptions) {
|
|
this.dimensions = options.dimensions;
|
|
}
|
|
|
|
async init(): Promise<void> {
|
|
const module = await initWasm();
|
|
this.db = new module.VectorDB(
|
|
this.dimensions,
|
|
'cosine',
|
|
true
|
|
);
|
|
}
|
|
|
|
insert(vector: Float32Array | number[], id?: string, metadata?: Record<string, any>): string {
|
|
if (!this.db) throw new Error('Database not initialized. Call init() first.');
|
|
const vectorArray = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
|
return this.db.insert(vectorArray, id, metadata);
|
|
}
|
|
|
|
insertBatch(entries: VectorEntry[]): string[] {
|
|
if (!this.db) throw new Error('Database not initialized. Call init() first.');
|
|
const processedEntries = entries.map(entry => ({
|
|
id: entry.id,
|
|
vector: entry.vector instanceof Float32Array ? entry.vector : new Float32Array(entry.vector),
|
|
metadata: entry.metadata
|
|
}));
|
|
return this.db.insertBatch(processedEntries);
|
|
}
|
|
|
|
search(query: Float32Array | number[], k: number, filter?: Record<string, any>): SearchResult[] {
|
|
if (!this.db) throw new Error('Database not initialized. Call init() first.');
|
|
const queryArray = query instanceof Float32Array ? query : new Float32Array(query);
|
|
const results = this.db.search(queryArray, k, filter);
|
|
return results.map((r: any) => ({
|
|
id: r.id,
|
|
score: r.score,
|
|
vector: r.vector,
|
|
metadata: r.metadata
|
|
}));
|
|
}
|
|
|
|
delete(id: string): boolean {
|
|
if (!this.db) throw new Error('Database not initialized. Call init() first.');
|
|
return this.db.delete(id);
|
|
}
|
|
|
|
get(id: string): VectorEntry | null {
|
|
if (!this.db) throw new Error('Database not initialized. Call init() first.');
|
|
const entry = this.db.get(id);
|
|
if (!entry) return null;
|
|
return { id: entry.id, vector: entry.vector, metadata: entry.metadata };
|
|
}
|
|
|
|
len(): number {
|
|
if (!this.db) throw new Error('Database not initialized. Call init() first.');
|
|
return this.db.len();
|
|
}
|
|
|
|
isEmpty(): boolean {
|
|
if (!this.db) throw new Error('Database not initialized. Call init() first.');
|
|
return this.db.isEmpty();
|
|
}
|
|
|
|
getDimensions(): number {
|
|
return this.dimensions;
|
|
}
|
|
|
|
// Node.js specific: save to file system
|
|
async saveToFile(path: string): Promise<void> {
|
|
console.warn('Node.js file persistence not yet implemented');
|
|
}
|
|
|
|
static async loadFromFile(path: string, options: DbOptions): Promise<VectorDB> {
|
|
const db = new VectorDB(options);
|
|
await db.init();
|
|
console.warn('Node.js file persistence not yet implemented');
|
|
return db;
|
|
}
|
|
}
|
|
|
|
export async function detectSIMD(): Promise<boolean> {
|
|
const module = await initWasm();
|
|
return module.detectSIMD();
|
|
}
|
|
|
|
export async function version(): Promise<string> {
|
|
const module = await initWasm();
|
|
return module.version();
|
|
}
|
|
|
|
export async function benchmark(name: string, iterations: number, dimensions: number): Promise<number> {
|
|
const module = await initWasm();
|
|
return module.benchmark(name, iterations, dimensions);
|
|
}
|
|
|
|
export type { VectorEntry, SearchResult, DbOptions };
|
|
export default VectorDB;
|