Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 184 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,193 @@
- [ ] All Admin
- [x] Database support (CRUD operations with fluent query builder)

### Quickstart
Add the following dependency to your toml file:
```
## Quickstart

Add the following dependency to your `Cargo.toml`:
```toml
[dependencies]
supabase_rust = "0.1.0"
supabase-rust = "0.1.2"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
```

### Client Initialization

You can initialize the client with explicit values or via environment variables:

```rust
use supabase_rust::Supabase;

// Option 1: Using environment variables
// Set SUPABASE_URL, SUPABASE_API_KEY, and optionally SUPABASE_JWT_SECRET
let client = Supabase::new(None, None, None);

// Option 2: Explicit configuration
let client = Supabase::new(
Some("https://your-project.supabase.co"),
Some("your-api-key"),
Some("your-jwt-secret"),
);
```

## Usage

### Authentication

```rust
use supabase_rust::Supabase;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Supabase::new(None, None, None);

// Sign up a new user
let response = client
.signup_email_password("user@example.com", "password123")
.await?;

// Sign in with email and password
let response = client
.sign_in_password("user@example.com", "password123")
.await?;

// Parse the response to get tokens
let json: serde_json::Value = response.json().await?;
let access_token = json["access_token"].as_str().unwrap();
let refresh_token = json["refresh_token"].as_str().unwrap();

// Refresh an access token
let response = client.refresh_token(refresh_token).await?;

// Validate a JWT token
let claims = client.jwt_valid(access_token).await?;
println!("User email: {}", claims.email);

Ok(())
}
```

You can initialize the two configuration keys either inline in the intialization or via environment variables (`SUPABASE_API_KEY` and `SUPABASE_URL`).
### Database Operations

The library provides a fluent query builder for PostgREST database operations:

```rust
use supabase_rust::Supabase;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct User {
id: i64,
name: String,
email: String,
status: String,
}

#[derive(Debug, Serialize)]
struct NewUser {
name: String,
email: String,
status: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Supabase::new(None, None, None);

// SELECT: Get all users
let response = client
.from("users")
.select("*")
.execute()
.await?;
let users: Vec<User> = response.json().await?;

// SELECT: Get specific columns with filters
let response = client
.from("users")
.select("id,name,email")
.eq("status", "active")
.order("name")
.limit(10)
.execute()
.await?;

// INSERT: Create a new record
let new_user = NewUser {
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
status: "active".to_string(),
};
let response = client
.from("users")
.insert(&new_user)
.execute()
.await?;

// UPDATE: Modify existing records
let updates = serde_json::json!({
"status": "inactive"
});
let response = client
.from("users")
.update(&updates)
.eq("id", "123")
.execute()
.await?;

// DELETE: Remove records
let response = client
.from("users")
.delete()
.eq("id", "123")
.execute()
.await?;

Ok(())
}
```

### Available Filter Methods

| Method | Description | PostgREST Equivalent |
|--------|-------------|---------------------|
| `eq(col, val)` | Equal | `col=eq.val` |
| `neq(col, val)` | Not equal | `col=neq.val` |
| `gt(col, val)` | Greater than | `col=gt.val` |
| `gte(col, val)` | Greater than or equal | `col=gte.val` |
| `lt(col, val)` | Less than | `col=lt.val` |
| `lte(col, val)` | Less than or equal | `col=lte.val` |
| `like(col, pattern)` | Pattern match (use `*` as wildcard) | `col=like.pattern` |
| `ilike(col, pattern)` | Case-insensitive pattern match | `col=ilike.pattern` |
| `in_(col, &[vals])` | Value in list | `col=in.(v1,v2,v3)` |
| `is_null(col)` | Is null | `col=is.null` |
| `not_null(col)` | Is not null | `col=not.is.null` |

### Query Modifiers

| Method | Description |
|--------|-------------|
| `order(col)` | Order by column (use `col.desc` for descending) |
| `limit(n)` | Limit number of rows |
| `offset(n)` | Skip first n rows |

### Combining Filters

Filters can be chained to create complex queries:

```rust
let response = client
.from("products")
.select("id,name,price,category")
.gte("price", "10")
.lte("price", "100")
.neq("status", "discontinued")
.in_("category", &["electronics", "accessories"])
.order("price.desc")
.limit(20)
.execute()
.await?;
```

## Tips
The Supabase team has an outline of their OpenAPI specs over in [this yaml file](https://github.com/supabase/gotrue/blob/master/openapi.yaml).
Expand Down