Docs

Properties

Properties describe what an object knows. Each one is a named value on an object type, declared with prop(...).

TS
import { defineObjectType, prop, stringEnum } from "@sixb/core/ontology"

export const Customer = defineObjectType({
  id: "Customer",
  name: "Customer",
  properties: [
    prop("id", "string", { required: true, primary: true }),
    prop("name", "string", { required: true }),
    prop("email", "string"),
    prop("tier", stringEnum(["bronze", "silver", "gold", "platinum"])),
  ],
})

prop() signature

prop(id, schema, options?):

ArgumentRequiredWhat it is
idYesA stable property key, unique within the object type.
schemaYesA Schema describing which values the property accepts.
optionsNoMetadata and behavior (see below). name defaults to id.

Options

OptionTypeMeaning
namestringDisplay name. Defaults to the property id.
descriptionstringHuman-readable context for the property.
requiredbooleanThe property must be present when writing an object.
nullablebooleanThe property may be set to null.
primarytrueMarks the property as the object identifier.
mode"static" | "telemetry"How the value is stored over time. Defaults to "static".
semanticTypeQuantitative type idUnit family for physical numeric readings. See units and semantics.
queryPropertyQueryMetadataSearch, filter, and sort flags. See search metadata.

Each object type must have exactly one primary property, declared with { required: true, primary: true } and a "string" schema. Only true is accepted for primary — there is no "explicitly not primary" value.

A property is only queryable if it declares query metadata. Without it, you can't filter, sort, or search on that property.

TS
prop("status", stringEnum(["draft", "sent", "paid", "overdue", "cancelled"]), {
  query: { searchable: true, filterable: true, exact: true, facet: true },
})
prop("amount", "double", {
  query: { searchable: true, filterable: true, sortable: true },
})

Schema forms

The schema argument is one of these forms:

FormExamplesUse it for
Primitive"string", "boolean", "integer", "double", "decimal"Scalar values
Date/time"date", "timestamp"Dates or timestamps, as Date values or ISO strings
Identifier"uuid"String identifiers treated as UUIDs
File reference"fileRef"Blob-backed documents, images, and attachments
EnumstringEnum([...]), integerEnum([...])A fixed set of string or integer values
Value type refvalueTypeRef("...")Reusing a named value shape

Enum helpers constrain a property to a fixed set of values:

TS
prop("tier", stringEnum(["bronze", "silver", "gold", "platinum"]))
prop("status", stringEnum(["draft", "active", "paused", "completed", "cancelled"]))

integerEnum([...]) is the integer counterpart for a fixed set of numeric codes, such as integerEnum([1, 2, 3]) for a rating scale.

A value type ref points at a reusable named shape — reach for it when several properties share the same semantics. See value types.

TS
import { prop, valueTypeRef } from "@sixb/core/ontology"

prop("budget", valueTypeRef("MoneyAmount"))

Modeling money

Money is two properties: an amount and a currency. There is no money quantitative type — do not use semanticType for it.

TS
prop("amount", "double", { required: true }),
prop("currency", stringEnum(["EUR", "USD", "GBP"])),

semanticType is for physical readings (temperature, pressure) and only applies to numeric schemas. See units and semantics.

Static vs telemetry mode

mode controls how a value is stored over time.

ModeUse it for
"static" (default)Facts stored on the object record, like name, status, or budget.
"telemetry"Values that change over time, like a progress counter or a headcount.

A static value is stored as a fact on the object record and overwritten on each write. A telemetry value is appended to a time series; the object record keeps only the latest value, and the history is queryable.

TS
prop("progress", "integer", { mode: "telemetry" })

Start with static properties. Add telemetry only when you care about the history of a value. Telemetry properties cannot use the "fileRef" schema, and a telemetry property with no semanticType cannot carry a unit.

Appending and reading telemetry values is covered in objects / telemetry.

Keep properties shallow

Avoid complex nested shapes — object fields holding arrays, arrays of objects, or deeply nested records. When a value starts to behave like another thing in your domain, model it as a separate object type and connect it with a link instead.

Search docs

Search the documentation