@ruvector/rvf-node 0.1.2 → 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/README.md +277 -33
- package/index.d.ts +95 -0
- package/index.js +150 -0
- package/package.json +32 -13
- package/rvf-node.linux-x64-gnu.node +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ruvector/rvf-node
|
|
2
2
|
|
|
3
|
-
Node.js
|
|
3
|
+
Native Node.js bindings for the [RuVector Format](https://github.com/ruvnet/ruvector/tree/main/crates/rvf) (RVF) vector database. Built with Rust via N-API for native speed with zero serialization overhead.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,52 +8,296 @@ Node.js native bindings for the RuVector Format (RVF) cognitive container.
|
|
|
8
8
|
npm install @ruvector/rvf-node
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Native Rust performance** via N-API (napi-rs), no FFI marshaling
|
|
14
|
+
- **Single-file vector database** — crash-safe, no WAL, append-only
|
|
15
|
+
- **k-NN search** with HNSW progressive indexing (recall 0.70 → 0.95)
|
|
16
|
+
- **Metadata filtering** — Eq, Ne, Lt, Gt, Range, In, And, Or, Not
|
|
17
|
+
- **Lineage tracking** — DNA-style parent/child derivation chains
|
|
18
|
+
- **Kernel & eBPF embedding** — embed compute alongside vector data
|
|
19
|
+
- **Segment inspection** — enumerate all segments in the file
|
|
20
|
+
- **Cross-platform** — Linux (x86_64, aarch64), macOS (x86_64, Apple Silicon), Windows (x86_64)
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
12
23
|
|
|
13
24
|
```javascript
|
|
14
25
|
const { RvfDatabase } = require('@ruvector/rvf-node');
|
|
15
26
|
|
|
16
|
-
// Create a
|
|
17
|
-
const db = RvfDatabase.create('vectors.rvf', {
|
|
27
|
+
// Create a store
|
|
28
|
+
const db = RvfDatabase.create('vectors.rvf', {
|
|
29
|
+
dimension: 384,
|
|
30
|
+
metric: 'cosine',
|
|
31
|
+
});
|
|
18
32
|
|
|
19
33
|
// Insert vectors
|
|
20
|
-
|
|
34
|
+
const vectors = new Float32Array(384 * 2); // 2 vectors, 384 dims each
|
|
35
|
+
vectors.fill(0.1);
|
|
36
|
+
db.ingestBatch(vectors, [1, 2]);
|
|
21
37
|
|
|
22
38
|
// Query nearest neighbors
|
|
23
|
-
const
|
|
24
|
-
|
|
39
|
+
const query = new Float32Array(384);
|
|
40
|
+
query.fill(0.15);
|
|
41
|
+
const results = db.query(query, 5);
|
|
42
|
+
// [{ id: 1, distance: 0.002 }, { id: 2, distance: 0.002 }]
|
|
43
|
+
|
|
44
|
+
db.close();
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API Reference
|
|
48
|
+
|
|
49
|
+
### Store Lifecycle
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// Create a new store
|
|
53
|
+
const db = RvfDatabase.create(path: string, options: RvfOptions);
|
|
54
|
+
|
|
55
|
+
// Open existing store (read-write, acquires writer lock)
|
|
56
|
+
const db = RvfDatabase.open(path: string);
|
|
25
57
|
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
console.log(db.dimension()); // 384
|
|
29
|
-
console.log(db.segments()); // [{ type, id, size }]
|
|
58
|
+
// Open read-only (no lock, concurrent readers allowed)
|
|
59
|
+
const db = RvfDatabase.openReadonly(path: string);
|
|
30
60
|
|
|
61
|
+
// Close and flush
|
|
31
62
|
db.close();
|
|
32
63
|
```
|
|
33
64
|
|
|
34
|
-
|
|
65
|
+
**RvfOptions:**
|
|
66
|
+
|
|
67
|
+
| Field | Type | Default | Description |
|
|
68
|
+
|-------|------|---------|-------------|
|
|
69
|
+
| `dimension` | `number` | required | Vector dimensionality |
|
|
70
|
+
| `metric` | `string` | `"l2"` | `"l2"`, `"cosine"`, or `"inner_product"` |
|
|
71
|
+
| `profile` | `number` | `0` | Hardware profile: 0=Generic, 1=Core, 2=Hot, 3=Full |
|
|
72
|
+
| `signing` | `boolean` | `false` | Enable segment signing |
|
|
73
|
+
| `m` | `number` | `16` | HNSW M parameter (neighbor count) |
|
|
74
|
+
| `efConstruction` | `number` | `200` | HNSW index build quality |
|
|
75
|
+
|
|
76
|
+
### Ingest Vectors
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const result = db.ingestBatch(
|
|
80
|
+
vectors: Float32Array, // flat array of n * dimension floats
|
|
81
|
+
ids: number[], // vector IDs
|
|
82
|
+
metadata?: RvfMetadataEntry[] // optional metadata per vector
|
|
83
|
+
);
|
|
84
|
+
// Returns: { accepted: number, rejected: number, epoch: number }
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Metadata entry format:**
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
{ fieldId: 0, valueType: 'string', value: 'category_a' }
|
|
91
|
+
{ fieldId: 1, valueType: 'f64', value: '0.95' }
|
|
92
|
+
{ fieldId: 2, valueType: 'u64', value: '42' }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Query
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
const results = db.query(
|
|
99
|
+
vector: Float32Array, // query vector
|
|
100
|
+
k: number, // number of neighbors
|
|
101
|
+
options?: RvfQueryOptions // optional search parameters
|
|
102
|
+
);
|
|
103
|
+
// Returns: [{ id: number, distance: number }, ...]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**RvfQueryOptions:**
|
|
107
|
+
|
|
108
|
+
| Field | Type | Default | Description |
|
|
109
|
+
|-------|------|---------|-------------|
|
|
110
|
+
| `efSearch` | `number` | `100` | HNSW search quality (higher = better recall, slower) |
|
|
111
|
+
| `filter` | `string` | — | Filter expression as JSON string |
|
|
112
|
+
| `timeoutMs` | `number` | `0` | Query timeout in ms (0 = no timeout) |
|
|
113
|
+
|
|
114
|
+
### Filter Expressions
|
|
115
|
+
|
|
116
|
+
Filters are passed as JSON strings. All leaf filters require `fieldId`, `valueType`, and `value`:
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Equality
|
|
120
|
+
db.query(vec, 10, {
|
|
121
|
+
filter: '{"op":"eq","fieldId":0,"valueType":"string","value":"science"}'
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Range
|
|
125
|
+
db.query(vec, 10, {
|
|
126
|
+
filter: '{"op":"range","fieldId":1,"valueType":"f64","low":"0.5","high":"1.0"}'
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// In-set
|
|
130
|
+
db.query(vec, 10, {
|
|
131
|
+
filter: '{"op":"in","fieldId":0,"valueType":"u64","values":["1","2","5"]}'
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Boolean combinations
|
|
135
|
+
db.query(vec, 10, {
|
|
136
|
+
filter: JSON.stringify({
|
|
137
|
+
op: 'and',
|
|
138
|
+
children: [
|
|
139
|
+
{ op: 'eq', fieldId: 0, valueType: 'string', value: 'science' },
|
|
140
|
+
{ op: 'gt', fieldId: 1, valueType: 'f64', value: '0.8' }
|
|
141
|
+
]
|
|
142
|
+
})
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Negation
|
|
146
|
+
db.query(vec, 10, {
|
|
147
|
+
filter: '{"op":"not","child":{"op":"eq","fieldId":0,"valueType":"string","value":"spam"}}'
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Supported operators:** `eq`, `ne`, `lt`, `le`, `gt`, `ge`, `in`, `range`, `and`, `or`, `not`
|
|
152
|
+
|
|
153
|
+
**Supported value types:** `u64`, `i64`, `f64`, `string`, `bool`
|
|
154
|
+
|
|
155
|
+
### Delete
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// Delete by ID
|
|
159
|
+
const result = db.delete([1, 2, 3]);
|
|
160
|
+
// Returns: { deleted: number, epoch: number }
|
|
161
|
+
|
|
162
|
+
// Delete by filter
|
|
163
|
+
const result = db.deleteByFilter(
|
|
164
|
+
'{"op":"gt","fieldId":1,"valueType":"f64","value":"0.9"}'
|
|
165
|
+
);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Compact
|
|
169
|
+
|
|
170
|
+
Reclaims space from deleted vectors:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
const result = db.compact();
|
|
174
|
+
// Returns: { segmentsCompacted: number, bytesReclaimed: number, epoch: number }
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Status
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const status = db.status();
|
|
181
|
+
// {
|
|
182
|
+
// totalVectors: number,
|
|
183
|
+
// totalSegments: number,
|
|
184
|
+
// fileSize: number,
|
|
185
|
+
// currentEpoch: number,
|
|
186
|
+
// profileId: number,
|
|
187
|
+
// compactionState: 'idle' | 'running' | 'emergency',
|
|
188
|
+
// deadSpaceRatio: number,
|
|
189
|
+
// readOnly: boolean
|
|
190
|
+
// }
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Lineage & Derivation
|
|
194
|
+
|
|
195
|
+
RVF tracks parent/child relationships with cryptographic hashes:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
db.fileId(); // hex string — unique file identifier
|
|
199
|
+
db.parentId(); // hex string — parent's ID (zeros if root)
|
|
200
|
+
db.lineageDepth(); // 0 for root files
|
|
201
|
+
|
|
202
|
+
// Derive a child store (inherits dimensions and options)
|
|
203
|
+
const child = db.derive('/tmp/child.rvf');
|
|
204
|
+
child.lineageDepth(); // 1
|
|
205
|
+
child.parentId(); // matches parent's fileId()
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Kernel & eBPF Embedding
|
|
209
|
+
|
|
210
|
+
Embed compute segments alongside vector data:
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
// Embed a Linux microkernel
|
|
214
|
+
db.embedKernel(
|
|
215
|
+
1, // arch: 0=x86_64, 1=aarch64
|
|
216
|
+
0, // kernel type
|
|
217
|
+
0, // flags
|
|
218
|
+
Buffer.from(kernelImage), // kernel binary
|
|
219
|
+
8080, // API port
|
|
220
|
+
'console=ttyS0 quiet' // kernel cmdline (optional)
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
// Extract kernel
|
|
224
|
+
const kernel = db.extractKernel();
|
|
225
|
+
if (kernel) {
|
|
226
|
+
console.log(kernel.header); // Buffer: 128-byte KernelHeader
|
|
227
|
+
console.log(kernel.image); // Buffer: kernel image bytes
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Embed an eBPF XDP program
|
|
231
|
+
db.embedEbpf(
|
|
232
|
+
1, // program type (XDP distance)
|
|
233
|
+
2, // attach type (XDP ingress)
|
|
234
|
+
384, // max vector dimension
|
|
235
|
+
Buffer.from(bytecode), // BPF ELF object
|
|
236
|
+
Buffer.from(btf) // optional BTF section
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
// Extract eBPF
|
|
240
|
+
const ebpf = db.extractEbpf();
|
|
241
|
+
if (ebpf) {
|
|
242
|
+
console.log(ebpf.header); // Buffer: 64-byte EbpfHeader
|
|
243
|
+
console.log(ebpf.payload); // Buffer: bytecode + BTF
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Segment Inspection
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
const segments = db.segments();
|
|
251
|
+
// [{ id: 1, offset: 0, payloadLength: 4096, segType: 'manifest' },
|
|
252
|
+
// { id: 2, offset: 4160, payloadLength: 51200, segType: 'vec' },
|
|
253
|
+
// { id: 3, offset: 55424, payloadLength: 12288, segType: 'index' }]
|
|
254
|
+
|
|
255
|
+
db.dimension(); // 384
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Self-Booting RVF
|
|
259
|
+
|
|
260
|
+
An `.rvf` file can embed a Linux kernel, eBPF programs, and SSH keys alongside vector data — producing a single file that boots as a microservice.
|
|
261
|
+
|
|
262
|
+
The Claude Code Appliance example builds a complete AI dev environment:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
cd examples/rvf
|
|
266
|
+
cargo run --example claude_code_appliance
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
claude_code_appliance.rvf
|
|
271
|
+
├── KERNEL_SEG Linux 6.8.12 bzImage (5.2 MB, x86_64)
|
|
272
|
+
├── EBPF_SEG Socket filter — ports 2222, 8080 only
|
|
273
|
+
├── VEC_SEG 20 package embeddings (128-dim)
|
|
274
|
+
├── INDEX_SEG HNSW graph for package search
|
|
275
|
+
├── WITNESS_SEG 6-entry tamper-evident audit trail
|
|
276
|
+
└── CRYPTO_SEG 3 Ed25519 SSH user keys
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Final file: **5.1 MB single `.rvf`** — boots Linux, serves queries, runs Claude Code.
|
|
280
|
+
|
|
281
|
+
See the [full RVF documentation](https://github.com/ruvnet/ruvector/tree/main/crates/rvf) for details.
|
|
282
|
+
|
|
283
|
+
## Build from Source
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# Prerequisites: Rust 1.87+, Node.js 18+
|
|
287
|
+
cd crates/rvf/rvf-node
|
|
288
|
+
npm install
|
|
289
|
+
npm run build
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Related Packages
|
|
35
293
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
## API
|
|
43
|
-
|
|
44
|
-
| Method | Description |
|
|
45
|
-
|--------|-------------|
|
|
46
|
-
| `RvfDatabase.create(path, options)` | Create a new RVF store |
|
|
47
|
-
| `RvfDatabase.open(path)` | Open an existing store |
|
|
48
|
-
| `db.ingestBatch(vectors, ids)` | Insert vectors |
|
|
49
|
-
| `db.query(vector, k)` | k-NN similarity search |
|
|
50
|
-
| `db.delete(ids)` | Delete vectors by ID |
|
|
51
|
-
| `db.compact()` | Reclaim deleted space |
|
|
52
|
-
| `db.status()` | Get store stats |
|
|
53
|
-
| `db.segments()` | List all segments |
|
|
54
|
-
| `db.fileId()` | Get unique file UUID |
|
|
55
|
-
| `db.close()` | Close and release lock |
|
|
294
|
+
| Package | Description |
|
|
295
|
+
|---------|-------------|
|
|
296
|
+
| [`@ruvector/rvf`](https://www.npmjs.com/package/@ruvector/rvf) | Unified TypeScript SDK |
|
|
297
|
+
| [`@ruvector/rvf-wasm`](https://www.npmjs.com/package/@ruvector/rvf-wasm) | Browser WASM package |
|
|
298
|
+
| [`@ruvector/rvf-mcp-server`](https://www.npmjs.com/package/@ruvector/rvf-mcp-server) | MCP server for AI agents |
|
|
299
|
+
| [`rvf-runtime`](https://crates.io/crates/rvf-runtime) | Rust runtime (powers this package) |
|
|
56
300
|
|
|
57
301
|
## License
|
|
58
302
|
|
|
59
|
-
MIT
|
|
303
|
+
MIT OR Apache-2.0
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* auto-generated: TypeScript declarations for @ruvector/rvf-node */
|
|
2
|
+
|
|
3
|
+
export interface RvfOptions {
|
|
4
|
+
dimension: number;
|
|
5
|
+
metric?: string;
|
|
6
|
+
profile?: number;
|
|
7
|
+
signing?: boolean;
|
|
8
|
+
m?: number;
|
|
9
|
+
efConstruction?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RvfQueryOptions {
|
|
13
|
+
efSearch?: number;
|
|
14
|
+
filter?: string;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RvfSearchResult {
|
|
19
|
+
id: number;
|
|
20
|
+
distance: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface RvfIngestResult {
|
|
24
|
+
accepted: number;
|
|
25
|
+
rejected: number;
|
|
26
|
+
epoch: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface RvfDeleteResult {
|
|
30
|
+
deleted: number;
|
|
31
|
+
epoch: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface RvfCompactionResult {
|
|
35
|
+
segmentsCompacted: number;
|
|
36
|
+
bytesReclaimed: number;
|
|
37
|
+
epoch: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface RvfStatus {
|
|
41
|
+
totalVectors: number;
|
|
42
|
+
totalSegments: number;
|
|
43
|
+
fileSize: number;
|
|
44
|
+
currentEpoch: number;
|
|
45
|
+
profileId: number;
|
|
46
|
+
compactionState: string;
|
|
47
|
+
deadSpaceRatio: number;
|
|
48
|
+
readOnly: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface RvfMetadataEntry {
|
|
52
|
+
fieldId: number;
|
|
53
|
+
valueType: string;
|
|
54
|
+
value: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface RvfKernelData {
|
|
58
|
+
header: Buffer;
|
|
59
|
+
image: Buffer;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface RvfEbpfData {
|
|
63
|
+
header: Buffer;
|
|
64
|
+
payload: Buffer;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface RvfSegmentInfo {
|
|
68
|
+
id: number;
|
|
69
|
+
offset: number;
|
|
70
|
+
payloadLength: number;
|
|
71
|
+
segType: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export class RvfDatabase {
|
|
75
|
+
static create(path: string, options: RvfOptions): RvfDatabase;
|
|
76
|
+
static open(path: string): RvfDatabase;
|
|
77
|
+
static openReadonly(path: string): RvfDatabase;
|
|
78
|
+
ingestBatch(vectors: Float32Array, ids: number[], metadata?: RvfMetadataEntry[]): RvfIngestResult;
|
|
79
|
+
query(vector: Float32Array, k: number, options?: RvfQueryOptions): RvfSearchResult[];
|
|
80
|
+
delete(ids: number[]): RvfDeleteResult;
|
|
81
|
+
deleteByFilter(filterJson: string): RvfDeleteResult;
|
|
82
|
+
compact(): RvfCompactionResult;
|
|
83
|
+
status(): RvfStatus;
|
|
84
|
+
close(): void;
|
|
85
|
+
fileId(): string;
|
|
86
|
+
parentId(): string;
|
|
87
|
+
lineageDepth(): number;
|
|
88
|
+
derive(childPath: string, options?: RvfOptions): RvfDatabase;
|
|
89
|
+
embedKernel(arch: number, kernelType: number, flags: number, image: Buffer, apiPort: number, cmdline?: string): number;
|
|
90
|
+
extractKernel(): RvfKernelData | null;
|
|
91
|
+
embedEbpf(programType: number, attachType: number, maxDimension: number, bytecode: Buffer, btf?: Buffer): number;
|
|
92
|
+
extractEbpf(): RvfEbpfData | null;
|
|
93
|
+
segments(): RvfSegmentInfo[];
|
|
94
|
+
dimension(): number;
|
|
95
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/* auto-generated: NAPI-RS platform loader for @ruvector/rvf-node */
|
|
3
|
+
|
|
4
|
+
const { existsSync, readFileSync } = require('fs');
|
|
5
|
+
const { join } = require('path');
|
|
6
|
+
|
|
7
|
+
const { platform, arch } = process;
|
|
8
|
+
|
|
9
|
+
let nativeBinding = null;
|
|
10
|
+
let localFileExisted = false;
|
|
11
|
+
let loadError = null;
|
|
12
|
+
|
|
13
|
+
function isMusl() {
|
|
14
|
+
// For Node 12+, check report.header.glibcVersionRuntime
|
|
15
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
16
|
+
try {
|
|
17
|
+
const lddPath = require('child_process')
|
|
18
|
+
.execSync('which ldd')
|
|
19
|
+
.toString()
|
|
20
|
+
.trim();
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl');
|
|
22
|
+
} catch {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const report = process.report.getReport();
|
|
27
|
+
const rep = typeof report === 'string' ? JSON.parse(report) : report;
|
|
28
|
+
return !rep.header.glibcVersionRuntime;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
switch (platform) {
|
|
33
|
+
case 'darwin':
|
|
34
|
+
switch (arch) {
|
|
35
|
+
case 'x64':
|
|
36
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.darwin-x64.node'));
|
|
37
|
+
try {
|
|
38
|
+
if (localFileExisted) {
|
|
39
|
+
nativeBinding = require('./rvf-node.darwin-x64.node');
|
|
40
|
+
} else {
|
|
41
|
+
nativeBinding = require('@ruvector/rvf-node-darwin-x64');
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {
|
|
44
|
+
loadError = e;
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
case 'arm64':
|
|
48
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.darwin-arm64.node'));
|
|
49
|
+
try {
|
|
50
|
+
if (localFileExisted) {
|
|
51
|
+
nativeBinding = require('./rvf-node.darwin-arm64.node');
|
|
52
|
+
} else {
|
|
53
|
+
nativeBinding = require('@ruvector/rvf-node-darwin-arm64');
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
loadError = e;
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 'win32':
|
|
64
|
+
switch (arch) {
|
|
65
|
+
case 'x64':
|
|
66
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.win32-x64-msvc.node'));
|
|
67
|
+
try {
|
|
68
|
+
if (localFileExisted) {
|
|
69
|
+
nativeBinding = require('./rvf-node.win32-x64-msvc.node');
|
|
70
|
+
} else {
|
|
71
|
+
nativeBinding = require('@ruvector/rvf-node-win32-x64-msvc');
|
|
72
|
+
}
|
|
73
|
+
} catch (e) {
|
|
74
|
+
loadError = e;
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
default:
|
|
78
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`);
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
case 'linux':
|
|
82
|
+
switch (arch) {
|
|
83
|
+
case 'x64':
|
|
84
|
+
if (isMusl()) {
|
|
85
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-x64-musl.node'));
|
|
86
|
+
try {
|
|
87
|
+
if (localFileExisted) {
|
|
88
|
+
nativeBinding = require('./rvf-node.linux-x64-musl.node');
|
|
89
|
+
} else {
|
|
90
|
+
nativeBinding = require('@ruvector/rvf-node-linux-x64-musl');
|
|
91
|
+
}
|
|
92
|
+
} catch (e) {
|
|
93
|
+
loadError = e;
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-x64-gnu.node'));
|
|
97
|
+
try {
|
|
98
|
+
if (localFileExisted) {
|
|
99
|
+
nativeBinding = require('./rvf-node.linux-x64-gnu.node');
|
|
100
|
+
} else {
|
|
101
|
+
nativeBinding = require('@ruvector/rvf-node-linux-x64-gnu');
|
|
102
|
+
}
|
|
103
|
+
} catch (e) {
|
|
104
|
+
loadError = e;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
case 'arm64':
|
|
109
|
+
if (isMusl()) {
|
|
110
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-arm64-musl.node'));
|
|
111
|
+
try {
|
|
112
|
+
if (localFileExisted) {
|
|
113
|
+
nativeBinding = require('./rvf-node.linux-arm64-musl.node');
|
|
114
|
+
} else {
|
|
115
|
+
nativeBinding = require('@ruvector/rvf-node-linux-arm64-musl');
|
|
116
|
+
}
|
|
117
|
+
} catch (e) {
|
|
118
|
+
loadError = e;
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-arm64-gnu.node'));
|
|
122
|
+
try {
|
|
123
|
+
if (localFileExisted) {
|
|
124
|
+
nativeBinding = require('./rvf-node.linux-arm64-gnu.node');
|
|
125
|
+
} else {
|
|
126
|
+
nativeBinding = require('@ruvector/rvf-node-linux-arm64-gnu');
|
|
127
|
+
}
|
|
128
|
+
} catch (e) {
|
|
129
|
+
loadError = e;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`);
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
default:
|
|
138
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!nativeBinding) {
|
|
142
|
+
if (loadError) {
|
|
143
|
+
throw loadError;
|
|
144
|
+
}
|
|
145
|
+
throw new Error('Failed to load native binding');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const { RvfDatabase } = nativeBinding;
|
|
149
|
+
|
|
150
|
+
module.exports.RvfDatabase = RvfDatabase;
|
package/package.json
CHANGED
|
@@ -1,25 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ruvector/rvf-node",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "RuVector Format Node.js native bindings",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"index.js",
|
|
9
|
+
"index.d.ts",
|
|
10
|
+
"*.node"
|
|
11
|
+
],
|
|
7
12
|
"napi": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
"binaryName": "rvf-node",
|
|
14
|
+
"targets": [
|
|
15
|
+
"x86_64-unknown-linux-gnu",
|
|
16
|
+
"x86_64-apple-darwin",
|
|
17
|
+
"aarch64-apple-darwin",
|
|
18
|
+
"x86_64-pc-windows-msvc",
|
|
19
|
+
"aarch64-unknown-linux-gnu"
|
|
20
|
+
]
|
|
16
21
|
},
|
|
17
22
|
"scripts": {
|
|
18
|
-
"build": "napi build --platform --release"
|
|
19
|
-
"test": "jest"
|
|
23
|
+
"build": "napi build --platform --release"
|
|
20
24
|
},
|
|
21
25
|
"license": "MIT",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/ruvnet/ruvector"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">= 16"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"registry": "https://registry.npmjs.org/",
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"optionalDependencies": {
|
|
38
|
+
"@ruvector/rvf-node-linux-x64-gnu": "0.1.4",
|
|
39
|
+
"@ruvector/rvf-node-darwin-x64": "0.1.4",
|
|
40
|
+
"@ruvector/rvf-node-darwin-arm64": "0.1.4",
|
|
41
|
+
"@ruvector/rvf-node-win32-x64-msvc": "0.1.4",
|
|
42
|
+
"@ruvector/rvf-node-linux-arm64-gnu": "0.1.4"
|
|
24
43
|
}
|
|
25
44
|
}
|
|
Binary file
|