Skip to content

Property Types

xNet provides 16 property types organized into five categories.

A string property with optional length and pattern constraints.

import { text } from '@xnet/data'
title: text({ required: true, maxLength: 500 })
draft: false
description: text({ placeholder: 'Enter a description...' })
slug: text({ pattern: /^[a-z0-9-]+$/ })
OptionTypeDefaultDescription
requiredbooleanfalseReject null/undefined values.
minLengthnumberMinimum string length.
maxLengthnumberMaximum string length.
patternRegExpRegex pattern to match.
placeholderstringUI hint (not enforced).

Infers to: string Coercion: String(value). Returns null for null/undefined.


A numeric property with optional range and integer constraints.

import { number } from '@xnet/data'
priority: number({ min: 1, max: 5 })
score: number({ min: 0, integer: true })
OptionTypeDefaultDescription
requiredbooleanfalse
minnumberMinimum value.
maxnumberMaximum value.
integerbooleanfalseRound to nearest integer.

Infers to: number Coercion: Number(value). If integer, applies Math.round(). Returns null for NaN.


A boolean property with an optional default.

import { checkbox } from '@xnet/data'
completed: checkbox({ default: false })
isPublic: checkbox({ default: true })
OptionTypeDefaultDescription
requiredbooleanfalse
defaultbooleanDefault value for null/undefined.

Infers to: boolean Coercion: 'true'/1 to true, 'false'/0 to false, else Boolean(value).


A timestamp stored as Unix milliseconds.

import { date } from '@xnet/data'
dueDate: date()
scheduledAt: date({ includeTime: true })
OptionTypeDefaultDescription
requiredbooleanfalse
includeTimebooleanfalseUI hint for showing time picker.

Infers to: number (Unix timestamp in ms) Coercion: Accepts number, Date objects (.getTime()), ISO strings (Date.parse()). Returns null if unparseable. Validation: Must be between 0 and year 3000 (32503680000000).


A range with a start and optional end date.

import { dateRange } from '@xnet/data'
timeline: dateRange()
sprint: dateRange({ includeTime: true })
OptionTypeDefaultDescription
requiredbooleanfalse
includeTimebooleanfalseUI hint.

Infers to: { start: string; end?: string } (ISO 8601 strings) Coercion: Parses start and end through new Date() and converts to ISO strings.


A single choice from a predefined list.

import { select } from '@xnet/data'
status: select({
options: [
{ id: 'todo', name: 'To Do', color: '#6366f1' },
{ id: 'doing', name: 'Doing', color: '#f59e0b' },
{ id: 'done', name: 'Done', color: '#10b981' }
] as const,
default: 'todo'
})
OptionTypeDefaultDescription
optionsSelectOption[]Available choices. Each has id, name, optional color.
requiredbooleanfalse
defaultstringDefault option ID.

Infers to: Union of option IDs (e.g., 'todo' | 'doing' | 'done'). Requires as const on the options array. Coercion: Returns default for null/undefined. Tries case-insensitive name matching as fallback.


Multiple choices from a predefined list.

import { multiSelect } from '@xnet/data'
tags: multiSelect({
options: [
{ id: 'bug', name: 'Bug', color: '#ef4444' },
{ id: 'feature', name: 'Feature', color: '#3b82f6' },
{ id: 'docs', name: 'Docs', color: '#8b5cf6' }
] as const
})
OptionTypeDefaultDescription
optionsSelectOption[]Available choices.
requiredbooleanfalse
defaultstring[]Default option IDs.

Infers to: Union of option IDs as array (e.g., ('bug' | 'feature' | 'docs')[]) Coercion: Returns default ?? [] for null/undefined. Coerces single string to [value]. Filters invalid entries.


A reference to another node by ID.

import { relation } from '@xnet/data'
project: relation({ target: 'xnet://my-app/Project' })
children: relation({ multiple: true })
OptionTypeDefaultDescription
targetSchemaIRIConstrain to a specific schema (optional).
requiredbooleanfalse
multiplebooleanfalseAllow array of references.

Infers to: string (single) or string[] (multiple) Coercion: Returns null/[] for null/undefined. Filters empty strings.

See Relations for patterns and temp ID resolution in transactions.


A reference to a user by DID.

import { person } from '@xnet/data'
assignee: person()
collaborators: person({ multiple: true })
OptionTypeDefaultDescription
requiredbooleanfalse
multiplebooleanfalseAllow array of DIDs.

Infers to: string (DID) or string[] (multiple DIDs) Validation: Must match DID pattern: /^did:[a-z]+:[a-zA-Z0-9._:-]+$/ Coercion: Returns null/[] for null/undefined. Filters invalid DIDs.


A validated URL string.

import { url } from '@xnet/data'
website: url()
repository: url({ placeholder: 'https://github.com/...' })
OptionTypeDefaultDescription
requiredbooleanfalse
placeholderstringUI hint.

Infers to: string Validation: Must match /^https?:\/\/.+/i Coercion: Trims whitespace. Auto-prepends https:// if no protocol present.


A validated email string.

import { email } from '@xnet/data'
contactEmail: email()
OptionTypeDefaultDescription
requiredbooleanfalse
placeholderstringUI hint.

Infers to: string Validation: Must match /^[^\s@]+@[^\s@]+\.[^\s@]+$/ Coercion: Trims and lowercases.


A validated phone number string.

import { phone } from '@xnet/data'
contactPhone: phone()
OptionTypeDefaultDescription
requiredbooleanfalse
placeholderstringUI hint.

Infers to: string Validation: Must match /^[+]?[(]?[0-9]{1,4}[)]?[-\s./0-9]*$/ with at least 7 digits. Coercion: Trims, collapses whitespace. Preserves formatting.


A content-addressed file reference.

import { file } from '@xnet/data'
avatar: file({ accept: ['image/*'], maxSize: 5 * 1024 * 1024 })
attachments: file({ multiple: true })
OptionTypeDefaultDescription
requiredbooleanfalse
multiplebooleanfalseAllow array of files.
acceptstring[]Allowed MIME types (e.g., ['image/*', 'application/pdf']).
maxSizenumberMaximum file size in bytes.

Infers to: FileRef or FileRef[]

interface FileRef {
cid: string // Content-addressed ID
name: string // Original filename
mimeType: string // MIME type
size: number // File size in bytes
}

These are read-only fields populated automatically by the system.

Timestamp of when the node was created.

import { created } from '@xnet/data'
createdAt: created()

Infers to: number (Unix timestamp in ms) Behavior: Set to Date.now() at creation time. Read-only afterward.


Timestamp of the last modification.

import { updated } from '@xnet/data'
updatedAt: updated()

Infers to: number (Unix timestamp in ms) Behavior: Set to Date.now() on every update. Read-only.


DID of the user who created the node.

import { createdBy } from '@xnet/data'
author: createdBy()

Infers to: string (DID) Behavior: Set to the author’s DID at creation time. Read-only afterward.


TypeInfers toValidatesNotable
textstringlength, pattern
numbernumbermin, max, integer
checkboxbooleanhas default
datenumber0 to year 3000stored as ms timestamp
dateRange{ start, end? }valid datesISO 8601 strings
selectliteral unionoption IDsuse as const
multiSelectliteral union[]option IDsuse as const
relationstring | string[]non-emptysupports temp IDs
personstring | string[]DID patterndid:*:*
urlstringhttp(s)auto-prepends https
emailstringemail patternlowercased
phonestringphone pattern7+ digits
fileFileRef | FileRef[]cid, name, mimeType, sizecontent-addressed
creatednumberauto, read-only
updatednumberauto, read-only
createdBystring (DID)auto, read-only