wowsql 1.2.0

Official Rust SDK for WOWSQL - MySQL Backend-as-a-Service with S3 Storage
Documentation
# 🚀 WOWSQL Rust SDK


Official Rust SDK for [WOWSQL](https://wowsql.com) - MySQL Backend-as-a-Service with S3 Storage.

[![Crates.io](https://img.shields.io/crates/v/WOWSQL.svg)](https://crates.io/crates/WOWSQL)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Rust](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://www.rust-lang.org/)

## ✨ Features


### Database Features

- 🗄️ Full CRUD operations (Create, Read, Update, Delete)
- 🔍 Advanced filtering (eq, neq, gt, gte, lt, lte, like, isNull)
- 📄 Pagination (limit, offset)
- 📊 Sorting (orderBy)
- 🎯 Fluent query builder API
- 🔒 Type-safe queries with Serde
- ⚡ async/await support
- 📝 Raw SQL queries
- 📋 Table schema introspection

### Storage Features

- 📦 S3-compatible storage for file management
- ⬆️ File upload with automatic quota validation
- ⬇️ File download (presigned URLs)
- 📂 File listing with metadata
- 🗑️ File deletion (single and batch)
- 📊 Storage quota management

## 📦 Installation


Add this to your `Cargo.toml`:

```toml
[dependencies]
WOWSQL = "1.0"
tokio = { version = "1.0", features = ["full"] }
```

## 🚀 Quick Start


### Database Operations


```rust
use WOWSQL::WOWSQLClient;
use serde_json::Value;

#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = WOWSQLClient::new(
        "https://your-project.wowsql.com",
        "your-api-key"
    )?;

    // Query data
    let response = client.table("users")
        .select(&["id", "name", "email"])
        .eq("status", "active")
        .limit(10)
        .execute::<Value>()
        .await?;

    println!("Found {} users", response.count);
    for user in response.data {
        println!("{:?}", user);
    }

    Ok(())
}
```

### Storage Operations


```rust
use WOWSQL::WOWSQLStorage;

#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let storage = WOWSQLStorage::new(
        "https://your-project.wowsql.com",
        "your-api-key"
    )?;

    // Upload file
    let file_data = std::fs::read("document.pdf")?;
    let result = storage.upload_bytes(
        &file_data,
        "uploads/document.pdf",
        Some("application/pdf")
    ).await?;

    println!("Uploaded: {}", result.url);

    // Check quota
    let quota = storage.get_quota().await?;
    println!("Storage used: {}GB / {}GB", 
        quota.storage_used_gb, quota.storage_quota_gb);

    Ok(())
}
```

## 🔧 Schema Management


Programmatically manage your database schema with the `WOWSQLSchema` client.

> **⚠️ IMPORTANT**: Schema operations require a **Service Role Key** (`service_*`). Anonymous keys will return a 403 Forbidden error.

### Quick Start


```rust
use WOWSQL::WOWSQLSchema;

#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize schema client with SERVICE ROLE KEY
    let schema = WOWSQLSchema::new(
        "https://your-project.wowsql.com",
        "service_xyz789..."  // ⚠️ Backend only! Never expose!
    )?;
    
    Ok(())
}
```

### Create Table


```rust
use WOWSQL::{WOWSQLSchema, CreateTableRequest, ColumnDefinition, IndexDefinition};

// Create a new table
schema.create_table(CreateTableRequest {
    table_name: "products".to_string(),
    columns: vec![
        ColumnDefinition {
            name: "id".to_string(),
            column_type: "INT".to_string(),
            auto_increment: Some(true),
            ..Default::default()
        },
        ColumnDefinition {
            name: "name".to_string(),
            column_type: "VARCHAR(255)".to_string(),
            not_null: Some(true),
            ..Default::default()
        },
        ColumnDefinition {
            name: "price".to_string(),
            column_type: "DECIMAL(10,2)".to_string(),
            not_null: Some(true),
            ..Default::default()
        },
        ColumnDefinition {
            name: "created_at".to_string(),
            column_type: "TIMESTAMP".to_string(),
            default: Some("CURRENT_TIMESTAMP".to_string()),
            ..Default::default()
        },
    ],
    primary_key: Some("id".to_string()),
    indexes: Some(vec![
        IndexDefinition {
            name: "idx_price".to_string(),
            columns: vec!["price".to_string()],
        },
    ]),
}).await?;

println!("Table created successfully!");
```

### Alter Table


```rust
use WOWSQL::AlterTableRequest;

// Add a new column
schema.alter_table(AlterTableRequest {
    table_name: "products".to_string(),
    add_columns: Some(vec![
        ColumnDefinition {
            name: "stock_quantity".to_string(),
            column_type: "INT".to_string(),
            default: Some("0".to_string()),
            ..Default::default()
        },
    ]),
    ..Default::default()
}).await?;

// Drop a column
schema.alter_table(AlterTableRequest {
    table_name: "products".to_string(),
    drop_columns: Some(vec!["category".to_string()]),
    ..Default::default()
}).await?;
```

### Drop Table


```rust
// Drop a table
schema.drop_table("old_table", false).await?;

// Drop with CASCADE
schema.drop_table("products", true).await?;
```

### Execute Raw SQL


```rust
// Execute custom schema SQL
schema.execute_sql(r#"
    CREATE INDEX idx_product_name 
    ON products(product_name);
"#).await?;
```

### Security & Best Practices


#### ✅ DO:

- Use service role keys **only in backend/server code**
- Store service keys in environment variables
- Test schema changes in development first

#### ❌ DON'T:

- Never expose service role keys in client code
- Never commit service keys to version control
- Don't use anonymous keys for schema operations (will fail)

### Example: Backend Migration Script


```rust
use WOWSQL::{WOWSQLSchema, CreateTableRequest, ColumnDefinition, IndexDefinition};
use std::env;

#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let schema = WOWSQLSchema::new(
        &env::var("WOWSQL_PROJECT_URL")?,
        &env::var("WOWSQL_SERVICE_KEY")?  // From env var
    )?;
    
    // Create users table
    schema.create_table(CreateTableRequest {
        table_name: "users".to_string(),
        columns: vec![
            ColumnDefinition {
                name: "id".to_string(),
                column_type: "INT".to_string(),
                auto_increment: Some(true),
                ..Default::default()
            },
            ColumnDefinition {
                name: "email".to_string(),
                column_type: "VARCHAR(255)".to_string(),
                unique: Some(true),
                not_null: Some(true),
                ..Default::default()
            },
        ],
        primary_key: Some("id".to_string()),
        indexes: Some(vec![
            IndexDefinition {
                name: "idx_email".to_string(),
                columns: vec!["email".to_string()],
            },
        ]),
    }).await?;
    
    println!("Migration completed!");
    Ok(())
}
```

---

## 📚 Documentation


## 🔑 Unified Authentication


**✨ One Project = One Set of Keys for ALL Operations**

WOWSQL uses **unified authentication** - the same API keys work for both database operations AND authentication operations.

### Key Types


1. **Anonymous Key** (`wowsql_anon_...`) ✨ **Unified Key**
   - Used for: 
     - ✅ Client-side auth operations (signup, login, OAuth)
     - ✅ Public/client-side database operations with limited permissions
   - **Safe to expose** in frontend code (browser, mobile apps)

2. **Service Role Key** (`wowsql_service_...`) ✨ **Unified Key**
   - Used for:
     - ✅ Server-side auth operations (admin, full access)
     - ✅ Server-side database operations (full access, bypass RLS)
   - **NEVER expose** in frontend code - server-side only!

### Usage Example


```rust
use WOWSQL::{WOWSQLClient, ProjectAuthClient, ProjectAuthConfig};

// Database operations
let db_client = WOWSQLClient::new(
    "https://your-project.wowsql.com",
    "wowsql_anon_..."  // Anonymous Key
)?;

// Authentication operations - SAME KEY!
let auth_config = ProjectAuthConfig {
    project_url: "your-project".to_string(),
    api_key: Some("wowsql_anon_...".to_string()),  // Same Anonymous Key
    ..Default::default()
};
let auth_client = ProjectAuthClient::new(auth_config)?;
```

**Note:** The `public_api_key` parameter is deprecated but still works for backward compatibility. Use `api_key` instead.

Full documentation available at: https://wowsql.com/docs/rust

## 📄 License


MIT License - see [LICENSE](LICENSE) file for details.

---

Made with ❤️ by the WOWSQL Team