vantage-vista 1.2.0

Universal, schema-bearing data handle for the Vantage data framework
Documentation

Vantage Vista

Vista takes a typed table — the kind you define in your model layer like bakery_model3::Product::sqlite_table() or vantage_aws::models::ecs::clusters_table() — and wraps it behind a uniform handle that generic code can drive.

Vantage's Table<T, E> is typed end-to-end, which is what business logic wants. Anything generic — CLI, desktop UI, config-driven dashboard — can't consume that without giving up the erasure it needs. Vista is the bridge.

Build a Vista

Define the table once, in the model layer. Then wrap it with the matching driver factory:

use bakery_model3::Product;
use vantage_sql::sqlite::SqliteVistaFactory;

let factory = SqliteVistaFactory::new(db.clone());
let products: Vista = factory.from_table(Product::sqlite_table(db));

from_table consumes the typed table and produces a Vista that knows its columns, references, id field, and the backend's capabilities. The schema is locked from there — Vista has no add_column. Conditions can still be added; that's narrowing the data set, not the schema.

Or skip the model crate

No Rust entity for the table? Hand the factory a YAML schema instead:

let products: Vista = factory.from_yaml(include_str!("products.yaml"))?;

Same Vista. Useful for CLIs that talk to arbitrary databases at runtime, or admin tools that load schemas from configuration.

Drive it

Anything taking &Vista works against any backend:

use vantage_dataset::ReadableValueSet;

async fn render(vista: &Vista) -> VantageResult<()> {
    for col in vista.get_column_names() {
        if vista.get_column(col).unwrap().is_hidden() { continue; }
        print!("{}\t", col);
    }
    println!();

    for (_id, row) in vista.list_values().await? {
        for col in vista.get_column_names() {
            if vista.get_column(col).unwrap().is_hidden() { continue; }
            print!("{:?}\t", row.get(col));
        }
        println!();
    }
    Ok(())
}

render(&products).await?;

Swap SQLite for Mongo, AWS, or CSV — render doesn't change.

Obey what the backend can do

Drivers advertise capabilities so generic UIs render the right controls instead of guessing and erroring at runtime:

let caps = vista.capabilities();
if caps.can_insert       { /* show "+ New" */ }
if caps.can_subscribe    { /* wire live updates */ }
if caps.can_order        { /* render column sort headers */ }
if caps.can_search       { /* render the quicksearch box */ }
if caps.can_set_page_size { /* expose page-size picker */ }
if caps.can_fetch_page   { /* show random-access page selector */ }
else if caps.can_fetch_next { /* show forward-only "Next" button */ }
else                      { /* no pagination — fetch everything */ }

A read-only AWS API and a writable SQLite table look the same shape from outside; the capability flags tell the UI which buttons to draw.

Narrow with conditions

Exact-equality only at this stage:

products.add_condition_eq("category", CborValue::Text("pastries".into()))?;

let pastries = products.list_values().await?;   // honours the filter
let count    = products.get_count().await?;     // also honours it

A conditioned Vista is a narrowed view of the data set, not a query result — same mental model as Table::with_condition. Richer conditions arrive later without breaking this surface.

CRUD over CBOR

Vista's wire type is ciborium::Value, regardless of what the backend stores natively. CSV strings, MongoDB BSON, SurrealDB CBOR records, AWS JSON-1.1 blobs — drivers translate to and from CBOR at the boundary. That's what lets one render work over all of them. Ids are String for the same reason: Mongo ObjectId, Surreal Thing, composite keys all stringify in the driver.

Vista implements ValueSet, ReadableValueSet, WritableValueSet, and InsertableValueSet — the same trait family Table<T, E> does, so code written against those traits works against a Vista unchanged.

Scripting with Rhai

The rhai feature adds DataVocab, the one data vocabulary every Vantage script uses:

let due = table("order").where("status", "due");
due.ref("client").list()

table(name) returns a handle that narrows (where, sort, search, limit, ref) and then reads (list, get, first, count, ids), writes (insert, upsert, patch, delete, import_from) or opens a record draft. A host picks the tables behind table(name) and which verbs exist. The full guide is Scripting with Rhai in the Vantage book.

Status

Incubating. Ships Vista, TableShell, VistaMetadata, VistaCapabilities, Column, Reference, plus MockShell for tests. Driver factories (SQLite, Mongo, AWS, …) and the YAML loader land in later crates.

Integration

  • vantage-dataset — ValueSet traits Vista implements
  • vantage-types — Record<V> carrier
  • vantage-core — Result / VantageError