This package gives you:
Supabase::Credentialsfor shared project configurationSupabase::AuthClientfor sign-in, sign-up, OAuth, and password resetSupabase::DatabaseClientfor fluent PostgREST queriesSupabase::StorageClientfor storage URLs, listing, downloads, remove, and signed URLsSupabase::RealtimeClientfor live Postgres change subscriptions over WebSocket
Install from the Coi registry:
coi add @coi/supabaseThen import it:
import "@coi/supabase";
import "@coi/supabase";
module App;
mut Supabase::Credentials creds = Supabase::Credentials(
"https://your-project.supabase.co",
"your-publishable-key"
);
mut Supabase::AuthClient auth = Supabase::AuthClient(creds);
mut Supabase::DatabaseClient db = Supabase::DatabaseClient(creds);
mut Supabase::StorageClient storage = Supabase::StorageClient(creds);
mut Supabase::RealtimeClient realtime = Supabase::RealtimeClient(creds);
pub pod Credentials {
string url;
string publishableKey;
}
Use one credentials object and pass it to all clients.
Create a client:
mut Supabase::AuthClient auth = Supabase::AuthClient(creds);
Main methods:
onSuccess(handler)onError(handler)onAuthSuccess(handler)onAuthError(handler)signUp(email, password)signIn(email, password)signInWithOAuth(provider, redirectTo)resetPassword(email)signOut()isAuthenticated() : boolgetAccessToken() : stringgetPublishableKey() : stringconfigure(url, publishableKey)configureCredentials(credentials)setPublishableKey(key)
State fields you can read:
loadingauthenticatedaccessTokenuserIduserEmaillastErrorlastResponse
Example:
def handleAuthSuccess(string response) : void {
System.log(response);
}
def handleAuthError(string error) : void {
System.error(error);
}
auth.onSuccess(&handleAuthSuccess);
auth.onError(&handleAuthError);
auth.signIn("email@example.com", "password");
if (!auth.lastError.isEmpty()) {
System.error(auth.lastError);
}
Create a client:
mut Supabase::DatabaseClient db = Supabase::DatabaseClient(creds);
Simple one-liner style:
db.selectFrom("users", "*", 1);
if (!db.lastError.isEmpty()) {
System.error(db.lastError);
} else {
System.log(db.lastResponse);
}
Builder style (when you need multiple filters/modifiers):
def handleDbSuccess(string response) : void {
System.log(response);
}
def handleDbError(string error) : void {
System.error(error);
}
db.onSuccess(&handleDbSuccess);
db.onError(&handleDbError);
db.from("users");
db.limit(1);
db.select("*");
if (!db.lastError.isEmpty()) {
System.error(db.lastError);
} else {
System.log(db.lastResponse);
}
onSuccess(handler)onError(handler)onSelectSuccess(handler)onSelectError(handler)from(table)select(columns)selectFrom(table, columns, count)insert(jsonData)insertInto(table, jsonData)update(jsonData)updateWhereEq(table, column, value, jsonData)single()resetQuery()configure(url, publishableKey)configureCredentials(credentials)
eq(column, value)neq(column, value)gt(column, value)lt(column, value)gte(column, value)lte(column, value)like(column, pattern)ilike(column, pattern)inList(column, values)order(column, ascending)limit(count)offset(start)
State fields:
loadinglastErrorlastResponse
Create a client:
mut Supabase::StorageClient storage = Supabase::StorageClient(creds);
Main methods:
onSuccess(handler)onError(handler)onStorageSuccess(handler)onStorageError(handler)from(bucket)getPublicUrl(path) : stringpublicUrl(bucket, path) : stringdownload(path)list(path)listFrom(bucket, path)remove(path)removeFrom(bucket, path)createSignedUrl(path, expiresIn)createSignedUrlFrom(bucket, path, expiresIn)configure(url, publishableKey)configureCredentials(credentials)
State fields:
loadinglastErrorlastResponse
Example:
def handleStorageSuccess(string response) : void {
System.log(response);
}
def handleStorageError(string error) : void {
System.error(error);
}
storage.onSuccess(&handleStorageSuccess);
storage.onError(&handleStorageError);
storage.from("avatars");
string publicUrl = storage.getPublicUrl("user-123.png");
System.log(publicUrl);
Create a client:
mut Supabase::RealtimeClient realtime = Supabase::RealtimeClient(creds);
Main methods:
connect()disconnect()reconnect()subscribeToTable(schema, table, event)unsubscribe()ping()onEvent(handler)onError(handler)configure(url, publishableKey)configureCredentials(credentials)
Note: Realtime uses onEvent + onError (no onSuccess callback).
State fields:
connectedloadingeventCountlastEventlastError
Example:
def handleRealtimeEvent(string payload) : void {
System.log(payload);
}
def handleRealtimeError(string error) : void {
System.error(error);
}
realtime.onEvent(&handleRealtimeEvent);
realtime.onError(&handleRealtimeError);
// Subscribe to all row changes in public.messages
realtime.subscribeToTable("public", "messages", "*");
Event filter examples for subscribeToTable:
"*"(all events)"INSERT""UPDATE""DELETE"
Note: Enable Realtime for your table in Supabase first, otherwise no row-change events will be emitted.
import "@coi/supabase";
module App;
mut Supabase::Credentials creds = Supabase::Credentials(
"https://your-project.supabase.co",
"your-publishable-key"
);
mut Supabase::AuthClient auth = Supabase::AuthClient(creds);
mut Supabase::DatabaseClient db = Supabase::DatabaseClient(creds);
mut Supabase::StorageClient storage = Supabase::StorageClient(creds);
mut Supabase::RealtimeClient realtime = Supabase::RealtimeClient(creds);
import "@coi/supabase";
module App;
component AuthDemo {
mut Supabase::Credentials creds = Supabase::Credentials(
"https://your-project.supabase.co",
"your-publishable-key"
);
mut Supabase::AuthClient auth = Supabase::AuthClient(creds);
def handleAuthSuccess(string response) : void {
System.log(response);
}
def handleAuthError(string error) : void {
System.error(error);
}
def run() : void {
auth.onSuccess(&handleAuthSuccess);
auth.onError(&handleAuthError);
auth.signUp("new-user@example.com", "password123");
auth.signIn("new-user@example.com", "password123");
auth.signInWithOAuth("github", "http://localhost:8000/auth/callback");
auth.resetPassword("new-user@example.com");
if (!auth.lastError.isEmpty()) {
System.error(auth.lastError);
}
if (auth.isAuthenticated()) {
System.log("Signed in");
System.log(auth.getAccessToken());
}
auth.signOut();
}
}
import "@coi/supabase";
module App;
component DatabaseDemo {
mut Supabase::Credentials creds = Supabase::Credentials(
"https://your-project.supabase.co",
"your-publishable-key"
);
mut Supabase::DatabaseClient db = Supabase::DatabaseClient(creds);
def handleDbSuccess(string response) : void {
System.log(response);
}
def handleDbError(string error) : void {
System.error(error);
}
def run() : void {
db.onSuccess(&handleDbSuccess);
db.onError(&handleDbError);
// Simple one-liner query
db.selectFrom("users", "id,name,email", 10);
// Builder query with filters/modifiers
db.from("users");
db.ilike("email", "%@example.com");
db.order("id", true);
db.limit(5);
db.select("id,name,email");
// Insert row
db.insertInto("users", `{"name":"Ava","email":"ava@example.com"}`);
// Update row (where id == 1)
db.updateWhereEq("users", "id", "1", `{"name":"Ava Updated"}`);
if (!db.lastError.isEmpty()) {
System.error(db.lastError);
} else {
System.log(db.lastResponse);
}
}
}
import "@coi/supabase";
module App;
component StorageDemo {
mut Supabase::Credentials creds = Supabase::Credentials(
"https://your-project.supabase.co",
"your-publishable-key"
);
mut Supabase::StorageClient storage = Supabase::StorageClient(creds);
def handleStorageSuccess(string response) : void {
System.log(response);
}
def handleStorageError(string error) : void {
System.error(error);
}
def run() : void {
storage.onSuccess(&handleStorageSuccess);
storage.onError(&handleStorageError);
storage.from("avatars");
string url = storage.getPublicUrl("users/user-1.png");
System.log(url);
storage.list("users");
storage.download("users/user-1.png");
storage.createSignedUrl("users/user-1.png", 3600);
storage.remove("users/user-1.png");
// One-call helper
string sameUrl = storage.publicUrl("avatars", "users/user-2.png");
System.log(sameUrl);
if (!storage.lastError.isEmpty()) {
System.error(storage.lastError);
} else {
System.log(storage.lastResponse);
}
}
}
import "@coi/supabase";
module App;
component RealtimeDemo {
mut Supabase::Credentials creds = Supabase::Credentials(
"https://your-project.supabase.co",
"your-publishable-key"
);
mut Supabase::RealtimeClient realtime = Supabase::RealtimeClient(creds);
def handleRealtimeEvent(string payload) : void {
System.log(payload);
}
def handleRealtimeError(string error) : void {
System.error(error);
}
mount {
realtime.onEvent(&handleRealtimeEvent);
realtime.onError(&handleRealtimeError);
// Subscribe to all changes on public.messages
realtime.subscribeToTable("public", "messages", "*");
}
def cleanup() : void {
realtime.unsubscribe();
realtime.disconnect();
}
}
With your Coi app set up in the same workspace, build as usual:
coi build or coi devMIT License (see LICENSE).