sqlitenow_oversqlite 0.16.0
sqlitenow_oversqlite: ^0.16.0 copied to clipboard
Dart Oversqlite sync runtime for SQLiteNow generated sync metadata.
sqlitenow_oversqlite #
Add offline-first synchronization to SQLiteNow databases in Dart and Flutter applications.
sqlitenow_oversqlite tracks local changes, pushes them to an Oversync server, applies remote
changes to SQLite, and keeps generated reactive queries up to date. It supports explicit and
automatic downloads, conflict resolution, snapshot recovery, and multiple devices attached to the
same user account.
This package targets Dart VM and Flutter native applications. It is used with a database generated
by sqlitenow_cli and a compatible Oversync server.
Install #
Use the same version for all SQLiteNow packages:
dependencies:
sqlitenow_runtime: ^0.16.0
sqlitenow_oversqlite: ^0.16.0
dev_dependencies:
sqlitenow_cli: ^0.16.0
Generate a sync-enabled database #
Enable Oversqlite for your database in sqlitenow.yaml:
databases:
AppDatabase:
input: lib/db/sql/AppDatabase
output: lib/db/generated
package: app.db
runtime: dart
oversqlite: true
Mark every table that should synchronize with enableSync=true:
-- @@{ enableSync=true }
CREATE TABLE person (
id TEXT PRIMARY KEY NOT NULL,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL
);
Generate the Dart database:
dart run sqlitenow_cli generate
For a Flutter application, use:
flutter pub run sqlitenow_cli generate
The generated database exposes buildOversqliteConfig(...) and
newOversqliteClient(...) for the synchronized tables.
Numeric wire handling is automatic. SQLite INTEGER and finite REAL values synchronize as
canonical JSON strings, exact decimals remain SQLite TEXT strings, and SQLite Boolean affinity
uses strict "0"/"1" ingress strings. No per-column numeric configuration is required.
Connect and sync #
Open the generated database, create an authenticated HTTP transport, and create the generated Oversqlite client:
import 'dart:io';
import 'package:sqlitenow_oversqlite/sqlitenow_oversqlite.dart';
import 'db/generated/app_database.dart';
final database = AppDatabase(path: databasePath);
await database.open();
final httpClient = IoOversqliteHttpClient(
baseUri: Uri.parse('https://api.example.com'),
defaultHeaders: {
HttpHeaders.authorizationHeader: 'Bearer $accessToken',
},
);
final syncClient = database.newOversqliteClient(
schema: 'app',
httpClient: httpClient,
);
await syncClient.open();
final attachResult = await syncClient.attach(userId);
if (attachResult case AttachConnected()) {
await syncClient.sync();
}
Call open() on each application launch. Call attach(userId) after authentication establishes
the current account, then use sync() whenever the application should exchange local and remote
changes. AttachRetryLater indicates that the remote attachment should be retried later.
Every remote capabilities check compares the generated local table/key contract with the server's
required registered_table_specs. Initial and remote attach fail before connect or snapshot work
when the contracts differ. A same-user durable attach resume remains network-free and validates on
the next operation that already contacts the server. SyncTableContractMismatchException exposes
sorted serverOnlyTables, clientOnlyTables, and syncKeyMismatches; automatic downloads treat it
as terminal. This check covers exact table and ordered sync-key compatibility, not wire-profile or
projection negotiation.
Your application owns authentication. IoOversqliteHttpClient sends the headers you provide along
with the Oversqlite source identity managed by the local database.
Sync operations #
sync()pushes pending local changes and pulls remote changes until stable.pushPending()uploads pending local changes without running a pull.pullToStable()downloads and applies remote changes without running a push.syncStatus()reports pending local and remote work.rebuild()restores the local synchronized state from a server snapshot.syncThenDetach()synchronizes and disconnects the current account.
Normal sync() and pullToStable() automatically recover checkpoints when server history no
longer matches local state. See the sync documentation
for recovery behavior and pending-work handling.
Generated SQLiteNow writes are captured automatically. Remote changes applied by Oversqlite also invalidate generated reactive queries, so active query streams receive the updated rows.
Automatic downloads #
Automatic downloads are optional and disabled by default:
final downloads = syncClient.startAutomaticDownloads();
// Stop the worker when its owning application scope shuts down.
await downloads.stop();
Configure polling and bundle-change watching through the generated newOversqliteClient(...)
arguments.