Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/hypertekorg/hyperstack/llms.txt

Use this file to discover all available pages before exploring further.

Views provide typed access to your stack’s data. All views return collections (Vec<T>). Use .first() on the result if you need a single item.

View Types

ViewHandle

A handle to a view that provides get/watch operations for collections:
let rounds = hs.views.latest().get().await;
// Returns Vec<T>

// Get first item from a limited view
let latest_round = hs.views.latest().get().await.first().cloned();

StateView

A view that requires a key for access:
let round = hs.views.state().get("round_key").await;
// Returns Option<T>

Getting Data

get()

Fetch all items from a view asynchronously:
// Get all rounds
let rounds = hs.views.list().get().await;

// Get single item from limited view
if let Some(latest) = hs.views.latest().get().await.first() {
    println!("Latest round: {:?}", latest);
}
Returns: Vec<T> for ViewHandle, Option<T> for StateView

get_sync()

Synchronously get cached data without waiting:
let rounds = hs.views.list().get_sync();
// Returns immediately with cached data or empty vec
Returns: Cached data without waiting for subscription

Streaming Updates

listen() - Simplest API

Stream merged entity values directly (filters out deletes):
use futures_util::StreamExt;

// Stream latest round updates
let mut stream = hs.views.latest().listen();
while let Some(round) = stream.next().await {
    println!("Round updated: {:?}", round);
}
Returns: UseBuilder<T> implementing Stream<Item = T>

watch() - Full Update Control

Watch for updates with operation types:
let mut stream = hs.views.latest().watch();
while let Some(update) = stream.next().await {
    match update {
        Update::Upsert { key, data } => {
            println!("Upserted {}: {:?}", key, data);
        }
        Update::Patch { key, data } => {
            println!("Patched {}: {:?}", key, data);
        }
        Update::Delete { key } => {
            println!("Deleted {}", key);
        }
    }
}
Returns: WatchBuilder<T> implementing Stream<Item = Update<T>>

watch_rich() - Before/After Diffs

Watch with detailed before/after state:
let mut stream = hs.views.latest().watch_rich();
while let Some(update) = stream.next().await {
    match update {
        RichUpdate::Created { key, data } => {
            println!("Created {}: {:?}", key, data);
        }
        RichUpdate::Updated { key, before, after, patch } => {
            println!("Updated {}", key);
            println!("  Before: {:?}", before);
            println!("  After: {:?}", after);
            println!("  Patch: {:?}", patch);
        }
        RichUpdate::Deleted { key, last_known } => {
            println!("Deleted {}: {:?}", key, last_known);
        }
    }
}
Returns: RichWatchBuilder<T> implementing Stream<Item = RichUpdate<T>>

Stream Builders

All stream builders support chaining configuration methods:

take(n)

Limit subscription to top N items:
let stream = hs.views.list().listen().take(10);
// Only receives updates for top 10 items

skip(n)

Skip the first N items:
let stream = hs.views.list().listen().skip(5).take(10);
// Items 6-15

filter(key, value)

Add server-side filter:
let stream = hs.views.list()
    .listen()
    .filter("status", "active")
    .filter("type", "premium");

StateView Methods

For views requiring a key:

get(key)

let round = hs.views.state().get("round_123").await;
if let Some(r) = round {
    println!("Found round: {:?}", r);
}

listen(key)

let mut stream = hs.views.state().listen("round_123");
while let Some(round) = stream.next().await {
    println!("Round updated: {:?}", round);
}

watch(key)

let mut stream = hs.views.state().watch("round_123");
while let Some(update) = stream.next().await {
    // Handle Update<T>
}

watch_rich(key)

let mut stream = hs.views.state().watch_rich("round_123");
while let Some(update) = stream.next().await {
    // Handle RichUpdate<T>
}

Update Types

Update<T>

Basic update enum with helper methods:
pub enum Update<T> {
    Upsert { key: String, data: T },
    Patch { key: String, data: T },
    Delete { key: String },
}

impl<T> Update<T> {
    pub fn key(&self) -> &str;
    pub fn data(&self) -> Option<&T>;
    pub fn is_delete(&self) -> bool;
    pub fn has_data(&self) -> bool;
    pub fn into_data(self) -> Option<T>;
    pub fn into_key(self) -> String;
    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Update<U>;
}

RichUpdate<T>

Detailed update with before/after state:
pub enum RichUpdate<T> {
    Created {
        key: String,
        data: T,
    },
    Updated {
        key: String,
        before: T,
        after: T,
        patch: Option<serde_json::Value>,
    },
    Deleted {
        key: String,
        last_known: Option<T>,
    },
}

impl<T> RichUpdate<T> {
    pub fn key(&self) -> &str;
    pub fn data(&self) -> Option<&T>;
    pub fn before(&self) -> Option<&T>;
    pub fn into_data(self) -> Option<T>;
    pub fn is_created(&self) -> bool;
    pub fn is_updated(&self) -> bool;
    pub fn is_deleted(&self) -> bool;
    pub fn patch(&self) -> Option<&serde_json::Value>;
    pub fn has_patch_field(&self, field: &str) -> bool;
}

ViewBuilder

The ViewBuilder is used internally by generated code to create view handles:
pub struct ViewBuilder {
    connection: ConnectionManager,
    store: SharedStore,
    initial_data_timeout: Duration,
}

impl ViewBuilder {
    pub fn view<T>(&self, view_path: &str) -> ViewHandle<T>;
}

Custom Stack Views

Implement the Views trait for custom stacks:
use hyperstack_sdk::view::{Views, ViewBuilder};

pub struct MyViews {
    builder: ViewBuilder,
}

impl Views for MyViews {
    fn from_builder(builder: ViewBuilder) -> Self {
        Self { builder }
    }
}

impl MyViews {
    pub fn my_view(&self) -> ViewHandle<MyData> {
        self.builder.view("my_view")
    }
}

Best Practices

  • Use listen() for the simplest streaming API (no deletes)
  • Use watch() when you need to handle deletions
  • Use watch_rich() for detailed before/after tracking
  • Chain take() and skip() for pagination
  • Use get_sync() for immediate cached access
  • Remember: views return Vec<T>, use .first() for single items

Build docs developers (and LLMs) love