LogoZonai
zonai.dev

Database

Using the Dart client to read, write, and stream database records.

The db property on ZonaiClient wraps the server's database endpoints. All methods accept a body object that mirrors the corresponding REST request body.

Live UI: see Real-Time Streaming below (client.db.listen). Server guide: Streaming (Live Queries).

Real-Time Streaming#

Zonai pushes live query updates over long-lived HTTP. Server routes: GET /db/stream, /db/stream/list, /db/stream/count. Full protocol notes: Streaming (Live Queries).

client.db.listen exposes three methods that keep a Stream open and emit whenever the underlying SQLite result changes.

Stream a single record#

client.db.listen
    .one(
      body: StreamBody(
        table: 'posts',
        where: Eq('id', 'abc_ps'),
      ),
      fromJson: (row) => row,
    )
    .listen((record) {
      // Called on connect and whenever the record changes
    });

Stream a list#

client.db.listen
    .list(
      body: StreamListBody(table: 'posts', limit: 20),
      fromJson: (row) => row,
    )
    .listen((records) {
      // Called whenever the result set changes
    });

Stream a count#

client.db.listen
    .count(body: StreamCountBody(table: 'posts', where: Eq('published', true)))
    .listen((total) {
      // Called whenever the count changes
    });

Cancel the subscription when you no longer need updates:

final sub = client.db.listen
    .list(
      body: StreamListBody(table: 'posts'),
      fromJson: (row) => row,
    )
    .listen((_) {});
// Later:
await sub.cancel();

CRUD Operations#

Get a single record#

final record = await client.db.get(
  body: GetBody(table: 'posts', where: Eq('id', 'abc_ps')),
  fromJson: (row) => row,
);
// record is Map<String, Object?>

List records#

final page = await client.db.list(
  body: ListBody(table: 'posts', limit: 20),
  fromJson: (row) => row,
);
// page is Paginated<Map<String, Object?>>

Count records#

final total = await client.db.count(
  body: CountBody(table: 'posts'),
);

Create a record#

final created = await client.db.create(
  body: CreateBody(table: 'posts', object: {'title': 'Hello'}),
  fromJson: (row) => row,
);

Update records#

// Update every record matching a filter
await client.db.updateMany(
  body: UpdateBody(
    table: 'posts',
    updates: [Update.column('published', UpdateValue.literal(true))],
    where: Eq('author_id', 'abc_au'),
  ),
  fromJson: (row) => row,
);

// Update exactly one record
await client.db.update(
  body: UpdateOneBody(
    table: 'posts',
    updates: [Update.column('title', UpdateValue.literal('New title'))],
    where: Eq('id', 'abc_ps'),
  ),
  fromJson: (row) => row,
);

Delete records#

// Delete every record matching a filter
await client.db.deleteMany(
  body: DeleteBody(table: 'posts', where: Eq('author_id', 'abc_au')),
);

// Delete exactly one record
await client.db.delete(
  body: DeleteOneBody(table: 'posts', where: Eq('id', 'abc_ps')),
);