ruvector-fixed / dist /index.js
Archie
Fix dimension/dimensions bug and positional insert/search args
40d7073
"use strict";
/**
* ruvector - High-performance vector database for Node.js
*
* This package automatically detects and uses the best available implementation:
* 1. Native (Rust-based, fastest) - if available for your platform
* 2. RVF (persistent store) - if @ruvector/rvf is installed
* 3. Stub (testing fallback) - limited functionality
*
* Also provides safe wrappers for GNN and Attention modules that handle
* array type conversions automatically.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeVectorDb = exports.VectorDB = exports.VectorDb = void 0;
exports.getImplementationType = getImplementationType;
exports.isNative = isNative;
exports.isRvf = isRvf;
exports.isWasm = isWasm;
exports.getVersion = getVersion;
__exportStar(require("./types"), exports);
// Export core wrappers (safe interfaces with automatic type conversion)
__exportStar(require("./core"), exports);
__exportStar(require("./services"), exports);
let implementation;
let implementationType = 'wasm';
// Check for explicit --backend rvf flag or RUVECTOR_BACKEND env var
const rvfRequested = process.env.RUVECTOR_BACKEND === 'rvf' ||
process.argv.includes('--backend') && process.argv[process.argv.indexOf('--backend') + 1] === 'rvf';
if (rvfRequested) {
// Explicit rvf backend requested - fail hard if not available
try {
implementation = require('@ruvector/rvf');
implementationType = 'rvf';
}
catch (e) {
throw new Error('@ruvector/rvf is not installed.\n' +
' Run: npm install @ruvector/rvf\n' +
' The --backend rvf flag requires this package.');
}
}
else {
try {
// Try to load native module first
implementation = require('@ruvector/core');
implementationType = 'native';
// Verify it's actually working (native module exports VectorDb, not VectorDB)
if (typeof implementation.VectorDb !== 'function') {
throw new Error('Native module loaded but VectorDb class not found');
}
}
catch (e) {
// Try rvf (persistent store) as second fallback
try {
implementation = require('@ruvector/rvf');
implementationType = 'rvf';
}
catch (rvfErr) {
// Graceful fallback - don't crash, just warn
console.warn('[RuVector] Native module not available:', e.message);
console.warn('[RuVector] RVF module not available:', rvfErr.message);
console.warn('[RuVector] Vector operations will be limited. Install @ruvector/core or @ruvector/rvf for full functionality.');
// Create a stub implementation that provides basic functionality
implementation = {
VectorDb: class StubVectorDb {
constructor() {
console.warn('[RuVector] Using stub VectorDb - install @ruvector/core for native performance');
}
async insert() { return 'stub-id-' + Date.now(); }
async insertBatch(entries) { return entries.map(() => 'stub-id-' + Date.now()); }
async search() { return []; }
async delete() { return true; }
async get() { return null; }
async len() { return 0; }
async isEmpty() { return true; }
}
};
implementationType = 'wasm'; // Mark as fallback mode
}
}
}
/**
* Get the current implementation type
*/
function getImplementationType() {
return implementationType;
}
/**
* Check if native implementation is being used
*/
function isNative() {
return implementationType === 'native';
}
/**
* Check if RVF implementation is being used
*/
function isRvf() {
return implementationType === 'rvf';
}
/**
* Check if stub/fallback implementation is being used
*/
function isWasm() {
return implementationType === 'wasm';
}
/**
* Get version information
*/
function getVersion() {
const pkg = require('../package.json');
return {
version: pkg.version,
implementation: implementationType
};
}
/**
* Wrapper class that automatically handles metadata JSON conversion
*/
class VectorDBWrapper {
constructor(options) {
// Normalize: accept both 'dimension' (singular) and 'dimensions' (plural)
if (options && options.dimension && !options.dimensions) {
options = { ...options, dimensions: options.dimension };
delete options.dimension;
}
this.db = new implementation.VectorDb(options);
}
/**
* Insert a vector with optional metadata (objects are auto-converted to JSON)
*/
async insert(entryOrVector, metadata) {
// Support positional args: insert(vector, metadata) as well as insert({vector, metadata})
let entry;
if (entryOrVector instanceof Float32Array || Array.isArray(entryOrVector)) {
entry = { vector: entryOrVector, metadata: metadata };
} else {
entry = entryOrVector;
}
const nativeEntry = {
id: entry.id,
vector: entry.vector instanceof Float32Array ? entry.vector : new Float32Array(entry.vector),
};
// Auto-convert metadata object to JSON string
if (entry.metadata) {
nativeEntry.metadata = JSON.stringify(entry.metadata);
}
return this.db.insert(nativeEntry);
}
/**
* Insert multiple vectors in batch
*/
async insertBatch(entries) {
const nativeEntries = entries.map(entry => ({
id: entry.id,
vector: entry.vector instanceof Float32Array ? entry.vector : new Float32Array(entry.vector),
metadata: entry.metadata ? JSON.stringify(entry.metadata) : undefined,
}));
return this.db.insertBatch(nativeEntries);
}
/**
* Search for similar vectors (metadata is auto-parsed from JSON)
*/
async search(queryOrVector, k, efSearch) {
// Support positional args: search(vector, k) as well as search({vector, k})
let query;
if (queryOrVector instanceof Float32Array || Array.isArray(queryOrVector)) {
query = { vector: queryOrVector, k: k || 10, efSearch: efSearch };
} else {
query = queryOrVector;
}
const nativeQuery = {
vector: query.vector instanceof Float32Array ? query.vector : new Float32Array(query.vector),
k: query.k,
efSearch: query.efSearch,
};
// Auto-convert filter object to JSON string
if (query.filter) {
nativeQuery.filter = JSON.stringify(query.filter);
}
const results = await this.db.search(nativeQuery);
// Auto-parse metadata JSON strings back to objects
return results.map((r) => ({
id: r.id,
score: r.score,
vector: r.vector,
metadata: r.metadata ? JSON.parse(r.metadata) : undefined,
}));
}
/**
* Get a vector by ID (metadata is auto-parsed from JSON)
*/
async get(id) {
const entry = await this.db.get(id);
if (!entry)
return null;
return {
id: entry.id,
vector: entry.vector,
metadata: entry.metadata ? JSON.parse(entry.metadata) : undefined,
};
}
/**
* Delete a vector by ID
*/
async delete(id) {
return this.db.delete(id);
}
/**
* Get the number of vectors in the database
*/
async len() {
return this.db.len();
}
/**
* Check if the database is empty
*/
async isEmpty() {
return this.db.isEmpty();
}
}
// Export the wrapper class (aliased as VectorDB for backwards compatibility)
exports.VectorDb = VectorDBWrapper;
exports.VectorDB = VectorDBWrapper;
// Also export the raw native implementation for advanced users
exports.NativeVectorDb = implementation.VectorDb;
// Export everything from the implementation
exports.default = implementation;