RafikiDB JS / TypeScript SDK#
You are working with @rafikidb/sdk (npm, TypeScript, ESM + CJS). Install:
npm install @rafikidb/sdk.
Setup#
import { createClient } from "@rafikidb/sdk";
export const db = createClient({
projectId: "5c73dab0-...",
apiKey: "raf_live_...",
baseUrl: "https://api.rafikidb.com/api/v1", // optional
persistSession: true, // localStorage key: rafikidb_session.{projectId}
});
TypeScriptbaseUrldefaults tohttp://localhost:8080/api/v1.- All calls return the API
ApiEnvelope<T>:{ success, message, data?, errors? }. - Failures throw
RafikiDBErrorwithstatus,code(unauthorized, forbidden, not_found, conflict, invalid_input, quota_exceeded, internal_error) anderrors: string[].
Data#
// Read with filters
const { data } = await db
.from<Profile>("profiles")
.select("id, nationality")
.eq("nationality", "Tanzania")
.gt("age", 18)
.in("region", ["dar", "mba"])
.order("created_at", { ascending: false })
.limit(25)
.execute();
// Filters: eq, neq, gt, gte, lt, lte, like, ilike, isNull, isNotNull, in
// Pagination: limit, offset, cursor(id) (keyset, for large tables)
// Single row: .get(id), first row: .single(), count: .head()
TypeScriptexecute() is thenable, so await db.from("t").select() also works.
Joins (no SQL, via query engine)#
const { data } = await db
.from("messages")
.select("id, message, users.full_name")
.join({
type: "LEFT JOIN", // INNER | LEFT | RIGHT | FULL
table: "users",
from_column: "user_id",
to_column: "id",
})
.limit(20)
.execute();
TypeScriptJoined columns appear as {table}.{column}. Joins route through
POST /projects/{id}/query/run.
Writes#
await db.from("profiles").insert({ full_name: "Asha", nationality: "Tanzania" }); // single or array
await db.from("profiles").eq("id", id).update({ nationality: "Kenya" });
await db.from("profiles").eq("id", id).delete();
TypeScriptupdate() / delete() require an eq("id", ...) filter, else they throw.
Auth (project users, not dashboard)#
// Sign up / sign in (session auto-stored, sent with every request -> RLS)
const res = await db.auth.signup({ email, password, full_name, phone, metadata });
const session = await db.auth.login({ email, password }); // alias: signin
// OTP / reset
await db.auth.otpRequest("+255712345678");
await db.auth.otpVerify({ phone, code, full_name });
await db.auth.resetPassword(email);
await db.auth.confirmResetPassword({ email, code, new_password });
// Session
db.getSession(); // Session { user, tokens } | null
db.setSession(session); // manual restore/persist
db.subscribeSession((s) => {}); // unsubscribe fn returned
db.auth.signOut(); // clears + unpersists
db.auth.refresh(refreshToken); // rotates tokens
db.auth.logout(refreshToken);
TypeScriptpersistSession: trueauto-saves to localStorage underrafikidb_session.{projectId}and restores on boot.- Dashboard login is
db.auth.platformLogin({ email, password })- use only for RafikiDB account holders.
Realtime#
const sub = db.realtime.subscribe(
"messages",
(event) => {
// event: { id, type: "INSERT"|"UPDATE"|"DELETE", table, project_id, record, old_record?, created_at }
console.log(event.type, event.record);
},
{ events: ["INSERT", "DELETE"], transport: "auto" } // auto | centrifugo | sse
);
sub.unsubscribe();
TypeScriptautoprefers Centrifugo WebSocket (POST/realtime/connect-> scoped JWT, v6 wire: send{ id: 1, connect: { token } }, frames carrypush.channel+push.pub.data), falls back to SSE. Auto-reconnects with exponential backoff (1s..30s).
Modules#
// Storage
await db.storage.createBucket({ name, slug, is_public, file_size_limit, allowed_mime_types });
await db.storage.listBuckets();
await db.storage.signedUploadUrl({ bucket_id, object_name, content_length });
await db.storage.signedDownloadUrl(objectId);
db.storage.publicUrl(bucketId, objectId);
// Env vars
await db.env.set("STRIPE_KEY", "sk_test_123", "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, url, events, secret });
await db.webhooks.listDeliveries(webhookId);
// Edge functions
await db.functions.create({ name, runtime: "javascript", code });
await db.functions.deploy(fnId);
await db.functions.invoke(fnId, { method: "POST", body: "{}" });
// Payments (Snippe + M-Pesa)
await db.payments.stkPush({ phone: "+255712345678", amount: 5000, description });
await db.payments.snippeSession({ amount, redirect_url, order_id });
await db.payments.snippeStatus(reference);
TypeScriptReact hooks#
import { useAuth } from "@rafikidb/sdk/react";
const { user, session, signOut } = useAuth(); // reacts to db session changes
TypeScriptGotchas#
- Never call
platformLoginfor app users; app auth is project-scoped (/projects/{id}/auth/*). update/deletethrow unless.eq("id", ...)is set first.persistSessionkey includes the project id, so multiple projects do not collide.- If you pass a custom
fetch, it is invoked with the global receiver to avoid detached-fetch "Illegal invocation" errors.