From 30bf241b4a4c3f049ef71d23b6cde93ef759c613 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Wed, 25 Mar 2026 16:14:10 +0100 Subject: [PATCH 1/6] Draft for Tauri SDK --- client-sdks/reference/rust.mdx | 16 +- client-sdks/reference/tauri.mdx | 345 ++++++++++++++++++++++++++++++ docs.json | 7 + intro/examples.mdx | 5 + logo/tauri.svg | 1 + logo/tauri_sidebar.svg | 1 + resources/supported-platforms.mdx | 13 ++ snippets/tauri/installation.mdx | 46 ++++ 8 files changed, 424 insertions(+), 10 deletions(-) create mode 100644 client-sdks/reference/tauri.mdx create mode 100644 logo/tauri.svg create mode 100644 logo/tauri_sidebar.svg create mode 100644 snippets/tauri/installation.mdx diff --git a/client-sdks/reference/rust.mdx b/client-sdks/reference/rust.mdx index 1f918410..44f014bb 100644 --- a/client-sdks/reference/rust.mdx +++ b/client-sdks/reference/rust.mdx @@ -121,8 +121,8 @@ For maximum flexibility, the PowerSync Rust SDK can be configured with different These dependencies can be configured through the [`PowerSyncEnvironment`](https://docs.rs/powersync/latest/powersync/env/struct.PowerSyncEnvironment.html) struct, which wraps: -1. An HTTP client (using traits from the `http-client` crate). We recommend enabling the `curl_client` feature - on that crate and then using an `IsahcClient`. The `H1Client` is known not to work with PowerSync because it can't cancel response streams properly. +1. An HTTP client (implement the `powersync::http::HttpClient` trait). When enabling the `reqwest` feature on + the `powersync` crate, that trait is implemented for `reqwest::Client`. 2. An asynchronous pool giving out leases to SQLite connections. 3. A timer implementation allowing the sync client to implement delayed retries on connection errors. This is typically provided by async runtimes like Tokio. @@ -176,11 +176,10 @@ async fn main() { .expect("could not load PowerSync core extension"); let pool = open_pool().expect("open pool"); - let client = Arc::new(IsahcClient::new()); let env = PowerSyncEnvironment::custom( - client.clone(), + reqwest::Client::new(), pool, - Box::new(PowerSyncEnvironment::tokio_timer()), + PowerSyncEnvironment::tokio_timer(), ); let db = PowerSyncDatabase::new(env, schema::app_schema()); @@ -195,12 +194,11 @@ Ensure you depend on `powersync` with the `smol` feature enabled. ```Rust async fn start_app() { let pool = open_pool().expect("open pool"); - let client = Arc::new(IsahcClient::new()); let env = PowerSyncEnvironment::custom( - client.clone(), + reqwest::Client::new(), pool, // Use the async_io crate to implement timers in PowerSync - Box::new(PowerSyncEnvironment::async_io_timer()), + PowerSyncEnvironment::async_io_timer(), ); let db = PowerSyncDatabase::new(env, schema::app_schema()); @@ -242,7 +240,6 @@ Finally, instruct PowerSync to sync data from your backend: ```Rust // MyBackendConnector is defined in the next step... db.connect(SyncOptions::new(MyBackendConnector { - client, db: db.clone(), })).await; ``` @@ -265,7 +262,6 @@ Accordingly, the connector must implement two methods: ```Rust struct MyBackendConnector { - client: Arc, db: PowerSyncDatabase, } diff --git a/client-sdks/reference/tauri.mdx b/client-sdks/reference/tauri.mdx new file mode 100644 index 00000000..396f209c --- /dev/null +++ b/client-sdks/reference/tauri.mdx @@ -0,0 +1,345 @@ +--- +title: "Tauri SDK (pre-alpha)" +description: "Full SDK guide for using PowerSync in Tauri applications" +sidebarTitle: "SDK Reference" +--- + + +import SdkFeatures from '/snippets/sdk-features.mdx'; +import TauriInstallation from '/snippets/tauri/installation.mdx'; +import JavaScriptAsyncWatch from '/snippets/basic-watch-query-javascript-async.mdx'; +import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-callback.mdx'; +import GenerateSchemaAutomatically from '/snippets/generate-schema-automatically.mdx'; +import MutationConfirmationWithReturning from '/snippets/javascript-mutation-confirmation-returning.mdx'; + + + + The JavaScript part of the SDK is distributed via NPM + + + The Rust part of the SDK is available via crates.io + + + Refer to `packages/capacitor` in the `powersync-js` repo on GitHub + + + TODO: Update + Full API reference for the SDK + + + Gallery of example projects/demo apps built with Capacitor and PowerSync + + + Changelog for the SDK + + + + + This SDK is currently in a [**pre-alpha** release](/resources/feature-status). + + While the JavaScript parts are built with the stable `@powersync/common` package, database + access and sync is implemented with our experimental Rust SDK. + There are [known limitations](#limitations) currently. + + +### SDK Features + + + +## Installation + + + +## Getting Started + +**Prerequisites**: To sync data between your client-side app and your backend source database, you must have completed the necessary setup for PowerSync, which includes connecting your source database to the PowerSync Service and deploying Sync Streams (or legacy Sync Rules) (steps 1-4 in the [Setup Guide](/intro/setup-guide)). + +### 1. Define the Client-Side Schema + +import SdkClientSideSchema from '/snippets/sdk-client-side-schema.mdx'; + + + + + +The types available are `text`, `integer` and `real`. These should map directly to the values produced by your [Sync Streams](/sync/streams/overview) (or legacy [Sync Rules](/sync/rules/overview)). If a value doesn't match, it is cast automatically. For details on how backend source database types are mapped to the SQLite types, see [Types](/sync/types). + +**Example**: + + + **Note on imports**: While you install `@powersync/capacitor`, the Capacitor SDK extends the Web SDK so you import general components from `@powersync/web` (installed as a peer dependency). See the [JavaScript Web SDK schema definition section](/client-sdks/reference/javascript-web#1-define-the-client-side-schema) for more advanced examples. + + +```js +// AppSchema.ts +import { column, Schema, Table } from '@powersync/common'; + +const lists = new Table({ + created_at: column.text, + name: column.text, + owner_id: column.text +}); + +const todos = new Table( + { + list_id: column.text, + created_at: column.text, + completed_at: column.text, + description: column.text, + created_by: column.text, + completed_by: column.text, + completed: column.integer + }, + { indexes: { list: ['list_id'] } } +); + +export const AppSchema = new Schema({ + todos, + lists +}); + +// For types +export type Database = (typeof AppSchema)['types']; +export type TodoRecord = Database['todos']; +// OR: +// export type Todo = RowType; +export type ListRecord = Database['lists']; +``` + + + **Note**: No need to declare a primary key `id` column, as PowerSync will automatically create this. + + +### 2. Instantiate the PowerSync Database + +Next, you need to instantiate the PowerSync database. PowerSync streams changes from your backend source database into the client-side SQLite database, based on your [Sync Streams](/sync/streams/overview) (or legacy [Sync Rules](/sync/rules/overview)). In your client-side app, you can read from and write to the local SQLite database, whether the user is online or offline. + +**Example**: + +```js +import { PowerSyncTauriDatabase } from '@powersync/tauri-plugin'; +import { appDataDir } from '@tauri-apps/api/path'; + +import { AppSchema } from './AppSchema'; + +export const db = new PowerSyncTauriDatabase({ + // The schema you defined in the previous step + schema: AppSchema, + database: { + // Filename for the SQLite database. + dbFilename: 'powersync.db', + // An optional directory to store the database file in. + dbLocationAsync: appDataDir, + } +}); +``` + +Finally, instruct PowerSync to sync data from your backend. For Tauri apps, the sync client +must be driven from Rust code. + +To do that, add a new Tauri command to your Rust application: + +```Rust +use tauri_plugin_powersync::PowerSyncExt; + +#[tauri::command] +async fn connect( + app: AppHandle, + handle: usize, +) -> tauri_plugin_powersync::Result<()> { + let ps = app.powersync(); + let database = ps.database_from_javascript_handle(handle)?; + + // MyBackendConnector is defined in the next step... + let options = SyncOptions::new(MyRustConnector { + db: database.clone(), + }); + database.connect(options).await; + + Ok(()) +} +``` + +Ensure the command is registered by including it in the invoke handler with +`tauri::generate_handler![connect]`. + +You can then invoke that command from your JavaScript code to connect: + +```TypeScript +import { PowerSyncTauriDatabase } from '@powersync/tauri-plugin'; +import { invoke } from '@tauri-apps/api/core'; + +async function connect(db: PowerSyncTauriDatabase) { + await db.init(); + const handle = db.rustHandle; + await invoke('connect', { handle }); +} +``` + +### 3. Integrate with your Backend + +The PowerSync backend connector provides the connection between your application backend and the PowerSync client-side managed SQLite database. It is used to: + +1. Retrieve an auth token to connect to the PowerSync instance. +2. Upload client-side writes to your backend API. Any writes that are made to the SQLite database are placed into an upload queue by the PowerSync Client SDK and automatically uploaded to your app backend (where you apply those changes to the backend source database) when the user is connected. + + +At the moment, backend connectors for the Tauri SDK must be implemented in Rust. +This allows the connector to be used across multiple windows and even when no JavaScript is running. + + +Accordingly, the connector must implement two methods: + +1. `fetch_credentials` \- This method will be automatically invoked by the PowerSync Client SDK every couple of minutes to obtain authentication credentials. See [Authentication Setup](/configuration/auth/overview) for instructions on how the credentials should be generated. +2. `upload_data` \- This method will be automatically invoked by the PowerSync Client SDK whenever it needs to upload client-side writes to your app backend via your backend API. Therefore, in your implementation, you need to define how your backend API is called. See [Writing Client Changes](/handling-writes/writing-client-changes) for considerations on the app backend implementation. + +**Example**: + +```Rust +struct MyBackendConnector { + db: PowerSyncDatabase, +} + +#[async_trait] +impl BackendConnector for MyBackendConnector { + async fn fetch_credentials(&self) -> Result { + // implement fetchCredentials to obtain the necessary credentials to connect to your backend + // See an example implementation in https://github.com/powersync-ja/powersync-native/blob/508193b0822b8dad1a534a16462e2fcd36a9ac68/examples/egui_todolist/src/database.rs#L119-L133 + + Ok(PowerSyncCredentials { + endpoint: "[Your PowerSync instance URL or self-hosted endpoint]".to_string(), + // Use a development token (see Authentication Setup https://docs.powersync.com/configuration/auth/development-tokens) to get up and running quickly + token: "An authentication token".to_string(), + }) + } + + async fn upload_data(&self) -> Result<(), PowerSyncError> { + // Implement uploadData to send local changes to your backend service + // You can omit this method if you only want to sync data from the server to the client + // See an example implementation under Usage Examples (sub-page) + // See https://docs.powersync.com/handling-writes/writing-client-changes for considerations. + let mut local_writes = self.db.crud_transactions(); + while let Some(tx) = local_writes.try_next().await? { + todo!("Inspect tx.crud for local writes that need to be uploaded to your backend"); + tx.complete().await?; + } + + Ok(()) + } +} +``` + +## Using PowerSync: CRUD functions + +Once the PowerSync instance is configured you can start using the SQLite DB functions. + + + **All CRUD examples from the JavaScript Web SDK apply**: The Capacitor SDK uses the same API as the Web SDK. See the [JavaScript Web SDK CRUD functions section](/client-sdks/reference/javascript-web#using-powersync-crud-functions) for examples of `get`, `getAll`, `watch`, `execute`, `writeTransaction`, incremental watch updates, and differential results. + + +The most commonly used CRUD functions to interact with your SQLite data are: + +- [PowerSyncDatabase.get](/client-sdks/reference/javascript-web#fetching-a-single-item) - get (SELECT) a single row from a table. +- [PowerSyncDatabase.getAll](/client-sdks/reference/javascript-web#querying-items-powersync.getall) - get (SELECT) a set of rows from a table. +- [PowerSyncDatabase.watch](/client-sdks/reference/javascript-web#watching-queries-powersync.watch) - execute a read query every time source tables are modified. +- [PowerSyncDatabase.execute](/client-sdks/reference/javascript-web#mutations-powersync.execute) - execute a write (INSERT/UPDATE/DELETE) query. + +### Fetching a Single Item + +The [get](https://powersync-ja.github.io/powersync-js/web-sdk/classes/PowerSyncDatabase#get) method executes a read-only (SELECT) query and returns a single result. It throws an exception if no result is found. Use [getOptional](https://powersync-ja.github.io/powersync-js/web-sdk/classes/PowerSyncDatabase#getoptional) to return a single optional result (returns `null` if no result is found). + +```js +// Find a list item by ID +export const findList = async (id) => { + const result = await db.get('SELECT * FROM lists WHERE id = ?', [id]); + return result; +} +``` + +### Querying Items (PowerSync.getAll) + +The [getAll](https://powersync-ja.github.io/powersync-js/web-sdk/classes/PowerSyncDatabase#getall) method returns a set of rows from a table. + +```js +// Get all list IDs +export const getLists = async () => { + const results = await db.getAll('SELECT * FROM lists'); + return results; +} +``` + +### Watching Queries (PowerSync.watch) + +The [watch](https://powersync-ja.github.io/powersync-js/web-sdk/classes/PowerSyncDatabase#watch) method executes a read query whenever a change to a dependent table is made. + + + + + + + + + + +For advanced watch query features like incremental updates and differential results, see [Live Queries / Watch Queries](/client-sdks/watch-queries). + +### Mutations (PowerSync.execute, PowerSync.writeTransaction) + +The [execute](https://powersync-ja.github.io/powersync-js/web-sdk/classes/PowerSyncDatabase#execute) method can be used for executing single SQLite write statements. + +```js +// Delete a list item by ID +export const deleteList = async (id) => { + const result = await db.execute('DELETE FROM lists WHERE id = ?', [id]); + return TodoList.fromRow(results); +} + +// OR: using a transaction +const deleteList = async (id) => { + await db.writeTransaction(async (tx) => { + // Delete associated todos + await tx.execute(`DELETE FROM ${TODOS_TABLE} WHERE list_id = ?`, [id]); + // Delete list record + await tx.execute(`DELETE FROM ${LISTS_TABLE} WHERE id = ?`, [id]); + }); +}; +``` + + +## Configure Logging + +The Rust SDK uses the `log` crate which can be enabled using the [Tauri logging plugin](https://v2.tauri.app/plugin/logging/). + +## Sharing a database with Rust code + +A `PowerSyncTauriDatabase` instance can be shared with Rust code: + +1. Call and await `.init()` on the database to ensure the database has been opened. +2. Use the `.rustHandle` getter, which returns a number representing the database instance. +3. This handle can now be passed as an argument to one of your Tauri commands. + In Rust SDK, you can use `AppHandle::powersync()` and + `PowerSync::database_from_javascript_handle` to inspect the database from Rust. + See the [Rust SDK guide](/client-sdks/reference/rust) for more information. + +Connection locks and table updates are automatically shared between Rust and JavaScript code. + +## Limitations + +- The Rust SDK, which is used to implement the Tauri plugin, has limited support for legacy Sync Rules: + On `SyncStatus`, `lastSyncedAt`, `hasSynced` and `priorityStatusEntries` are not available. + Use the status on individual Sync Streams through `SyncStatus.forStream` instead. +- Connecting to the PowerSync service is only possible from Rust. Calling `connect()` from JavaScript + will throw. + +## Additional Usage Examples + +For more usage examples including accessing connection status, monitoring sync progress, and waiting for initial sync, see the [Usage Examples](/client-sdks/usage-examples) page. + +## ORM Support + +See [JavaScript ORM Support](/client-sdks/orms/js/overview) for details. + +## Troubleshooting + +See [Troubleshooting](/debugging/troubleshooting) for pointers to debug common issues. + diff --git a/docs.json b/docs.json index 0ec74daf..02aceca0 100644 --- a/docs.json +++ b/docs.json @@ -271,6 +271,13 @@ "client-sdks/reference/node-api" ] }, + { + "group": "Tauri", + "icon": "/logo/tauri_sidebar.svg", + "pages": [ + "client-sdks/reference/tauri" + ] + }, { "group": "Frameworks/Integrations", "pages": [ diff --git a/intro/examples.mdx b/intro/examples.mdx index a2b9dd28..b2c25943 100644 --- a/intro/examples.mdx +++ b/intro/examples.mdx @@ -108,6 +108,11 @@ All examples are organized by platform and backend technology. You can adapt any - [Capacitor Example](https://github.com/powersync-ja/powersync-js/tree/main/demos/example-capacitor#readme) - PowerSync in a Capacitor app with web, Android, and iOS support + + #### Examples + + - [Tauri Example](https://github.com/powersync-ja/powersync-js/tree/main/demos/tauri-app#readme) - PowerSync in a Tauri app with Desktop support. + #### Examples diff --git a/logo/tauri.svg b/logo/tauri.svg new file mode 100644 index 00000000..c4b6ac92 --- /dev/null +++ b/logo/tauri.svg @@ -0,0 +1 @@ + diff --git a/logo/tauri_sidebar.svg b/logo/tauri_sidebar.svg new file mode 100644 index 00000000..af93073a --- /dev/null +++ b/logo/tauri_sidebar.svg @@ -0,0 +1 @@ + diff --git a/resources/supported-platforms.mdx b/resources/supported-platforms.mdx index c62a3020..bf9ad267 100644 --- a/resources/supported-platforms.mdx +++ b/resources/supported-platforms.mdx @@ -53,6 +53,19 @@ description: "Supported platforms and major features by PowerSync Client SDK" | HTTP connection method | Yes | | | WebSocket connection method | Yes | | +## Tauri SDK + +| Platform / Feature | Supported? | Notes | +| --- | --- | --- | +| Windows | Yes | Untested. | +| macOS | Yes | | +| Linux | Yes | | +| iOS | Yes | Untested. | +| Android | Yes | Untested. | +| HTTP connection method | Yes | Connections must currently be managed through Rust. | +| WebSocket connection method | No | | + + ## Node.js SDK | Platform / Feature | Supported? | Notes | diff --git a/snippets/tauri/installation.mdx b/snippets/tauri/installation.mdx new file mode 100644 index 00000000..b5766cee --- /dev/null +++ b/snippets/tauri/installation.mdx @@ -0,0 +1,46 @@ +Add the [PowerSync Tauri NPM package](https://www.npmjs.com/package/@powersync/tauri-plugin) to your project: + + + + ```bash + npm install @powersync/tauri-plugin + ``` + + + + ```bash + yarn add @powersync/tauri-plugin + ``` + + + + ```bash + pnpm install @powersync/tauri-plugin + ``` + + + + +Like all trusted PowerSync packages, the Tauri plugin is only available through the `@powersync/` scope on npm. +The PowerSync Tauri plugin __cannot__ be installed with the `tauri add` command. + + +Additionally, add the Tauri plugin crate to your Rust app (in the `src-tauri` directory): + +```bash +cargo add tauri-plugin-powersync +``` + +In your `lib.rs`, ensure the plugin is loaded: + +```diff +pub fn run() { + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![connect]) ++ .plugin(tauri_plugin_powersync::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +In `src-tauri/capabilities/default.json`, ensure `powersync:default` is listed under `permissions` to make PowerSync APIs available to JavaScript. From ec8a5b2e16c9947d4b505dcb825d329954131fab Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 26 Mar 2026 13:36:28 +0200 Subject: [PATCH 2/6] Add Tauri to feature status list --- resources/feature-status.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/feature-status.mdx b/resources/feature-status.mdx index 15fc2531..15db6205 100644 --- a/resources/feature-status.mdx +++ b/resources/feature-status.mdx @@ -56,6 +56,7 @@ Below is a summary of the current main PowerSync features and their release stat | Postgres Bucket Storage | V1 | | | | | **Client SDKs** | | +| Tauri SDK | Experimental | | Rust SDK | Experimental | | .NET SDK | Beta | | Capacitor SDK | Alpha | From 93ed7e297264d8c127d2eac1e532af56bc9a2f4e Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 26 Mar 2026 14:14:12 +0200 Subject: [PATCH 3/6] A few more Tauri-specific references --- client-sdks/reference/tauri.mdx | 23 +++---- .../app-backend/client-side-integration.mdx | 2 + intro/setup-guide.mdx | 64 ++++++++++++++++++- snippets/client-sdks.mdx | 2 + snippets/generate-schema-automatically.mdx | 2 +- snippets/sdk-instantiate-db-examples.mdx | 15 +++++ snippets/sdk-schema-examples.mdx | 21 ++++++ 7 files changed, 115 insertions(+), 14 deletions(-) diff --git a/client-sdks/reference/tauri.mdx b/client-sdks/reference/tauri.mdx index 396f209c..774bbf9e 100644 --- a/client-sdks/reference/tauri.mdx +++ b/client-sdks/reference/tauri.mdx @@ -19,15 +19,15 @@ import MutationConfirmationWithReturning from '/snippets/javascript-mutation-con The Rust part of the SDK is available via crates.io - - Refer to `packages/capacitor` in the `powersync-js` repo on GitHub + + Refer to `packages/tauri` in the `powersync-js` repo on GitHub - - TODO: Update + Full API reference for the SDK - Gallery of example projects/demo apps built with Capacitor and PowerSync + Gallery of example projects/demo apps built with Tauri and PowerSync Changelog for the SDK @@ -38,7 +38,8 @@ import MutationConfirmationWithReturning from '/snippets/javascript-mutation-con This SDK is currently in a [**pre-alpha** release](/resources/feature-status). While the JavaScript parts are built with the stable `@powersync/common` package, database - access and sync is implemented with our experimental Rust SDK. + access and sync is implemented with our experimental [Rust SDK](/client-sdks/reference/rust). + There are [known limitations](#limitations) currently. @@ -64,12 +65,12 @@ import SdkClientSideSchema from '/snippets/sdk-client-side-schema.mdx'; The types available are `text`, `integer` and `real`. These should map directly to the values produced by your [Sync Streams](/sync/streams/overview) (or legacy [Sync Rules](/sync/rules/overview)). If a value doesn't match, it is cast automatically. For details on how backend source database types are mapped to the SQLite types, see [Types](/sync/types). -**Example**: - - **Note on imports**: While you install `@powersync/capacitor`, the Capacitor SDK extends the Web SDK so you import general components from `@powersync/web` (installed as a peer dependency). See the [JavaScript Web SDK schema definition section](/client-sdks/reference/javascript-web#1-define-the-client-side-schema) for more advanced examples. + The Tauri SDK inherits the same APIs from the JavaScript Web SDK via `@powersync/common`, with a few exceptions detailed below. See the [Web SDK schema definition section](/client-sdks/reference/javascript-web#1-define-the-client-side-schema) for more advanced examples. +**Example**: + ```js // AppSchema.ts import { column, Schema, Table } from '@powersync/common'; @@ -234,7 +235,7 @@ impl BackendConnector for MyBackendConnector { Once the PowerSync instance is configured you can start using the SQLite DB functions. - **All CRUD examples from the JavaScript Web SDK apply**: The Capacitor SDK uses the same API as the Web SDK. See the [JavaScript Web SDK CRUD functions section](/client-sdks/reference/javascript-web#using-powersync-crud-functions) for examples of `get`, `getAll`, `watch`, `execute`, `writeTransaction`, incremental watch updates, and differential results. + **All CRUD examples from the JavaScript Web SDK apply**: The Tauri SDK exposes the same JavaScript database API as the Web SDK. See the [JavaScript Web SDK CRUD functions section](/client-sdks/reference/javascript-web#using-powersync-crud-functions) for examples of `get`, `getAll`, `watch`, `execute`, `writeTransaction`, incremental watch updates, and differential results. The most commonly used CRUD functions to interact with your SQLite data are: @@ -328,7 +329,7 @@ Connection locks and table updates are automatically shared between Rust and Jav - The Rust SDK, which is used to implement the Tauri plugin, has limited support for legacy Sync Rules: On `SyncStatus`, `lastSyncedAt`, `hasSynced` and `priorityStatusEntries` are not available. Use the status on individual Sync Streams through `SyncStatus.forStream` instead. -- Connecting to the PowerSync service is only possible from Rust. Calling `connect()` from JavaScript +- Connecting to the PowerSync Service is only possible from Rust. Calling `connect()` from JavaScript will throw. ## Additional Usage Examples diff --git a/configuration/app-backend/client-side-integration.mdx b/configuration/app-backend/client-side-integration.mdx index 751c2ec2..4ab9413e 100644 --- a/configuration/app-backend/client-side-integration.mdx +++ b/configuration/app-backend/client-side-integration.mdx @@ -36,9 +36,11 @@ For an example implementation of a PowerSync 'backend connector', see the SDK gu + + ## More Examples diff --git a/intro/setup-guide.mdx b/intro/setup-guide.mdx index 86fb33c1..e54fd2f0 100644 --- a/intro/setup-guide.mdx +++ b/intro/setup-guide.mdx @@ -9,6 +9,7 @@ import ReactNativeInstallation from '/snippets/react-native/installation.mdx'; import JavaScriptWebInstallation from '/snippets/javascript-web/installation.mdx'; import NodeInstallation from '/snippets/node/installation.mdx'; import CapacitorInstallation from '/snippets/capacitor/installation.mdx'; +import TauriInstallation from '/snippets/tauri/installation.mdx'; import FlutterInstallation from '/snippets/flutter/installation.mdx'; import KotlinInstallation from '/snippets/kotlin/installation.mdx'; import SwiftInstallation from '/snippets/swift/installation.mdx'; @@ -745,6 +746,10 @@ Add the PowerSync Client SDK to your app project. PowerSync provides SDKs for va + + + + @@ -1059,6 +1064,61 @@ For development, you can use the development token you generated in the [Generat })) .await; ``` + + ```rust Tauri (Rust) + // For Tauri, connecting to PowerSync must be done in Rust so that sync state + // is shared across all windows. Calling connect() from JavaScript will throw. + // + // 1. Define your backend connector in Rust: + + use async_trait::async_trait; + use tauri_plugin_powersync::PowerSyncExt; + use powersync::{BackendConnector, PowerSyncCredentials, PowerSyncDatabase, SyncOptions}; + use powersync::error::PowerSyncError; + + struct MyBackendConnector { + db: PowerSyncDatabase, + } + + #[async_trait] + impl BackendConnector for MyBackendConnector { + async fn fetch_credentials(&self) -> Result { + // for development: use development token + Ok(PowerSyncCredentials { + endpoint: "https://your-instance.powersync.com".to_string(), + token: "your-development-token-here".to_string(), + }) + } + + async fn upload_data(&self) -> Result<(), PowerSyncError> { + let mut local_writes = self.db.crud_transactions(); + while let Some(tx) = local_writes.try_next().await? { + // upload to your backend API + tx.complete().await?; + } + Ok(()) + } + } + + // 2. Add a Tauri command that receives the database handle from JavaScript: + #[tauri::command] + async fn connect( + app: tauri::AppHandle, + handle: usize, + ) -> tauri_plugin_powersync::Result<()> { + let database = app.powersync().database_from_javascript_handle(handle)?; + let options = SyncOptions::new(MyBackendConnector { db: database.clone() }); + database.connect(options).await; + Ok(()) + } + + // 3. Register the command in your Tauri builder: + // .invoke_handler(tauri::generate_handler![connect]) + + // 4. Then call it from JavaScript after initializing the database: + // await db.init(); + // await invoke('connect', { handle: db.rustHandle }); + ``` Once connected, you can read from and write to the client-side SQLite database. Changes from your source database will be automatically synced down into the SQLite database. For client-side mutations to be uploaded back to your source database, you need to complete the backend integration as we'll explain below. @@ -1067,7 +1127,7 @@ Once connected, you can read from and write to the client-side SQLite database. Read data using SQL queries. The data comes from your client-side SQLite database: - ```typescript React Native, Web, Node.js & Capacitor (TS) + ```typescript React Native, Web, Node.js, Capacitor & Tauri (TS) // Get all todos const todos = await db.getAll('SELECT * FROM todos'); @@ -1253,7 +1313,7 @@ Read data using SQL queries. The data comes from your client-side SQLite databas Write data using SQL `INSERT`, `UPDATE`, or `DELETE` statements. PowerSync automatically queues these mutations and uploads them to your backend via the `uploadData()` function, once you've fully implemented your _backend connector_ (as we'll talk about below). - ```typescript React Native (TS), Web & Node.js + ```typescript React Native, Web, Node.js, Capacitor & Tauri (TS) // Insert a new todo await db.execute( 'INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)', diff --git a/snippets/client-sdks.mdx b/snippets/client-sdks.mdx index 3c4cf0fc..32e0ec17 100644 --- a/snippets/client-sdks.mdx +++ b/snippets/client-sdks.mdx @@ -7,6 +7,8 @@ + + diff --git a/snippets/generate-schema-automatically.mdx b/snippets/generate-schema-automatically.mdx index 5efeb2e5..b56deea0 100644 --- a/snippets/generate-schema-automatically.mdx +++ b/snippets/generate-schema-automatically.mdx @@ -1,7 +1,7 @@ **Generate schema automatically** - In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and click the **Connect** button in the top bar to generate the client-side schema in your preferred language. The schema will be generated based off your Sync Rules. + In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and click the **Connect** button in the top bar to generate the client-side schema in your preferred language. The schema will be generated based off your Sync Streams/Rules. Similar functionality exists in the [CLI](/tools/cli). diff --git a/snippets/sdk-instantiate-db-examples.mdx b/snippets/sdk-instantiate-db-examples.mdx index 882505f8..736bc312 100644 --- a/snippets/sdk-instantiate-db-examples.mdx +++ b/snippets/sdk-instantiate-db-examples.mdx @@ -35,6 +35,21 @@ }); ``` + ```typescript Tauri (TS) + import { PowerSyncTauriDatabase } from '@powersync/tauri-plugin'; + import { appDataDir } from '@tauri-apps/api/path'; + import { AppSchema } from './AppSchema'; + + export const db = new PowerSyncTauriDatabase({ + schema: AppSchema, + database: { + dbFilename: 'powersync.db', + // Store the database in the app data directory + dbLocationAsync: appDataDir, + } + }); + ``` + ```typescript Capacitor (TS) import { PowerSyncDatabase } from '@powersync/capacitor'; diff --git a/snippets/sdk-schema-examples.mdx b/snippets/sdk-schema-examples.mdx index e31f6a54..2c127d68 100644 --- a/snippets/sdk-schema-examples.mdx +++ b/snippets/sdk-schema-examples.mdx @@ -41,6 +41,27 @@ }); ``` + ```typescript Tauri (TS) + import { column, Schema, Table } from '@powersync/common'; + + const todos = new Table( + { + list_id: column.text, + created_at: column.text, + completed_at: column.text, + description: column.text, + created_by: column.text, + completed_by: column.text, + completed: column.integer + }, + { indexes: { list: ['list_id'] } } + ); + + export const AppSchema = new Schema({ + todos + }); + ``` + ```typescript Node.js (TS) import { column, Schema, Table } from '@powersync/node'; From a0bd1395f509502c7a0a0d0cb92e726ab205b189 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 26 Mar 2026 14:26:49 +0200 Subject: [PATCH 4/6] Examples across other pages should cover Tauri too --- client-sdks/reading-data.mdx | 2 +- client-sdks/writing-data.mdx | 2 +- configuration/auth/development-tokens.mdx | 10 ++++++++++ intro/setup-guide.mdx | 4 ++-- sync/streams/client-usage.mdx | 10 ++++++++++ sync/streams/migration.mdx | 1 + 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/client-sdks/reading-data.mdx b/client-sdks/reading-data.mdx index 80cbcb2e..a749dac6 100644 --- a/client-sdks/reading-data.mdx +++ b/client-sdks/reading-data.mdx @@ -11,7 +11,7 @@ On the client-side, you can read data directly from the local SQLite database us Read data using SQL queries: - ```typescript React Native, Web, Node.js & Capacitor (TS) + ```typescript TypeScript // Get all todos const todos = await db.getAll('SELECT * FROM todos'); diff --git a/client-sdks/writing-data.mdx b/client-sdks/writing-data.mdx index c7921b9a..23776b2d 100644 --- a/client-sdks/writing-data.mdx +++ b/client-sdks/writing-data.mdx @@ -9,7 +9,7 @@ Write data using SQL `INSERT`, `UPDATE`, or `DELETE` statements. PowerSync autom ## Basic Write Operations - ```typescript React Native (TS), Web & Node.js + ```typescript TypeScript // Insert a new todo await db.execute( 'INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)', diff --git a/configuration/auth/development-tokens.mdx b/configuration/auth/development-tokens.mdx index e3dce902..f6ac7bb5 100644 --- a/configuration/auth/development-tokens.mdx +++ b/configuration/auth/development-tokens.mdx @@ -120,4 +120,14 @@ To use the temporary development token in your application, update the [`fetchCr return new PowerSyncCredentials(powerSyncUrl, authToken); } ``` + + ```rust Tauri (Rust) + // For Tauri, fetchCredentials is implemented inside your Rust BackendConnector + async fn fetch_credentials(&self) -> Result { + Ok(PowerSyncCredentials { + endpoint: "https://your-instance.powersync.com".to_string(), + token: "your-development-token-here".to_string(), + }) + } + ``` \ No newline at end of file diff --git a/intro/setup-guide.mdx b/intro/setup-guide.mdx index e54fd2f0..d71df299 100644 --- a/intro/setup-guide.mdx +++ b/intro/setup-guide.mdx @@ -1127,7 +1127,7 @@ Once connected, you can read from and write to the client-side SQLite database. Read data using SQL queries. The data comes from your client-side SQLite database: - ```typescript React Native, Web, Node.js, Capacitor & Tauri (TS) + ```typescript TypeScript // Get all todos const todos = await db.getAll('SELECT * FROM todos'); @@ -1313,7 +1313,7 @@ Read data using SQL queries. The data comes from your client-side SQLite databas Write data using SQL `INSERT`, `UPDATE`, or `DELETE` statements. PowerSync automatically queues these mutations and uploads them to your backend via the `uploadData()` function, once you've fully implemented your _backend connector_ (as we'll talk about below). - ```typescript React Native, Web, Node.js, Capacitor & Tauri (TS) + ```typescript TypeScript // Insert a new todo await db.execute( 'INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)', diff --git a/sync/streams/client-usage.mdx b/sync/streams/client-usage.mdx index dddd3516..d65b7333 100644 --- a/sync/streams/client-usage.mdx +++ b/sync/streams/client-usage.mdx @@ -11,8 +11,13 @@ Streams that are configured to [auto-subscribe](/sync/streams/overview#using-aut For any other streams, the basic pattern is: **subscribe** to a stream, **wait** for data to sync, then **unsubscribe** when done. + + + **Tauri SDK**: The JavaScript API shown in the TypeScript/JavaScript tabs throughout this page applies to Tauri as well. Import from `@powersync/tauri-plugin` (for `PowerSyncTauriDatabase`) or `@powersync/common` (for shared types). See the [Connection Parameters](#connection-parameters) section below for how Tauri handles connect-time parameters differently. + + ```js // Subscribe to a stream with parameters const sub = await db.syncStream('list_todos', { list_id: 'abc123' }).subscribe(); @@ -288,6 +293,7 @@ The generated output (JavaScript/TypeScript) looks like: ```typescript import { column, Schema, Table, PowerSyncDatabase, SyncStream } from '@powersync/web'; // OR: import { ... } from '@powersync/react-native'; +// OR (Tauri): import { ... } from '@powersync/common'; // ... table definitions ... @@ -551,6 +557,10 @@ streams: Set connection parameters when connecting: + + **Tauri SDK**: Since `connect()` must be called from Rust for Tauri, connection parameters are passed via `SyncOptions` in your Rust connector. See the [Tauri SDK reference](/client-sdks/reference/tauri#2-instantiate-the-powersync-database) for details on setting up the Rust connector. + + ```js diff --git a/sync/streams/migration.mdx b/sync/streams/migration.mdx index e976846c..c904c4dc 100644 --- a/sync/streams/migration.mdx +++ b/sync/streams/migration.mdx @@ -52,6 +52,7 @@ If you want "sync everything upfront" behavior (like Sync Rules), set [`auto_sub | React hooks | v1.8.0 | — | | Node.js | v0.11.0 | v0.16.0 | | Capacitor | v0.0.1 | v0.3.0 | +| Tauri | v0.0.1 | Always (Rust client only) | | Dart/Flutter | v1.16.0 | v1.17.0 | | Kotlin | v1.7.0 | v1.9.0 | | Swift | v1.11.0 | v1.8.0 | From fb353d4e7a85ab0bd83229169f283b9d8b14571f Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 26 Mar 2026 14:33:13 +0200 Subject: [PATCH 5/6] pre-alpha wording --- client-sdks/reference/kotlin.mdx | 19 ------------------- client-sdks/reference/rust.mdx | 2 +- .../app-backend/client-side-integration.mdx | 4 ++-- resources/feature-status.mdx | 4 ++-- 4 files changed, 5 insertions(+), 24 deletions(-) diff --git a/client-sdks/reference/kotlin.mdx b/client-sdks/reference/kotlin.mdx index 9effe884..c54090a6 100644 --- a/client-sdks/reference/kotlin.mdx +++ b/client-sdks/reference/kotlin.mdx @@ -342,22 +342,3 @@ See [Supported Platforms -> Kotlin SDK](/resources/supported-platforms#kotlin-sd ## Upgrading the SDK Update your project's Gradle file (`build.gradle.kts`) with the latest version of the [SDK](https://central.sonatype.com/artifact/com.powersync/core). - -## Developer Notes - -### Client Implementation - -The PowerSync Service sends encoded instructions about data to sync to connected clients. -These instructions are decoded by our SDKs, and on Kotlin there are two implementations available for this: - -1. **Kotlin (default)** - - This is the original implementation method, mostly implemented in Kotlin. - - Most upcoming features will not be ported to this implementation, and we intend to remove it eventually. -2. **Rust (currently experimental)** - - This is a newer implementation, mostly implemented in Rust but still using Kotlin for networking. - - Apart from newer features, this implementation is also more performant. - - We [encourage interested users to try it out](https://releases.powersync.com/announcements/improved-sync-performance-in-our-client-sdks) - and report feedback, as we intend to make it the default after a stabilization period. - -To enable the Rust client, pass `SyncOptions(newClientImplementation = true)` as a second parameter when -[connecting](https://powersync-ja.github.io/powersync-kotlin/core/com.powersync/-power-sync-database/connect.html). diff --git a/client-sdks/reference/rust.mdx b/client-sdks/reference/rust.mdx index 44f014bb..8331368c 100644 --- a/client-sdks/reference/rust.mdx +++ b/client-sdks/reference/rust.mdx @@ -11,7 +11,7 @@ import GenerateSchemaAutomatically from '/snippets/generate-schema-automatically import LocalOnly from '/snippets/local-only-escape.mdx'; - This SDK is currently in a **pre-alpha / experimental** state and is intended for gathering external feedback. It is not suitable for production use. + This SDK is currently in **pre-alpha** and is intended for gathering external feedback. It is not suitable for production use. We also can't guarantee continued support for the SDK at this time. If you're interested in using the PowerSync Rust SDK, please [contact us](/resources/contact-us) with details about your use case. diff --git a/configuration/app-backend/client-side-integration.mdx b/configuration/app-backend/client-side-integration.mdx index 4ab9413e..84bfc0ff 100644 --- a/configuration/app-backend/client-side-integration.mdx +++ b/configuration/app-backend/client-side-integration.mdx @@ -36,11 +36,11 @@ For an example implementation of a PowerSync 'backend connector', see the SDK gu - + - + ## More Examples diff --git a/resources/feature-status.mdx b/resources/feature-status.mdx index 15db6205..fab2e9f6 100644 --- a/resources/feature-status.mdx +++ b/resources/feature-status.mdx @@ -56,8 +56,8 @@ Below is a summary of the current main PowerSync features and their release stat | Postgres Bucket Storage | V1 | | | | | **Client SDKs** | | -| Tauri SDK | Experimental | -| Rust SDK | Experimental | +| Tauri SDK | Pre-alpha | +| Rust SDK | Pre-alpha | | .NET SDK | Beta | | Capacitor SDK | Alpha | | TanStack Query | Alpha | From 771c518baf2b2b33bb7bede264db00ce744431aa Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 26 Mar 2026 14:51:53 +0200 Subject: [PATCH 6/6] android kotlin icon --- README.md | 2 +- client-sdks/advanced/data-encryption.mdx | 2 +- client-sdks/orms/overview.mdx | 2 +- configuration/app-backend/client-side-integration.mdx | 2 +- docs.json | 2 +- intro/examples.mdx | 2 +- resources/supported-platforms.mdx | 2 +- snippets/client-sdks.mdx | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3a186563..3aed5a0f 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ We use the following icons for supported backend databases and SDKs: - Flutter: `icon="flutter"` - React Native: `icon="react"` - Web: `icon="js"` -- Kotlin: `icon="k"` +- Kotlin: `icon="android"` - Swift: `icon="swift"` - Node.js: `icon="node-js"` - .NET: `icon="microsoft"` diff --git a/client-sdks/advanced/data-encryption.mdx b/client-sdks/advanced/data-encryption.mdx index 241a17ea..0b8a9746 100644 --- a/client-sdks/advanced/data-encryption.mdx +++ b/client-sdks/advanced/data-encryption.mdx @@ -48,7 +48,7 @@ The client-side database can be encrypted at rest. This is currently available f Encryption support is available for PowerSync's Node.js SDK using [`better-sqlite3-multiple-ciphers`](https://www.npmjs.com/package/better-sqlite3-multiple-ciphers). See usage details and code examples in the [Node.js SDK reference](/client-sdks/reference/node#encryption-and-custom-sqlite-drivers). - + Encryption support is available for PowerSync's Kotlin SDK (since version 1.9.0) using [`SQLite3MultipleCiphers`](https://utelle.github.io/SQLite3MultipleCiphers/) via the [`com.powersync:sqlite3multipleciphers`](https://central.sonatype.com/artifact/com.powersync/sqlite3multipleciphers) package. This allows you to encrypt your local SQLite database with various cipher algorithms. **Setup:** diff --git a/client-sdks/orms/overview.mdx b/client-sdks/orms/overview.mdx index feae310d..80177a6d 100644 --- a/client-sdks/orms/overview.mdx +++ b/client-sdks/orms/overview.mdx @@ -19,7 +19,7 @@ We specifically avoid implementing our own ORM since we feel it's better to supp - + ## Learn More diff --git a/configuration/app-backend/client-side-integration.mdx b/configuration/app-backend/client-side-integration.mdx index 84bfc0ff..537fb9ee 100644 --- a/configuration/app-backend/client-side-integration.mdx +++ b/configuration/app-backend/client-side-integration.mdx @@ -37,7 +37,7 @@ For an example implementation of a PowerSync 'backend connector', see the SDK gu - + diff --git a/docs.json b/docs.json index 02aceca0..d55f044e 100644 --- a/docs.json +++ b/docs.json @@ -302,7 +302,7 @@ }, { "group": "Kotlin", - "icon": "k", + "icon": "android", "pages": [ "client-sdks/reference/kotlin", { diff --git a/intro/examples.mdx b/intro/examples.mdx index 4cd4f675..05004697 100644 --- a/intro/examples.mdx +++ b/intro/examples.mdx @@ -120,7 +120,7 @@ All examples are organized by platform and backend technology. You can adapt any - [Electron Main Process](https://github.com/powersync-ja/powersync-js/tree/main/demos/example-electron-node#readme) - PowerSync in Electron's main process using the Node.js SDK. See [this blog post](https://www.powersync.com/blog/speeding-up-electron-apps-with-powersync) for more background - [Node.js + Drizzle Minimal Demo](https://github.com/powersync-community/nodejs-drizzle-example) - + #### Supabase Backend - [To-Do List App](https://github.com/powersync-ja/powersync-kotlin/tree/main/demos/supabase-todolist#readme) diff --git a/resources/supported-platforms.mdx b/resources/supported-platforms.mdx index 7aa0aa3b..0a15831e 100644 --- a/resources/supported-platforms.mdx +++ b/resources/supported-platforms.mdx @@ -76,7 +76,7 @@ description: "Supported platforms and major features by PowerSync Client SDK" | HTTP connection method | Yes | | | WebSocket connection method | Yes | | -## Kotlin SDK +## Kotlin SDK | Platform / Feature | Supported? | Notes | | --- | --- | --- | diff --git a/snippets/client-sdks.mdx b/snippets/client-sdks.mdx index 32e0ec17..6064e897 100644 --- a/snippets/client-sdks.mdx +++ b/snippets/client-sdks.mdx @@ -11,7 +11,7 @@ - +