Manual LiveTable Scopes

Scopes

elements man livetable/scopes Read as markdown

How a scope decides which rows a client sees, and how scoped subscriptions stay in sync.

Sometimes a page wants a scoped view of a table. The comments for a given post, the messages in a given chat room, the tasks for a given project. A scoped LiveTable declares the partition column and binds a value per request.

let comments = new LiveTable<Comment>({ scope: "roomId" });

export default function route(req) {
  return new html({ comments: comments.scope(req.params.id) });
}

The scope value is any string produced on the server: a URL parameter, the current user id, a team id. To scope a table to the authenticated user, pass session.getOrThrow("userId") after a logged-in check.

let transfers = new LiveTable<Transfer>({ scope: "userId" });

export default function route(req) {
  session.isLoggedInOrThrow();

  return new html({ transfers: transfers.scope(session.getOrThrow("userId")) });
}

What .scope(value) does:

  • Each scope value gets its own pub/sub channel, so a mutation in one scope only broadcasts to watchers of that same scope.
  • Auto-SELECT adds where <scope_col> = $1.
  • Optimistic inserts auto-fill the scope column when omitted.
  • Every mutation is validated against the bound scope value. Mismatches throw ScopeMismatchError.

Scope columns are immutable on existing rows. To move a row between scopes, delete and re-insert.

.scope() is server-only. Bind the scope value in the route handler, and the browser receives the already-scoped instance.