Examples
This page contains practical code examples demonstrating key Ankurah features.
Defining a Model
#[derive(Model, Debug, Serialize, Deserialize)]
pub struct Album {
#[active_type(YrsString)]
pub name: String,
pub artist: String,
pub year: i32,
}
This automatically generates:
AlbumView(read-only)AlbumMutable(for updates)
See Defining Models for full documentation.
Server Setup
let storage = SledStorageEngine::with_path(storage_dir)?;
let node = Node::new_durable(Arc::new(storage), PermissiveAgent::new());
node.system.create().await?;
let mut server = WebsocketServer::new(node);
println!("Running server...");
server.run("0.0.0.0:9797").await?;
Rust Client
let storage = SledStorageEngine::new_test()?;
let node = Node::new(Arc::new(storage), PermissiveAgent::new());
let _client = WebsocketClient::new(node.clone(), "ws://localhost:9797").await?;
node.system.wait_system_ready().await;
// Create album
let ctx = node.context(ankurah::policy::DEFAULT_CONTEXT)?;
let trx = ctx.begin();
trx.create(&Album { name: "Parade".into(), artist: "Prince".into(), year: 1986 }).await?;
trx.commit().await?;
React Component
/* creates and Binds a ReactObserver to the component */
const AlbumList = signalObserver(({ albums }: Props) => {
return (
<ul>
/* React Observer automatically tracks albums */
{albums.items.map((album) => (
<li>{album.name}</li>
))}
</ul>
);
});
See React Usage for full documentation.
Live Query
// Using selection! macro with ctx.query()
let q: LiveQuery<AlbumView> = ctx.query(selection!("year > 1985"))?;
See Querying Data for full documentation.
Entity References
Create relationships between entities with Ref<T>:
// Create an artist
let trx = ctx.begin();
let artist = trx.create(&Artist { name: "Radiohead".into() }).await?;
let artist_id = artist.id();
trx.commit().await?;
// Create a song that references the artist
let trx = ctx.begin();
trx.create(&Song {
title: "Paranoid Android".into(),
artist: Ref::new(artist_id),
}).await?;
trx.commit().await?;
Traverse references to fetch related entities:
// Fetch the song and traverse to get the artist
let songs: Vec<SongView> = ctx.fetch("title = 'Paranoid Android'").await?;
let song = songs.first().unwrap();
// Get the referenced artist entity
let artist: ArtistView = song.artist()?.get(&ctx).await?;
println!("Artist: {}", artist.name()?);
JSON Queries
Create entities with dynamic JSON fields:
let trx = ctx.begin();
trx.create(&Track {
name: "Test Track".into(),
metadata: Json::new(serde_json::json!({
"genre": "rock",
"bpm": 120,
"tags": ["guitar", "drums"]
})),
}).await?;
trx.commit().await?;
Query by nested JSON paths:
// Query by nested JSON path
let tracks: Vec<TrackView> = ctx.fetch("metadata.genre = 'rock'").await?;
Numeric comparisons work too:
// Numeric comparison on JSON field
let fast_tracks: Vec<TrackView> = ctx.fetch("metadata.bpm > 100").await?;
Storage Backends
Sled (Embedded)
let storage = SledStorageEngine::new()?;
Postgres
let storage = Postgres::open(uri).await?;
IndexedDB (WASM)
#![allow(unused)]
fn main() {
let storage = IndexedDBStorageEngine::new("my-app").await?;
}
Next Steps
- Check out the Getting Started guide for step-by-step setup
- Review the Glossary to understand key terms
- Study the Architecture to see how it all fits together
- Join the Discord to discuss your use case!