Something went wrong

Thank you for being patient! We're working hard on resolving the issue

Backends - Lona Docs Log in

Backends

The Backend interface is the read/write seam between @tento-lona/sheets and a concrete network/storage layer.

Interface

interface Backend {
  fetchSheet(sheetId: string): Promise<RawSheet>;
  fetchRowByKey(key: RowKey): Promise<RawRow | null>;
  fetchCells(rowId: RowId, range: DateRange): Promise<RawCell[]>;
  setCell(rowId: RowId, date: NaiveDate, entry: CellEntry): Promise<void>;
  subscribeRow(rowId: RowId, cb: (change: RowChange) => void): Unsubscribe;
  subscribeCell(rowId: RowId, date: NaiveDate, cb: (change: CellChange) => void): Unsubscribe;
}

Built-in implementations

TestBackend

In-memory backend for fixtures + unit tests. Hydrate from a RawSheet then mutate freely; nothing leaves the process.

import { TestBackend, Sheet } from "@tento-lona/sheets";

const backend = new TestBackend();
backend.seed(rawSheet);
const sheet = await Sheet.from(rawSheet, { backend });

await sheet.setCell(rowLocalId, date, { value: 42 });
// → backend in-memory state updated, invalidation event fired

HttpBackend

Talks to the Lona REST API. Used by the SDK client.

import { HttpBackend } from "@tento-lona/sheets";

const backend = new HttpBackend({
  baseUrl: "https://api.lona.so",
  accessToken: process.env.LONA_ACCESS_TOKEN,
});

NormalizingBackend

Wraps another backend and runs the encoding registry on every read so consumers see canonical values instead of wire JSON. Most SDK code wraps HttpBackend in NormalizingBackend.

import { HttpBackend, NormalizingBackend, EncodingRegistry } from "@tento-lona/sheets";

const transport = new HttpBackend({ /* ... */ });
const encoding = new EncodingRegistry();
registerBuiltinEncodings(encoding);

const backend = new NormalizingBackend({ transport, encoding });

CanonicalBackend

Dedup layer over a normalizing backend that shares provider-keyed (:~) cell reads across multiple Sheet instances in one client. App code rarely instantiates this directly — SheetsAccessor (in @tento-lona) sets it up.

Writing a custom backend

Implement the interface and you have a new transport. Common custom backends:

  • A read-only stub for a docs site (returns fixtures).
  • A WebSocket-streaming backend that funnels every server-side cell change through subscribeRow callbacks.
  • A "two-phase" backend that buffers writes until commit().

The Backend contract has no DOM dependency, so a custom backend runs unchanged under Node, Deno, or the browser.

See also