Skip to content

Commit 5b6c4c9

Browse files
author
Marcus Pousette
committed
fix: path resolvement
1 parent b8865ec commit 5b6c4c9

5 files changed

Lines changed: 124 additions & 27 deletions

File tree

dist-tests/import-name.spec.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { test } from 'node:test';
2+
import * as assert from 'node:assert/strict';
3+
import * as fs from 'node:fs';
4+
import * as os from 'node:os';
5+
import * as path from 'node:path';
6+
import { spawnSync } from 'node:child_process';
7+
8+
test('consumer import by package name works', async () => {
9+
// Create temp project with node_modules alias to this repo
10+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'sqlite3-vec-import-'));
11+
const nm = path.join(tmp, 'node_modules', '@dao-xyz');
12+
fs.mkdirSync(nm, { recursive: true });
13+
const linkTarget = process.cwd();
14+
const pkgPath = path.join(nm, 'sqlite3-vec');
15+
try {
16+
fs.symlinkSync(linkTarget, pkgPath, 'dir');
17+
} catch (e) {
18+
// Fallback: copy if symlink not permitted
19+
fs.cpSync(linkTarget, pkgPath, { recursive: true, dereference: true });
20+
}
21+
22+
// Write an ESM script which imports the package by name
23+
const runner = path.join(tmp, 'runner.mjs');
24+
fs.writeFileSync(
25+
runner,
26+
`import { createDatabase, resolveNativeExtensionPath } from '@dao-xyz/sqlite3-vec';
27+
const db = await createDatabase({});
28+
await db.open();
29+
const s = await db.prepare('select sqlite_version() as v');
30+
const row = s.get?.([]);
31+
if (!row || !(row.v || row[0])) throw new Error('no sqlite_version');
32+
// Not asserting ext presence; just ensure the API is callable
33+
void resolveNativeExtensionPath();
34+
await db.close();
35+
console.log('ok');
36+
`,
37+
);
38+
39+
const res = spawnSync(process.execPath, [runner], {
40+
cwd: tmp,
41+
stdio: 'pipe',
42+
env: { ...process.env, NODE_ENV: 'test' },
43+
encoding: 'utf8',
44+
});
45+
if (res.status !== 0) {
46+
console.error('[import-name] stderr:', res.stderr);
47+
console.error('[import-name] stdout:', res.stdout);
48+
}
49+
assert.equal(res.status, 0);
50+
assert.match(res.stdout || '', /ok/);
51+
});

dist-tests/simple.spec.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import * as assert from 'node:assert/strict';
33
// Import the built unified Node entry to test Node usage without bundlers.
44
import { createDatabase } from '../dist/unified-node.js';
55
test('unified import and factory availability', async () => {
6-
assert.equal(typeof createDatabase, 'function');
6+
assert.equal(typeof createDatabase, 'function');
77
});
88
test('unified createDatabase (native mode) basic usage', async () => {
9-
const db = await createDatabase({});
10-
await db.open();
11-
const s = await db.prepare('SELECT sqlite_version() as v');
12-
const row = s.get?.([]);
13-
assert.ok(row && (typeof row.v === 'string' || row[0]));
14-
await db.close();
9+
const db = await createDatabase({});
10+
await db.open();
11+
const s = await db.prepare('SELECT sqlite_version() as v');
12+
const row = s.get?.([]);
13+
assert.ok(row && (typeof row.v === 'string' || row[0]));
14+
await db.close();
1515
});

dist-tests/vec.spec.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
import { test } from 'node:test';
22
import * as assert from 'node:assert/strict';
3-
import {
4-
createDatabase,
5-
resolveNativeExtensionPath,
6-
} from '../dist/unified-node.js';
3+
import { createDatabase, resolveNativeExtensionPath, } from '../dist/unified-node.js';
74
test('vec extension provides vec_version() when present', async () => {
8-
const extPath = resolveNativeExtensionPath();
9-
if (!extPath) {
10-
// No prebuilt/native extension present in this environment; skip.
11-
return;
12-
}
13-
const db = await createDatabase({});
14-
await db.open();
15-
const stmt = await db.prepare('select vec_version() as v');
16-
const row = stmt.get?.([]);
17-
assert.ok(row && typeof (row.v ?? row[0]) === 'string');
18-
await db.close();
5+
const extPath = resolveNativeExtensionPath();
6+
if (!extPath) {
7+
// No prebuilt/native extension present in this environment; skip.
8+
return;
9+
}
10+
const db = await createDatabase({});
11+
await db.open();
12+
const stmt = await db.prepare('select vec_version() as v');
13+
const row = stmt.get?.([]);
14+
assert.ok(row && typeof (row.v ?? row[0]) === 'string');
15+
await db.close();
1916
});

