RustaBase Dart SDK
Official Dart & Flutter client for RustaBase: one Rust backend, everything you need.
Website · JavaScript SDK · npm · LinkedIn
Works on Flutter (iOS, Android, web, desktop) and pure Dart servers. Its API mirrors the RustaBase JavaScript SDK.
This package is independently structured for RustaBase. Shared HTTP paths and payload names belong to the RustaBase wire protocol; its Dart transport, session persistence, retry policy, and tests are package-specific implementations.
Install
dart pub add rustabase
# or
flutter pub add rustabase
Quick start
import "package:rustabase/rustabase.dart";
final rb = createClient("https://my-app.rustabase.net");
await rb.auth("users").signInWithPassword("me@example.com", "secret");
final page = await rb.from("posts").list(
options: ListOptions(
filter: rb.filter("status = {:status}", {"status": "live"}),
sort: "-created",
),
);
final all = await rb.from("posts").all();
final post = await rb.from("posts").get("RECORD_ID");
final latest = await rb.from("posts").first("featured = true");
final created = await rb.from("posts").create({"title": "Hello"});
await rb.from("posts").update(created["id"].toString(), {"title": "Hello again"});
await rb.from("posts").remove(created["id"].toString());
final stop = await rb.from("posts").subscribe("*", (event) {
print("${event.action}: ${event.record}");
});
await stop();
Files
Dart uses http.MultipartFile for uploads:
import "package:http/http.dart" as http;
await rb.from("posts").create(
{"title": "Hello"},
files: [http.MultipartFile.fromString("attachment", "content", filename: "note.txt")],
);
final url = rb.files.url(record, record["avatar"].toString(), thumb: "100x100");
final token = await rb.files.token();
Sessions
MemorySession is the default. Use AsyncSession with any Flutter persistence package:
final session = AsyncSession(
initial: await storage.read("rb_session"),
save: (value) => storage.write("rb_session", value),
clearStorage: () => storage.remove("rb_session"),
);
final rb = createClient(url, session: session);
The session exposes token, record, isValid, isSuperuser, isUser, and the onChange stream. rb.signOut() clears it and cancels pending requests. Cookie helpers are available for server-rendered Dart applications.
Authentication
final users = rb.auth("users");
await users.signInWithPassword(email, password, keepAlive: 1800);
final otp = await users.requestOtp(email);
await users.signInWithOtp(otp["otpId"]!, "123456");
await users.refresh();
await users.methods();
await users.signInWithOAuth(
provider: "google",
openUrl: (url) => launchUrl(url),
);
Password reset, verification, email-change, OAuth code, and impersonation methods use the same names as the JavaScript SDK.
Batch writes
final batch = rb.batch();
batch.from("posts").create({"title": "A"});
batch.from("posts").update("id1", {"title": "B"});
batch.from("posts").upsert({"id": "id2", "title": "C"});
batch.from("comments").remove("id3");
final results = await batch.send();
Errors and hooks
All failures throw RustaBaseError, exposing status, data, fieldErrors, cancelled, and url.
rb.onRequest = (request) => request.copyWith(
headers: {...request.headers, "X-Trace": "1"},
);
rb.onResponse = (response, data) => data;
Duplicate requests use newest-request-wins semantics by default. Pass RequestOptions(autoCancel: false), disable rb.autoCancel, or call rb.cancel(key) / rb.cancelAll().
Slow or flaky networks: RequestOptions(timeout: Duration(seconds: 10), retry: 2) fails after the timeout and retries GET/HEAD requests on network errors and 502/503/504 responses. Writes are never retried.
Admin
Superuser tools are grouped under rb.admin: collections, settings, logs, backups, crons, apiKeys, webhooks, functions, rls, and sql().
Links
- Website: rustabase.com
- npm: npmjs.com/package/rustabase
- JavaScript SDK: github.com/rustabase/rustabase-js-sdk
- Dart / Flutter SDK: github.com/rustabase/rustabase-dart-sdk
- LinkedIn: linkedin.com/company/rustabase
License
MIT © RustaBase contributors
Generated types
Generate Dart model classes for your tables with one command (needs a superuser):
dart run rustabase:gen_types --url https://api.example.com --email admin@example.com --password '...'
# or from an exported schema file
dart run rustabase:gen_types --file schema.json --out lib/rustabase_types.dart
RUSTABASE_URL, RUSTABASE_TOKEN, RUSTABASE_EMAIL and RUSTABASE_PASSWORD
can be used instead of flags. Each table becomes a class with fromJson,
toJson and tableName:
import "rustabase_types.dart";
final page = await rb.from(Posts.tableName).list();
final posts = page.items.map(Posts.fromJson).toList();
Run the command again whenever your tables change. Password and hidden columns are never generated.