Thank you for being patient! We're working hard on resolving the issue
Three layers, each with a job.
The protocol-level identifier. Variants:
| Variant | Form | Example |
|---|---|---|
| User | r_<hex> | r_3f9a8b2e7c1d4e6f |
| Lookup | :<key> | :weather, :home |
| Virtual | r_<hex>~<preset> | r_3f9a~daily-stats |
| System | system(<name>) | system(footer) |
Pure value type. === works for comparison, but prefer
a.equals(b) — see the comparison rule below.
import { RowKey } from "@tento-lona/sheets";
const key = RowKey.parse("r_3f9a8b2e7c1d4e6f");
key.isVirtual(); // false
key.isSystem(); // false
key.toHex(); // "3f9a8b2e7c1d4e6f"
The interned identifier inside a Sheet. Wraps a RowKey,
created via RowLocalId.Registry. Reference equality holds —
use RowLocalId as a Map/Set key without worrying about hash
collisions or string allocation.
Aliasing: a row with both a UUID and a lookup key gets one
RowLocalId covering both names; the registry keeps them
unified.
const localId = sheet.idRegistry.resolveFromString("r_3f9a8b2e7c1d4e6f");
sheet.findRow(localId);
Globally interned via RowId.intern. Used at API boundaries
where you call RowsClient, SheetModel, etc.
import { RowId } from "@tento-lona/sheets";
const rowId = RowId.intern("r_3f9a8b2e7c1d4e6f");
await rowsClient.fetch(rowId);
| From → To | Call |
|---|---|
RowId → RowLocalId | registry.resolveFromString(rowId.toString()) |
RowLocalId → RowId | RowId.parse(localId.toString()) |
RowLocalId → string (DOM/API) | localId.toString() |
RowKey → RowId | RowId.intern(key.toString()) |
RowLocalId. Reference equality, no string allocation.RowId.RowKey (variant introspection).For all three, prefer .equals() over ===. Each is
interned, so reference equality usually works — but instances can
diverge across JSON round-trips, registry rebuilds, or test
boundaries. === silently gives false negatives in those cases.
// GOOD
if (a.equals(b)) { ... }
// BAD — fragile across boundaries
if (a === b) { ... }
(See __learnings/2026-04-11-sheetid-reference-equality.toml.)