@ruvector/rvf-node 0.2.3 → 0.3.1
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 +75 -0
- package/index.d.ts +73 -259
- package/index.js +64 -229
- package/package.json +11 -11
- package/rvf-node.darwin-arm64.node +0 -0
- package/rvf-node.darwin-x64.node +0 -0
- package/rvf-node.linux-arm64-gnu.node +0 -0
- package/rvf-node.linux-x64-gnu.node +0 -0
- package/rvf-node.win32-x64-msvc.node +0 -0
package/README.md
CHANGED
|
@@ -18,6 +18,56 @@ npm install @ruvector/rvf-node
|
|
|
18
18
|
- **Kernel & eBPF embedding** — embed compute alongside vector data
|
|
19
19
|
- **Segment inspection** — enumerate all segments in the file
|
|
20
20
|
- **Cross-platform** — Linux (x86_64, aarch64), macOS (x86_64, Apple Silicon), Windows (x86_64)
|
|
21
|
+
- **AGI methods** — HNSW index stats, witness chain verification, state freeze, metric introspection
|
|
22
|
+
|
|
23
|
+
## AGI Methods
|
|
24
|
+
|
|
25
|
+
Four introspection and integrity methods for advanced use cases.
|
|
26
|
+
|
|
27
|
+
### `db.indexStats()` → `RvfIndexStats`
|
|
28
|
+
|
|
29
|
+
Returns HNSW index statistics.
|
|
30
|
+
|
|
31
|
+
| Field | Type | Description |
|
|
32
|
+
|-------|------|-------------|
|
|
33
|
+
| `indexedVectors` | `number` | Number of indexed vectors |
|
|
34
|
+
| `layers` | `number` | Number of HNSW layers |
|
|
35
|
+
| `m` | `number` | M parameter (max edges per node per layer) |
|
|
36
|
+
| `efConstruction` | `number` | ef_construction parameter |
|
|
37
|
+
| `needsRebuild` | `boolean` | Whether index needs rebuilding (dead_space_ratio > 0.3) |
|
|
38
|
+
|
|
39
|
+
### `db.verifyWitness()` → `RvfWitnessResult`
|
|
40
|
+
|
|
41
|
+
Verifies SHAKE-256 witness chain integrity.
|
|
42
|
+
|
|
43
|
+
| Field | Type | Description |
|
|
44
|
+
|-------|------|-------------|
|
|
45
|
+
| `valid` | `boolean` | Whether the chain is valid |
|
|
46
|
+
| `entries` | `number` | Number of entries in the chain |
|
|
47
|
+
| `error` | `string?` | Error message if invalid |
|
|
48
|
+
|
|
49
|
+
### `db.freeze()` → `number`
|
|
50
|
+
|
|
51
|
+
Snapshot-freeze current state. Returns the epoch number.
|
|
52
|
+
|
|
53
|
+
### `db.metric()` → `string`
|
|
54
|
+
|
|
55
|
+
Returns the distance metric name (`"l2"`, `"cosine"`, or `"inner_product"`).
|
|
56
|
+
|
|
57
|
+
### Usage Example
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
const stats = db.indexStats();
|
|
61
|
+
console.log(`Indexed: ${stats.indexedVectors}, HNSW layers: ${stats.layers}`);
|
|
62
|
+
|
|
63
|
+
const witness = db.verifyWitness();
|
|
64
|
+
console.log(`Witness chain: ${witness.entries} entries, valid: ${witness.valid}`);
|
|
65
|
+
|
|
66
|
+
console.log(`Distance metric: ${db.metric()}`);
|
|
67
|
+
|
|
68
|
+
const epoch = db.freeze();
|
|
69
|
+
console.log(`State frozen at epoch ${epoch}`);
|
|
70
|
+
```
|
|
21
71
|
|
|
22
72
|
## Quick Start
|
|
23
73
|
|
|
@@ -255,6 +305,31 @@ const segments = db.segments();
|
|
|
255
305
|
db.dimension(); // 384
|
|
256
306
|
```
|
|
257
307
|
|
|
308
|
+
## Self-Booting RVF
|
|
309
|
+
|
|
310
|
+
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.
|
|
311
|
+
|
|
312
|
+
The Claude Code Appliance example builds a complete AI dev environment:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
cd examples/rvf
|
|
316
|
+
cargo run --example claude_code_appliance
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
claude_code_appliance.rvf
|
|
321
|
+
├── KERNEL_SEG Linux 6.8.12 bzImage (5.2 MB, x86_64)
|
|
322
|
+
├── EBPF_SEG Socket filter — ports 2222, 8080 only
|
|
323
|
+
├── VEC_SEG 20 package embeddings (128-dim)
|
|
324
|
+
├── INDEX_SEG HNSW graph for package search
|
|
325
|
+
├── WITNESS_SEG 6-entry tamper-evident audit trail
|
|
326
|
+
└── CRYPTO_SEG 3 Ed25519 SSH user keys
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Final file: **5.1 MB single `.rvf`** — boots Linux, serves queries, runs Claude Code.
|
|
330
|
+
|
|
331
|
+
See the [full RVF documentation](https://github.com/ruvnet/ruvector/tree/main/crates/rvf) for details.
|
|
332
|
+
|
|
258
333
|
## Build from Source
|
|
259
334
|
|
|
260
335
|
```bash
|
package/index.d.ts
CHANGED
|
@@ -1,281 +1,95 @@
|
|
|
1
|
-
/*
|
|
2
|
-
/* eslint-disable */
|
|
1
|
+
/* auto-generated: TypeScript declarations for @ruvector/rvf-node */
|
|
3
2
|
|
|
4
|
-
/* auto-generated by NAPI-RS */
|
|
5
|
-
|
|
6
|
-
/** Options for creating a new RVF store. */
|
|
7
3
|
export interface RvfOptions {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/** Compression profile: "None" | "Scalar" | "Product". Defaults to "None". */
|
|
15
|
-
compression?: string
|
|
16
|
-
/** Whether segment signing is enabled. Defaults to false. */
|
|
17
|
-
signing?: boolean
|
|
18
|
-
/** HNSW M parameter. Defaults to 16. */
|
|
19
|
-
m?: number
|
|
20
|
-
/** HNSW ef_construction parameter. Defaults to 200. */
|
|
21
|
-
efConstruction?: number
|
|
4
|
+
dimension: number;
|
|
5
|
+
metric?: string;
|
|
6
|
+
profile?: number;
|
|
7
|
+
signing?: boolean;
|
|
8
|
+
m?: number;
|
|
9
|
+
efConstruction?: number;
|
|
22
10
|
}
|
|
23
|
-
|
|
24
|
-
* Options for a query operation.
|
|
25
|
-
*
|
|
26
|
-
* The `filter` field accepts a JSON string encoding a recursive filter tree.
|
|
27
|
-
* See `RvfDatabase.query()` for the filter expression format.
|
|
28
|
-
*/
|
|
11
|
+
|
|
29
12
|
export interface RvfQueryOptions {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* Optional filter expression as a JSON string.
|
|
34
|
-
*
|
|
35
|
-
* Format examples:
|
|
36
|
-
* `{"op":"eq","fieldId":0,"valueType":"string","value":"cat_a"}`
|
|
37
|
-
* `{"op":"and","children":[...]}`
|
|
38
|
-
* `{"op":"not","child":{...}}`
|
|
39
|
-
*/
|
|
40
|
-
filter?: string
|
|
41
|
-
/** Query timeout in milliseconds. 0 = no timeout. */
|
|
42
|
-
timeoutMs?: number
|
|
13
|
+
efSearch?: number;
|
|
14
|
+
filter?: string;
|
|
15
|
+
timeoutMs?: number;
|
|
43
16
|
}
|
|
44
|
-
|
|
17
|
+
|
|
45
18
|
export interface RvfSearchResult {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
/** Distance from the query vector (lower = more similar). */
|
|
49
|
-
distance: number
|
|
19
|
+
id: number;
|
|
20
|
+
distance: number;
|
|
50
21
|
}
|
|
51
|
-
|
|
22
|
+
|
|
52
23
|
export interface RvfIngestResult {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
rejected: number
|
|
57
|
-
/** Manifest epoch after commit. */
|
|
58
|
-
epoch: number
|
|
24
|
+
accepted: number;
|
|
25
|
+
rejected: number;
|
|
26
|
+
epoch: number;
|
|
59
27
|
}
|
|
60
|
-
|
|
28
|
+
|
|
61
29
|
export interface RvfDeleteResult {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
/** Manifest epoch after commit. */
|
|
65
|
-
epoch: number
|
|
30
|
+
deleted: number;
|
|
31
|
+
epoch: number;
|
|
66
32
|
}
|
|
67
|
-
|
|
68
|
-
export interface RvfStatus {
|
|
69
|
-
/** Total number of live (non-deleted) vectors. */
|
|
70
|
-
totalVectors: number
|
|
71
|
-
/** Total number of segments in the file. */
|
|
72
|
-
totalSegments: number
|
|
73
|
-
/** Total file size in bytes. */
|
|
74
|
-
fileSize: number
|
|
75
|
-
/** Current manifest epoch. */
|
|
76
|
-
currentEpoch: number
|
|
77
|
-
/** Hardware profile identifier. */
|
|
78
|
-
profileId: number
|
|
79
|
-
/** Current compaction state: "idle" | "running" | "emergency". */
|
|
80
|
-
compactionState: string
|
|
81
|
-
/** Ratio of dead (deleted) space to total (0.0 - 1.0). */
|
|
82
|
-
deadSpaceRatio: number
|
|
83
|
-
/** Whether the store is open in read-only mode. */
|
|
84
|
-
readOnly: boolean
|
|
85
|
-
}
|
|
86
|
-
/** Result of a compaction operation. */
|
|
33
|
+
|
|
87
34
|
export interface RvfCompactionResult {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
bytesReclaimed: number
|
|
92
|
-
/** Manifest epoch after compaction. */
|
|
93
|
-
epoch: number
|
|
35
|
+
segmentsCompacted: number;
|
|
36
|
+
bytesReclaimed: number;
|
|
37
|
+
epoch: number;
|
|
94
38
|
}
|
|
95
|
-
|
|
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
|
+
|
|
96
51
|
export interface RvfMetadataEntry {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
valueType: string
|
|
101
|
-
/** The value as a string representation (parsed based on value_type). */
|
|
102
|
-
value: string
|
|
52
|
+
fieldId: number;
|
|
53
|
+
valueType: string;
|
|
54
|
+
value: string;
|
|
103
55
|
}
|
|
104
|
-
|
|
56
|
+
|
|
105
57
|
export interface RvfKernelData {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/** Raw kernel image bytes. */
|
|
109
|
-
image: Buffer
|
|
58
|
+
header: Buffer;
|
|
59
|
+
image: Buffer;
|
|
110
60
|
}
|
|
111
|
-
|
|
61
|
+
|
|
112
62
|
export interface RvfEbpfData {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/** Program bytecode + optional BTF. */
|
|
116
|
-
payload: Buffer
|
|
63
|
+
header: Buffer;
|
|
64
|
+
payload: Buffer;
|
|
117
65
|
}
|
|
118
|
-
|
|
66
|
+
|
|
119
67
|
export interface RvfSegmentInfo {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/** Payload length in bytes. */
|
|
125
|
-
payloadLength: number
|
|
126
|
-
/** Segment type as a string (e.g. "vec", "manifest", "kernel"). */
|
|
127
|
-
segType: string
|
|
68
|
+
id: number;
|
|
69
|
+
offset: number;
|
|
70
|
+
payloadLength: number;
|
|
71
|
+
segType: string;
|
|
128
72
|
}
|
|
129
|
-
|
|
130
|
-
export
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
/** Quantization configuration. */
|
|
152
|
-
export interface RvfQuantConfig {
|
|
153
|
-
/** Quantization mode: "none" | "scalar" | "product" | "binary". */
|
|
154
|
-
mode: string
|
|
155
|
-
/** Number of subquantizers (for product quantization). */
|
|
156
|
-
numSubquantizers?: number
|
|
157
|
-
/** Number of centroids per subquantizer. */
|
|
158
|
-
numCentroids?: number
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* The main RVF database handle exposed to Node.js.
|
|
162
|
-
*
|
|
163
|
-
* All mutating methods acquire an internal mutex so the handle is safe
|
|
164
|
-
* to share across async operations (though RVF itself is single-writer).
|
|
165
|
-
*/
|
|
166
|
-
export declare class RvfDatabase {
|
|
167
|
-
/** Create a new RVF store at the given file path. */
|
|
168
|
-
static create(path: string, options: RvfOptions): RvfDatabase
|
|
169
|
-
/** Open an existing RVF store for read-write access. */
|
|
170
|
-
static open(path: string): RvfDatabase
|
|
171
|
-
/** Open an existing RVF store for read-only access (no lock required). */
|
|
172
|
-
static openReadonly(path: string): RvfDatabase
|
|
173
|
-
/**
|
|
174
|
-
* Ingest a batch of vectors.
|
|
175
|
-
*
|
|
176
|
-
* `vectors` is a flat Float32Array of length `n * dimension`.
|
|
177
|
-
* `ids` is a number[] of vector IDs.
|
|
178
|
-
* `metadata` is an optional array of metadata entries.
|
|
179
|
-
*/
|
|
180
|
-
ingestBatch(vectors: Float32Array, ids: Array<number>, metadata?: Array<RvfMetadataEntry> | undefined | null): RvfIngestResult
|
|
181
|
-
/**
|
|
182
|
-
* Query for the k nearest neighbors of the given vector.
|
|
183
|
-
*
|
|
184
|
-
* `vector` is a Float32Array of length `dimension`.
|
|
185
|
-
* `k` is the number of neighbors to return.
|
|
186
|
-
* `options` provides optional filter (as JSON string) and search parameters.
|
|
187
|
-
*
|
|
188
|
-
* Filter expression JSON format:
|
|
189
|
-
* - Leaf: `{"op":"eq","fieldId":0,"valueType":"string","value":"cat_a"}`
|
|
190
|
-
* - Boolean: `{"op":"and","children":[...]}`
|
|
191
|
-
* - Not: `{"op":"not","child":{...}}`
|
|
192
|
-
* - In: `{"op":"in","fieldId":0,"valueType":"u64","values":["1","2"]}`
|
|
193
|
-
* - Range: `{"op":"range","fieldId":1,"valueType":"u64","low":"10","high":"50"}`
|
|
194
|
-
*/
|
|
195
|
-
query(vector: Float32Array, k: number, options?: RvfQueryOptions | undefined | null): Array<RvfSearchResult>
|
|
196
|
-
/** Soft-delete vectors by ID. */
|
|
197
|
-
delete(ids: Array<number>): RvfDeleteResult
|
|
198
|
-
/**
|
|
199
|
-
* Soft-delete vectors matching a filter expression (passed as JSON string).
|
|
200
|
-
*
|
|
201
|
-
* See `query()` for the filter expression JSON format.
|
|
202
|
-
*/
|
|
203
|
-
deleteByFilter(filterJson: string): RvfDeleteResult
|
|
204
|
-
/** Run compaction to reclaim dead space from deleted vectors. */
|
|
205
|
-
compact(): RvfCompactionResult
|
|
206
|
-
/** Get a snapshot of the current store status. */
|
|
207
|
-
status(): RvfStatus
|
|
208
|
-
/**
|
|
209
|
-
* Close the store, releasing the writer lock and flushing data.
|
|
210
|
-
*
|
|
211
|
-
* After calling close(), all other methods will return an error.
|
|
212
|
-
*/
|
|
213
|
-
close(): void
|
|
214
|
-
/** Get this file's unique identifier as a hex string. */
|
|
215
|
-
fileId(): string
|
|
216
|
-
/** Get the parent file's identifier as a hex string (all zeros if root). */
|
|
217
|
-
parentId(): string
|
|
218
|
-
/** Get the lineage depth (0 for root files). */
|
|
219
|
-
lineageDepth(): number
|
|
220
|
-
/** Derive a child store from this parent. */
|
|
221
|
-
derive(childPath: string, options?: RvfOptions | undefined | null): RvfDatabase
|
|
222
|
-
/**
|
|
223
|
-
* Create a **queryable** copy-on-write branch of this store.
|
|
224
|
-
*
|
|
225
|
-
* Unlike [`derive`](Self::derive) — which records lineage only and
|
|
226
|
-
* produces a child that can see just its own edits — `branch` wires a
|
|
227
|
-
* real COW engine and membership filter so the child inherits the
|
|
228
|
-
* parent's vectors. Querying the child returns `parent ∪ child-edits`:
|
|
229
|
-
* the child's re-ingested vectors override the parent on an id
|
|
230
|
-
* collision, and deletes in the child hide inherited vectors. The
|
|
231
|
-
* branch stores only its own edits on disk, so it stays small
|
|
232
|
-
* regardless of the parent's size.
|
|
233
|
-
*
|
|
234
|
-
* The parent should be frozen (see [`freeze`](Self::freeze)) before
|
|
235
|
-
* branching to guarantee immutability of the inherited data.
|
|
236
|
-
*/
|
|
237
|
-
branch(childPath: string): RvfDatabase
|
|
238
|
-
/**
|
|
239
|
-
* Embed a kernel image into this RVF file.
|
|
240
|
-
* Returns the segment ID of the new kernel segment.
|
|
241
|
-
*/
|
|
242
|
-
embedKernel(arch: number, kernelType: number, flags: number, image: Buffer, apiPort: number, cmdline?: string | undefined | null): number
|
|
243
|
-
/**
|
|
244
|
-
* Extract the kernel image from this RVF file.
|
|
245
|
-
* Returns null if no kernel segment is present.
|
|
246
|
-
*/
|
|
247
|
-
extractKernel(): RvfKernelData | null
|
|
248
|
-
/**
|
|
249
|
-
* Embed an eBPF program into this RVF file.
|
|
250
|
-
* Returns the segment ID of the new eBPF segment.
|
|
251
|
-
*/
|
|
252
|
-
embedEbpf(programType: number, attachType: number, maxDimension: number, bytecode: Buffer, btf?: Buffer | undefined | null): number
|
|
253
|
-
/**
|
|
254
|
-
* Extract the eBPF program from this RVF file.
|
|
255
|
-
* Returns null if no eBPF segment is present.
|
|
256
|
-
*/
|
|
257
|
-
extractEbpf(): RvfEbpfData | null
|
|
258
|
-
/** Get the list of segments in the store. */
|
|
259
|
-
segments(): Array<RvfSegmentInfo>
|
|
260
|
-
/** Get the vector dimensionality of this store. */
|
|
261
|
-
dimension(): number
|
|
262
|
-
/** Get HNSW index statistics for this store. */
|
|
263
|
-
indexStats(): RvfIndexStats
|
|
264
|
-
/**
|
|
265
|
-
* Verify the tamper-evident witness chain in this store.
|
|
266
|
-
*
|
|
267
|
-
* Counts the witness segments present in the segment directory and
|
|
268
|
-
* checks whether the chain has been initialised (non-zero terminal
|
|
269
|
-
* hash). Returns the number of witness entries and validity status.
|
|
270
|
-
*/
|
|
271
|
-
verifyWitness(): RvfWitnessResult
|
|
272
|
-
/**
|
|
273
|
-
* Snapshot-freeze the current state of the store.
|
|
274
|
-
*
|
|
275
|
-
* Sets the store to read-only mode, preventing further writes.
|
|
276
|
-
* Returns the manifest epoch at freeze time.
|
|
277
|
-
*/
|
|
278
|
-
freeze(): number
|
|
279
|
-
/** Get the distance metric used by this store. */
|
|
280
|
-
metric(): string
|
|
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;
|
|
281
95
|
}
|
package/index.js
CHANGED
|
@@ -1,315 +1,150 @@
|
|
|
1
|
-
/* tslint:disable */
|
|
2
1
|
/* eslint-disable */
|
|
3
|
-
/*
|
|
2
|
+
/* auto-generated: NAPI-RS platform loader for @ruvector/rvf-node */
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
const { existsSync, readFileSync } = require('fs');
|
|
5
|
+
const { join } = require('path');
|
|
6
6
|
|
|
7
|
-
const {
|
|
8
|
-
const { join } = require('path')
|
|
7
|
+
const { platform, arch } = process;
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
let
|
|
13
|
-
let localFileExisted = false
|
|
14
|
-
let loadError = null
|
|
9
|
+
let nativeBinding = null;
|
|
10
|
+
let localFileExisted = false;
|
|
11
|
+
let loadError = null;
|
|
15
12
|
|
|
16
13
|
function isMusl() {
|
|
17
|
-
// For Node
|
|
14
|
+
// For Node 12+, check report.header.glibcVersionRuntime
|
|
18
15
|
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
16
|
try {
|
|
20
|
-
const lddPath = require('child_process')
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
24
|
}
|
|
25
25
|
} else {
|
|
26
|
-
const
|
|
27
|
-
|
|
26
|
+
const report = process.report.getReport();
|
|
27
|
+
const rep = typeof report === 'string' ? JSON.parse(report) : report;
|
|
28
|
+
return !rep.header.glibcVersionRuntime;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
switch (platform) {
|
|
32
|
-
case '
|
|
33
|
-
switch (arch) {
|
|
34
|
-
case 'arm64':
|
|
35
|
-
localFileExisted = existsSync(join(__dirname, 'index.android-arm64.node'))
|
|
36
|
-
try {
|
|
37
|
-
if (localFileExisted) {
|
|
38
|
-
nativeBinding = require('./index.android-arm64.node')
|
|
39
|
-
} else {
|
|
40
|
-
nativeBinding = require('@ruvector/rvf-node-android-arm64')
|
|
41
|
-
}
|
|
42
|
-
} catch (e) {
|
|
43
|
-
loadError = e
|
|
44
|
-
}
|
|
45
|
-
break
|
|
46
|
-
case 'arm':
|
|
47
|
-
localFileExisted = existsSync(join(__dirname, 'index.android-arm-eabi.node'))
|
|
48
|
-
try {
|
|
49
|
-
if (localFileExisted) {
|
|
50
|
-
nativeBinding = require('./index.android-arm-eabi.node')
|
|
51
|
-
} else {
|
|
52
|
-
nativeBinding = require('@ruvector/rvf-node-android-arm-eabi')
|
|
53
|
-
}
|
|
54
|
-
} catch (e) {
|
|
55
|
-
loadError = e
|
|
56
|
-
}
|
|
57
|
-
break
|
|
58
|
-
default:
|
|
59
|
-
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
-
}
|
|
61
|
-
break
|
|
62
|
-
case 'win32':
|
|
33
|
+
case 'darwin':
|
|
63
34
|
switch (arch) {
|
|
64
35
|
case 'x64':
|
|
65
|
-
localFileExisted = existsSync(
|
|
66
|
-
join(__dirname, 'index.win32-x64-msvc.node')
|
|
67
|
-
)
|
|
36
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.darwin-x64.node'));
|
|
68
37
|
try {
|
|
69
38
|
if (localFileExisted) {
|
|
70
|
-
nativeBinding = require('./
|
|
39
|
+
nativeBinding = require('./rvf-node.darwin-x64.node');
|
|
71
40
|
} else {
|
|
72
|
-
nativeBinding = require('@ruvector/rvf-node-
|
|
41
|
+
nativeBinding = require('@ruvector/rvf-node-darwin-x64');
|
|
73
42
|
}
|
|
74
43
|
} catch (e) {
|
|
75
|
-
loadError = e
|
|
44
|
+
loadError = e;
|
|
76
45
|
}
|
|
77
|
-
break
|
|
78
|
-
case 'ia32':
|
|
79
|
-
localFileExisted = existsSync(
|
|
80
|
-
join(__dirname, 'index.win32-ia32-msvc.node')
|
|
81
|
-
)
|
|
82
|
-
try {
|
|
83
|
-
if (localFileExisted) {
|
|
84
|
-
nativeBinding = require('./index.win32-ia32-msvc.node')
|
|
85
|
-
} else {
|
|
86
|
-
nativeBinding = require('@ruvector/rvf-node-win32-ia32-msvc')
|
|
87
|
-
}
|
|
88
|
-
} catch (e) {
|
|
89
|
-
loadError = e
|
|
90
|
-
}
|
|
91
|
-
break
|
|
46
|
+
break;
|
|
92
47
|
case 'arm64':
|
|
93
|
-
localFileExisted = existsSync(
|
|
94
|
-
join(__dirname, 'index.win32-arm64-msvc.node')
|
|
95
|
-
)
|
|
48
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.darwin-arm64.node'));
|
|
96
49
|
try {
|
|
97
50
|
if (localFileExisted) {
|
|
98
|
-
nativeBinding = require('./
|
|
51
|
+
nativeBinding = require('./rvf-node.darwin-arm64.node');
|
|
99
52
|
} else {
|
|
100
|
-
nativeBinding = require('@ruvector/rvf-node-
|
|
53
|
+
nativeBinding = require('@ruvector/rvf-node-darwin-arm64');
|
|
101
54
|
}
|
|
102
55
|
} catch (e) {
|
|
103
|
-
loadError = e
|
|
56
|
+
loadError = e;
|
|
104
57
|
}
|
|
105
|
-
break
|
|
58
|
+
break;
|
|
106
59
|
default:
|
|
107
|
-
throw new Error(`Unsupported architecture on
|
|
60
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`);
|
|
108
61
|
}
|
|
109
|
-
break
|
|
110
|
-
case '
|
|
111
|
-
localFileExisted = existsSync(join(__dirname, 'index.darwin-universal.node'))
|
|
112
|
-
try {
|
|
113
|
-
if (localFileExisted) {
|
|
114
|
-
nativeBinding = require('./index.darwin-universal.node')
|
|
115
|
-
} else {
|
|
116
|
-
nativeBinding = require('@ruvector/rvf-node-darwin-universal')
|
|
117
|
-
}
|
|
118
|
-
break
|
|
119
|
-
} catch {}
|
|
62
|
+
break;
|
|
63
|
+
case 'win32':
|
|
120
64
|
switch (arch) {
|
|
121
65
|
case 'x64':
|
|
122
|
-
localFileExisted = existsSync(join(__dirname, '
|
|
66
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.win32-x64-msvc.node'));
|
|
123
67
|
try {
|
|
124
68
|
if (localFileExisted) {
|
|
125
|
-
nativeBinding = require('./
|
|
69
|
+
nativeBinding = require('./rvf-node.win32-x64-msvc.node');
|
|
126
70
|
} else {
|
|
127
|
-
nativeBinding = require('@ruvector/rvf-node-
|
|
71
|
+
nativeBinding = require('@ruvector/rvf-node-win32-x64-msvc');
|
|
128
72
|
}
|
|
129
73
|
} catch (e) {
|
|
130
|
-
loadError = e
|
|
74
|
+
loadError = e;
|
|
131
75
|
}
|
|
132
|
-
break
|
|
133
|
-
case 'arm64':
|
|
134
|
-
localFileExisted = existsSync(
|
|
135
|
-
join(__dirname, 'index.darwin-arm64.node')
|
|
136
|
-
)
|
|
137
|
-
try {
|
|
138
|
-
if (localFileExisted) {
|
|
139
|
-
nativeBinding = require('./index.darwin-arm64.node')
|
|
140
|
-
} else {
|
|
141
|
-
nativeBinding = require('@ruvector/rvf-node-darwin-arm64')
|
|
142
|
-
}
|
|
143
|
-
} catch (e) {
|
|
144
|
-
loadError = e
|
|
145
|
-
}
|
|
146
|
-
break
|
|
76
|
+
break;
|
|
147
77
|
default:
|
|
148
|
-
throw new Error(`Unsupported architecture on
|
|
149
|
-
}
|
|
150
|
-
break
|
|
151
|
-
case 'freebsd':
|
|
152
|
-
if (arch !== 'x64') {
|
|
153
|
-
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
-
}
|
|
155
|
-
localFileExisted = existsSync(join(__dirname, 'index.freebsd-x64.node'))
|
|
156
|
-
try {
|
|
157
|
-
if (localFileExisted) {
|
|
158
|
-
nativeBinding = require('./index.freebsd-x64.node')
|
|
159
|
-
} else {
|
|
160
|
-
nativeBinding = require('@ruvector/rvf-node-freebsd-x64')
|
|
161
|
-
}
|
|
162
|
-
} catch (e) {
|
|
163
|
-
loadError = e
|
|
78
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`);
|
|
164
79
|
}
|
|
165
|
-
break
|
|
80
|
+
break;
|
|
166
81
|
case 'linux':
|
|
167
82
|
switch (arch) {
|
|
168
83
|
case 'x64':
|
|
169
84
|
if (isMusl()) {
|
|
170
|
-
localFileExisted = existsSync(
|
|
171
|
-
join(__dirname, 'index.linux-x64-musl.node')
|
|
172
|
-
)
|
|
85
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-x64-musl.node'));
|
|
173
86
|
try {
|
|
174
87
|
if (localFileExisted) {
|
|
175
|
-
nativeBinding = require('./
|
|
88
|
+
nativeBinding = require('./rvf-node.linux-x64-musl.node');
|
|
176
89
|
} else {
|
|
177
|
-
nativeBinding = require('@ruvector/rvf-node-linux-x64-musl')
|
|
90
|
+
nativeBinding = require('@ruvector/rvf-node-linux-x64-musl');
|
|
178
91
|
}
|
|
179
92
|
} catch (e) {
|
|
180
|
-
loadError = e
|
|
93
|
+
loadError = e;
|
|
181
94
|
}
|
|
182
95
|
} else {
|
|
183
|
-
localFileExisted = existsSync(
|
|
184
|
-
join(__dirname, 'index.linux-x64-gnu.node')
|
|
185
|
-
)
|
|
96
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-x64-gnu.node'));
|
|
186
97
|
try {
|
|
187
98
|
if (localFileExisted) {
|
|
188
|
-
nativeBinding = require('./
|
|
99
|
+
nativeBinding = require('./rvf-node.linux-x64-gnu.node');
|
|
189
100
|
} else {
|
|
190
|
-
nativeBinding = require('@ruvector/rvf-node-linux-x64-gnu')
|
|
101
|
+
nativeBinding = require('@ruvector/rvf-node-linux-x64-gnu');
|
|
191
102
|
}
|
|
192
103
|
} catch (e) {
|
|
193
|
-
loadError = e
|
|
104
|
+
loadError = e;
|
|
194
105
|
}
|
|
195
106
|
}
|
|
196
|
-
break
|
|
107
|
+
break;
|
|
197
108
|
case 'arm64':
|
|
198
109
|
if (isMusl()) {
|
|
199
|
-
localFileExisted = existsSync(
|
|
200
|
-
join(__dirname, 'index.linux-arm64-musl.node')
|
|
201
|
-
)
|
|
110
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-arm64-musl.node'));
|
|
202
111
|
try {
|
|
203
112
|
if (localFileExisted) {
|
|
204
|
-
nativeBinding = require('./
|
|
113
|
+
nativeBinding = require('./rvf-node.linux-arm64-musl.node');
|
|
205
114
|
} else {
|
|
206
|
-
nativeBinding = require('@ruvector/rvf-node-linux-arm64-musl')
|
|
115
|
+
nativeBinding = require('@ruvector/rvf-node-linux-arm64-musl');
|
|
207
116
|
}
|
|
208
117
|
} catch (e) {
|
|
209
|
-
loadError = e
|
|
118
|
+
loadError = e;
|
|
210
119
|
}
|
|
211
120
|
} else {
|
|
212
|
-
localFileExisted = existsSync(
|
|
213
|
-
join(__dirname, 'index.linux-arm64-gnu.node')
|
|
214
|
-
)
|
|
215
|
-
try {
|
|
216
|
-
if (localFileExisted) {
|
|
217
|
-
nativeBinding = require('./index.linux-arm64-gnu.node')
|
|
218
|
-
} else {
|
|
219
|
-
nativeBinding = require('@ruvector/rvf-node-linux-arm64-gnu')
|
|
220
|
-
}
|
|
221
|
-
} catch (e) {
|
|
222
|
-
loadError = e
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
break
|
|
226
|
-
case 'arm':
|
|
227
|
-
if (isMusl()) {
|
|
228
|
-
localFileExisted = existsSync(
|
|
229
|
-
join(__dirname, 'index.linux-arm-musleabihf.node')
|
|
230
|
-
)
|
|
121
|
+
localFileExisted = existsSync(join(__dirname, 'rvf-node.linux-arm64-gnu.node'));
|
|
231
122
|
try {
|
|
232
123
|
if (localFileExisted) {
|
|
233
|
-
nativeBinding = require('./
|
|
124
|
+
nativeBinding = require('./rvf-node.linux-arm64-gnu.node');
|
|
234
125
|
} else {
|
|
235
|
-
nativeBinding = require('@ruvector/rvf-node-linux-
|
|
126
|
+
nativeBinding = require('@ruvector/rvf-node-linux-arm64-gnu');
|
|
236
127
|
}
|
|
237
128
|
} catch (e) {
|
|
238
|
-
loadError = e
|
|
129
|
+
loadError = e;
|
|
239
130
|
}
|
|
240
|
-
} else {
|
|
241
|
-
localFileExisted = existsSync(
|
|
242
|
-
join(__dirname, 'index.linux-arm-gnueabihf.node')
|
|
243
|
-
)
|
|
244
|
-
try {
|
|
245
|
-
if (localFileExisted) {
|
|
246
|
-
nativeBinding = require('./index.linux-arm-gnueabihf.node')
|
|
247
|
-
} else {
|
|
248
|
-
nativeBinding = require('@ruvector/rvf-node-linux-arm-gnueabihf')
|
|
249
|
-
}
|
|
250
|
-
} catch (e) {
|
|
251
|
-
loadError = e
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
break
|
|
255
|
-
case 'riscv64':
|
|
256
|
-
if (isMusl()) {
|
|
257
|
-
localFileExisted = existsSync(
|
|
258
|
-
join(__dirname, 'index.linux-riscv64-musl.node')
|
|
259
|
-
)
|
|
260
|
-
try {
|
|
261
|
-
if (localFileExisted) {
|
|
262
|
-
nativeBinding = require('./index.linux-riscv64-musl.node')
|
|
263
|
-
} else {
|
|
264
|
-
nativeBinding = require('@ruvector/rvf-node-linux-riscv64-musl')
|
|
265
|
-
}
|
|
266
|
-
} catch (e) {
|
|
267
|
-
loadError = e
|
|
268
|
-
}
|
|
269
|
-
} else {
|
|
270
|
-
localFileExisted = existsSync(
|
|
271
|
-
join(__dirname, 'index.linux-riscv64-gnu.node')
|
|
272
|
-
)
|
|
273
|
-
try {
|
|
274
|
-
if (localFileExisted) {
|
|
275
|
-
nativeBinding = require('./index.linux-riscv64-gnu.node')
|
|
276
|
-
} else {
|
|
277
|
-
nativeBinding = require('@ruvector/rvf-node-linux-riscv64-gnu')
|
|
278
|
-
}
|
|
279
|
-
} catch (e) {
|
|
280
|
-
loadError = e
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
break
|
|
284
|
-
case 's390x':
|
|
285
|
-
localFileExisted = existsSync(
|
|
286
|
-
join(__dirname, 'index.linux-s390x-gnu.node')
|
|
287
|
-
)
|
|
288
|
-
try {
|
|
289
|
-
if (localFileExisted) {
|
|
290
|
-
nativeBinding = require('./index.linux-s390x-gnu.node')
|
|
291
|
-
} else {
|
|
292
|
-
nativeBinding = require('@ruvector/rvf-node-linux-s390x-gnu')
|
|
293
|
-
}
|
|
294
|
-
} catch (e) {
|
|
295
|
-
loadError = e
|
|
296
131
|
}
|
|
297
|
-
break
|
|
132
|
+
break;
|
|
298
133
|
default:
|
|
299
|
-
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
134
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`);
|
|
300
135
|
}
|
|
301
|
-
break
|
|
136
|
+
break;
|
|
302
137
|
default:
|
|
303
|
-
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
138
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`);
|
|
304
139
|
}
|
|
305
140
|
|
|
306
141
|
if (!nativeBinding) {
|
|
307
142
|
if (loadError) {
|
|
308
|
-
throw loadError
|
|
143
|
+
throw loadError;
|
|
309
144
|
}
|
|
310
|
-
throw new Error(
|
|
145
|
+
throw new Error('Failed to load native binding');
|
|
311
146
|
}
|
|
312
147
|
|
|
313
|
-
const { RvfDatabase } = nativeBinding
|
|
148
|
+
const { RvfDatabase } = nativeBinding;
|
|
314
149
|
|
|
315
|
-
module.exports.RvfDatabase = RvfDatabase
|
|
150
|
+
module.exports.RvfDatabase = RvfDatabase;
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ruvector/rvf-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "RuVector Format Node.js native bindings",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"index.js",
|
|
9
9
|
"index.d.ts",
|
|
10
|
-
"
|
|
11
|
-
"package.json"
|
|
10
|
+
"*.node"
|
|
12
11
|
],
|
|
13
12
|
"napi": {
|
|
14
13
|
"binaryName": "rvf-node",
|
|
@@ -24,14 +23,15 @@
|
|
|
24
23
|
"build": "napi build --platform --release"
|
|
25
24
|
},
|
|
26
25
|
"license": "MIT",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/ruvnet/ruvector"
|
|
29
29
|
},
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">= 16"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"registry": "https://registry.npmjs.org/",
|
|
35
|
+
"access": "public"
|
|
36
36
|
}
|
|
37
37
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|