@ruvector/rvf 0.1.3 → 0.1.5

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.
@@ -0,0 +1,110 @@
1
+ import type { RvfOptions, RvfQueryOptions, RvfSearchResult, RvfIngestResult, RvfIngestEntry, RvfDeleteResult, RvfCompactionResult, RvfStatus, RvfFilterExpr, RvfKernelData, RvfEbpfData, RvfSegmentInfo, BackendType } from './types';
2
+ /**
3
+ * Abstract backend that wraps either the native (N-API) or WASM build of
4
+ * rvf-runtime. The `RvfDatabase` class delegates all I/O to a backend
5
+ * instance, keeping the public API identical regardless of runtime.
6
+ */
7
+ export interface RvfBackend {
8
+ /** Create a new store file at `path` with the given options. */
9
+ create(path: string, options: RvfOptions): Promise<void>;
10
+ /** Open an existing store at `path` for read-write access. */
11
+ open(path: string): Promise<void>;
12
+ /** Open an existing store at `path` for read-only access. */
13
+ openReadonly(path: string): Promise<void>;
14
+ /** Ingest a batch of vectors. */
15
+ ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
16
+ /** Query the k nearest neighbors. */
17
+ query(vector: Float32Array, k: number, options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
18
+ /** Soft-delete vectors by ID. */
19
+ delete(ids: string[]): Promise<RvfDeleteResult>;
20
+ /** Soft-delete vectors matching a filter. */
21
+ deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult>;
22
+ /** Run compaction to reclaim dead space. */
23
+ compact(): Promise<RvfCompactionResult>;
24
+ /** Get the current store status. */
25
+ status(): Promise<RvfStatus>;
26
+ /** Close the store, releasing locks. */
27
+ close(): Promise<void>;
28
+ fileId(): Promise<string>;
29
+ parentId(): Promise<string>;
30
+ lineageDepth(): Promise<number>;
31
+ derive(childPath: string, options?: RvfOptions): Promise<RvfBackend>;
32
+ embedKernel(arch: number, kernelType: number, flags: number, image: Uint8Array, apiPort: number, cmdline?: string): Promise<number>;
33
+ extractKernel(): Promise<RvfKernelData | null>;
34
+ embedEbpf(programType: number, attachType: number, maxDimension: number, bytecode: Uint8Array, btf?: Uint8Array): Promise<number>;
35
+ extractEbpf(): Promise<RvfEbpfData | null>;
36
+ segments(): Promise<RvfSegmentInfo[]>;
37
+ dimension(): Promise<number>;
38
+ }
39
+ /**
40
+ * Backend that delegates to the `@ruvector/rvf-node` native N-API addon.
41
+ *
42
+ * The native addon is loaded lazily on first use so that the SDK package can
43
+ * be imported in environments where the native build is unavailable (e.g.
44
+ * browsers) without throwing at import time.
45
+ */
46
+ export declare class NodeBackend implements RvfBackend {
47
+ private native;
48
+ private handle;
49
+ private loadNative;
50
+ private ensureHandle;
51
+ create(path: string, options: RvfOptions): Promise<void>;
52
+ open(path: string): Promise<void>;
53
+ openReadonly(path: string): Promise<void>;
54
+ ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
55
+ query(vector: Float32Array, k: number, options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
56
+ delete(ids: string[]): Promise<RvfDeleteResult>;
57
+ deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult>;
58
+ compact(): Promise<RvfCompactionResult>;
59
+ status(): Promise<RvfStatus>;
60
+ close(): Promise<void>;
61
+ fileId(): Promise<string>;
62
+ parentId(): Promise<string>;
63
+ lineageDepth(): Promise<number>;
64
+ derive(childPath: string, options?: RvfOptions): Promise<RvfBackend>;
65
+ embedKernel(arch: number, kernelType: number, flags: number, image: Uint8Array, apiPort: number, cmdline?: string): Promise<number>;
66
+ extractKernel(): Promise<RvfKernelData | null>;
67
+ embedEbpf(programType: number, attachType: number, maxDimension: number, bytecode: Uint8Array, btf?: Uint8Array): Promise<number>;
68
+ extractEbpf(): Promise<RvfEbpfData | null>;
69
+ segments(): Promise<RvfSegmentInfo[]>;
70
+ dimension(): Promise<number>;
71
+ }
72
+ /**
73
+ * Backend that delegates to the `@ruvector/rvf-wasm` WASM build.
74
+ *
75
+ * Suitable for browser environments. The WASM module is loaded lazily.
76
+ */
77
+ export declare class WasmBackend implements RvfBackend {
78
+ private wasm;
79
+ private handle;
80
+ private loadWasm;
81
+ private ensureHandle;
82
+ create(path: string, options: RvfOptions): Promise<void>;
83
+ open(path: string): Promise<void>;
84
+ openReadonly(path: string): Promise<void>;
85
+ ingestBatch(entries: RvfIngestEntry[]): Promise<RvfIngestResult>;
86
+ query(vector: Float32Array, k: number, options?: RvfQueryOptions): Promise<RvfSearchResult[]>;
87
+ delete(ids: string[]): Promise<RvfDeleteResult>;
88
+ deleteByFilter(filter: RvfFilterExpr): Promise<RvfDeleteResult>;
89
+ compact(): Promise<RvfCompactionResult>;
90
+ status(): Promise<RvfStatus>;
91
+ close(): Promise<void>;
92
+ fileId(): Promise<string>;
93
+ parentId(): Promise<string>;
94
+ lineageDepth(): Promise<number>;
95
+ derive(_childPath: string, _options?: RvfOptions): Promise<RvfBackend>;
96
+ embedKernel(): Promise<number>;
97
+ extractKernel(): Promise<RvfKernelData | null>;
98
+ embedEbpf(): Promise<number>;
99
+ extractEbpf(): Promise<RvfEbpfData | null>;
100
+ segments(): Promise<RvfSegmentInfo[]>;
101
+ dimension(): Promise<number>;
102
+ }
103
+ /**
104
+ * Resolve a `BackendType` to a concrete `RvfBackend` instance.
105
+ *
106
+ * - `'node'` Always returns a `NodeBackend`.
107
+ * - `'wasm'` Always returns a `WasmBackend`.
108
+ * - `'auto'` Tries `node` first, falls back to `wasm`.
109
+ */
110
+ export declare function resolveBackend(type: BackendType): RvfBackend;
@@ -0,0 +1,580 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WasmBackend = exports.NodeBackend = void 0;
37
+ exports.resolveBackend = resolveBackend;
38
+ const errors_1 = require("./errors");
39
+ // ---------------------------------------------------------------------------
40
+ // NodeBackend — wraps @ruvector/rvf-node (N-API)
41
+ // ---------------------------------------------------------------------------
42
+ /**
43
+ * Backend that delegates to the `@ruvector/rvf-node` native N-API addon.
44
+ *
45
+ * The native addon is loaded lazily on first use so that the SDK package can
46
+ * be imported in environments where the native build is unavailable (e.g.
47
+ * browsers) without throwing at import time.
48
+ */
49
+ class NodeBackend {
50
+ constructor() {
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ this.native = null;
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ this.handle = null;
55
+ }
56
+ async loadNative() {
57
+ if (this.native)
58
+ return;
59
+ try {
60
+ // Dynamic import so the SDK can be bundled for browsers without
61
+ // pulling in the native addon at compile time.
62
+ this.native = await Promise.resolve().then(() => __importStar(require('@ruvector/rvf-node')));
63
+ }
64
+ catch {
65
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'Could not load @ruvector/rvf-node — is it installed?');
66
+ }
67
+ }
68
+ ensureHandle() {
69
+ if (!this.handle) {
70
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.StoreClosed);
71
+ }
72
+ }
73
+ async create(path, options) {
74
+ await this.loadNative();
75
+ try {
76
+ this.handle = await this.native.create(path, mapOptionsToNative(options));
77
+ }
78
+ catch (err) {
79
+ throw errors_1.RvfError.fromNative(err);
80
+ }
81
+ }
82
+ async open(path) {
83
+ await this.loadNative();
84
+ try {
85
+ this.handle = await this.native.open(path);
86
+ }
87
+ catch (err) {
88
+ throw errors_1.RvfError.fromNative(err);
89
+ }
90
+ }
91
+ async openReadonly(path) {
92
+ await this.loadNative();
93
+ try {
94
+ this.handle = await this.native.openReadonly(path);
95
+ }
96
+ catch (err) {
97
+ throw errors_1.RvfError.fromNative(err);
98
+ }
99
+ }
100
+ async ingestBatch(entries) {
101
+ this.ensureHandle();
102
+ try {
103
+ const ids = entries.map((e) => e.id);
104
+ const vectors = entries.map((e) => e.vector instanceof Float32Array ? e.vector : new Float32Array(e.vector));
105
+ const metadata = entries.some((e) => e.metadata)
106
+ ? entries.map((e) => e.metadata ?? {})
107
+ : undefined;
108
+ const result = await this.native.ingestBatch(this.handle, ids, vectors, metadata);
109
+ return {
110
+ accepted: result.accepted,
111
+ rejected: result.rejected,
112
+ epoch: result.epoch,
113
+ };
114
+ }
115
+ catch (err) {
116
+ throw errors_1.RvfError.fromNative(err);
117
+ }
118
+ }
119
+ async query(vector, k, options) {
120
+ this.ensureHandle();
121
+ try {
122
+ const nativeOpts = options ? mapQueryOptionsToNative(options) : undefined;
123
+ const results = await this.native.query(this.handle, vector, k, nativeOpts);
124
+ return results.map((r) => ({
125
+ id: r.id,
126
+ distance: r.distance,
127
+ }));
128
+ }
129
+ catch (err) {
130
+ throw errors_1.RvfError.fromNative(err);
131
+ }
132
+ }
133
+ async delete(ids) {
134
+ this.ensureHandle();
135
+ try {
136
+ const result = await this.native.delete(this.handle, ids);
137
+ return { deleted: result.deleted, epoch: result.epoch };
138
+ }
139
+ catch (err) {
140
+ throw errors_1.RvfError.fromNative(err);
141
+ }
142
+ }
143
+ async deleteByFilter(filter) {
144
+ this.ensureHandle();
145
+ try {
146
+ const result = await this.native.deleteByFilter(this.handle, filter);
147
+ return { deleted: result.deleted, epoch: result.epoch };
148
+ }
149
+ catch (err) {
150
+ throw errors_1.RvfError.fromNative(err);
151
+ }
152
+ }
153
+ async compact() {
154
+ this.ensureHandle();
155
+ try {
156
+ const result = await this.native.compact(this.handle);
157
+ return {
158
+ segmentsCompacted: result.segmentsCompacted ?? result.segments_compacted,
159
+ bytesReclaimed: result.bytesReclaimed ?? result.bytes_reclaimed,
160
+ epoch: result.epoch,
161
+ };
162
+ }
163
+ catch (err) {
164
+ throw errors_1.RvfError.fromNative(err);
165
+ }
166
+ }
167
+ async status() {
168
+ this.ensureHandle();
169
+ try {
170
+ const s = await this.native.status(this.handle);
171
+ return mapNativeStatus(s);
172
+ }
173
+ catch (err) {
174
+ throw errors_1.RvfError.fromNative(err);
175
+ }
176
+ }
177
+ async close() {
178
+ if (!this.handle)
179
+ return;
180
+ try {
181
+ await this.native.close(this.handle);
182
+ }
183
+ catch (err) {
184
+ throw errors_1.RvfError.fromNative(err);
185
+ }
186
+ finally {
187
+ this.handle = null;
188
+ }
189
+ }
190
+ async fileId() {
191
+ this.ensureHandle();
192
+ try {
193
+ return this.handle.fileId();
194
+ }
195
+ catch (err) {
196
+ throw errors_1.RvfError.fromNative(err);
197
+ }
198
+ }
199
+ async parentId() {
200
+ this.ensureHandle();
201
+ try {
202
+ return this.handle.parentId();
203
+ }
204
+ catch (err) {
205
+ throw errors_1.RvfError.fromNative(err);
206
+ }
207
+ }
208
+ async lineageDepth() {
209
+ this.ensureHandle();
210
+ try {
211
+ return this.handle.lineageDepth();
212
+ }
213
+ catch (err) {
214
+ throw errors_1.RvfError.fromNative(err);
215
+ }
216
+ }
217
+ async derive(childPath, options) {
218
+ this.ensureHandle();
219
+ try {
220
+ const nativeOpts = options ? mapOptionsToNative(options) : undefined;
221
+ const childHandle = this.handle.derive(childPath, nativeOpts);
222
+ const child = new NodeBackend();
223
+ child.native = this.native;
224
+ child.handle = childHandle;
225
+ return child;
226
+ }
227
+ catch (err) {
228
+ throw errors_1.RvfError.fromNative(err);
229
+ }
230
+ }
231
+ async embedKernel(arch, kernelType, flags, image, apiPort, cmdline) {
232
+ this.ensureHandle();
233
+ try {
234
+ return this.handle.embedKernel(arch, kernelType, flags, Buffer.from(image), apiPort, cmdline);
235
+ }
236
+ catch (err) {
237
+ throw errors_1.RvfError.fromNative(err);
238
+ }
239
+ }
240
+ async extractKernel() {
241
+ this.ensureHandle();
242
+ try {
243
+ const result = this.handle.extractKernel();
244
+ if (!result)
245
+ return null;
246
+ return {
247
+ header: new Uint8Array(result.header),
248
+ image: new Uint8Array(result.image),
249
+ };
250
+ }
251
+ catch (err) {
252
+ throw errors_1.RvfError.fromNative(err);
253
+ }
254
+ }
255
+ async embedEbpf(programType, attachType, maxDimension, bytecode, btf) {
256
+ this.ensureHandle();
257
+ try {
258
+ return this.handle.embedEbpf(programType, attachType, maxDimension, Buffer.from(bytecode), btf ? Buffer.from(btf) : undefined);
259
+ }
260
+ catch (err) {
261
+ throw errors_1.RvfError.fromNative(err);
262
+ }
263
+ }
264
+ async extractEbpf() {
265
+ this.ensureHandle();
266
+ try {
267
+ const result = this.handle.extractEbpf();
268
+ if (!result)
269
+ return null;
270
+ return {
271
+ header: new Uint8Array(result.header),
272
+ payload: new Uint8Array(result.payload),
273
+ };
274
+ }
275
+ catch (err) {
276
+ throw errors_1.RvfError.fromNative(err);
277
+ }
278
+ }
279
+ async segments() {
280
+ this.ensureHandle();
281
+ try {
282
+ const segs = this.handle.segments();
283
+ return segs.map((s) => ({
284
+ id: s.id,
285
+ offset: s.offset,
286
+ payloadLength: s.payloadLength ?? s.payload_length,
287
+ segType: s.segType ?? s.seg_type,
288
+ }));
289
+ }
290
+ catch (err) {
291
+ throw errors_1.RvfError.fromNative(err);
292
+ }
293
+ }
294
+ async dimension() {
295
+ this.ensureHandle();
296
+ try {
297
+ return this.handle.dimension();
298
+ }
299
+ catch (err) {
300
+ throw errors_1.RvfError.fromNative(err);
301
+ }
302
+ }
303
+ }
304
+ exports.NodeBackend = NodeBackend;
305
+ // ---------------------------------------------------------------------------
306
+ // WasmBackend — wraps @ruvector/rvf-wasm
307
+ // ---------------------------------------------------------------------------
308
+ /**
309
+ * Backend that delegates to the `@ruvector/rvf-wasm` WASM build.
310
+ *
311
+ * Suitable for browser environments. The WASM module is loaded lazily.
312
+ */
313
+ class WasmBackend {
314
+ constructor() {
315
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
316
+ this.wasm = null;
317
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
318
+ this.handle = null;
319
+ }
320
+ async loadWasm() {
321
+ if (this.wasm)
322
+ return;
323
+ try {
324
+ this.wasm = await Promise.resolve().then(() => __importStar(require('@ruvector/rvf-wasm')));
325
+ if (typeof this.wasm.default === 'function') {
326
+ await this.wasm.default();
327
+ }
328
+ }
329
+ catch {
330
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'Could not load @ruvector/rvf-wasm — is it installed?');
331
+ }
332
+ }
333
+ ensureHandle() {
334
+ if (!this.handle) {
335
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.StoreClosed);
336
+ }
337
+ }
338
+ async create(path, options) {
339
+ await this.loadWasm();
340
+ try {
341
+ this.handle = this.wasm.create(path, mapOptionsToNative(options));
342
+ }
343
+ catch (err) {
344
+ throw errors_1.RvfError.fromNative(err);
345
+ }
346
+ }
347
+ async open(path) {
348
+ await this.loadWasm();
349
+ try {
350
+ this.handle = this.wasm.open(path);
351
+ }
352
+ catch (err) {
353
+ throw errors_1.RvfError.fromNative(err);
354
+ }
355
+ }
356
+ async openReadonly(path) {
357
+ await this.loadWasm();
358
+ try {
359
+ this.handle = this.wasm.open_readonly(path);
360
+ }
361
+ catch (err) {
362
+ throw errors_1.RvfError.fromNative(err);
363
+ }
364
+ }
365
+ async ingestBatch(entries) {
366
+ this.ensureHandle();
367
+ try {
368
+ const ids = entries.map((e) => e.id);
369
+ const vectors = entries.map((e) => e.vector instanceof Float32Array ? e.vector : new Float32Array(e.vector));
370
+ const metadata = entries.some((e) => e.metadata)
371
+ ? entries.map((e) => e.metadata ?? {})
372
+ : undefined;
373
+ const result = this.wasm.ingest_batch(this.handle, ids, vectors, metadata);
374
+ return {
375
+ accepted: result.accepted,
376
+ rejected: result.rejected,
377
+ epoch: result.epoch,
378
+ };
379
+ }
380
+ catch (err) {
381
+ throw errors_1.RvfError.fromNative(err);
382
+ }
383
+ }
384
+ async query(vector, k, options) {
385
+ this.ensureHandle();
386
+ try {
387
+ const nativeOpts = options ? mapQueryOptionsToNative(options) : undefined;
388
+ const results = this.wasm.query(this.handle, vector, k, nativeOpts);
389
+ return results.map((r) => ({
390
+ id: r.id,
391
+ distance: r.distance,
392
+ }));
393
+ }
394
+ catch (err) {
395
+ throw errors_1.RvfError.fromNative(err);
396
+ }
397
+ }
398
+ async delete(ids) {
399
+ this.ensureHandle();
400
+ try {
401
+ const result = this.wasm.delete(this.handle, ids);
402
+ return { deleted: result.deleted, epoch: result.epoch };
403
+ }
404
+ catch (err) {
405
+ throw errors_1.RvfError.fromNative(err);
406
+ }
407
+ }
408
+ async deleteByFilter(filter) {
409
+ this.ensureHandle();
410
+ try {
411
+ const result = this.wasm.delete_by_filter(this.handle, filter);
412
+ return { deleted: result.deleted, epoch: result.epoch };
413
+ }
414
+ catch (err) {
415
+ throw errors_1.RvfError.fromNative(err);
416
+ }
417
+ }
418
+ async compact() {
419
+ this.ensureHandle();
420
+ try {
421
+ const result = this.wasm.compact(this.handle);
422
+ return {
423
+ segmentsCompacted: result.segments_compacted ?? result.segmentsCompacted,
424
+ bytesReclaimed: result.bytes_reclaimed ?? result.bytesReclaimed,
425
+ epoch: result.epoch,
426
+ };
427
+ }
428
+ catch (err) {
429
+ throw errors_1.RvfError.fromNative(err);
430
+ }
431
+ }
432
+ async status() {
433
+ this.ensureHandle();
434
+ try {
435
+ const s = this.wasm.status(this.handle);
436
+ return mapNativeStatus(s);
437
+ }
438
+ catch (err) {
439
+ throw errors_1.RvfError.fromNative(err);
440
+ }
441
+ }
442
+ async close() {
443
+ if (!this.handle)
444
+ return;
445
+ try {
446
+ this.wasm.close(this.handle);
447
+ }
448
+ catch (err) {
449
+ throw errors_1.RvfError.fromNative(err);
450
+ }
451
+ finally {
452
+ this.handle = null;
453
+ }
454
+ }
455
+ async fileId() {
456
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'fileId not supported in WASM backend');
457
+ }
458
+ async parentId() {
459
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'parentId not supported in WASM backend');
460
+ }
461
+ async lineageDepth() {
462
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'lineageDepth not supported in WASM backend');
463
+ }
464
+ async derive(_childPath, _options) {
465
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'derive not supported in WASM backend');
466
+ }
467
+ async embedKernel() {
468
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'embedKernel not supported in WASM backend');
469
+ }
470
+ async extractKernel() {
471
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'extractKernel not supported in WASM backend');
472
+ }
473
+ async embedEbpf() {
474
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'embedEbpf not supported in WASM backend');
475
+ }
476
+ async extractEbpf() {
477
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'extractEbpf not supported in WASM backend');
478
+ }
479
+ async segments() {
480
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'segments not supported in WASM backend');
481
+ }
482
+ async dimension() {
483
+ throw new errors_1.RvfError(errors_1.RvfErrorCode.BackendNotFound, 'dimension not supported in WASM backend');
484
+ }
485
+ }
486
+ exports.WasmBackend = WasmBackend;
487
+ // ---------------------------------------------------------------------------
488
+ // Backend resolution
489
+ // ---------------------------------------------------------------------------
490
+ /**
491
+ * Resolve a `BackendType` to a concrete `RvfBackend` instance.
492
+ *
493
+ * - `'node'` Always returns a `NodeBackend`.
494
+ * - `'wasm'` Always returns a `WasmBackend`.
495
+ * - `'auto'` Tries `node` first, falls back to `wasm`.
496
+ */
497
+ function resolveBackend(type) {
498
+ switch (type) {
499
+ case 'node':
500
+ return new NodeBackend();
501
+ case 'wasm':
502
+ return new WasmBackend();
503
+ case 'auto': {
504
+ // In Node.js environments, prefer native; in browsers, prefer WASM.
505
+ const isNode = typeof process !== 'undefined' &&
506
+ typeof process.versions !== 'undefined' &&
507
+ typeof process.versions.node === 'string';
508
+ return isNode ? new NodeBackend() : new WasmBackend();
509
+ }
510
+ }
511
+ }
512
+ // ---------------------------------------------------------------------------
513
+ // Mapping helpers (TS options -> native/wasm shapes)
514
+ // ---------------------------------------------------------------------------
515
+ function mapMetricToNative(metric) {
516
+ switch (metric) {
517
+ case 'cosine':
518
+ return 'Cosine';
519
+ case 'dotproduct':
520
+ return 'InnerProduct';
521
+ case 'l2':
522
+ default:
523
+ return 'L2';
524
+ }
525
+ }
526
+ function mapCompressionToNative(compression) {
527
+ switch (compression) {
528
+ case 'scalar':
529
+ return 'Scalar';
530
+ case 'product':
531
+ return 'Product';
532
+ case 'none':
533
+ default:
534
+ return 'None';
535
+ }
536
+ }
537
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
538
+ function mapOptionsToNative(options) {
539
+ return {
540
+ dimension: options.dimensions,
541
+ metric: mapMetricToNative(options.metric),
542
+ profile: options.profile ?? 0,
543
+ compression: mapCompressionToNative(options.compression),
544
+ signing: options.signing ?? false,
545
+ m: options.m ?? 16,
546
+ ef_construction: options.efConstruction ?? 200,
547
+ };
548
+ }
549
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
550
+ function mapQueryOptionsToNative(options) {
551
+ return {
552
+ ef_search: options.efSearch ?? 100,
553
+ filter: options.filter,
554
+ timeout_ms: options.timeoutMs ?? 0,
555
+ };
556
+ }
557
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
558
+ function mapNativeStatus(s) {
559
+ return {
560
+ totalVectors: s.total_vectors ?? s.totalVectors ?? 0,
561
+ totalSegments: s.total_segments ?? s.totalSegments ?? 0,
562
+ fileSizeBytes: s.file_size ?? s.fileSizeBytes ?? 0,
563
+ epoch: s.current_epoch ?? s.epoch ?? 0,
564
+ profileId: s.profile_id ?? s.profileId ?? 0,
565
+ compactionState: mapCompactionState(s.compaction_state ?? s.compactionState),
566
+ deadSpaceRatio: s.dead_space_ratio ?? s.deadSpaceRatio ?? 0,
567
+ readOnly: s.read_only ?? s.readOnly ?? false,
568
+ };
569
+ }
570
+ function mapCompactionState(state) {
571
+ if (typeof state === 'string') {
572
+ const lower = state.toLowerCase();
573
+ if (lower === 'running')
574
+ return 'running';
575
+ if (lower === 'emergency')
576
+ return 'emergency';
577
+ }
578
+ return 'idle';
579
+ }
580
+ //# sourceMappingURL=backend.js.map