bunnydb-rs
Async Rust client for the Bunny.net Database SQL pipeline API —
works on native (tokio) and WebAssembly (wasm32-unknown-unknown,
Bunny Edge Scripts).
Target endpoint format:
https://<db-id>.lite.bunnydb.net/v2/pipeline
Highlights
- Async API with
query,execute,batch - Positional (
?) and named (:name) parameters - Typed values:
null, integer, float, text, blob base64 - Structured error model: transport, HTTP, pipeline, decode
- Configurable timeout and retry/backoff for
429and5xx - Query telemetry fields (
rows_read,rows_written,query_duration_ms) - ✅
wasm32-unknown-unknown— runs inside Bunny Edge Scripts via the browserfetchAPI
Installation
Native (server, Docker, Magic Container)
[]
= "0.3"
= { = "1", = ["rt-multi-thread", "macros"] }
WebAssembly (Bunny Edge Script)
[]
= ["cdylib"]
[]
= "0.3" # reqwest uses fetch API automatically on wasm32
= "0.2"
= "0.4"
No extra feature flags — the crate detects wasm32-unknown-unknown at
compile time and swaps tokio for the browser runtime automatically.
Client Construction
Choose the constructor that fits your deployment:
| Constructor | When to use |
|---|---|
BunnyDbClient::from_env() |
12-factor apps, Docker, CI: reads BUNNYDB_PIPELINE_URL + BUNNYDB_TOKEN |
BunnyDbClient::from_env_db_id() |
Edge scripts / containers: reads BUNNYDB_ID + BUNNYDB_TOKEN |
BunnyDbClient::from_db_id(id, tok) |
Known DB ID, token from config |
BunnyDbClient::new_bearer(url, tok) |
Full URL + bearer token |
BunnyDbClient::new_raw_auth(url, auth) |
Full URL + custom auth header |
# Recommended defaults for production
=https://<db-id>.lite.bunnydb.net/v2/pipeline
=<your-token>
Quick Start
Option A — environment variables (recommended)
The most autonomous setup: set env vars once, no URL construction in code.
use BunnyDbClient;
async
Option B — database ID + token
use BunnyDbClient;
// URL is derived automatically from the ID
let db = from_db_id;
Option C — explicit URL
use ;
async
Authentication and Endpoint
BunnyDbClient::from_env():
ReadsBUNNYDB_PIPELINE_URLandBUNNYDB_TOKENfrom environment. Ideal for 12-factor apps, Docker, CI.BunnyDbClient::from_env_db_id():
ReadsBUNNYDB_IDandBUNNYDB_TOKEN. URL constructed automatically.BunnyDbClient::from_db_id(db_id, token):
Provide a database ID; URL constructed ashttps://<db_id>.lite.bunnydb.net/v2/pipeline.BunnyDbClient::new_bearer(url, token):
Pass the full pipeline URL and token.Bearerprefix added automatically.BunnyDbClient::new_raw_auth(url, authorization):
Pass full authorization value directly.BunnyDbClient::new(url, token):
Backward-compatible raw constructor.
url must point to the pipeline endpoint (.../v2/pipeline).
Parameters
Positional:
db.query.await?;
Named:
db.query
.await?;
Batch Semantics
batch returns per-statement outcomes and does not fail the full request for SQL-level statement errors.
use ;
let outcomes = db.batch.await?;
for outcome in outcomes
Timeout and Retry
use ;
let db = new_bearer.with_options;
Defaults:
timeout_ms = 10_000max_retries = 0retry_backoff_ms = 250
Error Model
BunnyDbError::Transport(reqwest::Error)BunnyDbError::Http { status, body }BunnyDbError::Pipeline { request_index, message, code }BunnyDbError::Decode(String)
Optional Features
| Feature | Description |
|---|---|
tracing |
retry/debug tracing hooks |
raw-mode |
experimental raw response types |
row-map |
experimental row mapping helpers |
baton-experimental |
experimental baton/session types |
Platform Support
| Target | Status | Notes |
|---|---|---|
x86_64-unknown-linux-gnu |
✅ | Primary target, full tokio |
aarch64-unknown-linux-gnu |
✅ | ARM64, Docker, Magic Containers |
x86_64-apple-darwin |
✅ | macOS native |
wasm32-unknown-unknown |
✅ | Bunny Edge Scripts, browser, Deno |
On wasm32-unknown-unknown:
reqwestuses the browserfetchAPI (no TLS layer needed)tokiois not linked — the WASM runtime drives the event loopfrom_env()/from_env_db_id()are not available (nostd::envin browsers)- Retry backoff sleep is a no-op — edge functions prefer fast failures
BunnyDbClient::new_bearer(),from_db_id(),query,execute,batchwork identically
Bunny Edge Scripting & Magic Containers
Option 1 — Magic Container (pure Rust, native binary)
Bunny Magic Containers run a Docker workload co-located with the database — full Rust ecosystem, no WASM needed.
- Open the Bunny dashboard → Database → your DB → Access → generate a token.
- In your Magic Container environment variables:
BUNNYDB_PIPELINE_URL = https://<your-db-id>.lite.bunnydb.net/v2/pipeline
BUNNYDB_TOKEN = <your-token>
- In your Rust code:
let db = from_env.expect;
Option 2 — Edge Script (Rust → WASM) 🆕
Compile your Rust logic to wasm32-unknown-unknown and deploy it as a
Bunny Edge Script. The same BunnyDbClient API, same type safety —
running at the CDN edge PoP nearest to your users.
Bunny CDN edge PoP
└── edge/main.ts tiny TypeScript host (~30 lines)
↕ wasm-bindgen
└── src/lib.rs your Rust logic compiled to .wasm
└── bunnydb-rs reqwest → browser fetch API
└── BunnyDB /v2/pipeline
Rust side (src/lib.rs)
use ;
use *;
Edge Script host (edge/main.ts)
import * as BunnySDK from "https://esm.sh/@bunny.net/edgescript-sdk@0.12.0";
import process from "node:process";
import init, { EdgeHandler } from "./pkg/my_handler.js"; // wasm-pack output
// Load the .wasm binary once at cold start
await init(fetch(process.env.WASM_URL!));
// Create Rust handler — credentials from Bunny env vars
const handler = new EdgeHandler(process.env.DB_URL!, process.env.DB_TOKEN!);
BunnySDK.net.http.serve(async (req: Request): Promise<Response> => {
const url = new URL(req.url);
if (req.method === "GET" && url.pathname === "/users") {
const json = await handler.get_users();
return new Response(json, { headers: { "Content-Type": "application/json" } });
}
if (req.method === "POST" && url.pathname === "/users") {
const { name, email } = await req.json();
const result = await handler.create_user(name, email);
return new Response(result, { status: 201, headers: { "Content-Type": "application/json" } });
}
return new Response("not found", { status: 404 });
});
Build & deploy
# 1. Install wasm-pack
# 2. Compile Rust → WASM
# → pkg/my_handler_bg.wasm (~150–250 KB optimized)
# → pkg/my_handler.js (wasm-bindgen glue)
# 3. Upload .wasm to Bunny Storage
# 4. Set env vars in Edge Script dashboard:
# WASM_URL = https://your-cdn.b-cdn.net/my_handler_bg.wasm
# DB_URL = https://<db-id>.lite.bunnydb.net/v2/pipeline
# DB_TOKEN = <your-token>
A complete, ready-to-deploy example is in examples/wasm-edge/.
See docs/edge-scripting.md for the full wire protocol reference, authentication details, and replication notes.
GUI Client (Example)
This repo includes a desktop GUI example built with eframe/egui.
Run it:
The GUI supports:
- Query / Execute / Batch modes
- Bearer or raw authorization mode
- JSON params:
[]for positional,{}for named - Batch JSON format:
Testing
Run all tests:
Live integration test reads credentials in this order:
- Environment:
BUNNYDB_PIPELINE_URLandBUNNYDB_TOKEN - Local file fallback:
secrets.jsonwith eitherBUNNYDB_PIPELINE_URL+BUNNYDB_TOKENorBUNNY_DATABASE_URL+BUNNY_DATABASE_AUTH_TOKEN
secrets.json is excluded from packaging.
Documentation
| Document | Description |
|---|---|
| docs/architecture.md | Module map, data flow, design decisions |
| docs/edge-scripting.md | Edge Scripting, Magic Containers, wire protocol reference |
MSRV
Rust 1.75
License
MIT