### Start Local Supabase Instance Source: https://github.com/xylex-group/supabase_rs/blob/main/src/tests/readme.md Use this command to start a local Supabase instance. Ensure Supabase CLI and Docker are installed. ```bash supabase start ``` -------------------------------- ### Install Dependencies Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md Check the project dependencies to ensure all necessary packages are installed. ```bash cargo check ``` -------------------------------- ### Set Up Development Environment Variables Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Copy the example environment file and edit it with your Supabase credentials to configure the development environment. ```bash cp .env.example .env # Edit .env with your Supabase credentials ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md Copy the example environment file and edit it with your Supabase credentials for testing purposes. ```bash cp .env.example .env # Edit .env with your Supabase credentials for testing ``` -------------------------------- ### SQL for RPC Test Setup Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md This SQL script is used to set up test functions in your database for RPC testing. It should be executed as part of your test environment setup. ```sql -- src/tests/setup_rpc.sql -- This creates test functions for RPC testing ``` -------------------------------- ### RPC Function Documentation Examples Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN.md Illustrates how to call a Supabase RPC function with and without filters. The `no_run` attribute indicates that these examples are not meant to be compiled and run directly. ```rust /// Calls a Postgres RPC function. /// /// # Examples /// /// ```rust,no_run /// // Call a function 'echo' with arguments /// let result = client.rpc("echo", json!({"message": "hello"})).execute().await?; /// /// // Call a function returning a table and filter the results /// let users = client.rpc("get_active_users", json!({})) /// .eq("role", "admin") /// .limit(10) /// .execute() /// .await?; /// ``` ``` -------------------------------- ### SQL Setup Script for RPC Testing Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN_V2.md Defines sample PostgreSQL functions for testing RPC calls. Includes functions for void, scalar, and setof return types. ```sql -- Void return CREATE OR REPLACE FUNCTION test_void_func() RETURNS void AS $$ BEGIN -- do nothing END; $$ LANGUAGE plpgsql; -- Scalar return CREATE OR REPLACE FUNCTION test_echo(val text) RETURNS text AS $$ BEGIN RETURN val; END; $$ LANGUAGE plpgsql; -- Set return CREATE OR REPLACE FUNCTION test_get_users() RETURNS SETOF users AS $$ BEGIN RETURN QUERY SELECT * FROM users; END; $$ LANGUAGE plpgsql; ``` -------------------------------- ### Integration Test Example Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md Example of an integration test using Tokio, designed to test complete CRUD operations against a live Supabase instance. ```rust #[tokio::test] async fn test_user_crud() -> Result<(), String> { // Test complete CRUD operations } ``` -------------------------------- ### Initialize RpcBuilder Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN.md Use this to start building an RPC call. It requires the Supabase client, the function name, and any parameters to be passed to the function, which will be serialized to JSON. ```rust pub fn new(client: SupabaseClient, function_name: &str, params: T) -> Self { Self { client, function_name: function_name.to_string(), params: serde_json::to_value(params).unwrap_or(json!({})) query: Query::new(), } } ``` -------------------------------- ### RPC Client Setup Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md To enable RPC functionality, add the `rpc` feature to your `Cargo.toml` file. You can also combine it with other features like `native_tls` and disable default features if needed. ```APIDOC ## Enabling RPC Functionality To use the RPC module, you need to enable the `rpc` feature in your `Cargo.toml`. ### Add to Cargo.toml ```toml [dependencies] supabase_rs = { version = "0.5.1", features = ["rpc"] } ``` ### Customizing Features If you need to exclude default features (like `nightly`) and include `rpc` along with other specific features (e.g., `native_tls`): ```toml supabase_rs = { version = "0.5.1", features = ["rpc", "native_tls"], default-features = false } ``` ``` -------------------------------- ### Cargo.toml Version Pinning Strategies Source: https://github.com/xylex-group/supabase_rs/blob/main/MIGRATION.md Examples of how to pin the supabase_rs dependency in Cargo.toml for stability or to allow patch updates. ```toml # Pin to specific version for stability supabase_rs = "=0.4.14" ``` ```toml # Or use compatible versions supabase_rs = "~0.4.14" # Accepts patch updates ``` -------------------------------- ### Performance Test Example Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md Example of a performance test using Tokio, intended to measure the efficiency of bulk operations. ```rust #[tokio::test] async fn test_bulk_insert_performance() { // Measure performance of bulk operations } ``` -------------------------------- ### Insert Operation Implementation Source: https://github.com/xylex-group/supabase_rs/blob/main/ARCHITECTURE.md Shows the typical implementation pattern for CRUD operations within the SupabaseClient. This example specifically details the insert method signature. ```rust impl SupabaseClient { pub async fn insert(&self, table: &str, data: T) -> Result where T: serde::Serialize { // Implementation } } ``` -------------------------------- ### Unit Test Example Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md Example of a unit test within the Rust project, focusing on query construction without network calls. ```rust #[cfg(test)] mod tests { use super::*; #[test] fn test_query_building() { // Test query construction without network calls } } ``` -------------------------------- ### Download Files from Supabase Storage in Rust Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Initialize `SupabaseStorage` with your Supabase URL, bucket name, and filename. Use `.download()` to get file bytes into memory or `.save()` to download directly to disk. Ensure the `storage` feature is enabled in `Cargo.toml`. ```rust use supabase_rs::storage::SupabaseStorage; // Initialize storage client let storage = SupabaseStorage { supabase_url: std::env::var("SUPABASE_URL").unwrap(), bucket_name: "avatars".to_string(), filename: "user-123-avatar.jpg".to_string(), }; // Download file to memory let file_bytes = storage.download().await?; println!("Downloaded {} bytes", file_bytes.len()); // Download file directly to disk storage.save("./downloads/avatar.jpg").await?; ``` -------------------------------- ### Perform Insert Operations in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Provides examples of inserting data into Supabase tables using various methods: basic insert, insert with a struct, insert if unique, bulk insert, and insert with a client-generated ID. ```rust use supabase_rs::SupabaseClient; use serde::{Serialize}; use serde_json::json; #[derive(Serialize)] struct User { name: String, email: String, age: u32, } async fn insert_examples(client: &SupabaseClient) -> Result<(), String> { // Basic insert - returns the new row's ID let user_id = client.insert("users", json!({ "name": "Alice Johnson", "email": "alice@example.com", "age": 28 })).await?; println!("Created user with ID: {}", user_id); // Insert with struct let new_user = User { name: "Bob Smith".to_string(), email: "bob@example.com".to_string(), age: 35, }; let bob_id = client.insert("users", new_user).await?; // Insert only if unique (checks all provided fields) match client.insert_if_unique("users", json!({ "email": "unique@example.com", "username": "unique_user" })).await { Ok(id) => println!("Created unique user: {}", id), Err(err) if err.contains("409") => println!("User already exists"), Err(err) => return Err(err), } // Bulk insert for multiple records (single HTTP request) let users = vec![ json!({"name": "User 1", "email": "user1@example.com"}), json!({"name": "User 2", "email": "user2@example.com"}), json!({"name": "User 3", "email": "user3@example.com"}), ]; client.bulk_insert("users", users).await?; // Insert with client-generated random ID let id = client.insert_with_generated_id("logs", json!({ "message": "Application started", "level": "info" })).await?; Ok(()) } ``` -------------------------------- ### Custom RPC Test Structure Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md Example structure for writing custom RPC tests. This includes creating a test client, making an RPC call, and asserting the result. Ensure you handle potential errors. ```rust #[tokio::test] async fn test_custom_rpc() -> Result<(), String> { let client = create_test_client(); // Test scalar function let result = client.rpc("test_add_numbers", json!({"a": 5, "b": 3})) .execute_single() .await .map_err(|e| format!("RPC failed: {:?}", e))?; assert_eq!(result.as_i64().unwrap(), 8); Ok(()) } ``` -------------------------------- ### RPC Testing Infrastructure Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN_V2.md Outlines the setup for testing RPC functionality, including SQL scripts for creating test functions and integration tests in Rust. ```APIDOC ## Testing Infrastructure ### Setup Script (`src/tests/setup_rpc.sql`) ```sql -- Void return CREATE OR REPLACE FUNCTION test_void_func() RETURNS void AS $$ BEGIN -- do nothing END; $$ LANGUAGE plpgsql; -- Scalar return CREATE OR REPLACE FUNCTION test_echo(val text) RETURNS text AS $$ BEGIN RETURN val; END; $$ LANGUAGE plpgsql; -- Set return CREATE OR REPLACE FUNCTION test_get_users() RETURNS SETOF users AS $$ BEGIN RETURN QUERY SELECT * FROM users; END; $$ LANGUAGE plpgsql; ``` ### Integration Test (`src/tests/methods/rpc.rs`) ```rust #[tokio::test] async fn test_rpc_echo() { let client = create_client(); let res = client.rpc("test_echo", json!({"val": "hello"})) .execute_single() .await .unwrap(); assert_eq!(res.as_str().unwrap(), "hello"); } ``` ``` -------------------------------- ### Rust Deprecation Handling Example Source: https://github.com/xylex-group/supabase_rs/blob/main/MIGRATION.md Shows how to mark a function as deprecated in Rust, indicating a newer method to use and the version from which it is deprecated. ```rust // Watch for deprecation warnings #[deprecated(since = "0.4.0", note = "Use new_method instead")] pub fn old_method() { // Handle deprecations proactively } ``` -------------------------------- ### Offset-Based Pagination for Users Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Retrieves a subset of user records using offset-based pagination. This example fetches the second page of results, skipping the first 25 records and limiting to 25 records per page. ```rust // Using offset-based pagination let page_2: Vec = client .from("users") .columns(vec!["id", "email"]) .limit(25) .offset(25) // Skip first 25 records .execute() .await?; ``` -------------------------------- ### Custom User Operations Test Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md An example of a custom integration test demonstrating user insertion, selection, and deletion using the Supabase client. ```rust use supabase_rs::SupabaseClient; use serde_json::json; #[tokio::test] async fn test_user_operations() -> Result<(), String> { let client = SupabaseClient::new( std::env::var("SUPABASE_URL").unwrap(), std::env::var("SUPABASE_KEY").unwrap(), ).unwrap(); // Test insert let user_id = client.insert("users", json!({ "email": "test@example.com", "name": "Test User" })).await?; // Test select let users = client .select("users") .eq("id", &user_id) .execute() .await?; assert!(!users.is_empty()); // Cleanup client.delete("users", &user_id).await?; Ok(()) } ``` -------------------------------- ### Initialize Supabase Client in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Demonstrates how to initialize the Supabase client using environment variables for URL and Key. Shows cloning the client and setting a custom schema. ```rust use supabase_rs::SupabaseClient; use dotenv::dotenv; #[tokio::main] async fn main() -> Result<(), Box> { dotenv().ok(); // Initialize the Supabase client let client = SupabaseClient::new( std::env::var("SUPABASE_URL")?, std::env::var("SUPABASE_KEY")?, )?; // The client is clone-friendly - shares underlying connection pool let client_clone = client.clone(); // Use with custom schema (default is "public") let client_with_schema = SupabaseClient::new( std::env::var("SUPABASE_URL")?, std::env::var("SUPABASE_KEY")?, )?.schema("custom_schema"); println!("Client initialized successfully"); Ok(()) } ``` -------------------------------- ### Rust Client Creation: Panic vs. Error Handling Source: https://github.com/xylex-group/supabase_rs/blob/main/MIGRATION.md Demonstrates the difference between a panicking client creation in older versions and proper error handling for missing environment variables in newer versions. ```rust // This will panic in v0.4.x if env vars are missing let client = SupabaseClient::new( std::env::var("SUPABASE_URL").unwrap(), std::env::var("SUPABASE_KEY").unwrap(), ).unwrap(); ``` ```rust // Proper error handling let client = SupabaseClient::new( std::env::var("SUPABASE_URL") .map_err(|_| "SUPABASE_URL not set")?, std::env::var("SUPABASE_KEY") .map_err(|_| "SUPABASE_KEY not set")?, )?; ``` -------------------------------- ### Configuration Management via Environment Variables Source: https://github.com/xylex-group/supabase_rs/blob/main/ARCHITECTURE.md Shows how to retrieve configuration values like `SUPABASE_URL` and `SUPABASE_KEY` from environment variables. This centralizes configuration handling. ```rust // Centralized configuration handling fn get_config() -> Result { Ok(Config { url: std::env::var("SUPABASE_URL")?, key: std::env::var("SUPABASE_KEY")?, // ... other config }) } ``` -------------------------------- ### Example Git Commit Titles for PRs Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md Use clear and descriptive titles for your pull requests, following conventional commit message formats. Examples include 'feat:' for new features, 'fix:' for bug fixes, and 'docs:' for documentation changes. ```git feat: add bulk insert functionality fix: resolve connection timeout in select operations docs: improve GraphQL examples and error handling ``` -------------------------------- ### Initialize Supabase Client in Rust Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Set up the Supabase client in a Rust application using environment variables for URL and key. Requires tokio runtime. ```rust use supabase_rs::SupabaseClient; use dotenv::dotenv; #[tokio::main] async fn main() -> Result<(), Box> { // Load environment variables from .env file dotenv().ok(); // Initialize the Supabase client let client = SupabaseClient::new( std::env::var("SUPABASE_URL")?, std::env::var("SUPABASE_KEY")?, )?; // The client is ready to use! println!("✅ Supabase client initialized successfully"); Ok(()) } ``` -------------------------------- ### Client Creation and Multi-threaded Usage Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Demonstrates how to create a Supabase client instance and use it safely across multiple threads. ```APIDOC ## Helper Function for Reusable Client ### Description Provides a helper function to create a configured Supabase client instance. ### Panics This function will panic if the `SUPABASE_URL` or `SUPABASE_KEY` environment variables are not set. ### Code Example ```rust use supabase_rs::SupabaseClient; fn create_client() -> SupabaseClient { SupabaseClient::new( std::env::var("SUPABASE_URL").expect("SUPABASE_URL must be set"), std::env::var("SUPABASE_KEY").expect("SUPABASE_KEY must be set"), ).expect("Failed to create Supabase client") } ``` ## Multi-threaded Usage ### Description Shows how to use the Supabase client in a multi-threaded environment using `tokio` and `Arc` for shared ownership. ### Code Example ```rust use supabase_rs::SupabaseClient; use std::sync::Arc; use tokio::task; #[tokio::main] async fn main() -> Result<(), Box> { let client = Arc::new(create_client()); // Clone is cheap - shares the underlying connection pool let client_clone = Arc::clone(&client); let handle = task::spawn(async move { // Use client_clone in another task let _result = client_clone.select("users").execute().await; }); handle.await?; Ok(()) } ``` ``` -------------------------------- ### Create Supabase Client Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Creates a configured Supabase client instance. Panics if SUPABASE_URL or SUPABASE_KEY environment variables are not set. ```rust use supabase_rs::SupabaseClient; /// Creates a configured Supabase client instance /// /// # Panics /// Panics if SUPABASE_URL or SUPABASE_KEY environment variables are not set fn create_client() -> SupabaseClient { SupabaseClient::new( std::env::var("SUPABASE_URL").expect("SUPABASE_URL must be set"), std::env::var("SUPABASE_KEY").expect("SUPABASE_KEY must be set"), ).expect("Failed to create Supabase client") } ``` -------------------------------- ### Basic Select and Filtering in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Demonstrates basic select operations with filtering using the .eq() method. Ensure SupabaseClient is initialized. ```rust use supabase_rs::SupabaseClient; use serde_json::Value; async fn select_examples(client: &SupabaseClient) -> Result<(), String> { // Basic select with filtering let active_users: Vec = client .select("users") .eq("status", "active") .execute() .await?; // Using .from() alias (matches official Supabase API style) let users: Vec = client .from("users") .eq("verified", "true") .execute() .await?; Ok(()) } ``` -------------------------------- ### RPC Migration Considerations Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN_V2.md Addresses migration aspects related to the RPC feature, emphasizing its non-breaking nature and compatibility with existing PostgREST setups. ```APIDOC ## Migration Considerations * **Non-Breaking**: Adding `rpc` is additive. * **Deprecation**: None required. * **Compatibility**: Works with standard PostgREST setup. Requires no changes to existing `select`, `insert`, etc. ``` -------------------------------- ### Inner Join and Filtering in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Demonstrates an inner join to retrieve only parent rows that have matching related rows, with an example of filtering on the joined table. ```rust use supabase_rs::SupabaseClient; use supabase_rs::query::JoinSpec; use serde_json::Value; async fn join_examples(client: &SupabaseClient) -> Result<(), String> { // Inner join: filter parent rows to those with matching related rows let woodwinds_only: Vec = client .from("orchestral_sections") .select_with_joins( &["id", "name"], &[JoinSpec::new("instruments", &["id", "name"]).inner()] ) .eq("instruments.name", "flute") .execute() .await?; Ok(()) } ``` -------------------------------- ### Test Client Creation Utility Source: https://github.com/xylex-group/supabase_rs/blob/main/ARCHITECTURE.md Provides a utility function `create_test_client` for easily creating a `SupabaseClient` instance for tests. It expects `SUPABASE_URL` and `SUPABASE_KEY` environment variables. ```rust // Shared test utilities pub fn create_test_client() -> SupabaseClient { SupabaseClient::new( std::env::var("SUPABASE_URL").expect("Test env required"), std::env::var("SUPABASE_KEY").expect("Test env required"), ).expect("Failed to create test client") } ``` -------------------------------- ### Migrate Supabase Client Creation Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Update client creation from v0.3.x to v0.4.x. The `new()` method now returns a `Result` to handle potential errors during client initialization. ```rust // Old (v0.3.x) let client = SupabaseClient::new(url, key); // Could panic // New (v0.4.x) let client = SupabaseClient::new(url, key)?; ``` -------------------------------- ### Fluent Interface for Query Construction Source: https://github.com/xylex-group/supabase_rs/blob/main/ARCHITECTURE.md Demonstrates the fluent interface pattern for building Supabase queries. Use method chaining for readable query construction and IDE autocomplete. ```rust client .select("users") // Start query .eq("status", "active") // Add filter .order("created_at", false) // Add sorting .limit(50) // Add limit .execute() // Execute .await?; ``` -------------------------------- ### Delete Records in Supabase Source: https://context7.com/xylex-group/supabase_rs/llms.txt Use `delete` to remove records by ID. For custom column matching, use `delete_without_defined_key`. Includes examples for handling common deletion errors. ```rust use supabase_rs::SupabaseClient; async fn delete_examples(client: &SupabaseClient) -> Result<(), String> { // Delete by ID client.delete("users", "123").await?; // Delete by custom column client.delete_without_defined_key("sessions", "token", "abc123xyz").await?; // Delete with comprehensive error handling match client.delete("posts", "456").await { Ok(_) => println!("Post deleted"), Err(err) => { if err.contains("404") { println!("Post not found (may already be deleted)"); } else if err.contains("403") { println!("Permission denied - check RLS policies"); } else if err.contains("409") { println!("Cannot delete - record has dependent references"); } else { return Err(err); } } } Ok(()) } ``` -------------------------------- ### Rust: Void Function RPC Call Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md Example of calling an RPC function that does not return any data (void). Uses `execute_void` to confirm execution without expecting a return value. ```rust // Clean up old sessions client.rpc("cleanup_old_sessions", json!({ "days": 30 })) .execute_void() .await?; ``` -------------------------------- ### Module Reorganization: v0.2.x vs v0.4.x Source: https://github.com/xylex-group/supabase_rs/blob/main/MIGRATION.md v0.4.x simplifies imports by using `SupabaseClient` directly, unlike v0.2.x which required importing individual functions. ```rust // Old (v0.2.x) use supabase_rs::{select, insert, update}; // New (v0.4.x) use supabase_rs::SupabaseClient; ``` -------------------------------- ### Adding New Filter Operations to QueryBuilder Source: https://github.com/xylex-group/supabase_rs/blob/main/ARCHITECTURE.md Provides an example of how to extend `QueryBuilder` with a new custom filter operation. This is useful for adding support for new PostgREST filter types. ```rust // In query_builder/builder.rs impl QueryBuilder { pub fn your_new_filter(mut self, column: &str, value: &str) -> Self { self.query.add_param(column, &format!("your_op.{}", value)); self } } ``` -------------------------------- ### Basic GraphQL Query with Supabase Client Source: https://context7.com/xylex-group/supabase_rs/llms.txt Performs a basic GraphQL query to fetch user data, demonstrating the structure for querying collections and their nodes. ```rust use supabase_rs::SupabaseClient; use supabase_rs::graphql::{request::Request, RootTypes}; use serde_json::json; async fn graphql_examples(client: SupabaseClient) -> Result<(), Box> { // Basic GraphQL query // Note: Supabase tables in GraphQL end with "Collection" (users -> usersCollection) let request = Request::new( client.clone(), json!({ "query": r#"$ { usersCollection(first: 10) { edges { node { id email created_at } } pageInfo { hasNextPage endCursor } } } "# }), RootTypes::Query ); let response = request.send().await?; // GraphQL with variables let query_with_variables = Request::new( client.clone(), json!({ "query": r#"$ query GetUsersByAge($minAge: Int!, $limit: Int!) { usersCollection( filter: { age: { gte: $minAge } } first: $limit ) { edges { node { id name age email } } } } "#, "variables": { "minAge": 18, "limit": 50 } }), RootTypes::Query ); let response = query_with_variables.send().await?; // Complex relational queries - fetch users with posts and comments let complex_query = Request::new( client, json!({ "query": r#"$ { usersCollection(first: 5) { edges { node { id name postsCollection(first: 3) { edges { node { id title commentsCollection(first: 2) { edges { node { id content } } } } } } } } } } "# }), RootTypes::Query ); Ok(()) } ``` -------------------------------- ### Multi-threaded Supabase Client Usage Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Demonstrates how to use the Supabase client in a multi-threaded environment using Tokio. Cloning the client is cheap as it shares the underlying connection pool. ```rust use supabase_rs::SupabaseClient; use std::sync::Arc; use tokio::task; #[tokio::main] async fn main() -> Result<(), Box> { let client = Arc::new(create_client()); // Clone is cheap - shares the underlying connection pool let client_clone = Arc::clone(&client); let handle = task::spawn(async move { // Use client_clone in another task let _result = client_clone.select("users").execute().await; }); handle.await?; Ok(()) } ``` -------------------------------- ### Rust Type Generation for RPC Arguments Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN_V2.md Generates Rust structs for RPC function arguments, enabling type-safe calls. The `CreateUserArgs` struct is an example for a function `create_user(name text, age int)`. ```rust pub mod rpc { use serde::Serialize; #[derive(Serialize)] pub struct CreateUserArgs { pub name: String, pub age: i32, } } ``` -------------------------------- ### Implement Retry Logic for Supabase Operations in Rust Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Create a robust function to automatically retry failed Supabase operations. This example uses `tokio::time::sleep` to introduce delays between retries, increasing with each attempt. ```rust use tokio::time::{sleep, Duration}; async fn insert_with_retry( client: &SupabaseClient, table: &str, data: serde_json::Value, max_retries: u32 ) -> Result { for attempt in 1..=max_retries { match client.insert(table, data.clone()).await { Ok(id) => return Ok(id), Err(err) if attempt < max_retries => { println!("Attempt {} failed: {}. Retrying...", attempt, err); sleep(Duration::from_millis(1000 * attempt as u64)).await; }, Err(err) => return Err(format!("Failed after {} attempts: {}", max_retries, err)), } } unreachable!() } ``` -------------------------------- ### Run Supabase Integration Tests (Local) Source: https://github.com/xylex-group/supabase_rs/blob/main/src/tests/readme.md Resets the database and runs all integration tests. This command is used after setting up the local Supabase instance and environment variables. ```bash supabase db reset && cargo test ``` -------------------------------- ### Run Tests Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md Execute various test suites, including unit tests, integration tests, and all tests with captured output. ```bash # Unit tests (no network required) cargo test unit_ # Integration tests (requires Supabase credentials) cargo test # All tests with output cargo test -- --nocapture ``` -------------------------------- ### Rust: Basic Scalar RPC Call Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md Example of calling a Supabase RPC function that returns a single value. Ensure you have `SUPABASE_URL` and `SUPABASE_KEY` environment variables set. Uses `execute_single` to retrieve the scalar result. ```rust use supabase_rs::SupabaseClient; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = SupabaseClient::new( std::env::var("SUPABASE_URL")?, std::env::var("SUPABASE_KEY")?, )?; // Call a function that returns a single value let count = client.rpc("count_users", json!({})) .execute_single() .await?; println!("User count: {}", count.as_i64().unwrap()); Ok(()) } ``` -------------------------------- ### Update Client Creation: v0.3.x vs v0.4.x Source: https://github.com/xylex-group/supabase_rs/blob/main/MIGRATION.md Client creation in v0.4.x returns a Result, unlike v0.3.x which could panic. Ensure to handle the Result appropriately. ```rust // Old (v0.3.x) let client = SupabaseClient::new(url, key); // Could panic // New (v0.4.x) let client = SupabaseClient::new(url, key)?; // Returns Result ``` -------------------------------- ### Create RpcBuilder for Function Call Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md Use the `rpc()` method on `SupabaseClient` to create an `RpcBuilder` for calling a PostgreSQL function. The parameters must implement `serde::Serialize`. ```rust pub fn rpc(&self, function_name: &str, params: T) -> crate::rpc::RpcBuilder where T: serde::Serialize, ``` ```rust let builder = client.rpc("my_function", json!({ "param": "value" })); ``` -------------------------------- ### Running All Tests Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md Execute all tests in your project with the `rpc` feature enabled using this Cargo command. ```bash cargo test --features rpc ``` -------------------------------- ### Download and Save Files with Supabase Storage Source: https://context7.com/xylex-group/supabase_rs/llms.txt Demonstrates downloading files to memory or directly to disk, handling nested file paths, and basic error handling for 404 and 403 errors. ```rust use supabase_rs::storage::SupabaseStorage; async fn storage_examples() -> Result<(), Box> { // Initialize storage client for a specific file let storage = SupabaseStorage { supabase_url: std::env::var("SUPABASE_URL")?, bucket_name: "avatars".to_string(), filename: "user-123/profile.jpg".to_string(), }; // Download to memory let file_bytes = storage.download().await?; println!("Downloaded {} bytes", file_bytes.len()); // Save directly to disk storage.save("./downloads/profile.jpg").await?; // Nested file paths let document = SupabaseStorage { supabase_url: std::env::var("SUPABASE_URL")?, bucket_name: "documents".to_string(), filename: "users/123/contracts/agreement.pdf".to_string(), }; document.save("./downloads/agreement.pdf").await?; // Error handling match storage.download().await { Ok(bytes) => println!("Downloaded {} bytes", bytes.len()), Err(err) => { let err_str = err.to_string(); if err_str.contains("404") { println!("File not found"); } else if err_str.contains("403") { println!("Access denied - check bucket permissions"); } else { println!("Download failed: {}", err); } } } Ok(()) } ``` -------------------------------- ### Multiple Joins with Aliases and FK Disambiguation in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Shows how to perform multiple joins, use aliases for clarity when joining the same table multiple times, and specify foreign keys to disambiguate. ```rust use supabase_rs::SupabaseClient; use supabase_rs::query::JoinSpec; use serde_json::Value; async fn join_examples(client: &SupabaseClient) -> Result<(), String> { // Multiple joins with explicit FK disambiguation and aliases // Use when multiple foreign keys exist between tables let orders: Vec = client .from("orders") .select_with_joins( &["id", "name"], &[ JoinSpec::new("addresses", &["name", "city"]) .alias("billing") .foreign_key("orders_billing_address_id_fkey"), JoinSpec::new("addresses", &["name", "city"]) .alias("shipping") .foreign_key("orders_shipping_address_id_fkey"), ] ) .execute() .await?; // Result: { "id": 1, "name": "Order", "billing": {...}, "shipping": {...} } Ok(()) } ``` -------------------------------- ### Pagination with Range and Offset in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Illustrates two pagination methods: range-based (recommended) and offset-based. Ensure correct order and limit parameters are used. ```rust use supabase_rs::SupabaseClient; use serde_json::Value; async fn select_examples(client: &SupabaseClient) -> Result<(), String> { // Pagination using range (recommended - more efficient) let page_1: Vec = client .from("articles") .range(0, 24) // Get first 25 records (0-24 inclusive) .order("published_at", false) // descending (newest first) .execute() .await?; // Offset-based pagination let page_2: Vec = client .from("posts") .columns(vec!["id", "title", "excerpt"]) .eq("published", "true") .limit(10) .offset(10) // Skip first 10 records .execute() .await?; Ok(()) } ``` -------------------------------- ### Fetching Single and First Records in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Demonstrates fetching a single record using .single() (errors if zero or multiple matches) and the first matching record using .first(). ```rust use supabase_rs::SupabaseClient; use serde_json::Value; async fn select_examples(client: &SupabaseClient) -> Result<(), String> { // Get first matching record let first_user: Option = client .from("users") .eq("email", "alice@example.com") .first() .await?; // Get exactly one record (errors if 0 or >1 matches) let single_user: Value = client .from("users") .eq("id", "123") .single() .await?; Ok(()) } ``` -------------------------------- ### Test Client Creation Function Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md A helper function to create a Supabase client instance for testing. It reads the Supabase URL and key from environment variables. ```rust fn create_test_client() -> SupabaseClient { SupabaseClient::new( std::env::var("SUPABASE_URL").expect("SUPABASE_URL required"), std::env::var("SUPABASE_KEY").expect("SUPABASE_KEY required"), ).expect("Failed to create client") } ``` -------------------------------- ### Environment Configuration for Testing Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md This `.env` file is used to configure the Supabase client for testing. Ensure you replace the placeholder URL and key with your actual test project credentials. ```env SUPABASE_URL=https://your-test-project.supabase.co SUPABASE_KEY=your-test-key SUPABASE_RS_NO_NIGHTLY_MSG=true ``` -------------------------------- ### SupabaseClient Extension for RPC Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN.md Demonstrates how to extend the SupabaseClient to initiate RPC calls using the new RpcBuilder pattern. ```APIDOC ## SupabaseClient::rpc ### Description Provides a method on `SupabaseClient` to start an RPC call, returning an `RpcBuilder` for further configuration. ### Method Signature ```rust impl SupabaseClient { /// Calls a Postgres RPC function. /// /// # Arguments /// * `function_name` - The name of the RPC function to call. /// * `params` - The arguments to pass to the function (serializable to JSON). pub fn rpc(&self, function_name: &str, params: T) -> RpcBuilder where T: serde::Serialize; } ``` ### Usage Example ```rust let client = SupabaseClient::new("YOUR_URL", "YOUR_KEY"); let result = client .rpc("my_function", json!({ "name": "John Doe" })) .eq("status", "active") .execute() .await; ``` ``` -------------------------------- ### Using Generated RPC Types Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/RPC.md Demonstrates how to instantiate and use the generated RPC argument structs with the Supabase client. Ensure the `supabase_types::rpc` module is imported. ```rust use supabase_types::rpc::CreateUserArgs; let args = CreateUserArgs { name: "Alice".to_string(), age: 28, }; let result = client.rpc("create_user", args) .execute_single() .await?; ``` -------------------------------- ### Builder Pattern for Query Construction Source: https://github.com/xylex-group/supabase_rs/blob/main/ARCHITECTURE.md Illustrates the Builder pattern for constructing queries. Use this pattern to create complex queries step-by-step. ```rust pub struct QueryBuilder { client: SupabaseClient, query: Query, table_name: String, } impl QueryBuilder { pub fn eq(mut self, column: &str, value: &str) -> Self { self.query.add_param(column, &format!("eq.{}", value)); self } } ``` -------------------------------- ### Select Specific Columns and Range Filtering in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Shows how to select specific columns for efficiency and apply range filters like .gte() and .lte(). ```rust use supabase_rs::SupabaseClient; use serde_json::Value; async fn select_examples(client: &SupabaseClient) -> Result<(), String> { // Select specific columns for efficiency let user_emails: Vec = client .from("users") .columns(vec!["id", "email", "name"]) .gte("age", "18") .execute() .await?; // Complex filtering with multiple conditions let filtered_products: Vec = client .select("products") .gte("price", "10.00") .lte("price", "100.00") .neq("category", "discontinued") .in_("brand", &["apple", "samsung", "google"]) .text_search("description", "smartphone") .order("price", true) // ascending .limit(50) .execute() .await?; Ok(()) } ``` -------------------------------- ### Select Specific Columns and Paginate Users Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Selects specific columns ('id', 'email', 'created_at') for users and paginates the results. Orders the results by creation date, oldest first. Retrieves the first 50 records (0-49 inclusive). ```rust // Select specific columns with pagination let users: Vec = client .from("users") .columns(vec!["id", "email", "created_at"]) .range(0, 49) // Get first 50 records (0-49 inclusive) .order("created_at", true) // Oldest first .execute() .await?; ``` -------------------------------- ### RPC Header Management for Schema Source: https://github.com/xylex-group/supabase_rs/blob/main/RPC_DESIGN_V2.md Illustrates how to set `Content-Type`, `Content-Profile`, and `Accept-Profile` headers within the RpcBuilder's execution logic. This ensures correct schema handling for both request parameters and response values when interacting with PostgREST. ```rust // Inside RpcBuilder::execute() let mut headers = self.client.headers.clone(); // Assuming headers are accessible or re-created // 1. Content-Type is always application/json headers.insert("Content-Type", "application/json"); // 2. Handle Schema if self.client.schema != "public" { // Tell PostgREST to search for the function/types in this schema headers.insert("Content-Profile", &self.client.schema); // Tell PostgREST to return results from this schema headers.insert("Accept-Profile", &self.client.schema); } // 3. RPC Parameter Format // Default PostgREST behavior expects a JSON object for parameters. // If we ever need single unnamed parameter support, we'd use: // headers.insert("Prefer", "params=single-object"); ``` -------------------------------- ### Basic GraphQL Query with Supabase Rust Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Executes a basic GraphQL query to fetch user data. Requires the 'nightly' feature to be enabled for GraphQL support. Ensure the client is properly created. ```rust use supabase_rs::graphql::{Request, RootTypes}; use serde_json::json; let client = create_client(); let graphql_request = Request::new( client, json!({"query": r#"\n {\n usersCollection(first: 10) {\n edges {\n node {\n id\n email\n created_at\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n "#}), RootTypes::Query ); let response = graphql_request.send().await?; println!("GraphQL Response: {:#?}", response); ``` -------------------------------- ### Download File using Supabase Storage Source: https://github.com/xylex-group/supabase_rs/blob/main/MIGRATION.md Use the `SupabaseStorage` struct to interact with Supabase Storage, including downloading files. Ensure correct URL, bucket name, and filename are provided. ```rust // New in v0.4.x use supabase_rs::storage::SupabaseStorage; let storage = SupabaseStorage { supabase_url: env::var("SUPABASE_URL")?, bucket_name: "avatars".to_string(), filename: "user-123.jpg".to_string(), }; let bytes = storage.download().await?; ``` -------------------------------- ### Migrate Complex Queries with Chaining Source: https://github.com/xylex-group/supabase_rs/blob/main/MIGRATION.md Demonstrates the new query builder pattern in v0.4.x, using method chaining for complex queries with filters and ordering. ```rust // Old pattern let result = select_with_filters(table, filters); // New pattern let results = client .select("users") .eq("status", "active") .gte("age", "18") .order("created_at", false) .limit(50) .execute() .await?; ``` -------------------------------- ### Commit Join Fixture Changes Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/plans/2026-03-05-joins-support.md Bash command to stage and commit the SQL migration and seed files for join fixtures. ```bash git add supabase/migrations/20260305_add_join_fixtures.sql supabase/seed.sql git commit -m "chore: add join fixture tables and seed data" ``` -------------------------------- ### Optimize Query Performance with Pagination Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Implement pagination to fetch data in manageable chunks. This is crucial for large datasets to avoid performance issues and high memory usage. ```rust // Use pagination instead of fetching all records let page = client .from("large_table") .range(0, 999) // Get 1000 records at a time .execute() .await?; ``` -------------------------------- ### Run Test Command Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/plans/2026-03-05-joins-support.md Command to run a specific test suite for documentation verification. ```bash cargo test readme ``` -------------------------------- ### Run Supabase Integration Tests (Remote) Source: https://github.com/xylex-group/supabase_rs/blob/main/src/tests/readme.md Executes integration tests using the remote Supabase project configuration. Ensure the .env file is correctly set up with remote credentials. ```bash cargo test ``` -------------------------------- ### Commit Query Builder Join Implementation Source: https://github.com/xylex-group/supabase_rs/blob/main/docs/plans/2026-03-05-joins-support.md Bash command to stage and commit the Rust files related to the query builder and join implementation. ```bash git add src/query_builder/*.rs src/query.rs git commit -m "feat: add structured join selection to query builder" ``` -------------------------------- ### Rust Integration Test for Insert, Retrieve, and Delete Source: https://github.com/xylex-group/supabase_rs/blob/main/CONTRIBUTING.md This integration test verifies the insert, select, and delete operations for a 'users' table. It requires a Supabase client and inserts test data, verifies its retrieval, and cleans up afterward. Ensure the 'users' table exists and has 'id', 'name', and 'email' columns. ```rust #[tokio::test] async fn test_insert_and_retrieve() -> Result<(), String> { let client = create_test_client(); // Test data let test_user = json!({ "name": "Test User", "email": "test@example.com" }); // Insert let user_id = client.insert("users", test_user.clone()).await?; // Verify let users = client .select("users") .eq("id", &user_id) .execute() .await?; assert_eq!(users.len(), 1); assert_eq!(users[0]["name"], "Test User"); // Cleanup client.delete("users", &user_id).await?; Ok(()) } ``` -------------------------------- ### Count Operations in Rust Source: https://context7.com/xylex-group/supabase_rs/llms.txt Shows how to perform count operations. Use sparingly on large tables as they can be expensive. ```rust use supabase_rs::SupabaseClient; use serde_json::Value; async fn select_examples(client: &SupabaseClient) -> Result<(), String> { // Count operations (use sparingly - expensive on large tables) let active_count: Vec = client .select("users") .eq("status", "active") .count() .execute() .await?; Ok(()) } ``` -------------------------------- ### Run Tests in Release Mode Source: https://github.com/xylex-group/supabase_rs/blob/main/README.md Execute tests in release mode for potentially faster performance. This compiles the code with optimizations. ```bash cargo test --release ```