Skip to main content

Crate supabase_rp

Crate supabase_rp 

Source
Expand description

§supabase-rp

crates.io docs.rs

One entry point for Supabase from Rust. Client holds your project URL, your API key, and one shared HTTP connection pool. It gives you REST, auth, storage, edge functions, and realtime configuration.

§Install

[dependencies]
supabase-rp = { version = "0.5", features = ["full"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
FeatureDefaultEnables
restyesClient::rest, Client::from (PostgREST)
authyesClient::auth (Supabase Auth)
storagenoClient::storage (buckets, objects, signed URLs)
functionsnoClient::functions (edge functions)
realtimenoClient::realtime_config (websocket channels)
typednoRe-exports rp-supabase-client as supabase_rp::typed (schema runtime only)
typed-clientnotyped plus the client API of rp-supabase-client (enables serde_json/arbitrary_precision)
test-utilnorp-postgrest/test-util, for example postgrest::Error::from_response in tests
fullnoAll of the above except test-util

Each enabled crate is re-exported as a module (see Module map). You need only this one dependency.

The default HTTP client of Client::new follows up to 10 redirects, and only to the same origin (scheme, host, port), so credentials never reach another host. Client::new_with_client uses your client and its redirect policy unchanged.

§Quickstart

Pass the project root URL, for example https://abc.supabase.co/, and the project API key. A URL with a path, such as https://gateway.example/supabase, is rejected.

use supabase_rp::Client;

#[derive(Debug, serde::Deserialize)]
struct Todo {
    id: i64,
    title: String,
}

let client = Client::new("https://abc.supabase.co/", "your-anon-key")?;
let todos = client.from("todos").select("id,title").fetch::<Vec<Todo>>().await?;
println!("{todos:?}");

§Sign in and act as the user

Sign in, then call with_access_token. The new client sends the user token to REST, auth, storage, and functions, so row level security applies. The apikey header keeps the project key. The connection pool is shared.

use supabase_rp::auth::types::LoginCredentials;

let login = LoginCredentials::email("user@example.com".to_owned(), "password".to_owned());
let session = client.auth().sign_in_with_password(&login).await?;
let token = session.access_token.ok_or("sign-in returned no access token")?;
let user_client = client.with_access_token(&token)?;

let me = user_client.auth().get_user().await?;
println!("{me:?}");
user_client.auth().sign_out().await?;

§Storage

Requires the storage feature.

use supabase_rp::storage::FileOptions;

let avatars = client.storage().from("avatars");
let options = FileOptions {
    content_type: Some("image/png".to_owned()),
    ..FileOptions::default()
};
avatars.upload("user-1/avatar.png", vec![0_u8; 16], &options).await?;
let url = avatars.create_signed_url("user-1/avatar.png", 60).await?;
println!("{url}");

§Separate storage URL

A custom domain can proxy REST and auth but not storage. Call with_storage_url with the storage project root URL. Storage still joins storage/v1. REST, auth, and functions keep the URL from Client::new. An access token from with_access_token stays, in either call order.

let client = supabase_rp::Client::new("https://api.example.com/", "your-anon-key")?
    .with_storage_url("https://abc.supabase.co/")?;

§Edge functions

Requires the functions feature.

#[derive(serde::Serialize)]
struct Input<'a> {
    name: &'a str,
}

#[derive(Debug, serde::Deserialize)]
struct Output {
    message: String,
}

let reply: Output = client
    .functions()
    .invoke("hello")
    .json(&Input { name: "world" })
    .fetch()
    .await?;
println!("{}", reply.message);

§Realtime

Requires the realtime feature. realtime_config returns the configuration that RealtimeConnection::db_changes, presence, and broadcast take. Realtime signs in on its own with LoginCredentials. If sign-in or a token refresh fails, it retries up to 5 times, 3 seconds apart. The websocket itself does not reconnect. Change the returned fields to override the retry settings.

use supabase_rp::realtime::futures::StreamExt as _;
use supabase_rp::realtime::message::phx_join::PostgresChanges;
use supabase_rp::realtime::realtime::{RealtimeConnection, typed_changes};

#[derive(Debug, serde::Deserialize)]
struct Todo {
    id: i64,
    title: String,
}

let (stream, mut channel) = RealtimeConnection::db_changes(client.realtime_config())
    .connect(login)
    .await?;
channel.subscribe_to_changes(vec![PostgresChanges::table("todos")]).await?;
let mut changes = std::pin::pin!(typed_changes::<Todo>(stream));
while let Some(change) = changes.next().await {
    println!("{:?}", change?);
}

See rp-supabase-realtime for broadcast and presence.

§Typed queries from your schema

The typed feature re-exports rp-supabase-client. Generate Rust types for your tables with rp-supabase-codegen, then run typed queries against client.rest(). It is the same Postgrest the typed runtime takes.

typed enables only the schema runtime. Set the codegen runtime_path to ::supabase_rp::typed::schema, and you need no direct rp-supabase-client dependency. Enable typed-client for the client API (authentication helpers and response decoding).

§Module map

PathCrateFeature
supabase_rp::postgrestrp-postgrestrest
supabase_rp::authrp-supabase-authauth
supabase_rp::storagerp-supabase-storagestorage
supabase_rp::functionsrp-supabase-functionsfunctions
supabase_rp::realtimerp-supabase-realtimerealtime
supabase_rp::typedrp-supabase-clienttyped

The module supabase_rp::auth holds the auth types. The method Client::auth() returns the auth client.

§Underlying crates

CratePurpose
rp-postgrestPostgREST query builder and decoding
rp-postgrest-errorTyped PostgREST error codes
rp-supabase-authSupabase Auth API and token refresh
rp-supabase-storageStorage buckets, objects, signed URLs
rp-supabase-functionsEdge function invocation
rp-supabase-realtimeRealtime changes, broadcast, presence
rp-supabase-clientTyped runtime for generated schemas
rp-supabase-codegenRust types generated from your database
rp-supabase-mockMock Supabase server for tests

Re-exports§

pub use rp_postgrest as postgrest;
pub use rp_supabase_auth as auth;
pub use rp_supabase_client as typed;
pub use rp_supabase_functions as functions;
pub use rp_supabase_realtime as realtime;
pub use rp_supabase_storage as storage;

Structs§

Client
Client for one Supabase project.
Url
A parsed URL record.

Enums§

Error
Errors from building a Client.

Constants§

REALTIME_MAX_RECONNECT_ATTEMPTS
Maximum sign-in and token refresh retries in Client::realtime_config.
REALTIME_RECONNECT_INTERVAL
Delay between sign-in and token refresh retries in Client::realtime_config.