Relations
Relations are how you connect nodes together in xNet. Instead of embedding nested objects, you store references between nodes using two specialized property types: relation() and person().
relation()
Section titled “relation()”The relation() property stores a reference to another node by its ID. You can think of it like a foreign key in a relational database, except it works across peers in a local-first system. When you need to link a task to a project, or a comment to a post, relation() is the right choice.
import { defineSchema, relation, text } from '@xnet/data'
const Task = defineSchema('task', { title: text(), project: relation(), // single reference to a project node blockedBy: relation.many() // multiple references to other tasks})Relations support both single and multiple cardinality. Use relation() for a single link and relation.many() for an array of links. When creating nodes in a transaction, you can use temporary IDs to reference nodes that don’t exist yet — the NodeStore resolves them once all nodes in the batch are committed.
person()
Section titled “person()”The person() property links to a user by their DID (Decentralized Identifier) rather than a node ID. This is useful for ownership, assignment, and authorship fields where you need to reference an identity rather than a piece of data.
const Task = defineSchema('task', { title: text(), assignee: person(), // single DID reference watchers: person.many() // multiple DID references})Transactions with Temporary IDs
Section titled “Transactions with Temporary IDs”When creating multiple related nodes at once, you can use temporary IDs so that nodes can reference each other before they’re persisted:
const { commit } = store.transaction()const projectTempId = commit.create('project', { name: 'Acme' })commit.create('task', { title: 'Setup', project: projectTempId })await commit.execute()The NodeStore replaces temporary IDs with real IDs when the transaction is applied, ensuring all references are valid. This works seamlessly with sync — related nodes are sent together so that no dangling references appear on other peers.