Dart and Flutter
Native
On native Dart and Flutter targets, custom native code can be called viadart:ffi and linked with
build hooks.
The sqlite3 package used by PowerSync contains a complete example
adopting build hooks to link SQLite extensions.
Using that example, you would call the sqlite3.loadSqliteVectorExtension() extension method before using PowerSync to
ensure the extension is loaded.
Web
Because dynamic linking is not generally available with WebAssembly, loading extensions on the web requires a customsqlite3.wasm build linking both PowerSync and any additional extensions you may want to use.
The sqlite3 package provides instructions
and cmake build scripts to compile sqlite3.wasm.
The PowerSync Dart SDK adopts that
with a patch
to automatically load the PowerSync SQLite core extension when SQLite is loaded (in sqlite3_os_init).
To link additional extensions, you could add similar build script additions to call their entrypoint.
JavaScript
Web
Similar to Dart on the web, loading extensions with@powersync/web is only possible with a custom wa-sqlite WebAssembly
build.
PowerSync forks wa-sqlite for this reason, loading custom extension requires patching
build definitions in that repository and adding an override from your npm package manager to patch @journeyapps/wa-sqlite.
React Native
The recommended OP-SQLite library has builtin support for custom extensions, and excellent documentation on how to build and bundle them with your app.Node.js
Loading extensions is possible withbetter-sqlite3 and the loadExtension
method on databases.
Because the database is created on a worker, a custom worker is necessary to customize it:
Capacitor
The PowerSync Capacitor SDK uses@capacitor-community/sqlite
as a SQLite library, which doesn’t support loading extensions directly.
On Android however, you can use the load_extension
SQL function to load extensions.
To build and bundle extensions with your app, follow the approach for React Native or Kotlin.
On iOS, you’d have to follow the approach for Swift and expose your Swift helper method loading the extension
in a way that can be called from JavaScript.
Kotlin
On all platforms supported by the Kotlin SDK, a customPersistentConnectionFactory
can be used to customize how PowerSync opens SQLite connections. This can also be used to load additional extensions.
On Android and JVM platforms, the setup for that can look like this:
addExtension directly, as System.loadLibrary will resolve to it.
The safest way to load extensions on Kotlin/Native targets is to use cinterops
building the extension as a library and making its entrypoint available from Kotlin.
This entrypoint can then be called via sqlite3_auto_extension
before opening PowerSync databases.
.Net
The PowerSync .NET SDK has builtin support for loading extensions through theMDSQLiteOptions.Extensions field.
It is your responsibility to build and bundle extensions you want to use with your app so that they can be loaded.
Rust and Tauri
For the Rust and Tauri SDKs, your app is expected to link SQLite directly. This means that regular SQLite APIs to load extensions can be used. Forsqlite-vec for example, depending on this crate and calling
sqlite3_vec_init() before opening a PowerSync database ensures the extension is loaded.
Most other extensions have a similar entrypoint to invoke. For full control, you can also invoke
register_auto_extension
with the entrypoint function of the extension (useful for statically linked extensions) or use
load_extension on a
Connection before passing it to a ConnectionPool for the PowerSync Rust SDK.
Swift
The PowerSync Swift SDK depends on this package to link SQLite with your app. To add a custom extension:- Write Swift Package Manager definitions to build and link that extension with your app too.
- Depend on the PowerSync CSQLite target.
- Similar to the setup for PowerSync, add a module shim target allowing you to use the extension from Swift.
- Import that target and CSQLite to load the extension statically before opening a PowerSync database.