Skip to content

Commit

Permalink
Add nodejs binding
Browse files Browse the repository at this point in the history
  • Loading branch information
1yefuwang1 committed Aug 2, 2024
1 parent 70fbaa4 commit 102d32c
Show file tree
Hide file tree
Showing 17 changed files with 224 additions and 7 deletions.
49 changes: 43 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ on:
type: 'choice'
options: ['no', 'pypi', 'testpypi']

publish_npm:
description: 'whether to publish the npm packages'
required: false
default: 'no'
type: 'choice'
options: ['no', 'yes']

pull_request:
branches:
- main
Expand Down Expand Up @@ -88,20 +95,16 @@ jobs:
if: ${{ github.event.inputs.upload_wheel != 'no' && github.event_name != 'pull_request' }}
needs: build_wheels
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-13, macos-14]

steps:
- uses: actions/checkout@v4

- uses: benjlevesque/[email protected]
id: short_sha

# Download artifact
# Download all artifacts
- uses: actions/download-artifact@v4
with:
name: vectorlite-wheel-${{ matrix.os }}-${{ steps.short_sha.outputs.sha }}
path: ./wheelhouse

- name: Upload to test.pypi.org
Expand All @@ -122,4 +125,38 @@ jobs:
if: ${{ github.event.inputs.upload_wheel == 'pypi' && !startsWith(github.ref, 'refs/tags/v') }}
run: |
echo "Error: Uploading to pypi.org requires a tag"
exit 1
exit 1
publish_npm_pkgs:
name: Upload wheels
if: ${{ github.event.inputs.publish_npm == 'yes' && github.event_name != 'pull_request' }}
needs: build_wheels
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: benjlevesque/[email protected]
id: short_sha

# Download all artifacts
- uses: actions/download-artifact@v4
with:
path: ./wheelhouse

# extract vectorlite from wheels and copy to nodejs bindings directory
- name: unzip wheels
run: |
sh extract_wheels.sh

