RustaBase Dart SDK

Official Dart & Flutter client for RustaBase: one Rust backend, everything you need.

pub license JS SDK LinkedIn

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().

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.

Libraries

codegen
Turns a RustaBase schema (the list returned by GET /api/collections) into Dart model classes. Pure: no network or file access, so it can be used from build scripts and tests.
rustabase
Official multi-platform Dart and Flutter SDK for RustaBase.