Live by default
Clients subscribe to queries, and results update by themselves whenever a write changes the data they read. No cache to invalidate, no refetching to write.
Write typed Rust functions. Clients get live results. Ship it all as one binary.
A table and two functions on the server:
// src/todos.rs
use rxferrix::prelude::*;
#[table(name = "todos")]
pub struct Todo { pub text: String, pub done: bool }
#[query]
pub async fn list(ctx: &QueryCtx) -> Result<Vec<Doc<Todo>>> {
ctx.db.query::<Todo>().order(Order::Desc).take(100).await
}
#[mutation]
pub async fn add(ctx: &MutationCtx, text: String) -> Result<Id<Todo>> {
ctx.db.insert(Todo { text, done: false }).await
}
// src/main.rs
mod todos;
fn main() -> rxferrix::Result<()> { rxferrix::RxFerrix::new().run() }And a React component that uses them. When anyone adds a todo, every open list updates:
import { useMutation, useQuery } from "@rxferrix/react";
import { api } from "./rxferrix"; // generated from the functions above
function Todos() {
const todos = useQuery(api.todos.list);
const add = useMutation(api.todos.add);
return (
<>
<button onClick={() => add({ text: "Buy milk" })}>Add</button>
<ul>{todos?.map((t) => <li key={t._id}>{t.text}</li>)}</ul>
</>
);
}