From e5e1e7e75441fa940312182ca2e050ba0e959ca1 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Thu, 25 Sep 2025 20:29:18 +0200 Subject: [PATCH 01/15] fix(docs): update package references in browser WASM example --- examples/browser-wasm/index.html | 4 ++-- examples/browser-wasm/load_extension.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/browser-wasm/index.html b/examples/browser-wasm/index.html index d549d11..3c1c3cd 100644 --- a/examples/browser-wasm/index.html +++ b/examples/browser-wasm/index.html @@ -6,14 +6,14 @@ SQLite WASM Extension Example -

SQLite WASM with SQLite Sync Extension Example

+

SQLite WASM with SQLite Sync and SQLite Vector Extensions Example

Open the directory in the terminal and type: npx serve .

Check the browser console for output.

diff --git a/examples/browser-wasm/load_extension.js b/examples/browser-wasm/load_extension.js index f3af071..5fd5d93 100644 --- a/examples/browser-wasm/load_extension.js +++ b/examples/browser-wasm/load_extension.js @@ -1,15 +1,15 @@ /** - * This example uses the package `@sqliteai/sqlite-sync-wasm`. - * This version of SQLite WASM is bundled with the SQLite Sync extension. + * This example uses the package `@sqliteai/sqlite-wasm`. + * This version of SQLite WASM is bundled with SQLite Sync and SQLite Vector extensions. * Extensions cannot be loaded at runtime in the browser environment. * * Run: - * `npm install @sqliteai/sqlite-sync-wasm` + * `npm install @sqliteai/sqlite-wasm` * and serve the page with: * `npx serve .` */ -import { sqlite3Worker1Promiser } from '@sqliteai/sqlite-sync-wasm'; +import { sqlite3Worker1Promiser } from '@sqliteai/sqlite-wasm'; const log = console.log; const error = console.error; @@ -34,7 +34,7 @@ const initializeSQLite = async () => { await promiser('exec', { dbId, - sql: 'SELECT cloudsync_version();', + sql: 'SELECT cloudsync_version();', // or vector_version() callback: (result) => { if (!result.row) { return; From d7be9d5d60d2e39f0a7c41c9f5b93d690b0728b4 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni <48024736+Gioee@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:13:35 +0200 Subject: [PATCH 02/15] fix(macos): Python SQLite extension loading example path --- platforms/macos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/macos.md b/platforms/macos.md index 587b9bb..ad7f6e1 100644 --- a/platforms/macos.md +++ b/platforms/macos.md @@ -71,4 +71,4 @@ which python3 ``` After installing Python with Homebrew, the `python` command now uses the Homebrew version. -You can now load SQLite extensions in Python as shown in the [Python example](examples/python). \ No newline at end of file +You can now load SQLite extensions in Python as shown in the [Python example](../examples/python/load_extension.py). From f8e46e919ddedf1659d1a0ed091a6de49164b527 Mon Sep 17 00:00:00 2001 From: DAMLA YILDIZ Date: Tue, 30 Sep 2025 11:29:55 +0200 Subject: [PATCH 03/15] chore: typo --- platforms/linux.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/linux.md b/platforms/linux.md index e46b24c..ddbf1d1 100644 --- a/platforms/linux.md +++ b/platforms/linux.md @@ -57,4 +57,4 @@ SELECT my_custom_function(); | -------------------------------------------- | --------------------------------------------------------------------- | | `no such file or directory` | Ensure path to `.so` is correct and matches your platform. | | `incompatible architecture` | Download extension for your Linux system (e.g., x86\_64 vs arm64). | -| `Failed to load extension: symbol not found` | Download the extension for for `musl-x86_64` or `musl-arm64` targets | \ No newline at end of file +| `Failed to load extension: symbol not found` | Download the extension for `musl-x86_64` or `musl-arm64` targets | From 42f4417a7796786bdd4423ba133aa777035d4a70 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Wed, 1 Oct 2025 14:43:42 +0200 Subject: [PATCH 04/15] feat(android): add example app for SQLite AAR package extensions with setup instructions --- .gitignore | 30 +++++++++- examples/android/README.md | 13 +++++ examples/android/build.gradle | 52 +++++++++++++++++ examples/android/gradle.properties | 3 + examples/android/src/main/AndroidManifest.xml | 21 +++++++ .../java/ai/sqlite/example/MainActivity.java | 56 +++++++++++++++++++ .../src/main/res/layout/activity_main.xml | 18 ++++++ .../android/src/main/res/values/strings.xml | 4 ++ 8 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 examples/android/README.md create mode 100644 examples/android/build.gradle create mode 100644 examples/android/gradle.properties create mode 100644 examples/android/src/main/AndroidManifest.xml create mode 100644 examples/android/src/main/java/ai/sqlite/example/MainActivity.java create mode 100644 examples/android/src/main/res/layout/activity_main.xml create mode 100644 examples/android/src/main/res/values/strings.xml diff --git a/.gitignore b/.gitignore index accd193..2d9e570 100644 --- a/.gitignore +++ b/.gitignore @@ -79,4 +79,32 @@ Thumbs.db # SQLite *.db *.sqlite -*.sqlite3 \ No newline at end of file +*.sqlite3 + +# Build artifacts +build/ +/dist +.build +*.a +*.sqlite + +# iOS/macOS +*.xcworkspacedata +*.xcuserstate +*.xcbkptlist +*.plist + +# Android +.gradle/ +gradle/ +*.aar +local.properties +jniLibs/ +*.apk +*.ap_ +*.dex + +# IDE +.vscode +.idea/ +*.iml \ No newline at end of file diff --git a/examples/android/README.md b/examples/android/README.md new file mode 100644 index 0000000..2dc996f --- /dev/null +++ b/examples/android/README.md @@ -0,0 +1,13 @@ +# SQLite AAR Extensions - Android Example + +Simple Android app demonstrating SQLite AI extensions loaded from AAR package. + +## Setup + +1. Import project in Android Studio +2. Sync project +3. Run on device/emulator (API 26+) + +## What it does + +Tests `[extension]_version()` function using custom SQLite with extension support via AAR package. \ No newline at end of file diff --git a/examples/android/build.gradle b/examples/android/build.gradle new file mode 100644 index 0000000..131883d --- /dev/null +++ b/examples/android/build.gradle @@ -0,0 +1,52 @@ +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.6.0' + } +} + +apply plugin: 'com.android.application' + +android { + namespace 'ai.sqlite.example' + compileSdk 35 + + defaultConfig { + applicationId "ai.sqlite.example" + minSdk 26 + targetSdk 35 + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.debug + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + +} + +repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.10.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.github.requery:sqlite-android:3.49.0' + implementation files('app/libs/vector.aar') +} \ No newline at end of file diff --git a/examples/android/gradle.properties b/examples/android/gradle.properties new file mode 100644 index 0000000..fb86a57 --- /dev/null +++ b/examples/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +android.useAndroidX=true +android.enableJetifier=true \ No newline at end of file diff --git a/examples/android/src/main/AndroidManifest.xml b/examples/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c00953e --- /dev/null +++ b/examples/android/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java new file mode 100644 index 0000000..3e2161e --- /dev/null +++ b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java @@ -0,0 +1,56 @@ +package ai.sqlite.example; + +import android.database.Cursor; +import android.os.Bundle; +import android.widget.TextView; +import androidx.appcompat.app.AppCompatActivity; +import io.requery.android.database.sqlite.SQLiteCustomExtension; +import io.requery.android.database.sqlite.SQLiteDatabase; +import io.requery.android.database.sqlite.SQLiteDatabaseConfiguration; +import java.util.Collections; + +public class MainActivity extends AppCompatActivity { + private TextView resultTextView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + resultTextView = findViewById(R.id.result_text); + setupCustomSQLiteWithExtension(); + } + + private String getLibraryPath(String libraryName) { + return getApplicationInfo().nativeLibraryDir + "/lib" + libraryName + ".so"; + } + + private void setupCustomSQLiteWithExtension() { + try { + SQLiteCustomExtension vectorExtension = new SQLiteCustomExtension(getLibraryPath("vector"), null); + SQLiteDatabaseConfiguration config = new SQLiteDatabaseConfiguration( + getCacheDir().getPath() + "/vector_test.db", + SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.OPEN_READWRITE, + Collections.emptyList(), + Collections.emptyList(), + Collections.singletonList(vectorExtension) + ); + + SQLiteDatabase db = SQLiteDatabase.openDatabase(config, null, null); + testVectorVersionWithCustomSQLite(db); + + } catch (Exception e) { + resultTextView.setText("❌ Error: " + e.getMessage()); + } + } + + private void testVectorVersionWithCustomSQLite(SQLiteDatabase db) { + Cursor cursor = db.rawQuery("SELECT vector_version()", null); + if (cursor.moveToFirst()) { + String version = cursor.getString(0); + resultTextView.setText("vector_version(): " + version); + } + cursor.close(); + db.close(); + } +} \ No newline at end of file diff --git a/examples/android/src/main/res/layout/activity_main.xml b/examples/android/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..69b249f --- /dev/null +++ b/examples/android/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/examples/android/src/main/res/values/strings.xml b/examples/android/src/main/res/values/strings.xml new file mode 100644 index 0000000..abd9bcb --- /dev/null +++ b/examples/android/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + AAR Packages Extensions Loading Demo + \ No newline at end of file From 4d6dd71831e7d7ed6cf3bc65744fcff6fa8840ee Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Wed, 1 Oct 2025 18:23:36 +0200 Subject: [PATCH 05/15] fix(android): correct library path format in MainActivity --- .../android/src/main/java/ai/sqlite/example/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java index 3e2161e..a53919d 100644 --- a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java +++ b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java @@ -22,7 +22,7 @@ protected void onCreate(Bundle savedInstanceState) { } private String getLibraryPath(String libraryName) { - return getApplicationInfo().nativeLibraryDir + "/lib" + libraryName + ".so"; + return getApplicationInfo().nativeLibraryDir + "/" + libraryName + ".so"; } private void setupCustomSQLiteWithExtension() { From 18acfc56d6af8791928f3ac8df7dc0e6a9741dd4 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Wed, 1 Oct 2025 19:09:06 +0200 Subject: [PATCH 06/15] fix(android example): update sqlite-vector dependency version --- examples/android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/android/build.gradle b/examples/android/build.gradle index 131883d..e72b1d1 100644 --- a/examples/android/build.gradle +++ b/examples/android/build.gradle @@ -48,5 +48,5 @@ dependencies { implementation 'com.google.android.material:material:1.10.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.github.requery:sqlite-android:3.49.0' - implementation files('app/libs/vector.aar') + implementation 'com.github.sqliteai:sqlite-vector:0.9.28' } \ No newline at end of file From 5d4b3b8e6214d0d2b58209719d06ae45b74ba9db Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Thu, 2 Oct 2025 11:27:47 +0200 Subject: [PATCH 07/15] fix(android): update sqlite-vector dependency version namespace and prettier library path format in MainActivity --- examples/android/build.gradle | 2 +- .../android/src/main/java/ai/sqlite/example/MainActivity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/android/build.gradle b/examples/android/build.gradle index e72b1d1..01794ea 100644 --- a/examples/android/build.gradle +++ b/examples/android/build.gradle @@ -48,5 +48,5 @@ dependencies { implementation 'com.google.android.material:material:1.10.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.github.requery:sqlite-android:3.49.0' - implementation 'com.github.sqliteai:sqlite-vector:0.9.28' + implementation 'ai.sqlite:vector:0.9.32' } \ No newline at end of file diff --git a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java index a53919d..541a1e5 100644 --- a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java +++ b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java @@ -22,7 +22,7 @@ protected void onCreate(Bundle savedInstanceState) { } private String getLibraryPath(String libraryName) { - return getApplicationInfo().nativeLibraryDir + "/" + libraryName + ".so"; + return getApplicationInfo().nativeLibraryDir + "/" + libraryName; } private void setupCustomSQLiteWithExtension() { From 8381b22ff68d889207665b112e657e8c6586b0e4 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Thu, 2 Oct 2025 15:53:01 +0200 Subject: [PATCH 08/15] feat(examples/android): refactor MainActivity to load multiple SQLite extensions --- examples/android/build.gradle | 1 + .../java/ai/sqlite/example/MainActivity.java | 33 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/examples/android/build.gradle b/examples/android/build.gradle index 01794ea..bd3d313 100644 --- a/examples/android/build.gradle +++ b/examples/android/build.gradle @@ -49,4 +49,5 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.github.requery:sqlite-android:3.49.0' implementation 'ai.sqlite:vector:0.9.32' + implementation 'ai.sqlite:js:1.1.11' } \ No newline at end of file diff --git a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java index 541a1e5..6754ea6 100644 --- a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java +++ b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java @@ -7,7 +7,9 @@ import io.requery.android.database.sqlite.SQLiteCustomExtension; import io.requery.android.database.sqlite.SQLiteDatabase; import io.requery.android.database.sqlite.SQLiteDatabaseConfiguration; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; public class MainActivity extends AppCompatActivity { private TextView resultTextView; @@ -18,39 +20,50 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); resultTextView = findViewById(R.id.result_text); - setupCustomSQLiteWithExtension(); + setupCustomSQLiteWithExtensions(); } private String getLibraryPath(String libraryName) { return getApplicationInfo().nativeLibraryDir + "/" + libraryName; } - private void setupCustomSQLiteWithExtension() { + private List loadExtensions(String... extensionNames) { + List extensions = new ArrayList<>(); + for (String extensionName : extensionNames) { + extensions.add(new SQLiteCustomExtension(getLibraryPath(extensionName), null)); + } + return extensions; + } + + private void setupCustomSQLiteWithExtensions() { try { - SQLiteCustomExtension vectorExtension = new SQLiteCustomExtension(getLibraryPath("vector"), null); + List extensions = loadExtensions("vector", "js"); + SQLiteDatabaseConfiguration config = new SQLiteDatabaseConfiguration( - getCacheDir().getPath() + "/vector_test.db", + getCacheDir().getPath() + "/ext_test.db", SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.OPEN_READWRITE, Collections.emptyList(), Collections.emptyList(), - Collections.singletonList(vectorExtension) + extensions ); SQLiteDatabase db = SQLiteDatabase.openDatabase(config, null, null); - testVectorVersionWithCustomSQLite(db); + testExtVersionWithCustomSQLite(db, "vector"); + testExtVersionWithCustomSQLite(db, "js"); + + db.close(); } catch (Exception e) { resultTextView.setText("❌ Error: " + e.getMessage()); } } - private void testVectorVersionWithCustomSQLite(SQLiteDatabase db) { - Cursor cursor = db.rawQuery("SELECT vector_version()", null); + private void testExtVersionWithCustomSQLite(SQLiteDatabase db, String extName) { + Cursor cursor = db.rawQuery("SELECT " + extName + "_version()", null); if (cursor.moveToFirst()) { String version = cursor.getString(0); - resultTextView.setText("vector_version(): " + version); + resultTextView.append("\n" + extName + "_version(): " + version); } cursor.close(); - db.close(); } } \ No newline at end of file From bb50eeb701bd9640510f08825dfca5d1f89d0528 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Thu, 2 Oct 2025 16:53:43 +0200 Subject: [PATCH 09/15] feat(examples/android): add cloudsync extension to MainActivity --- examples/android/build.gradle | 1 + .../android/src/main/java/ai/sqlite/example/MainActivity.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/android/build.gradle b/examples/android/build.gradle index bd3d313..e313cae 100644 --- a/examples/android/build.gradle +++ b/examples/android/build.gradle @@ -50,4 +50,5 @@ dependencies { implementation 'com.github.requery:sqlite-android:3.49.0' implementation 'ai.sqlite:vector:0.9.32' implementation 'ai.sqlite:js:1.1.11' + implementation 'ai.sqlite:sync:0.8.39' } \ No newline at end of file diff --git a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java index 6754ea6..675fbaf 100644 --- a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java +++ b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java @@ -37,7 +37,7 @@ private List loadExtensions(String... extensionNames) { private void setupCustomSQLiteWithExtensions() { try { - List extensions = loadExtensions("vector", "js"); + List extensions = loadExtensions("vector", "js", "cloudsync"); SQLiteDatabaseConfiguration config = new SQLiteDatabaseConfiguration( getCacheDir().getPath() + "/ext_test.db", @@ -51,6 +51,7 @@ private void setupCustomSQLiteWithExtensions() { testExtVersionWithCustomSQLite(db, "vector"); testExtVersionWithCustomSQLite(db, "js"); + testExtVersionWithCustomSQLite(db, "cloudsync"); db.close(); } catch (Exception e) { From 918ccc42108dd147d22ed427186e5cd9d4047480 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Fri, 3 Oct 2025 18:14:56 +0200 Subject: [PATCH 10/15] feat(android): update documentation and examples for SQLite AAR package extensions --- README.md | 3 +- examples/android/README.md | 143 +++++++++++++++++- examples/android/build.gradle | 7 +- .../java/ai/sqlite/example/MainActivity.java | 3 +- platforms/android.md | 105 ++++++++++++- 5 files changed, 246 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 49d76b4..f426567 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Depending on the platform, compiled extensions will have different formats: | Platform | File Extension | | -------- | -----------------------| | Linux | `.so` | -| Android | `.so` | +| Android | `.so, .aar` | | macOS | `.dylib, .xcframework` | | iOS | `.dylib, .xcframework` | | Windows | `.dll` | @@ -37,6 +37,7 @@ Depending on the platform, compiled extensions will have different formats: * **.dylib** is used for iOS/macOS, for Intel and ARM processors. Apple (macOS/iOS) also provides a mechanism to embed different processor architectures (known as “fat” or “universal” binaries) into the same library. This is **not supported** on Linux and Windows. * **.xcframework** is used for iOS/macOS to package multiple versions of the same framework (different platforms, OS versions, and architectures) into a single distributable bundle. It replaces the older “fat binary” approach and makes it easier to ship libraries that work seamlessly across devices and simulators. * **.so** is used for Linux and Android. +* **.aar** (Android Archive) is an Android-specific package format that bundles compiled code, resources, and native libraries (`.so` files) for distribution via Maven Central or JitPack. When you add an `.aar` dependency to your Android project, the native `.so` libraries are automatically extracted to the device's `nativeLibraryDir` at installation time, where they can be loaded as SQLite extensions. This is the standard way to distribute SQLite extensions for Android apps. * **.dll** is used for Windows. On **iOS**, Apple heavily restricts loading arbitrary dynamic code for security reasons. You cannot just download and load a .dylib at runtime. The only dynamic code allowed must be signed, shipped with the app, and declared properly. diff --git a/examples/android/README.md b/examples/android/README.md index 2dc996f..bcb00bd 100644 --- a/examples/android/README.md +++ b/examples/android/README.md @@ -1,13 +1,140 @@ -# SQLite AAR Extensions - Android Example +# SQLite Extensions - Android Example -Simple Android app demonstrating SQLite AI extensions loaded from AAR package. +An Android application demonstrating how to load and use multiple SQLite extensions from AAR packages. -## Setup +## What This Example Does -1. Import project in Android Studio -2. Sync project -3. Run on device/emulator (API 26+) +This app demonstrates loading SQLite AI extensions in an Android application: + +1. **[sqlite-vector](https://github.com/sqliteai/sqlite-vector)** - Vector similarity search capabilities +2. **[sqlite-js](https://github.com/sqliteai/sqlite-js)** - JavaScript execution within SQLite queries +3. **[sqlite-sync](https://github.com/sqliteai/sqlite-sync)** - Cloud synchronization for SQLite databases +4. **[sqlite-ai](https://github.com/sqliteai/sqlite-ai)** - AI/ML functionality within SQLite + +The app (`MainActivity.java:38-61`) loads these extensions dynamically, opens a SQLite database, and verifies each extension by calling its version function (e.g., `vector_version()`, `js_version()`). + +## Package Repositories + +This project uses dependencies from two package repositories: + +### Important: Requery SQLite Required + +To load SQLite extensions on Android, you **must** use the [requery/sqlite-android](https://github.com/requery/sqlite-android) library instead of the standard Android SQLite implementation. The default Android SQLite framework does not support loading custom extensions at runtime. + +Requery's `sqlite-android` provides: +- Full SQLite C API access through JNI +- Support for `sqlite3_load_extension()` to dynamically load custom extensions +- Compatible API with standard Android SQLite classes + +This library is available on JitPack (see below). + +### Maven Central +[Maven Central](https://central.sonatype.com/) is the default repository for Java/Android libraries. SQLite AI extensions are published here: + +**Gradle (Groovy):** +```gradle +dependencies { + implementation 'ai.sqlite:vector:0.9.34' + implementation 'ai.sqlite:js:1.1.12' + implementation 'ai.sqlite:sync:0.8.41' + implementation 'ai.sqlite:ai:0.7.55' +} +``` + +**Kotlin Gradle (build.gradle.kts):** +```kotlin +dependencies { + implementation("ai.sqlite:vector:0.9.34") + implementation("ai.sqlite:js:1.1.12") + implementation("ai.sqlite:sync:0.8.41") + implementation("ai.sqlite:ai:0.7.55") +} +``` + +Browse packages: [ai.sqlite on Maven Central](https://central.sonatype.com/namespace/ai.sqlite) + +### JitPack +[JitPack](https://jitpack.io/) builds Maven/Gradle packages directly from GitHub repositories. You can use JitPack for both the SQLite Android library and the SQLite AI extensions: + +**SQLite Android Library:** + +**Gradle (Groovy):** +```gradle +repositories { + maven { url 'https://jitpack.io' } +} -## What it does +dependencies { + implementation 'com.github.requery:sqlite-android:3.49.0' +} +``` -Tests `[extension]_version()` function using custom SQLite with extension support via AAR package. \ No newline at end of file +**Kotlin Gradle (build.gradle.kts):** +```kotlin +repositories { + maven { url = uri("https://jitpack.io") } +} + +dependencies { + implementation("com.github.requery:sqlite-android:3.49.0") +} +``` + +Browse package: [requery/sqlite-android on JitPack](https://jitpack.io/#requery/sqlite-android) + +**SQLite AI Extensions (Alternative to Maven Central):** + +**Gradle (Groovy):** +```gradle +repositories { + maven { url 'https://jitpack.io' } +} + +dependencies { + implementation 'com.github.sqliteai:sqlite-vector:0.9.32' + implementation 'com.github.sqliteai:sqlite-js:1.1.12' + implementation 'com.github.sqliteai:sqlite-sync:0.8.41' + implementation 'com.github.sqliteai:sqlite-ai:0.7.55' +} +``` + +**Kotlin Gradle (build.gradle.kts):** +```kotlin +repositories { + maven { url = uri("https://jitpack.io") } +} + +dependencies { + implementation("com.github.sqliteai:sqlite-vector:0.9.32") + implementation("com.github.sqliteai:sqlite-js:1.1.12") + implementation("com.github.sqliteai:sqlite-sync:0.8.41") + implementation("com.github.sqliteai:sqlite-ai:0.7.55") +} +``` + +## Critical Android Configuration + +### `android:extractNativeLibs="true"` + +This flag in `AndroidManifest.xml:6` is **required** for loading SQLite extensions: + +```xml + +``` + +**Why it's needed:** +- SQLite extensions are compiled as native `.so` (shared object) libraries +- By default, Android API 23+ uses `extractNativeLibs="false"` to save space by running libraries directly from the APK +- However, SQLite's `sqlite3_load_extension()` requires a file path to load extensions +- Setting `extractNativeLibs="true"` extracts `.so` files to the device filesystem (`nativeLibraryDir`), making them accessible via file path +- The app then loads extensions using paths like: `getApplicationInfo().nativeLibraryDir + "/vector"` (see `MainActivity.java:27`) + +Without this flag, extension loading will fail with "file not found" errors. + +## Setup + +1. Import project in Android Studio +2. Sync Gradle dependencies +3. Run on device/emulator (requires Android API 26+) \ No newline at end of file diff --git a/examples/android/build.gradle b/examples/android/build.gradle index e313cae..512683b 100644 --- a/examples/android/build.gradle +++ b/examples/android/build.gradle @@ -48,7 +48,8 @@ dependencies { implementation 'com.google.android.material:material:1.10.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.github.requery:sqlite-android:3.49.0' - implementation 'ai.sqlite:vector:0.9.32' - implementation 'ai.sqlite:js:1.1.11' - implementation 'ai.sqlite:sync:0.8.39' + implementation 'ai.sqlite:vector:0.9.34' + implementation 'ai.sqlite:js:1.1.12' + implementation 'ai.sqlite:sync:0.8.41' + implementation 'ai.sqlite:ai:0.7.55' } \ No newline at end of file diff --git a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java index 675fbaf..3bed796 100644 --- a/examples/android/src/main/java/ai/sqlite/example/MainActivity.java +++ b/examples/android/src/main/java/ai/sqlite/example/MainActivity.java @@ -37,7 +37,7 @@ private List loadExtensions(String... extensionNames) { private void setupCustomSQLiteWithExtensions() { try { - List extensions = loadExtensions("vector", "js", "cloudsync"); + List extensions = loadExtensions("vector", "js", "cloudsync", "ai"); SQLiteDatabaseConfiguration config = new SQLiteDatabaseConfiguration( getCacheDir().getPath() + "/ext_test.db", @@ -52,6 +52,7 @@ private void setupCustomSQLiteWithExtensions() { testExtVersionWithCustomSQLite(db, "vector"); testExtVersionWithCustomSQLite(db, "js"); testExtVersionWithCustomSQLite(db, "cloudsync"); + testExtVersionWithCustomSQLite(db, "ai"); db.close(); } catch (Exception e) { diff --git a/platforms/android.md b/platforms/android.md index 52b460a..202eade 100644 --- a/platforms/android.md +++ b/platforms/android.md @@ -1,8 +1,109 @@ # Android Integration -This guide shows how to integrate a SQLite extension named `cloudsync.so` into your Android application. Since extension loading is disabled by default in Android's SQLite implementation, you need an alternative SQLite library that supports extensions. +This guide shows how to integrate SQLite extensions into your Android application. Since extension loading is disabled by default in Android's SQLite implementation, you need an alternative SQLite library that supports extensions. -This example uses the [requery:sqlite-android](https://github.com/requery/sqlite-android) library, but other options include building a custom SQLite with extension support or using other third-party SQLite libraries that enable extension loading. +We recommend using the [requery:sqlite-android](https://github.com/requery/sqlite-android) library, which provides full SQLite extension support. There are two approaches to using SQLite extensions on Android: + +1. **Using AAR packages** (Recommended) - Extensions distributed via Maven Central or JitPack +2. **Manually bundling `.so` files** - For custom or pre-compiled extensions + +--- + +## Method 1: Using AAR Packages (Recommended) + +SQLite AI extensions are distributed as AAR (Android Archive) packages via Maven Central and JitPack. This is the easiest method as dependencies are automatically resolved and native libraries are extracted at installation time. + +### Available Extensions + +- **[sqlite-vector](https://github.com/sqliteai/sqlite-vector)** - Vector similarity search +- **[sqlite-js](https://github.com/sqliteai/sqlite-js)** - JavaScript execution in SQLite +- **[sqlite-sync](https://github.com/sqliteai/sqlite-sync)** - Cloud synchronization +- **[sqlite-ai](https://github.com/sqliteai/sqlite-ai)** - AI/ML functionality + +### Installation + +Add the required repositories and dependencies to your `build.gradle` or `build.gradle.kts`: + +**Gradle (Groovy):** +```groovy +repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } +} + +dependencies { + // SQLite library with extension support (required) + implementation 'com.github.requery:sqlite-android:3.49.0' + + // SQLite AI extensions (Maven Central) + implementation 'ai.sqlite:vector:0.9.34' + implementation 'ai.sqlite:js:1.1.12' + implementation 'ai.sqlite:sync:0.8.41' + implementation 'ai.sqlite:ai:0.7.55' + + // Alternative: Use JitPack instead + // implementation 'com.github.sqliteai:sqlite-vector:0.9.32' + // implementation 'com.github.sqliteai:sqlite-js:1.1.12' + // implementation 'com.github.sqliteai:sqlite-sync:0.8.41' + // implementation 'com.github.sqliteai:sqlite-ai:0.7.55' +} +``` + +**Kotlin Gradle (build.gradle.kts):** +```kotlin +repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") +} + +dependencies { + // SQLite library with extension support (required) + implementation("com.github.requery:sqlite-android:3.49.0") + + // SQLite AI extensions (Maven Central) + implementation("ai.sqlite:vector:0.9.34") + implementation("ai.sqlite:js:1.1.12") + implementation("ai.sqlite:sync:0.8.41") + implementation("ai.sqlite:ai:0.7.55") +} +``` + +### Enable Native Library Extraction + +Add `android:extractNativeLibs="true"` to your `AndroidManifest.xml`: + +```xml + + +``` + +This is **required** because SQLite's `sqlite3_load_extension()` needs a file path to load extensions. By default, Android API 23+ keeps native libraries compressed inside the APK. Setting `extractNativeLibs="true"` extracts `.so` files to the device filesystem where SQLite can access them. + +### Complete Working Example + +For a complete, working Android application demonstrating multiple SQLite extensions, see: + +**[examples/android](../examples/android/README.md)** + +This example shows how to: +- Load multiple extensions (vector, js, sync, ai) +- Configure the database with extension support +- Verify extensions are loaded correctly +- Use extension functions in SQL queries + +--- + +## Method 2: Manually Bundling Extensions + +If you have custom `.so` files or pre-compiled extensions not available as AAR packages, you can manually bundle them in your app's assets and load them at runtime. + +### Prerequisites + +This method uses the [requery:sqlite-android](https://github.com/requery/sqlite-android) library, but other options include building a custom SQLite with extension support or using other third-party SQLite libraries that enable extension loading. ### 1. Add Dependencies From d8434109f4f5621ea75940e835d0bc7c72644fcc Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Mon, 6 Oct 2025 15:00:39 +0200 Subject: [PATCH 11/15] fix(apple): update security error handling and gatekeeper notes --- platforms/ios.md | 2 +- platforms/macos.md | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/platforms/ios.md b/platforms/ios.md index 807d783..45ce639 100644 --- a/platforms/ios.md +++ b/platforms/ios.md @@ -27,7 +27,7 @@ This guide will walk you through setting up SQLite in Swift to load SQLiteAI ext ## 3. Handle Security Permissions (macOS) -When you return to the main ContentView file, you may encounter an Apple security error: +When you return to the main ContentView file, you may encounter an Apple security error. **If you do not encounter this error, skip to Step 4.** Otherwise, follow these steps: 1. Click **Done** when the security dialog appears 2. Open **System Settings** → **Privacy & Security** diff --git a/platforms/macos.md b/platforms/macos.md index ad7f6e1..2e335fd 100644 --- a/platforms/macos.md +++ b/platforms/macos.md @@ -50,9 +50,6 @@ if sqlite3_load_extension(db, extensionPath, nil, nil) != SQLITE_OK { print("Extension loaded successfully.") ``` -> ⚠️ Gatekeeper may block unsigned `.dylib` files. You might need to codesign or use `spctl --add`. - - ## Python on macOS The default Python on macOS doesn't support loading SQLite extensions. From f68c757666275f2a72023bd3fabecc32b5db350e Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Mon, 6 Oct 2025 15:05:11 +0200 Subject: [PATCH 12/15] feat(macos): add information about SQLite extensions available as Python packages on PyPI --- platforms/macos.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platforms/macos.md b/platforms/macos.md index 2e335fd..54344dd 100644 --- a/platforms/macos.md +++ b/platforms/macos.md @@ -67,5 +67,7 @@ which python3 # /opt/homebrew/bin/python3 ``` -After installing Python with Homebrew, the `python` command now uses the Homebrew version. +After installing Python with Homebrew, the `python` command now uses the Homebrew version. You can now load SQLite extensions in Python as shown in the [Python example](../examples/python/load_extension.py). + +We also offer some of our SQLite extensions as Python packages. You can find them on PyPI at https://pypi.org/user/sqlitecloud/ From f768580e457f514e5a0fa40ab9dab6d649f112d7 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Mon, 20 Oct 2025 15:45:27 +0200 Subject: [PATCH 13/15] Add new @sqliteai packages example and usage in examples/node --- examples/node/README.md | 102 ++++ examples/node/example.js | 364 +++++++++++ examples/node/load_extension.js | 14 - examples/node/package-lock.json | 1015 +++++++++++++++++++++++++++++++ examples/node/package.json | 32 + 5 files changed, 1513 insertions(+), 14 deletions(-) create mode 100644 examples/node/README.md create mode 100644 examples/node/example.js delete mode 100644 examples/node/load_extension.js create mode 100644 examples/node/package-lock.json create mode 100644 examples/node/package.json diff --git a/examples/node/README.md b/examples/node/README.md new file mode 100644 index 0000000..ac43639 --- /dev/null +++ b/examples/node/README.md @@ -0,0 +1,102 @@ +# JavaScript/Node.js Examples + +Examples for using SQLite extensions from `@sqliteai` in Node.js applications. + +## Available Extensions + +| Extension | Package | Repository | +|-----------|---------|------------| +| **vector** | [`@sqliteai/sqlite-vector`](https://www.npmjs.com/package/@sqliteai/sqlite-vector) | [github.com/sqliteai/sqlite-vector](https://github.com/sqliteai/sqlite-vector) | +| **cloudsync** | [`@sqliteai/sqlite-sync`](https://www.npmjs.com/package/@sqliteai/sqlite-sync) | [github.com/sqliteai/sqlite-sync](https://github.com/sqliteai/sqlite-sync) | +| **js** | [`@sqliteai/sqlite-js`](https://www.npmjs.com/package/@sqliteai/sqlite-js) | [github.com/sqliteai/sqlite-js](https://github.com/sqliteai/sqlite-js) | +| **ai** | [`@sqliteai/sqlite-ai`](https://www.npmjs.com/package/@sqliteai/sqlite-ai) | [github.com/sqliteai/sqlite-ai](https://github.com/sqliteai/sqlite-ai) | + +## Prerequisites + +```bash +# Install required dependencies +npm install better-sqlite3 + +# Install one or more extensions +npm install @sqliteai/sqlite-vector +npm install @sqliteai/sqlite-sync +npm install @sqliteai/sqlite-js +npm install @sqliteai/sqlite-ai +``` + +## Example + +**File:** [`example.js`](./example.js) + +Comprehensive example showing how to load and use all SQLite extensions together. + +```bash +npm start +# or +node example.js +``` + +**Features:** +- Load all four extensions (vector, sync, js, ai) +- Automatic version detection +- Example 1: Vector search with embeddings and quantization +- Example 2: Database synchronization with CloudSync +- Example 3: JavaScript user-defined functions (slugify, factorial, eval) +- Example 4: AI inference setup instructions +- Example 5: Combining extensions for powerful workflows +- Graceful handling of missing extensions + +## Quick Start + +1. **Clone or download the examples:** + ```bash + cd sqlite-extensions-guide/examples/node + ``` + +2. **Install dependencies:** + ```bash + npm install + ``` + +3. **Run the example:** + ```bash + npm start + ``` + +## Load Extension + +```javascript +const { getExtensionPath } = require('@sqliteai/sqlite-vector'); // or @sqliteai/sqlite-sync @sqliteai/sqlite-js @sqliteai/sqlite-ai +const Database = require('better-sqlite3'); + +const db = new Database(':memory:'); +db.loadExtension(getExtensionPath()); + +// Get the extension version +db.prepare("SELECT vector_version()").pluck().get(); // or cloudsync_version() js_version() ai_version() +``` + +## Platform Support + +All extensions support: +- **macOS**: ARM64 (Apple Silicon), x64 (Intel) +- **Linux**: ARM64, x64 (both glibc and musl/Alpine) +- **Windows**: x64 + +Extensions are automatically installed for your platform via `optionalDependencies`. + +## Related Documentation + +- [SQLite Vector Documentation](https://github.com/sqliteai/sqlite-vector) +- [SQLite Sync Documentation](https://github.com/sqliteai/sqlite-sync) +- [SQLite JS Documentation](https://github.com/sqliteai/sqlite-js) +- [SQLite AI Documentation](https://github.com/sqliteai/sqlite-ai) +- [better-sqlite3 Documentation](https://github.com/WiseLibs/better-sqlite3) + +## Contributing + +Found an issue or have an improvement? Please open an issue or pull request on the respective repository. + +## License + +See individual package licenses for details. diff --git a/examples/node/example.js b/examples/node/example.js new file mode 100644 index 0000000..b9fd108 --- /dev/null +++ b/examples/node/example.js @@ -0,0 +1,364 @@ +/** + * Comprehensive example for loading and using all SQLite extensions from @sqliteai + * + * This example demonstrates: + * - Loading all four extensions: vector, sync, js, and ai + * - Getting version information + * - Quick examples of each extension's capabilities + * - Combining extensions for powerful workflows + * + * Usage: + * npm install better-sqlite3 @sqliteai/sqlite-vector @sqliteai/sqlite-sync @sqliteai/sqlite-js @sqliteai/sqlite-ai + * node basic-usage.js + */ + +const Database = require('better-sqlite3'); + +/** + * Extension registry with metadata + */ +const EXTENSIONS = { + vector: { + package: '@sqliteai/sqlite-vector', + versionFunction: 'vector_version', + description: 'Vector search and similarity matching', + }, + sync: { + package: '@sqliteai/sqlite-sync', + versionFunction: 'cloudsync_version', + description: 'Database synchronization', + }, + js: { + package: '@sqliteai/sqlite-js', + versionFunction: 'js_version', + description: 'JavaScript user-defined functions', + }, + ai: { + package: '@sqliteai/sqlite-ai', + versionFunction: 'ai_version', + description: 'On-device AI inference', + }, +}; + +/** + * Load all available extensions into a database + * @param {Database} db - better-sqlite3 database instance + * @returns {Object} Loaded extensions info + */ +function loadExtensions(db) { + const loaded = {}; + + console.log('═'.repeat(60)); + console.log('Loading SQLite Extensions'); + console.log('═'.repeat(60)); + console.log(); + + for (const [name, extension] of Object.entries(EXTENSIONS)) { + try { + const { getExtensionPath } = require(extension.package); + const path = getExtensionPath(); + + db.loadExtension(path); + + // Get version + let version = null; + try { + version = db.prepare(`SELECT ${extension.versionFunction}()`).pluck().get(); + } catch (e) { + // Version function might not exist + } + + loaded[name] = { + ...extension, + path, + version, + }; + + console.log(`✓ ${name.padEnd(10)} v${version || 'unknown'}`); + console.log(` ${extension.description}`); + console.log(); + + } catch (error) { + console.log(`✗ ${name.padEnd(10)} Not installed`); + console.log(` Install with: npm install ${extension.package}`); + console.log(); + } + } + + return loaded; +} + +/** + * Example: Vector search with embeddings + */ +function exampleVector(db) { + console.log('═'.repeat(60)); + console.log('Example 1: Vector Search'); + console.log('═'.repeat(60)); + console.log(); + + // Create a table with vector embeddings + db.exec(` + CREATE TABLE IF NOT EXISTS documents ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + content TEXT, + embedding BLOB + ); + `); + + // Initialize vector search (384-dimensional Float32 embeddings) + db.prepare("SELECT vector_init('documents', 'embedding', 'type=FLOAT32,dimension=384')").run(); + console.log('✓ Vector search initialized (384 dimensions, FLOAT32)'); + + // Helper function to generate normalized random embeddings + function generateEmbedding(dimension = 384) { + const embedding = new Float32Array(dimension); + for (let i = 0; i < dimension; i++) { + embedding[i] = Math.random() * 2 - 1; + } + const magnitude = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0)); + for (let i = 0; i < dimension; i++) { + embedding[i] /= magnitude; + } + return embedding; + } + + // Insert sample documents with embeddings + const docs = [ + 'Machine learning and artificial intelligence', + 'Database systems and query optimization', + 'Web development with JavaScript', + 'Vector embeddings for semantic search', + ]; + + const insertStmt = db.prepare('INSERT INTO documents (content, embedding) VALUES (?, ?)'); + for (const doc of docs) { + const embedding = generateEmbedding(); + insertStmt.run(doc, Buffer.from(embedding.buffer)); + } + console.log(`✓ Inserted ${docs.length} documents with embeddings`); + + // Quantize vectors for fast approximate search + db.prepare("SELECT vector_quantize('documents', 'embedding')").run(); + // Optional preload quantized version in memory (for a 4x/5x speedup) + db.prepare("SELECT vector_quantize_preload('documents', 'embedding')").run(); + console.log('✓ Vectors quantized for fast search'); + console.log(); + + // Perform similarity search + const queryEmbedding = generateEmbedding(); + const results = db.prepare(` + SELECT d.content, v.distance + FROM documents AS d + JOIN vector_quantize_scan('documents', 'embedding', ?, 3) AS v + ON d.id = v.rowid + ORDER BY v.distance ASC + `).all(Buffer.from(queryEmbedding.buffer)); + + console.log('Top 3 similar documents:'); + results.forEach((row, i) => { + console.log(` ${i + 1}. ${row.content}`); + console.log(` Distance: ${row.distance.toFixed(4)}`); + }); + console.log(); +} + +/** + * Example: Database synchronization + */ +function exampleSync(db) { + console.log('═'.repeat(60)); + console.log('Example 2: Database Synchronization'); + console.log('═'.repeat(60)); + console.log(); + + // Create a table for sync + db.exec(` + CREATE TABLE IF NOT EXISTS tasks ( + id TEXT PRIMARY KEY NOT NULL, + title TEXT NOT NULL DEFAULT '', + completed INTEGER NOT NULL DEFAULT 0, + created_at INTEGER NOT NULL DEFAULT 0 + ); + `); + + // Initialize CloudSync with CLS CRDT algorithm + db.prepare("SELECT cloudsync_init('tasks', 'cls')").run(); + console.log('✓ CloudSync initialized for tasks table (CLS algorithm)'); + + // Insert some data using cloudsync_uuid() for primary keys + const insertTask = db.prepare(` + INSERT INTO tasks (id, title, completed, created_at) + VALUES (cloudsync_uuid(), ?, ?, ?) + `); + + insertTask.run('Write documentation', 1, Date.now()); + insertTask.run('Test extensions', 0, Date.now()); + insertTask.run('Deploy to production', 0, Date.now()); + console.log('✓ Inserted 3 tasks with auto-generated UUIDs'); + + // Get sync status + const isEnabled = db.prepare("SELECT cloudsync_is_enabled('tasks')").pluck().get(); + console.log(`✓ Sync enabled: ${isEnabled === 1 ? 'Yes' : 'No'}`); + + console.log(); + console.log('Note: To sync with a remote server, use:'); + console.log(' cloudsync_network_init("connection-string")'); + console.log(' cloudsync_network_sync()'); + console.log(); +} + +/** + * Example: JavaScript user-defined functions + */ +function exampleJS(db) { + console.log('═'.repeat(60)); + console.log('Example 3: JavaScript Functions'); + console.log('═'.repeat(60)); + console.log(); + + // Create a scalar function to slugify text + db.prepare(` + SELECT js_create_scalar('slugify', + '(function(args) { + return args[0].toString().toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-|-$/g, ""); + })' + ) + `).run(); + console.log('✓ Created slugify() function'); + + // Use the custom function + const slug = db.prepare("SELECT slugify('Hello World! This is a Test')").pluck().get(); + console.log(` slugify("Hello World! This is a Test") = "${slug}"`); + console.log(); + + // Create a custom function to calculate factorial + db.prepare(` + SELECT js_create_scalar('factorial', + '(function(args) { + const n = args[0]; + if (n <= 1) return 1; + let result = 1; + for (let i = 2; i <= n; i++) result *= i; + return result; + })' + ) + `).run(); + console.log('✓ Created factorial() function'); + + const fact5 = db.prepare("SELECT factorial(5)").pluck().get(); + console.log(` factorial(5) = ${fact5}`); + console.log(); + + // Evaluate JavaScript directly + const result = db.prepare("SELECT js_eval('Math.PI * 2')").pluck().get(); + console.log('✓ Direct JavaScript evaluation:'); + console.log(` js_eval("Math.PI * 2") = ${result}`); + console.log(); +} + +/** + * Example: AI inference (placeholder) + */ +function exampleAI(db) { + console.log('═'.repeat(60)); + console.log('Example 4: AI Inference'); + console.log('═'.repeat(60)); + console.log(); + + console.log('AI extension loaded successfully!'); + console.log(); + console.log('To use AI features:'); + console.log(' 1. Load a GGUF model:'); + console.log(' SELECT llm_model_load(\'models/llama-2-7b.gguf\', \'context_size=4096,n_gpu_layers=99\');'); + console.log(); + console.log(' 2. Create an inference context:'); + console.log(' SELECT llm_context_create("n_ctx=2048,n_threads=6")'); + console.log(); + console.log(' 3. Generate text:'); + console.log(' SELECT llm_text_generate(\'What is the most beautiful city in Italy?\');'); + console.log(); + console.log(' 4. Generate embeddings:'); + console.log(' SELECT llm_embed_generate(\'hello world\', \'json_output=1\');'); + console.log(); +} + +function exampleCombination(db, loaded) { + if (!loaded.vector || !loaded.js) return; + + console.log('═'.repeat(60)); + console.log('Example 5: Combining Extensions'); + console.log('═'.repeat(60)); + console.log(); + + console.log('✓ Vector + Sync: Synchronized vector databases'); + console.log('✓ Vector + AI: Generate embeddings with AI models'); + console.log('✓ All combined: AI-powered semantic search with sync'); + console.log(); +} + +function main() { + // Create in-memory database + const db = new Database(':memory:'); + + console.log(); + console.log('SQLite Extensions - Comprehensive Example'); + console.log(); + + // Load all available extensions + const loaded = loadExtensions(db); + + const loadedCount = Object.keys(loaded).length; + if (loadedCount === 0) { + console.log('No extensions loaded. Install at least one extension to continue.'); + console.log('Run: npm install'); + db.close(); + return; + } + + console.log(`Loaded ${loadedCount} extension(s)\n`); + + // Run examples for each loaded extension + if (loaded.vector) { + exampleVector(db); + } + + if (loaded.sync) { + exampleSync(db); + } + + if (loaded.js) { + exampleJS(db); + } + + if (loaded.ai) { + exampleAI(db); + } + + // Show combination possibilities + if (loadedCount > 1) { + exampleCombination(db, loaded); + } + + // Cleanup + db.close(); + console.log('═'.repeat(60)); + console.log('Database closed.'); + console.log('═'.repeat(60)); +} + +// Run the example +if (require.main === module) { + try { + main(); + } catch (error) { + console.error('Error:', error.message); + console.error(error.stack); + process.exit(1); + } +} + +// Export for use in other modules +module.exports = { loadExtensions, EXTENSIONS }; diff --git a/examples/node/load_extension.js b/examples/node/load_extension.js deleted file mode 100644 index cbdf8a7..0000000 --- a/examples/node/load_extension.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * This example uses the package `better-sqlite3`. - * Run: `npm install better-sqlite3` - */ - -const Database = require("better-sqlite3"); -const db = new Database(":memory:"); - -// Path to your compiled extension (.dylib for macOS/iOS, .so for linux/Android, .dll for Windows) -// Using `https://github.com/sqliteai/sqlite-js` extension as an example -db.loadExtension("./js"); - -const result = db.prepare("SELECT js_version();").get(); -console.log(result); diff --git a/examples/node/package-lock.json b/examples/node/package-lock.json new file mode 100644 index 0000000..67756e2 --- /dev/null +++ b/examples/node/package-lock.json @@ -0,0 +1,1015 @@ +{ + "name": "sqliteai-extensions-examples", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sqliteai-extensions-examples", + "version": "1.0.0", + "dependencies": { + "better-sqlite3": "^12.4.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "@sqliteai/sqlite-ai": "*", + "@sqliteai/sqlite-js": "*", + "@sqliteai/sqlite-sync": "*", + "@sqliteai/sqlite-vector": "*" + } + }, + "node_modules/@sqliteai/sqlite-ai": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai/-/sqlite-ai-0.7.57.tgz", + "integrity": "sha512-FZ25aNonbGyRTnPADE1S2Rn92jftjZhDRDEIPm8jdIMKFUVLAj6FTDlxtMT16cbfUJJhtFck1g04TMVs07zmLw==", + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "@sqliteai/sqlite-ai-darwin-arm64": "0.7.57", + "@sqliteai/sqlite-ai-darwin-x86_64": "0.7.57", + "@sqliteai/sqlite-ai-linux-arm64": "0.7.57", + "@sqliteai/sqlite-ai-linux-arm64-musl": "0.7.57", + "@sqliteai/sqlite-ai-linux-x86_64": "0.7.57", + "@sqliteai/sqlite-ai-linux-x86_64-musl": "0.7.57", + "@sqliteai/sqlite-ai-win32-x86_64": "0.7.57" + } + }, + "node_modules/@sqliteai/sqlite-ai-darwin-arm64": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai-darwin-arm64/-/sqlite-ai-darwin-arm64-0.7.57.tgz", + "integrity": "sha512-Tbe0hLfqxhEEe3bMjGt/NlZT4R4tJ3T9CeQ/bt9+Pk0/z3kymBMQmEQxYvVaRKfR0MrX/mLlbg1Jrphx/GVdDg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-ai-darwin-x86_64": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai-darwin-x86_64/-/sqlite-ai-darwin-x86_64-0.7.57.tgz", + "integrity": "sha512-/rcZoo4fD2kBxKm5qfTSHrmCWGMvAjByCokKPvEKus3zB4w5fN1Ror7qWpvVj3qHhvJdH0r5g0ut4faPAJO+tA==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-ai-linux-arm64": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai-linux-arm64/-/sqlite-ai-linux-arm64-0.7.57.tgz", + "integrity": "sha512-pXXfeMWaMHeJZIOQrFgrV+nUcMP5fmUyZFEjMYWdPoqQI6fu+BYHsVE0FmUSaox4UeldQhIuNpr3M3OxNXGTig==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-ai-linux-arm64-musl": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai-linux-arm64-musl/-/sqlite-ai-linux-arm64-musl-0.7.57.tgz", + "integrity": "sha512-mLXTgEhOM2EkeEc303VNCGLPznwVAxPXafGR080QPeVQUSVLZ4xQ2R47HQSO3avvCGoG9/p4XC1GlGE4oNti5A==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-ai-linux-x86_64": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai-linux-x86_64/-/sqlite-ai-linux-x86_64-0.7.57.tgz", + "integrity": "sha512-lnlSokJxl8OkJTXqXrZjyMHdrl+ACLb+AbyUpP7X9mPR7B4baNY59ZMVZ5s0R5mUc3m5mSe9NNx1tkQpYIAgWQ==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-ai-linux-x86_64-musl": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai-linux-x86_64-musl/-/sqlite-ai-linux-x86_64-musl-0.7.57.tgz", + "integrity": "sha512-ShaGehHIJxPhHLByI6fTMeqdW8wU3DQj/dObhLVla59gTN+RnVaVVXMeEymwyylMlsMYf8ikhKkqNQ0L1WJOrA==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-ai-win32-x86_64": { + "version": "0.7.57", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-ai-win32-x86_64/-/sqlite-ai-win32-x86_64-0.7.57.tgz", + "integrity": "sha512-MT40NsiP3rpeCUB9z7nkp/n0u7CE3NGTBJ2k87SfNPpngzn1yPKCgNgeNx6BpOKkjvUcZ8CXnnkKOEBVQo6Htg==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-js": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js/-/sqlite-js-1.1.15.tgz", + "integrity": "sha512-mtcZVN44qr3laW8Us3bkCfoB/XAS/DUYuv0oSDuz29B/jkmvSquNBizLFuoYrEubYzcFVrF9K+L/IIuMj5Qkkg==", + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "@sqliteai/sqlite-js-darwin-arm64": "1.1.15", + "@sqliteai/sqlite-js-darwin-x86_64": "1.1.15", + "@sqliteai/sqlite-js-linux-arm64": "1.1.15", + "@sqliteai/sqlite-js-linux-arm64-musl": "1.1.15", + "@sqliteai/sqlite-js-linux-x86_64": "1.1.15", + "@sqliteai/sqlite-js-linux-x86_64-musl": "1.1.15", + "@sqliteai/sqlite-js-win32-x86_64": "1.1.15" + } + }, + "node_modules/@sqliteai/sqlite-js-darwin-arm64": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js-darwin-arm64/-/sqlite-js-darwin-arm64-1.1.15.tgz", + "integrity": "sha512-Q+3FDmMfBjZah/8tb9OfmoMbFbyeEwJS7p0eDR11fuzIuaQ7vzkYpuw71oh5TLzlMxqW/aOFPa3aR7yDMjtFog==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-js-darwin-x86_64": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js-darwin-x86_64/-/sqlite-js-darwin-x86_64-1.1.15.tgz", + "integrity": "sha512-rh2tYnljkXPheGnMDnp2EhbCmKnouEtwA0aimOIgeIFY0B/umydVIM8oR/Tadwq4CjGEahHLkq7NmpoM+uz8nw==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-js-linux-arm64": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js-linux-arm64/-/sqlite-js-linux-arm64-1.1.15.tgz", + "integrity": "sha512-6J/Dv7tzk8IAaJMTVqFOQrrMAf9uJkYmxgZiSX6VGVmrKtX+T7Dk1TP/McMlD990dEeLlRrpqR6zBQmC7kCbdw==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-js-linux-arm64-musl": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js-linux-arm64-musl/-/sqlite-js-linux-arm64-musl-1.1.15.tgz", + "integrity": "sha512-AX5Bz3tV4J/nJiSXlCADDp8zUiJ4FfItQjarxrXo/WTVfwInt8Qj2MIxB7lMQgrTDFOX6wEdR3FNbXBhQ8TLgg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-js-linux-x86_64": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js-linux-x86_64/-/sqlite-js-linux-x86_64-1.1.15.tgz", + "integrity": "sha512-98KMbEjs2qfxh0hjirHvaOCloeLVyrsSOPJYjti5txtePaVY9x2qrTw3Jssndam8H4vN/YiabTbAU9dwLaDDzw==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-js-linux-x86_64-musl": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js-linux-x86_64-musl/-/sqlite-js-linux-x86_64-musl-1.1.15.tgz", + "integrity": "sha512-acVovzn+4kNqwxkW0dhQTwHMeOOeV8MVOxhzQX3HTIXt+1MyerXWglJNfefQe6gMJd0K/yGR8anhu20oES+PyQ==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-js-win32-x86_64": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-js-win32-x86_64/-/sqlite-js-win32-x86_64-1.1.15.tgz", + "integrity": "sha512-CHirT/mDkoCtLTELy5dhYUX7gR3yfD6xo1MmTNKH2M1lMIU/v3z8x6btuX29+xzgFVWP2Qg+421H63rHgEVqhA==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-sync": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync/-/sqlite-sync-0.8.55.tgz", + "integrity": "sha512-2z5s4JxuC5hF5GYYPK/BC0pkqj3rQXZboZFkNAHVllVDKECBNdqjbjcxaQTV8536dQiiz1GEQti1LhrbTi8QNA==", + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "@sqliteai/sqlite-sync-darwin-arm64": "0.8.55", + "@sqliteai/sqlite-sync-darwin-x86_64": "0.8.55", + "@sqliteai/sqlite-sync-linux-arm64": "0.8.55", + "@sqliteai/sqlite-sync-linux-arm64-musl": "0.8.55", + "@sqliteai/sqlite-sync-linux-x86_64": "0.8.55", + "@sqliteai/sqlite-sync-linux-x86_64-musl": "0.8.55", + "@sqliteai/sqlite-sync-win32-x86_64": "0.8.55" + } + }, + "node_modules/@sqliteai/sqlite-sync-darwin-arm64": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync-darwin-arm64/-/sqlite-sync-darwin-arm64-0.8.55.tgz", + "integrity": "sha512-kla/kf0CzzQLHMScM9qt0Ylb0U+glxlX1rgvQSImw4URPm9XC/q+GU+mB59QXId0YqSTEgzbw2mBJ/ZfsaTlSw==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-sync-darwin-x86_64": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync-darwin-x86_64/-/sqlite-sync-darwin-x86_64-0.8.55.tgz", + "integrity": "sha512-rj7OqL4UuKpHa0JGTOODpiNMoV71uE7jGrLxWCAsq5KumKOLvadZkpiIuqbVzA3yF4tGLtJ7ooH5cmZm8zBrtA==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-sync-linux-arm64": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync-linux-arm64/-/sqlite-sync-linux-arm64-0.8.55.tgz", + "integrity": "sha512-g4npitpI9ZrpodY+VpS079qQxcTxP7gwY/0hHT3O3WHEkI3etDgle4xvCH5pecCX4u891SwbrkxQ+n9D9Y3W+Q==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-sync-linux-arm64-musl": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync-linux-arm64-musl/-/sqlite-sync-linux-arm64-musl-0.8.55.tgz", + "integrity": "sha512-jTNHTB5RuhwF6EcPceU+uHujUqArLqT/8XP8jTRr98kEDV5QWDx/y4Rl4IqQC7tLlvp8yz0VLuGmH8Ppuj89AA==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-sync-linux-x86_64": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync-linux-x86_64/-/sqlite-sync-linux-x86_64-0.8.55.tgz", + "integrity": "sha512-s9P8CcFiB+I6/Z3MeFSc08YSia7i28kUhmArxBcR18AKew/sNOvDgpBfwCdtRuSsimoc8HZpVjXEIcnGcFQ+PQ==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-sync-linux-x86_64-musl": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync-linux-x86_64-musl/-/sqlite-sync-linux-x86_64-musl-0.8.55.tgz", + "integrity": "sha512-rHJzV/1c5FXEhxUkIC9x46ahea1cXy0Tu4F3q3OavowXVj6m0YEoacDfd+3gIM+Afmwh86GYypeD7ubIqzV1aw==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-sync-win32-x86_64": { + "version": "0.8.55", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-sync-win32-x86_64/-/sqlite-sync-win32-x86_64-0.8.55.tgz", + "integrity": "sha512-kBWnpHz7kJ9flxD5619cpZo7xZF2ffns/v2BOEYc5EsxdZLa1mbt2119qGFip3tjCWnOXfC9/yQrVazyWMnrTw==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-vector": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector/-/sqlite-vector-0.9.51.tgz", + "integrity": "sha512-rEfQAXI+EJ/Aj5Ph99BHwEMTJCplxZiXCUBgOl1V2GF7wqIshp5SQ/amFA2igb313beodXAZPR7CMMAfF6BYow==", + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "@sqliteai/sqlite-vector-darwin-arm64": "0.9.51", + "@sqliteai/sqlite-vector-darwin-x86_64": "0.9.51", + "@sqliteai/sqlite-vector-linux-arm64": "0.9.51", + "@sqliteai/sqlite-vector-linux-arm64-musl": "0.9.51", + "@sqliteai/sqlite-vector-linux-x86_64": "0.9.51", + "@sqliteai/sqlite-vector-linux-x86_64-musl": "0.9.51", + "@sqliteai/sqlite-vector-win32-x86_64": "0.9.51" + } + }, + "node_modules/@sqliteai/sqlite-vector-darwin-arm64": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector-darwin-arm64/-/sqlite-vector-darwin-arm64-0.9.51.tgz", + "integrity": "sha512-nhJLTzaMZZ/AXecFCBZ2Bga9X4e0QnlrCCVSuwtsJq8NhKFLB3W9TSBaxxkrJne3ODyqMtAPZ6xl2s6YvAAx9A==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-vector-darwin-x86_64": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector-darwin-x86_64/-/sqlite-vector-darwin-x86_64-0.9.51.tgz", + "integrity": "sha512-qCuzB+2w90pYVG3cxEuQ1aN7krfjXAQN/f/oCTYxblcTIzsrX8U4xSV6/4Vu+Fo0ryh/hFT2dKWcQ5LyLAQKuQ==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-vector-linux-arm64": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector-linux-arm64/-/sqlite-vector-linux-arm64-0.9.51.tgz", + "integrity": "sha512-rbt0res35pnP+7HnvWsG4MW5eziCruKriY4H9aWWjvtWNe3F/7wT869cLApVRCvQVAvZk5PHPHbETs+GIxjmDg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-vector-linux-arm64-musl": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector-linux-arm64-musl/-/sqlite-vector-linux-arm64-musl-0.9.51.tgz", + "integrity": "sha512-BIil0SxhpKIMlOGwMm36PIL2/2inhDvHeFwG6an3IJDCHfYSbOFTnFFb16ed+bVnWwRR3D2kcZH7LRBGYWWyjQ==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-vector-linux-x86_64": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector-linux-x86_64/-/sqlite-vector-linux-x86_64-0.9.51.tgz", + "integrity": "sha512-gLrVGnTF7KdccbIFXVFHT9yvAaQFVKEdKycSOvdgNRBBpEtEWObCk81YEWOcouTb8j+2cD0Xwvs536nP0TjFyg==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-vector-linux-x86_64-musl": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector-linux-x86_64-musl/-/sqlite-vector-linux-x86_64-musl-0.9.51.tgz", + "integrity": "sha512-nWAn1ens328NrSGUW7W5rcYaZzU/YJ7LNGuschm9vFBiVal8X4I4aa/LpS4rTMno6hSALNVnggfNQXWDX+xVUw==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sqliteai/sqlite-vector-win32-x86_64": { + "version": "0.9.51", + "resolved": "https://registry.npmjs.org/@sqliteai/sqlite-vector-win32-x86_64/-/sqlite-vector-win32-x86_64-0.9.51.tgz", + "integrity": "sha512-ckaxpm+xMFghreXSKFlcKFKIB83oQniaPpFMCDTwRXuCK60xOLR5Z/0xR5D7IyF/WlciLu3ISIRxl9bhd67AaQ==", + "cpu": [ + "x64", + "ia32" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/better-sqlite3": { + "version": "12.4.1", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.4.1.tgz", + "integrity": "sha512-3yVdyZhklTiNrtg+4WqHpJpFDd+WHTg2oM7UcR80GqL05AOV0xEJzc6qNvFYoEtE+hRp1n9MpN6/+4yhlGkDXQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.78.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz", + "integrity": "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + } + } +} diff --git a/examples/node/package.json b/examples/node/package.json new file mode 100644 index 0000000..a8264de --- /dev/null +++ b/examples/node/package.json @@ -0,0 +1,32 @@ +{ + "name": "sqliteai-extensions-examples", + "version": "1.0.0", + "description": "Examples for using SQLite extensions from @sqliteai in Node.js", + "private": true, + "type": "commonjs", + "scripts": { + "start": "node example.js", + "example": "node example.js" + }, + "keywords": [ + "sqlite", + "extensions", + "vector", + "ai", + "sync", + "javascript" + ], + "author": "Gioele Cantoni (gioele@sqlitecloud.io)", + "dependencies": { + "better-sqlite3": "^12.4.1" + }, + "optionalDependencies": { + "@sqliteai/sqlite-ai": "*", + "@sqliteai/sqlite-js": "*", + "@sqliteai/sqlite-sync": "*", + "@sqliteai/sqlite-vector": "*" + }, + "engines": { + "node": ">=16.0.0" + } +} From 50f3ce142d4d7e477c5b79158e5830bdf4fae2f0 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Wed, 11 Feb 2026 19:03:29 +0100 Subject: [PATCH 14/15] Add Flutter/Dart multi-platform package example --- .gitignore | 8 +- README.md | 1 + examples/flutter/.gitignore | 57 ++++++++++++ examples/flutter/README.md | 91 ++++++++++++++++++ examples/flutter/lib/main.dart | 153 +++++++++++++++++++++++++++++++ examples/flutter/pubspec.yaml | 29 ++++++ platforms/flutter.md | 163 +++++++++++++++++++++++++++++++++ 7 files changed, 501 insertions(+), 1 deletion(-) create mode 100644 examples/flutter/.gitignore create mode 100644 examples/flutter/README.md create mode 100644 examples/flutter/lib/main.dart create mode 100644 examples/flutter/pubspec.yaml create mode 100644 platforms/flutter.md diff --git a/.gitignore b/.gitignore index 2d9e570..d97d364 100644 --- a/.gitignore +++ b/.gitignore @@ -107,4 +107,10 @@ jniLibs/ # IDE .vscode .idea/ -*.iml \ No newline at end of file +*.iml + +# Dart/Flutter +.dart_tool/ +pubspec.lock +.flutter-plugins +.flutter-plugins-dependencies \ No newline at end of file diff --git a/README.md b/README.md index f426567..3a3609d 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Refer to the platform-specific **loading instructions** below: * [Loading extension on Windows](platforms/windows.md) * [Loading extension on iOS](platforms/ios.md) * [Loading extension on Android](platforms/android.md) +* [Loading extension in Flutter/Dart](platforms/flutter.md) * [Loading extension on Web/WASM](https://github.com/sqliteai/sqlite-extensions-guide/tree/main/examples/browser-wasm) * [Loading extension on Expo/React Native](platforms/react-native-expo.md) diff --git a/examples/flutter/.gitignore b/examples/flutter/.gitignore new file mode 100644 index 0000000..7f31fcb --- /dev/null +++ b/examples/flutter/.gitignore @@ -0,0 +1,57 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# Platform scaffolding (generated by `flutter create .`) +/android/ +/ios/ +/linux/ +/macos/ +/web/ +/windows/ +/test/ +.metadata +analysis_options.yaml +.flutter-plugins + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/examples/flutter/README.md b/examples/flutter/README.md new file mode 100644 index 0000000..4f91d7f --- /dev/null +++ b/examples/flutter/README.md @@ -0,0 +1,91 @@ +# Flutter SQLiteAI Extensions Example + +A Flutter app demonstrating how to use multiple SQLiteAI extensions together. + +## Requirements + +- Dart 3.10+ / Flutter 3.38+ + +## Running + +### As a Flutter app (with UI) + +```bash +# Generate platform scaffolding (only needed once) +flutter create . --project-name sqliteai_flutter_example + +# Install dependencies and run +flutter pub get +flutter run +``` + +### As a Dart CLI (no UI) + +```bash +dart pub get +dart run lib/main.dart +``` + +## Available Extensions + +| Package | Description | +|---------|-------------| +| `sqlite_vector` | Vector similarity search with SIMD-optimized distance functions | +| `sqlite_js` | Execute JavaScript directly in SQLite using QuickJS | +| `sqlite_sync` | Real-time sync with SQLite Cloud | +| `sqlite_ai` | On-device LLM inference with llama.cpp | +| `sqlite_agent` | Connect to MCP servers for AI agent capabilities | +| `sqlite_mcp` | Expose databases as MCP resources | + +## What it does + +1. Loads all 6 SQLite extensions at startup +2. **sqlite-vector**: Vector similarity search with nearest neighbors +3. **sqlite-js**: JavaScript evaluation with `js_eval()` +4. **sqlite-sync**: UUID generation with `cloudsync_uuid()` +5. **sqlite-ai**: Version check (requires GGUF model for full features) +6. **sqlite-mcp**: Version check (requires MCP server for full features) +7. **sqlite-agent**: Version check (requires sqlite-ai + sqlite-mcp setup) + +## Expected output + +``` +=== sqlite-vector === +Version: 0.9.85 +Nearest neighbors: + id=1, distance=0.0 + id=3, distance=0.1999998688697815 + +=== sqlite-js === +Version: 1.2.3 +js_eval("1 + 2 + 3") = 6 + +=== sqlite-sync === +Version: 0.8.64 +cloudsync_uuid() examples: + 01956a8b-1234-7abc-8def-0123456789ab + 01956a8b-1235-7abc-8def-0123456789ab +(Cloud sync requires cloudsync_init() and network config) + +=== sqlite-ai === +Version: 0.7.59 +(Requires GGUF model for inference - see API.md) + +=== sqlite-mcp === +Version: 0.1.5 +(Requires MCP server connection - see API.md) + +=== sqlite-agent === +Version: 0.1.6 +(Requires sqlite-ai + sqlite-mcp setup - see API.md) +``` + +## Learn more + +- [Flutter Integration Guide](../../platforms/flutter.md) +- [sqlite_vector on pub.dev](https://pub.dev/packages/sqlite_vector) +- [sqlite_js on pub.dev](https://pub.dev/packages/sqlite_js) +- [sqlite_sync on pub.dev](https://pub.dev/packages/sqlite_sync) +- [sqlite_ai on pub.dev](https://pub.dev/packages/sqlite_ai) +- [sqlite_agent on pub.dev](https://pub.dev/packages/sqlite_agent) +- [sqlite_mcp on pub.dev](https://pub.dev/packages/sqlite_mcp) diff --git a/examples/flutter/lib/main.dart b/examples/flutter/lib/main.dart new file mode 100644 index 0000000..4728f69 --- /dev/null +++ b/examples/flutter/lib/main.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:sqlite3/sqlite3.dart'; +import 'package:sqlite_vector/sqlite_vector.dart'; +import 'package:sqlite_js/sqlite_js.dart'; +import 'package:sqlite_sync/sqlite_sync.dart'; +import 'package:sqlite_ai/sqlite_ai.dart'; +import 'package:sqlite_agent/sqlite_agent.dart'; +import 'package:sqlite_mcp/sqlite_mcp.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'SQLiteAI Extensions Demo', + theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)), + home: const ExtensionsTestPage(), + ); + } +} + +class ExtensionsTestPage extends StatefulWidget { + const ExtensionsTestPage({super.key}); + + @override + State createState() => _ExtensionsTestPageState(); +} + +class _ExtensionsTestPageState extends State { + String _result = 'Running tests...'; + + @override + void initState() { + super.initState(); + _runTests(); + } + + void _runTests() { + try { + // Load all extensions at startup + sqlite3.loadSqliteVectorExtension(); + sqlite3.loadSqliteJsExtension(); + sqlite3.loadSqliteSyncExtension(); + sqlite3.loadSqliteAiExtension(); + sqlite3.loadSqliteAgentExtension(); + sqlite3.loadSqliteMcpExtension(); + + final db = sqlite3.openInMemory(); + final buf = StringBuffer(); + + // Test sqlite-vector + buf.writeln('=== sqlite-vector ==='); + final vectorVersion = db.select('SELECT vector_version()').first.values.first; + buf.writeln('Version: $vectorVersion'); + + db.execute('CREATE TABLE items (id INTEGER PRIMARY KEY, embedding BLOB)'); + final stmt = db.prepare('INSERT INTO items (embedding) VALUES (vector_as_f32(?))'); + stmt.execute(['[1.0, 2.0, 3.0, 4.0]']); + stmt.execute(['[5.0, 6.0, 7.0, 8.0]']); + stmt.execute(['[1.1, 2.1, 3.1, 4.1]']); + stmt.dispose(); + + db.execute("SELECT vector_init('items', 'embedding', 'type=FLOAT32,dimension=4')"); + final results = db.select(''' + SELECT e.id, v.distance FROM items AS e + JOIN vector_full_scan('items', 'embedding', vector_as_f32('[1.0, 2.0, 3.0, 4.0]'), 2) AS v + ON e.id = v.rowid + '''); + buf.writeln('Nearest neighbors:'); + for (final row in results) { + buf.writeln(' id=${row['id']}, distance=${row['distance']}'); + } + buf.writeln(); + + // Test sqlite-js + buf.writeln('=== sqlite-js ==='); + final jsVersion = db.select('SELECT js_version()').first.values.first; + buf.writeln('Version: $jsVersion'); + final jsResult = db.select("SELECT js_eval('1 + 2 + 3')").first.values.first; + buf.writeln('js_eval("1 + 2 + 3") = $jsResult'); + buf.writeln(); + + // Test sqlite-sync + buf.writeln('=== sqlite-sync ==='); + final syncVersion = db.select('SELECT cloudsync_version()').first.values.first; + buf.writeln('Version: $syncVersion'); + + // Generate UUIDs (UUIDv7) - works without initialization + final uuid1 = db.select('SELECT cloudsync_uuid()').first.values.first; + final uuid2 = db.select('SELECT cloudsync_uuid()').first.values.first; + buf.writeln('cloudsync_uuid() examples:'); + buf.writeln(' $uuid1'); + buf.writeln(' $uuid2'); + buf.writeln('(Cloud sync requires cloudsync_init() and network config)'); + buf.writeln(); + + // Test sqlite-ai + buf.writeln('=== sqlite-ai ==='); + final aiVersion = db.select('SELECT ai_version()').first.values.first; + buf.writeln('Version: $aiVersion'); + buf.writeln('(Requires GGUF model for inference - see API.md)'); + buf.writeln(); + + // Test sqlite-mcp + buf.writeln('=== sqlite-mcp ==='); + final mcpVersion = db.select('SELECT mcp_version()').first.values.first; + buf.writeln('Version: $mcpVersion'); + buf.writeln('(Requires MCP server connection - see API.md)'); + buf.writeln(); + + // Test sqlite-agent + buf.writeln('=== sqlite-agent ==='); + final agentVersion = db.select('SELECT agent_version()').first.values.first; + buf.writeln('Version: $agentVersion'); + buf.writeln('(Requires sqlite-ai + sqlite-mcp setup - see API.md)'); + + db.dispose(); + + final resultStr = buf.toString(); + debugPrint(resultStr); + setState(() => _result = resultStr); + } catch (e) { + debugPrint('Error: $e'); + setState(() => _result = 'Error: $e'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: const Text('SQLiteAI Extensions'), + ), + body: Center( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24), + child: Text(_result, style: const TextStyle(fontSize: 14, fontFamily: 'monospace')), + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _runTests, + tooltip: 'Run tests', + child: const Icon(Icons.play_arrow), + ), + ); + } +} diff --git a/examples/flutter/pubspec.yaml b/examples/flutter/pubspec.yaml new file mode 100644 index 0000000..6c8176c --- /dev/null +++ b/examples/flutter/pubspec.yaml @@ -0,0 +1,29 @@ +name: sqliteai_flutter_example +description: Example Flutter app demonstrating SQLiteAI extensions with sqlite3. +publish_to: none + +version: 1.0.0+1 + +environment: + sdk: ^3.10.0 + +dependencies: + flutter: + sdk: flutter + sqlite3: ^3.0.0 + # SQLiteAI Extensions + sqlite_vector: ^0.9.85 + sqlite_js: ^1.2.3 + sqlite_sync: ^0.8.64 + sqlite_ai: ^0.7.59 + sqlite_agent: ^0.1.6 + sqlite_mcp: ^0.1.5 + cupertino_icons: ^1.0.8 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + +flutter: + uses-material-design: true diff --git a/platforms/flutter.md b/platforms/flutter.md new file mode 100644 index 0000000..688067a --- /dev/null +++ b/platforms/flutter.md @@ -0,0 +1,163 @@ +# Flutter / Dart Integration + +This guide shows how to use SQLite extensions in Flutter and Dart applications using the `sqlite_vector` package. + +**Requirements:** Dart 3.10+ / Flutter 3.38+ + +--- + +## Installation + +```bash +flutter pub add sqlite_vector +``` + +Or add to `pubspec.yaml`: + +```yaml +dependencies: + sqlite3: ^3.0.0 + sqlite_vector: ^0.9.70 +``` + +The package uses Dart build hooks to automatically bundle the correct native library for each platform. No additional configuration is needed. + +--- + +## Supported Platforms + +| Platform | Architectures | +|----------|---------------| +| Android | arm64, arm, x64 | +| iOS | arm64 (device + simulator) | +| macOS | arm64, x64 | +| Linux | arm64, x64 | +| Windows | x64 | + +--- + +## Usage + +### With `sqlite3` + +```dart +import 'package:sqlite3/sqlite3.dart'; +import 'package:sqlite_vector/sqlite_vector.dart'; + +void main() { + // Load extension once at app startup + sqlite3.loadSqliteVectorExtension(); + + final db = sqlite3.openInMemory(); + + // Create a regular table with a BLOB column for vectors + db.execute('CREATE TABLE items (id INTEGER PRIMARY KEY, embedding BLOB)'); + + // Insert vectors + final stmt = db.prepare('INSERT INTO items (embedding) VALUES (vector_as_f32(?))'); + stmt.execute(['[1.0, 2.0, 3.0, 4.0]']); + stmt.execute(['[5.0, 6.0, 7.0, 8.0]']); + stmt.dispose(); + + // Initialize the vector index + db.execute("SELECT vector_init('items', 'embedding', 'type=FLOAT32,dimension=4')"); + + // Find nearest neighbors + final results = db.select(''' + SELECT e.id, v.distance FROM items AS e + JOIN vector_full_scan('items', 'embedding', vector_as_f32('[1.0, 2.0, 3.0, 4.0]'), 2) AS v + ON e.id = v.rowid + '''); + + for (final row in results) { + print('id=${row['id']}, distance=${row['distance']}'); + } + + db.dispose(); +} +``` + +### With `drift` + +[drift](https://pub.dev/packages/drift) is a popular ORM built on top of `sqlite3`. The extension integrates seamlessly: + +```dart +import 'dart:io'; +import 'package:sqlite3/sqlite3.dart'; +import 'package:sqlite_vector/sqlite_vector.dart'; +import 'package:drift/native.dart'; + +Sqlite3 loadExtensions() { + sqlite3.loadSqliteVectorExtension(); + return sqlite3; +} + +// Use when creating your database connection +LazyDatabase openConnection() { + return LazyDatabase(() async { + final file = File('path/to/db.sqlite'); + return NativeDatabase.createInBackground( + file, + sqlite3: loadExtensions, + ); + }); +} +``` + +--- + +## How It Works + +The `sqlite_vector` package uses Dart's native assets system (build hooks) introduced in Dart 3.10 / Flutter 3.38. This is the same mechanism used by the `sqlite3` package itself. + +Key points: + +- **No Gradle, CocoaPods, or CMake configuration needed** — the build hook handles everything +- **Pre-built binaries** are bundled in the package and selected at build time based on target platform/architecture +- The `@Native` FFI annotation resolves `sqlite3_vector_init` from the bundled native library +- `loadSqliteVectorExtension()` calls `ensureExtensionLoaded()` which registers the extension with SQLite + +--- + +## API Reference + +See the full [sqlite-vector API documentation](https://github.com/sqliteai/sqlite-vector/blob/main/API.md) for all available functions: + +- `vector_version()` — Returns the extension version +- `vector_init()` — Initialize a vector column +- `vector_as_f32()`, `vector_as_f16()`, `vector_as_i8()`, etc. — Convert JSON arrays to vector BLOBs +- `vector_full_scan()` — Find nearest neighbors +- `vector_quantize()` — Quantize vectors for faster search + +--- + +## Example Project + +A complete Flutter example app is available at: +[examples/flutter](../examples/flutter) + +```bash +cd examples/flutter +flutter pub get +flutter run +``` + +--- + +## Troubleshooting + +### "Pre-built binary not found" + +This error occurs when running on a platform/architecture that doesn't have a bundled binary. The package supports the platforms listed above. + +### Extension loads but virtual table functions don't work + +Make sure you're using regular tables with BLOB columns, not virtual tables. sqlite-vector doesn't use virtual tables for storage — see the [main documentation](https://github.com/sqliteai/sqlite-vector) for the correct usage pattern. + +### "Dart SDK version too old" + +Build hooks require Dart 3.10+ / Flutter 3.38+. Update your SDK: + +```bash +flutter upgrade +``` From 454a73d26d87644d6f18af1c0ffc268b2a2d7b33 Mon Sep 17 00:00:00 2001 From: Gioele Cantoni Date: Wed, 11 Feb 2026 19:13:32 +0100 Subject: [PATCH 15/15] Update flutter.md --- platforms/flutter.md | 211 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 169 insertions(+), 42 deletions(-) diff --git a/platforms/flutter.md b/platforms/flutter.md index 688067a..c79296c 100644 --- a/platforms/flutter.md +++ b/platforms/flutter.md @@ -1,15 +1,44 @@ # Flutter / Dart Integration -This guide shows how to use SQLite extensions in Flutter and Dart applications using the `sqlite_vector` package. +This guide shows how to use SQLiteAI extensions in Flutter and Dart applications. **Requirements:** Dart 3.10+ / Flutter 3.38+ --- +## Available Packages + +| Package | Description | pub.dev | +|---------|-------------|---------| +| `sqlite_vector` | Vector similarity search with SIMD-optimized distance functions | [pub.dev](https://pub.dev/packages/sqlite_vector) | +| `sqlite_js` | Execute JavaScript directly in SQLite using QuickJS | [pub.dev](https://pub.dev/packages/sqlite_js) | +| `sqlite_sync` | Real-time sync with SQLite Cloud | [pub.dev](https://pub.dev/packages/sqlite_sync) | +| `sqlite_ai` | On-device LLM inference with llama.cpp | [pub.dev](https://pub.dev/packages/sqlite_ai) | +| `sqlite_agent` | Execute AI agents with MCP capabilities | [pub.dev](https://pub.dev/packages/sqlite_agent) | +| `sqlite_mcp` | Call MCP resources from databases | [pub.dev](https://pub.dev/packages/sqlite_mcp) | + +--- + ## Installation +Install the packages you need: + ```bash +# Flutter projects flutter pub add sqlite_vector +flutter pub add sqlite_js +flutter pub add sqlite_sync +flutter pub add sqlite_ai +flutter pub add sqlite_agent +flutter pub add sqlite_mcp + +# Dart projects +dart pub add sqlite_vector +dart pub add sqlite_js +dart pub add sqlite_sync +dart pub add sqlite_ai +dart pub add sqlite_agent +dart pub add sqlite_mcp ``` Or add to `pubspec.yaml`: @@ -17,10 +46,16 @@ Or add to `pubspec.yaml`: ```yaml dependencies: sqlite3: ^3.0.0 - sqlite_vector: ^0.9.70 + # Add the packages you need + sqlite_vector: ^0.9.85 + sqlite_js: ^1.2.3 + sqlite_sync: ^0.8.64 + sqlite_ai: ^0.7.59 + sqlite_agent: ^0.1.6 + sqlite_mcp: ^0.1.5 ``` -The package uses Dart build hooks to automatically bundle the correct native library for each platform. No additional configuration is needed. +Each package uses Dart build hooks to automatically bundle the correct native library for each platform. No additional configuration is needed. --- @@ -43,35 +78,30 @@ The package uses Dart build hooks to automatically bundle the correct native lib ```dart import 'package:sqlite3/sqlite3.dart'; import 'package:sqlite_vector/sqlite_vector.dart'; +import 'package:sqlite_js/sqlite_js.dart'; +import 'package:sqlite_sync/sqlite_sync.dart'; +import 'package:sqlite_ai/sqlite_ai.dart'; +import 'package:sqlite_agent/sqlite_agent.dart'; +import 'package:sqlite_mcp/sqlite_mcp.dart'; void main() { - // Load extension once at app startup + // Load extensions once at app startup sqlite3.loadSqliteVectorExtension(); + sqlite3.loadSqliteJsExtension(); + sqlite3.loadSqliteSyncExtension(); + sqlite3.loadSqliteAiExtension(); + sqlite3.loadSqliteAgentExtension(); + sqlite3.loadSqliteMcpExtension(); final db = sqlite3.openInMemory(); - // Create a regular table with a BLOB column for vectors - db.execute('CREATE TABLE items (id INTEGER PRIMARY KEY, embedding BLOB)'); - - // Insert vectors - final stmt = db.prepare('INSERT INTO items (embedding) VALUES (vector_as_f32(?))'); - stmt.execute(['[1.0, 2.0, 3.0, 4.0]']); - stmt.execute(['[5.0, 6.0, 7.0, 8.0]']); - stmt.dispose(); - - // Initialize the vector index - db.execute("SELECT vector_init('items', 'embedding', 'type=FLOAT32,dimension=4')"); - - // Find nearest neighbors - final results = db.select(''' - SELECT e.id, v.distance FROM items AS e - JOIN vector_full_scan('items', 'embedding', vector_as_f32('[1.0, 2.0, 3.0, 4.0]'), 2) AS v - ON e.id = v.rowid - '''); - - for (final row in results) { - print('id=${row['id']}, distance=${row['distance']}'); - } + // Now all extension functions are available + print(db.select('SELECT vector_version()').first.values.first); + print(db.select('SELECT js_version()').first.values.first); + print(db.select('SELECT cloudsync_version()').first.values.first); + print(db.select('SELECT ai_version()').first.values.first); + print(db.select('SELECT agent_version()').first.values.first); + print(db.select('SELECT mcp_version()').first.values.first); db.dispose(); } @@ -79,16 +109,21 @@ void main() { ### With `drift` -[drift](https://pub.dev/packages/drift) is a popular ORM built on top of `sqlite3`. The extension integrates seamlessly: +[drift](https://pub.dev/packages/drift) is a popular ORM built on top of `sqlite3`. The extensions integrate seamlessly: ```dart import 'dart:io'; import 'package:sqlite3/sqlite3.dart'; import 'package:sqlite_vector/sqlite_vector.dart'; +import 'package:sqlite_js/sqlite_js.dart'; +import 'package:sqlite_sync/sqlite_sync.dart'; import 'package:drift/native.dart'; Sqlite3 loadExtensions() { sqlite3.loadSqliteVectorExtension(); + sqlite3.loadSqliteJsExtension(); + sqlite3.loadSqliteSyncExtension(); + // Add other extensions as needed return sqlite3; } @@ -106,53 +141,136 @@ LazyDatabase openConnection() { --- +## Extension Examples + +### sqlite-vector: Vector Similarity Search + +```dart +// Create a table with a BLOB column for vectors +db.execute('CREATE TABLE items (id INTEGER PRIMARY KEY, embedding BLOB)'); + +// Insert vectors +final stmt = db.prepare('INSERT INTO items (embedding) VALUES (vector_as_f32(?))'); +stmt.execute(['[1.0, 2.0, 3.0, 4.0]']); +stmt.execute(['[5.0, 6.0, 7.0, 8.0]']); +stmt.dispose(); + +// Initialize the vector index +db.execute("SELECT vector_init('items', 'embedding', 'type=FLOAT32,dimension=4')"); + +// Find nearest neighbors +final results = db.select(''' + SELECT e.id, v.distance FROM items AS e + JOIN vector_full_scan('items', 'embedding', vector_as_f32('[1.0, 2.0, 3.0, 4.0]'), 2) AS v + ON e.id = v.rowid +'''); + +for (final row in results) { + print('id=${row['id']}, distance=${row['distance']}'); +} +``` + +### sqlite-js: JavaScript Evaluation + +```dart +// Evaluate JavaScript expressions +final result = db.select("SELECT js_eval('1 + 2 + 3')").first.values.first; +print('Result: $result'); // Result: 6 + +// Use JavaScript for complex calculations +final json = db.select("SELECT js_eval('JSON.stringify({a: 1, b: 2})')").first.values.first; +print('JSON: $json'); // JSON: {"a":1,"b":2} +``` + +### sqlite-sync: UUID Generation + +```dart +// Generate UUIDs (UUIDv7) - works without initialization +final uuid1 = db.select('SELECT cloudsync_uuid()').first.values.first; +final uuid2 = db.select('SELECT cloudsync_uuid()').first.values.first; +print('UUID 1: $uuid1'); +print('UUID 2: $uuid2'); + +// For cloud sync features, initialize with your SQLite Cloud connection +// db.execute("SELECT cloudsync_init('sqlitecloud://...')"); +``` + +### sqlite-ai, sqlite-agent, sqlite-mcp + +These extensions require additional setup (GGUF models, MCP server connections). See the API documentation for each extension: + +- [sqlite-ai API](https://github.com/sqliteai/sqlite-ai/blob/main/API.md) +- [sqlite-agent API](https://github.com/sqliteai/sqlite-agent/blob/main/API.md) +- [sqlite-mcp API](https://github.com/sqliteai/sqlite-mcp/blob/main/API.md) + +--- + ## How It Works -The `sqlite_vector` package uses Dart's native assets system (build hooks) introduced in Dart 3.10 / Flutter 3.38. This is the same mechanism used by the `sqlite3` package itself. +All SQLiteAI packages use Dart's native assets system (build hooks) introduced in Dart 3.10 / Flutter 3.38. This is the same mechanism used by the `sqlite3` package itself. Key points: - **No Gradle, CocoaPods, or CMake configuration needed** — the build hook handles everything - **Pre-built binaries** are bundled in the package and selected at build time based on target platform/architecture -- The `@Native` FFI annotation resolves `sqlite3_vector_init` from the bundled native library -- `loadSqliteVectorExtension()` calls `ensureExtensionLoaded()` which registers the extension with SQLite +- The `@Native` FFI annotation resolves the extension's init function from the bundled native library +- `loadSqlite*Extension()` calls `ensureExtensionLoaded()` which registers the extension with SQLite --- -## API Reference - -See the full [sqlite-vector API documentation](https://github.com/sqliteai/sqlite-vector/blob/main/API.md) for all available functions: +## API References -- `vector_version()` — Returns the extension version -- `vector_init()` — Initialize a vector column -- `vector_as_f32()`, `vector_as_f16()`, `vector_as_i8()`, etc. — Convert JSON arrays to vector BLOBs -- `vector_full_scan()` — Find nearest neighbors -- `vector_quantize()` — Quantize vectors for faster search +| Extension | API Documentation | +|-----------|-------------------| +| sqlite-vector | [API.md](https://github.com/sqliteai/sqlite-vector/blob/main/API.md) | +| sqlite-js | [API.md](https://github.com/sqliteai/sqlite-js/blob/main/API.md) | +| sqlite-sync | [API.md](https://github.com/sqliteai/sqlite-sync/blob/main/API.md) | +| sqlite-ai | [API.md](https://github.com/sqliteai/sqlite-ai/blob/main/API.md) | +| sqlite-agent | [API.md](https://github.com/sqliteai/sqlite-agent/blob/main/API.md) | +| sqlite-mcp | [API.md](https://github.com/sqliteai/sqlite-mcp/blob/main/API.md) | --- ## Example Project -A complete Flutter example app is available at: +A complete Flutter example app demonstrating all extensions is available at: [examples/flutter](../examples/flutter) ```bash cd examples/flutter + +# Generate platform scaffolding (only needed once) +flutter create . --project-name sqliteai_flutter_example + +# Install dependencies and run flutter pub get flutter run ``` +Or run as a Dart CLI (no UI): + +```bash +dart pub get +dart run lib/main.dart +``` + --- ## Troubleshooting ### "Pre-built binary not found" -This error occurs when running on a platform/architecture that doesn't have a bundled binary. The package supports the platforms listed above. +This error occurs when running on a platform/architecture that doesn't have a bundled binary. The packages support the platforms listed above. + +### Extension loads but functions don't work -### Extension loads but virtual table functions don't work +Make sure you've loaded the extension before opening the database or using its functions: -Make sure you're using regular tables with BLOB columns, not virtual tables. sqlite-vector doesn't use virtual tables for storage — see the [main documentation](https://github.com/sqliteai/sqlite-vector) for the correct usage pattern. +```dart +// Correct order +sqlite3.loadSqliteVectorExtension(); // Load first +final db = sqlite3.openInMemory(); // Then open database +``` ### "Dart SDK version too old" @@ -161,3 +279,12 @@ Build hooks require Dart 3.10+ / Flutter 3.38+. Update your SDK: ```bash flutter upgrade ``` + +### Extension-specific errors + +Some extensions require initialization before certain functions work: + +- **sqlite-sync**: `cloudsync_uuid()` works immediately, but sync features need `cloudsync_init()` +- **sqlite-ai**: Requires a GGUF model file for inference +- **sqlite-mcp**: Requires MCP server connection configuration +- **sqlite-agent**: Requires both sqlite-ai and sqlite-mcp setup