aurabase 0.1.1

Official Rust SDK for Aurabase: high-performance open-source Backend-as-a-Service (BaaS)
Documentation
use aurabase::{create_client, QueryBuilder};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Post {
    id: i32,
    title: String,
    published: bool,
    views: i32,
}

fn get_query_builder() -> QueryBuilder<Vec<Post>> {
    let client = create_client("http://localhost:8080", "aura_anon_test", None);
    client.db().from::<Post>("posts")
}

#[test]
fn test_query_builder_eq() {
    let qb = get_query_builder().eq("status", "active");
    let qs = qb.build_query_string();
    assert!(qs.contains("status=eq.active"), "Actual: {}", qs);
}

#[test]
fn test_query_builder_neq() {
    let qb = get_query_builder().neq("status", "deleted");
    let qs = qb.build_query_string();
    assert!(qs.contains("status=neq.deleted"), "Actual: {}", qs);
}

#[test]
fn test_query_builder_gt() {
    let qb = get_query_builder().gt("age", 18);
    let qs = qb.build_query_string();
    assert!(qs.contains("age=gt.18"), "Actual: {}", qs);
}

#[test]
fn test_query_builder_in() {
    let qb = get_query_builder().r#in("id", vec![1, 2, 3]);
    let qs = qb.build_query_string();
    let decoded = urlencoding::decode(&qs).unwrap().into_owned();
    assert!(decoded.contains("id=in.(1,2,3)"), "Actual: {}", decoded);
}

#[test]
fn test_query_builder_is() {
    let qb = get_query_builder().is("deleted_at", "null");
    let qs = qb.build_query_string();
    let decoded = urlencoding::decode(&qs).unwrap().into_owned();
    assert!(
        decoded.contains("deleted_at=is.null"),
        "Actual: {}",
        decoded
    );

    let qb_not_null = get_query_builder().is("email", "not.null");
    let qs_not_null = qb_not_null.build_query_string();
    let decoded_not_null = urlencoding::decode(&qs_not_null).unwrap().into_owned();
    assert!(
        decoded_not_null.contains("email=neq.null"),
        "Actual: {}",
        decoded_not_null
    );
}

#[test]
fn test_query_builder_or() {
    // or=(status=eq.active,priority=gt.5)
    // Nous devons passer des StoredFilter au groupe OR
    let client = create_client("http://localhost:8080", "aura_anon_test", None);
    let qb = client.db().from::<Post>("posts").or(vec![
        aurabase::services::db::StoredFilter {
            column: "status".to_string(),
            op: "eq".to_string(),
            value: serde_json::json!("active"),
        },
        aurabase::services::db::StoredFilter {
            column: "priority".to_string(),
            op: "gt".to_string(),
            value: serde_json::json!(5),
        },
    ]);

    let qs = qb.build_query_string();
    let decoded = urlencoding::decode(&qs).unwrap().into_owned();
    assert!(
        decoded.contains("or=(status.eq.active,priority.gt.5)"),
        "Actual: {}",
        decoded
    );
}

#[test]
fn test_query_builder_select() {
    let qb = get_query_builder().select("id,title");
    let qs = qb.build_query_string();
    let decoded = urlencoding::decode(&qs).unwrap().into_owned();
    assert!(decoded.contains("select=id,title"), "Actual: {}", decoded);

    let qb_embed = get_query_builder().select("*,customer:customers(name,email)");
    let qs_embed = qb_embed.build_query_string();
    let decoded_embed = urlencoding::decode(&qs_embed).unwrap().into_owned();
    assert!(
        decoded_embed.contains("select=*,customer:customers(name,email)"),
        "Actual: {}",
        decoded_embed
    );
}

#[test]
fn test_query_builder_pagination() {
    let qb = get_query_builder()
        .order("created_at", "desc")
        .limit(10)
        .offset(20);
    let qs = qb.build_query_string();
    let decoded = urlencoding::decode(&qs).unwrap().into_owned();
    assert!(
        decoded.contains("sort_by=created_at"),
        "Actual: {}",
        decoded
    );
    assert!(decoded.contains("sort_order=desc"), "Actual: {}", decoded);
    assert!(decoded.contains("limit=10"), "Actual: {}", decoded);
    assert!(decoded.contains("offset=20"), "Actual: {}", decoded);
}

#[test]
fn test_jwt_decoding() {
    // Un faux token JWT : header.payload.signature
    // Le payload est {"exp": 9999999999, "email": "test@example.com"} en base64url
    // payload_json = {"exp": 9999999999}
    let payload = r#"{"exp":9999999999,"email":"test@example.com"}"#;
    use base64::Engine;
    let b64 = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(payload);
    let token = format!("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.{}.signature", b64);

    let parsed = aurabase::decode_jwt_payload(&token).unwrap();
    assert_eq!(
        parsed.get("email").unwrap().as_str().unwrap(),
        "test@example.com"
    );

    let expired = aurabase::is_token_expired(&token, 0);
    assert!(!expired);
}