Persistence

Entity Decorators

All available entity decorators for configuring field behavior, indexing, relationships, and versioning in Kinotic persistence.

Kinotic provides a set of decorators to control how entity fields are stored, indexed, and queried. All decorators are imported from @kinotic-ai/persistence.

Field Decorators

@NotNull

Marks a field as required. The server will reject saves where this field is missing or null.

@NotNull
name: string = ''

@Text

Enables full-text search indexing on a string field. Without this decorator, string fields are indexed as keywords (exact match only). With @Text, you can perform partial and fuzzy text searches.

@Text
description: string = ''

@Precision

Controls the numeric precision used for storage and indexing. By default, numbers are stored as integers.

import { Precision, PrecisionType } from '@kinotic-ai/persistence'

@Precision(PrecisionType.SHORT)
age: number = 0

@Precision(PrecisionType.DOUBLE)
price: number = 0.0

Available PrecisionType values:

TypeDescription
SHORT16-bit integer
INT32-bit integer (default for numbers)
LONG64-bit integer
FLOAT32-bit floating point
DOUBLE64-bit floating point

@NotIndexed

Excludes a field from indexing. The field is still stored and returned in query results, but you cannot search or filter by it. Useful for large text blobs or fields that do not need to be queried.

@NotIndexed
notes: string = ''

@Flattened

Optimizes storage for dynamic key-value data where the keys are not known ahead of time. Flattened fields support keyword-level queries on both keys and values.

@Flattened
metadata: Record<string, any> = {}

@Nested

Preserves the independence of each element in an array of objects. This allows you to query individual elements without cross-matching between them.

@Nested
addresses: Address[] = []

Without @Nested, arrays of objects are flattened, which can produce unexpected results when querying across multiple fields of array elements.

Relationship Decorators

@Discriminator

Enables polymorphic (union) types. Apply @Discriminator to a property that determines the concrete type of the entity. This allows a single entity collection to store multiple subtypes.

import { Entity, AutoGeneratedId, Discriminator, MultiTenancyType } from '@kinotic-ai/persistence'

@Entity(MultiTenancyType.NONE)
export class Pet {
    @AutoGeneratedId
    id: string | null = null

    @Discriminator
    type: string = ''
}

export class Dog extends Pet {
    breed: string = ''
}

export class Cat extends Pet {
    lives: number = 9
}

Only the base class needs the @Entity decorator. Subclasses inherit the entity configuration. The discriminator field value is used during deserialization to determine which subclass to instantiate.

Versioning

@Version

Enables optimistic locking on the entity. When an entity with a @Version field is updated, the server checks that the version matches the current stored version. If another update occurred in between, the save is rejected with a conflict error. The field type must be string | null.

@Version
version: string | null = null

This is useful for preventing lost updates in concurrent environments.

Time Series

@TimeReference

Marks the time field for stream entities (EntityType.STREAM). This field is used as the timestamp for time-series indexing and partitioning.

import { Entity, AutoGeneratedId, TimeReference, MultiTenancyType, EntityType } from '@kinotic-ai/persistence'

@Entity(MultiTenancyType.NONE, EntityType.STREAM)
export class SensorReading {
    @AutoGeneratedId
    id: string | null = null

    @TimeReference
    timestamp: Date = new Date()

    value: number = 0.0
}

For a complete reference of all decorators, see the Decorators Reference.

Copyright © 2026