- uses: actions/setup-node@v4
with:
node-version: lts/*

- name: Publish to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
run:
cd bindings/nodejs
npm publish --workspaces

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ vcpkg_installed/*
*.pyc
dist/*

*egg-info
*egg-info

node_modules
bindings/nodejs/vectorlite/package-lock.json
4 changes: 4 additions & 0 deletions bindings/nodejs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "vectorlite-workspaces",
"workspaces": ["packages/vectorlite-win32-x64", "packages/vectorlite-linux-x64", "packages/vectorlite-darwin-x64", "packages/vectorlite-darwin-arm64", "packages/vectorlite"]
}
1 change: 1 addition & 0 deletions bindings/nodejs/packages/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This folder hosts nodejs bindings for vectorlite. `vectorlite.[so|dll|dylib]` is copied to their own platform dependent package folder. Please check ci.yml for details.
12 changes: 12 additions & 0 deletions bindings/nodejs/packages/vectorlite-darwin-arm64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "vectorlite-darwin-arm64",
"version": "0.1.0",
"main": "src/index.js",
"files": ["src"],
"author": "[email protected]",
"license": "Apache-2.0",
"description": "A fast and tunable vector search extension for SQLite",
"keywords": ["sqlite3", "vector database", "vectordb"],
"os": ["darwin"],
"cpu": ["arm64"]
}
7 changes: 7 additions & 0 deletions bindings/nodejs/packages/vectorlite-darwin-arm64/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const path = require('path');

function vectorlitePath() {
return path.join(__dirname, 'vectorlite');
}

exports.vectorlitePath = vectorlitePath;
12 changes: 12 additions & 0 deletions bindings/nodejs/packages/vectorlite-darwin-x64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "vectorlite-darwin-x64",
"version": "0.1.0",
"main": "src/index.js",
"files": ["src"],
"author": "[email protected]",
"license": "Apache-2.0",
"description": "A fast and tunable vector search extension for SQLite",
"keywords": ["sqlite3", "vector database", "vectordb"],
"os": ["darwin"],
"cpu": ["x64"]
}
7 changes: 7 additions & 0 deletions bindings/nodejs/packages/vectorlite-darwin-x64/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const path = require('path');

function vectorlitePath() {
return path.join(__dirname, 'vectorlite');
}

exports.vectorlitePath = vectorlitePath;
12 changes: 12 additions & 0 deletions bindings/nodejs/packages/vectorlite-linux-x64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "vectorlite-linux-x64",
"version": "0.1.0",
"main": "src/index.js",
"files": ["src"],
"author": "[email protected]",
"license": "Apache-2.0",
"description": "A fast and tunable vector search extension for SQLite",
"keywords": ["sqlite3", "vector database", "vectordb"],
"os": ["linux"],
"cpu": ["x64"]
}
7 changes: 7 additions & 0 deletions bindings/nodejs/packages/vectorlite-linux-x64/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const path = require('path');

function vectorlitePath() {
return path.join(__dirname, 'vectorlite');
}

exports.vectorlitePath = vectorlitePath;
12 changes: 12 additions & 0 deletions bindings/nodejs/packages/vectorlite-win32-x64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "vectorlite-win32-x64",
"version": "0.1.0",
"main": "src/index.js",
"files": ["src"],
"author": "[email protected]",
"license": "Apache-2.0",
"description": "A fast and tunable vector search extension for SQLite",
"keywords": ["sqlite3", "vector database", "vectordb"],
"os": ["win32"],
"cpu": ["x64"]
}
7 changes: 7 additions & 0 deletions bindings/nodejs/packages/vectorlite-win32-x64/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const path = require('path');

function vectorlitePath() {
return path.join(__dirname, 'vectorlite');
}

exports.vectorlitePath = vectorlitePath;
1 change: 1 addition & 0 deletions bindings/nodejs/packages/vectorlite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# `vectorlite` for nodejs
22 changes: 22 additions & 0 deletions bindings/nodejs/packages/vectorlite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "vectorlite",
"version": "0.1.0",
"main": "src/index.js",
"files": ["src"],
"scripts": {
"test": "node test/test.js"
},
"author": "[email protected]",
"license": "Apache-2.0",
"description": "A fast and tunable vector search extension for SQLite",
"keywords": ["sqlite3", "vector database", "vectordb"],
"devDependencies": {
"better-sqlite3": "^11.1.2"
},
"optionalDependencies": {
"vectorlite-darwin-x64": "0.1.0",
"vectorlite-darwin-arm64": "0.1.0",
"vectorlite-linux-x64": "file://../vectorlite-linux-x64",
"vectorlite-win32-x64": "0.1.0"
}
}
28 changes: 28 additions & 0 deletions bindings/nodejs/packages/vectorlite/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const os = require('os');

const supportedPlatformsAndArchs = {
'darwin-x64': 'vectorlite-darwin-x64',
'darwin-arm64': 'vectorlite-darwin-arm64',
'linux-x64': 'vectorlite-linux-x64',
'win32-x64': 'vectorlite-win32-x64',
};

const platformAndArch = `${os.platform()}-${os.arch()}`;

let vectorlitePathCache = undefined;

// Returns path to the vectorlite shared library
function vectorlitePath() {
if (vectorlitePathCache) {
return vectorlitePathCache;
}
const packageName = supportedPlatformsAndArchs[platformAndArch];
if (!packageName) {
throw new Error(`Platform ${platformAndArch} is not supported`);
}
const package = require(packageName);
vectorlitePathCache = package.vectorlitePath();
return vectorlitePathCache;
}

exports.vectorlitePath = vectorlitePath;
19 changes: 19 additions & 0 deletions bindings/nodejs/packages/vectorlite/test/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const sqlite3 = require('better-sqlite3');
const vectorlite = require('../src/index.js');

const db = new sqlite3(':memory:');
db.loadExtension(vectorlite.vectorlitePath());

console.log(db.prepare('select vectorlite_info()').all());

db.exec('create virtual table test using vectorlite(vec float32[10], hnsw(max_elements=100));')

// insert a json vector
db.prepare('insert into test(rowid, vec) values (?, vector_from_json(?))').run([0, JSON.stringify(Array.from({length: 10}, () => Math.random()))]);
// insert a raw vector
db.prepare('insert into test(rowid, vec) values (?, ?)').run([1, Buffer.from(Float32Array.from(Array.from({length: 10}, () => Math.random())).buffer)]);

const result = db.run('select rowid from test where knn_search(vec, knn_param(?, 2))')
.all([Buffer.from(Float32Array.from(Array.from({length: 10}, () => Math.random())).buffer)]);

console.log(result);
26 changes: 26 additions & 0 deletions extract_wheels.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

for wheel in dist/*.whl; do
unziped_dir=$wheel.unzipped
unzip $wheel -d $unziped_dir

case "$wheel" in
*linux*x86_64.whl)
cp $unziped_dir/vectorlite_py/vectorlite.so bindings/nodejs/packages/vectorlite-linux-x64/src
;;
*win*amd64.whl)
cp $unziped_dir/vectorlite_py/vectorlite.dll bindings/nodejs/packages/vectorlite-win32-x64/src
;;
*macosx*arm64.whl)
cp $unziped_dir/vectorlite_py/vectorlite.dylib bindings/nodejs/packages/vectorlite-darwin-arm64/src
;;
*macosx*x86_64.whl)
cp $unziped_dir/vectorlite_py/vectorlite.dylib bindings/nodejs/packages/vectorlite-darwin-x64/src
;;
*)
echo "Unknown wheel type: $wheel"
exit 1
;;
esac
done

0 comments on commit 102d32c

Please sign in to comment.