RafikiDB Dart SDK#
You are working with the rafikidb Dart package (pub.dev, pure Dart, works
in Flutter, server and CLI). Install: dart pub add rafikidb.
Setup#
import 'package:rafikidb/rafikidb.dart';
final db = RafikiDB(
projectId: '5c73dab0-...',
apiKey: 'raf_live_...',
baseUrl: 'https://api.rafikidb.com/api/v1', // optional
persistSession: true, // file store under ~/.rafikidb/{projectId}.json
);
DART- Every call returns
Envelope<T>withsuccess,message,data?,errors?. - Failures throw
RafikiDBErrorwithstatus,code(RafikiDBErrorCodeenum) anderrors. persistSession: trueuses aFileSessionStore(pure Dart). In Flutter, pass a customSessionStorebacked byshared_preferences.
Data#
final rows = await db
.from('profiles')
.select('id, nationality')
.eq('nationality', 'Tanzania')
.gt('age', 18)
.inList('region', ['dar', 'mba'])
.order('created_at', ascending: false)
.limit(25)
.execute();
DART- Filters:
eq, neq, gt, gte, lt, lte, like, ilike, isNull, isNotNull, inList. - Pagination:
limit,offset,cursor(id)(keyset, for large tables). - Single row:
.get(id); first row or null:.single(); count:.head().
Joins (no SQL, via query engine)#
final rows = await db
.from('messages')
.select('id, message, users.full_name')
.join(JoinSpec(
table: 'users',
fromColumn: 'user_id',
toColumn: 'id',
type: 'LEFT JOIN', // INNER | LEFT | RIGHT | FULL
))
.limit(20)
.execute();
DARTJoined columns appear as {table}.{column}. Joins route through
POST /projects/{id}/query/run.
Writes#
final created = await db.from('profiles').insert({
'full_name': 'Asha Mwinyi',
'nationality': 'Tanzania',
});
// update/delete are scoped with filters FIRST (they execute immediately)
await db.from('profiles').eq('id', id).update({'nationality': 'Kenya'});
await db.from('profiles').eq('id', id).delete();
DARTupdate() / delete() require an eq('id', ...) filter, else they throw a
StateError.
Auth (project users, not dashboard)#
final created = await db.auth.signup(SignupOptions(
email: 'asha@example.com',
password: 'strong-pass1',
fullName: 'Asha Mwinyi',
phone: '+255712345678',
));
final session = await db.auth.login(SigninOptions(email: ..., password: ...));
await db.auth.otpRequest('+255712345678');
await db.auth.otpVerify(phone: ..., code: '123456', fullName: 'Asha');
await db.auth.resetPassword(email);
await db.auth.confirmResetPassword(email: ..., code: ..., newPassword: ...);
db.auth.signOut();
await db.auth.refresh(refreshToken);
await db.auth.logout(refreshToken);
DART- Login/signup/OTP-verify auto-store the session; every request then carries the Bearer token so RLS sees the authenticated user.
- Session persistence:
persistSession: true(file) or a custom store:
class PrefsSessionStore implements SessionStore {
PrefsSessionStore(this.prefs);
final SharedPreferences prefs;
Session? read() {
final raw = prefs.getString('rafikidb_session');
return raw == null ? null : Session.fromJson(jsonDecode(raw));
}
void write(Session? session) {
if (session == null) {
prefs.remove('rafikidb_session');
} else {
prefs.setString('rafikidb_session', jsonEncode(session.toJson()));
}
}
}
DART- React to changes:
db.sessionStream.listen((s) {})(emits null on sign-out) ordb.subscribeSession((s) {}). - Dashboard login (RafikiDB account holders only):
db.auth.platformLogin(email:, password:).
Realtime#
final sub = db.realtime.subscribe(
'messages',
(event) => print('${event.type}: ${event.record}'),
options: const SubscribeOptions(
events: ['INSERT', 'DELETE'], // optional
transport: RealtimeTransport.auto, // auto | centrifugo | sse
),
);
sub.unsubscribe();
DARTeventis aRealtimeEvent:{ id, type, table, projectId, record, oldRecord?, createdAt }.auto/centrifugouse WebSocket via Centrifugo (POST /realtime/connect, v6 wire: send{"id": 1, "connect": {"token": token}});sseuses a plain HTTP stream. Both auto-reconnect with exponential backoff (1s..30s).
Modules#
// Storage
await db.storage.createBucket(name: 'Avatars', slug: 'avatars', isPublic: true, fileSizeLimit: 5 * 1024 * 1024);
await db.storage.listBuckets();
await db.storage.signedUploadUrl(bucketId: b['id'], objectName: 'user-1.png');
await db.storage.signedDownloadUrl(objectId);
db.storage.publicUrl(bucketId, objectId);
// Env vars
await db.env.set('STRIPE_KEY', 'sk_test_123', environment: 'production');
await db.env.bulkSet('development', {'DEBUG': 'true'});
// Secrets (write-only)
await db.secrets.set(key: 'API_SECRET', value: 's3cr3t', description: '...');
await db.secrets.reveal(secretId);
// Webhooks
await db.webhooks.create(name: 'Order', url: 'https://myapp.com/hooks/orders', events: ['order.created'], secret: 'whsec_...');
await db.webhooks.listDeliveries(webhookId);
// Edge functions
await db.functions.create(name: 'hello', runtime: 'javascript', code: '...');
await db.functions.deploy(fnId);
await db.functions.invoke(fnId, method: 'POST', body: '{"name":"Asha"}');
// Payments (Snippe + M-Pesa)
await db.payments.stkPush(phone: '+255712345678', amount: 5000, description: 'Order #123');
await db.payments.snippeSession(amount: 15000, redirectUrl: 'https://myapp.com/cb', orderId: 'o1');
await db.payments.snippeStatus(reference);
DARTFlutter pattern#
StreamBuilder<Session?>(
stream: db.sessionStream,
builder: (context, snapshot) {
final session = snapshot.data ?? db.session;
if (session == null) return const SignInForm();
return Text('Welcome, ${session.user.fullName}');
},
)
DARTGotchas#
update/deletethrow unless.eq('id', ...)is set first (filters chain before the write call).- Dashboard auth (
platformLogin) is NOT for app users; app auth is project-scoped. persistSessionwrites under~/.rafikidb/by default; use a customSessionStorefor Flutter.