dist-tests/vec0-native.spec.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { test } from 'node:test';
2+
import * as assert from 'node:assert/strict';
3+
import {
4+
createDatabase,
5+
resolveNativeExtensionPath,
6+
} from '../dist/unified-node.js';
7+
8+
test('vec0 create/insert/query works (native ext present)', async () => {
9+
const extPath = resolveNativeExtensionPath();
10+
if (!extPath) return; // skip if no native ext available
11+
12+
const db = await createDatabase({});
13+
await db.open();
14+
await db.exec('CREATE VIRTUAL TABLE IF NOT EXISTS v USING vec0(vector float[3])');
15+
16+
const toVec = () => new Float32Array([Math.random(), Math.random(), Math.random()]);
17+
const ins = await db.prepare('INSERT INTO v(rowid,vector) VALUES(?1,?2)');
18+
for (let i = 1; i <= 4; i++) ins.run([i, toVec().buffer]);
19+
20+
const probe = toVec();
21+
const q = await db.prepare(
22+
'SELECT rowid, vec_distance_l2(vector, ?1) AS d FROM v ORDER BY d LIMIT 2',
23+
);
24+
const rows = q.all([probe.buffer]);
25+
assert.ok(Array.isArray(rows) && rows.length === 2);
26+
assert.ok(typeof rows[0].d === 'number');
27+
await db.close();
28+
});

src/unified-node.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import type { Database, Statement } from './unified';
33
import * as fs from 'fs';
44
import * as path from 'path';
5+
import { fileURLToPath } from 'url';
56

67
function detectLibc(): 'gnu' | 'musl' {
78
try {
@@ -28,9 +29,14 @@ function libExt(): string {
2829
: 'so';
2930
}
3031

32+
function packageRootDir(): string {
33+
// dist/unified-node.js -> package root
34+
const here = path.dirname(fileURLToPath(import.meta.url));
35+
return path.resolve(here, '..');
36+
}
37+
3138
function findLocalPrebuilt(): string | undefined {
32-
const root = process.cwd();
33-
const outDir = path.join(root, 'dist', 'native');
39+
const outDir = path.join(packageRootDir(), 'dist', 'native');
3440
if (!fs.existsSync(outDir)) return undefined;
3541
const ext = libExt();
3642
const triple = platformTriple();
@@ -107,6 +113,21 @@ export async function createDatabase(
107113
}
108114
};
109115

116+
const toBuffer = (v: any): any => {
117+
if (!v) return v;
118+
// Convert ArrayBuffer/TypedArray/DataView to Node Buffer for better-sqlite3 BLOB binding
119+
if (typeof ArrayBuffer !== 'undefined') {
120+
if (v instanceof ArrayBuffer) return Buffer.from(new Uint8Array(v));
121+
if (ArrayBuffer.isView?.(v)) {
122+
const u8 = new Uint8Array(v.buffer, v.byteOffset, v.byteLength);
123+
return Buffer.from(u8);
124+
}
125+
}
126+
return v;
127+
};
128+
const normVals = (values?: any[] | undefined): any[] | undefined =>
129+
values ? values.map((x) => toBuffer(x)) : values;
130+
110131
const wrapStmt = (stmt: any): Statement => {
111132
let bound: any[] | undefined = undefined;
112133
return {
@@ -116,17 +137,17 @@ export async function createDatabase(
116137
},
117138
finalize() {},
118139
get(values?: any[]) {
119-
return stmt.get(values ?? bound);
140+
return stmt.get(normVals(values ?? bound));
120141
},
121142
run(values: any[]) {
122-
stmt.run(values ?? bound);
143+
stmt.run(normVals(values ?? bound));
123144
bound = undefined;
124145
},
125146
async reset() {
126147
return this;
127148
},
128149
all(values: any[]) {
129-
return stmt.all(values ?? bound);
150+
return stmt.all(normVals(values ?? bound));
130151
},
131152
step() {
132153
return false;

0 commit comments

Comments
 (0)