Thank you for being patient! We're working hard on resolving the issue
Three row identity types cover the three layers of the stack. Most app code only uses the first two, but knowing when to reach for each saves pain.
| Type | Layer | Use |
|---|---|---|
RowKey | Wire / serialized | A stable, serializable row reference |
RowLocalId | In-memory session | The interned identity used by trees, maps, UI state |
RowId | Typed API boundary | A generic-tagged interned id used at client APIs |
All three live in @tento-lona/sheets and are re-exported from @tento-lona.
Use RowKey when you need to parse, store, or pass around a stable reference
to a row.
import { RowKey } from "@tento-lona/sheets";
const weather = RowKey.reserved("weather");
const revenue = RowKey.lookup("revenue");
const explicit = RowKey.parse("r_0123456789abcdef0123456789abcdef");
This is the right choice for:
:~lona:tasksRowKey is a pure value type — no interning, no session context, just the
wire-format identifier as a parsed + validated object.
Use RowLocalId when you are working with a row that is already loaded into
the current app session. Reference equality is the key property:
const a = registry.resolveFromString("r_abc...");
const b = registry.resolveFromString("r_abc...");
a === b; // true — same object reference, safe as Map key
You will usually see RowLocalId values in:
sheet.tree()Map<RowLocalId, T> and Set<RowLocalId>const tree = sheet.tree();
for (const node of tree.nodes) {
const row = sheet.row(node.id);
}
RowLocalId also supports aliasing — a row's canonical id (r_<hex>)
and its lookup key (:revenue) resolve to the same RowLocalId instance
once the sheet loads. This is what makes sheet.row({ lookupKey: ":x" })
and sheet.row(rowLocalId) interchangeable.
RowId is the third identity type — a generic-tagged interned id used at
typed API boundaries. It appears in lower-level @tento-lona/sheets APIs where
TypeScript needs to discriminate between user-backed rows, lookup rows,
reserved rows, virtual rows, system rows, etc., at the type level.
import { RowId } from "@tento-lona/sheets";
const id: RowId = RowId.parse("r_0123456789abcdef0123456789abcdef");
if (id.isUser()) {
const userId: RowId<"user"> = id.asUser();
}
Most application code never touches RowId directly — use RowKey at the
wire boundary, convert to RowLocalId for the session. Reach for RowId
only when working with internals that explicitly type a parameter as
RowId<V>.
RowKey.resolve() converts a stable row reference into the in-memory identity
for the current session:
const key = RowKey.lookup("revenue");
const localId = key.resolve();
That matters because a RowLocalId is reference-equal. If you use it as a
Map key, resolving the same row again gives you the same in-memory key.
Not every row key is global.
In most app code this is handled by LonaSdk.Client. If your application
switches users in a long-lived client, call client.setCurrentUser(userId)
before resolving user-scoped row keys.
Use this rule of thumb:
RowKey at boundaries (config, persistence, formulas)RowLocalId inside the running app (maps, trees, UI state)RowId only when a typed API explicitly asks for itAll three identity types are defined in @tento-lona/sheets:
import { RowKey, RowLocalId, RowId } from "@tento-lona/sheets";
The SDK (@tento-lona) re-exports them for convenience, so existing code that
imports from @tento-lona continues to work. When writing new library-layer
code, prefer the @tento-lona/sheets path — it's the canonical home.