mik-sdk

Ergonomic SDK for building WASI HTTP handlers with pure Rust.
Experimental - This is version 0.0.1. The API may change between releases.
Features
- Type-Safe Routing -
routes! macro with path, query, and body extraction
- Derive Macros -
#[derive(Type)], #[derive(Query)], #[derive(Path)]
- Response Helpers -
ok!, error! with RFC 7807 support
- SQL Builder -
sql_read!, sql_create! with cursor pagination
- Minimal - ~200KB composed component size
Quick Start
use mik_sdk::prelude::*;
#[derive(Type)]
pub struct HelloResponse {
pub greeting: String,
pub name: String,
}
#[derive(Path)]
pub struct HelloPath {
pub name: String,
}
#[derive(Query)]
pub struct SearchQuery {
pub q: Option<String>,
#[field(default = 1)]
pub page: u32,
#[field(default = 10, max = 100)]
pub limit: u32,
}
routes! {
GET "/" => home,
GET "/hello/{name}" => hello(path: HelloPath) -> HelloResponse,
GET "/search" => search(query: SearchQuery),
}
fn home(_req: &Request) -> Response {
ok!({ "message": "Welcome!" })
}
fn hello(path: HelloPath, _req: &Request) -> Response {
ok!({
"greeting": str(format!("Hello, {}!", path.name)),
"name": str(&path.name)
})
}
fn search(query: SearchQuery, _req: &Request) -> Response {
ok!({
"query": query.q.as_ref().map(json::str).unwrap_or(json::null()),
"page": int(query.page),
"limit": int(query.limit)
})
}
Core Macros
Response Macros
ok!({ "data": value }) error! { status: 404, title: "Not Found" } created!("/users/123", { "id": "123" }) no_content!()
Routing
routes! {
GET "/" => home,
GET "/users/{id}" => get_user(path: Id) -> User,
POST "/users" => create_user(body: CreateInput) -> User,
GET "/search" => search(query: SearchQuery),
}
DX Macros
guard!(!name.is_empty(), 400, "Name required"); let user = ensure!(find_user(id), 404, "Not found");
For JSON body parsing, use typed inputs with #[derive(Type)] - the body is parsed automatically in the route handler.
SQL Builder
let (sql, params) = sql_read!(users {
select: [id, name, email],
filter: { active: true },
order: [-created_at, id],
after: cursor,
limit: 20,
});
Request Helpers
req.param("id") req.query("page") req.header("auth") req.body() req.text() req.is_json() req.is_html() req.is_form() req.accepts("json")
Type Hints
Use in ok!, json!, and error! macros:
str(expr) - JSON string
int(expr) - JSON integer
float(expr) - JSON float
bool(expr) - JSON boolean
API Reference
Modules
| Module |
Purpose |
json |
JSON building and lazy parsing |
time |
UTC timestamps and ISO 8601 |
random |
UUIDs, tokens, random bytes |
log |
Structured logging to stderr |
env |
Environment variable access |
status |
HTTP status code constants |
Response Macros
| Macro |
Status |
Description |
ok!({ ... }) |
200 |
JSON response |
created!(loc, { ... }) |
201 |
With Location header |
accepted!() |
202 |
Accepted |
no_content!() |
204 |
No Content |
redirect!(url) |
302 |
Redirect |
bad_request!(msg) |
400 |
Bad Request |
forbidden!(msg) |
403 |
Forbidden |
not_found!(msg) |
404 |
Not Found |
conflict!(msg) |
409 |
Conflict |
error! { ... } |
any |
RFC 7807 |
DX Macros
| Macro |
Purpose |
guard!(cond, status, msg) |
Early return if false |
ensure!(expr, status, msg) |
Unwrap or return error |
fetch!(METHOD url, ...) |
HTTP client request |
ids!(collection) |
Extract IDs for batching |
SQL Macros
| Macro |
Purpose |
sql_read!(table { ... }) |
SELECT |
sql_create!(table { ... }) |
INSERT |
sql_update!(table { ... }) |
UPDATE |
sql_delete!(table { ... }) |
DELETE |
time Module
| Function |
Returns |
time::now() |
u64 - Unix seconds |
time::now_millis() |
u64 - Unix milliseconds |
time::now_iso() |
String - ISO 8601 |
random Module
| Function |
Returns |
random::uuid() |
String - UUID v4 |
random::hex(n) |
String - n bytes as hex |
random::bytes(n) |
Vec<u8> - n random bytes |
random::u64() |
u64 - Random integer |
Request Methods
| Method |
Returns |
param(name) |
Option<&str> |
query(name) |
Option<&str> |
query_all(name) |
&[String] |
header(name) |
Option<&str> |
header_all(name) |
Vec<&str> |
trace_id() |
Option<&str> |
body() |
Option<&[u8]> |
text() |
Option<&str> |
json() |
Option<JsonValue> |
json_with(parser) |
Option<T> |
form(name) |
Option<&str> |
form_all(name) |
&[String] |
is_json() |
bool |
is_form() |
bool |
is_html() |
bool |
accepts(mime) |
bool |
has_body() |
bool |
content_type() |
Option<&str> |
Logging
log::info!("User {} logged in", id);
log::warn!("Cache miss: {}", key);
log::error!("Failed: {}", err);
log::debug!("Debug: {:?}", data);
log!(info, "user created", id: user_id, email: &email);
Requirements
- Rust 1.85+ (Edition 2024)
- Target:
wasm32-wasip2
- Build tool:
cargo-component
License
Licensed under MIT license. See LICENSE-MIT.