persql
PerSQL Dart and Flutter SDK. Query your edge SQLite databases, and sign a user in with OAuth + PKCE so each one gets their own private cloud database — the user owns the data, you fund it. No backups or storage to manage on the device.
flutter pub add persql # or: dart pub add persql
Give each user their own database ("Sign in with PerSQL")
The SDK does the OAuth 2.1 + PKCE handshake; your app only handles the browser
redirect (e.g. with flutter_web_auth_2).
import 'package:persql/persql.dart';
// 1. Begin sign-in. Open req.url; keep req.codeVerifier + req.state.
final req = PerSQL.beginConnect(
clientId: 'psqlrp_…',
redirectUri: 'https://app.example.com/callback', // App Link / Universal Link
scope: 'openid database',
);
// 2. After the redirect (verify state == req.state), exchange the code.
final persql = await PerSQL.completeConnect(
clientId: 'psqlrp_…',
redirectUri: 'https://app.example.com/callback',
code: code, // from the redirect
codeVerifier: req.codeVerifier,
);
// 3. Use the database provisioned in the user's own account.
final db = persql.database(persql.grant!.database);
await db.query('CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT)');
await db.query('INSERT INTO notes (body) VALUES (?)', params: ['first note']);
Store persql.grant!.accessToken with
flutter_secure_storage; on
later launches skip the OAuth dance:
final db = PerSQL(token: storedToken).database(storedDatabaseRef);
Query
final res = await db.query('SELECT id, body FROM notes WHERE id = ?', params: [1]);
for (final row in res.data) {
print('${row['id']}: ${row['body']}');
}
await db.batch([
Statement('INSERT INTO notes (body) VALUES (?)', ['a']),
Statement('INSERT INTO notes (body) VALUES (?)', ['b']),
], transaction: true);
final tables = await db.tables(); // List<TableInfo>
Errors throw `PerSQLException` with the HTTP status and message.
Notes
- Cloud-first by design. The user's data is durable from the first write — it survives a lost device and restores on reinstall, which is exactly what on-device-only storage can't promise.
- Redirect capture is your app's job — use
flutter_web_auth_2(or App Links / Universal Links). Custom URL schemes are rejected by PerSQL as phishable; register an HTTPS redirect or the platform proxy. - v0.1 covers
query/batch/tables+ the connect flow. Snapshots, branches, and change subscriptions are not wrapped yet.
See the User-owned app databases recipe.
Libraries
- persql
- PerSQL Dart and Flutter SDK.