Reference

Decorators Reference

Complete reference for all Kinotic decorators.

Entity Decorators

These decorators are imported from @kinotic-ai/persistence.

@Entity(multiTenancyType?, entityType?)

Marks a class as a Kinotic entity. Required for any class that should be persisted and managed by the entity service system.

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

@Entity()
export class Product {
    // ...
}

@Entity(MultiTenancyType.SHARED)
export class TenantProduct {
    // ...
}

@Entity(MultiTenancyType.NONE, EntityType.DATA_STREAM)
export class SensorReading {
    // ...
}

Parameters:

  • multiTenancyTypeMultiTenancyType.NONE (default), MultiTenancyType.SHARED, or MultiTenancyType.DEDICATED
  • entityTypeEntityType.TABLE (default) or EntityType.DATA_STREAM

@EntityServiceDecorators(config)

Configures per-operation decorators for the entity service. Used to apply ABAC policies, role checks, or other decorators to specific CRUD operations.

import { Entity, EntityServiceDecorators, $AbacPolicy } from '@kinotic-ai/persistence'

@EntityServiceDecorators({
    allRead: [
        $AbacPolicy("entity.ownerId == participant.id")
    ],
    allDelete: [
        $AbacPolicy("participant.roles contains 'admin'")
    ]
})
@Entity()
export class Document {
    // ...
}

Operation groups: allCreate, allRead, allUpdate, allDelete

Individual operations: save, bulkSave, findById, findByIds, findAll, search, count, countByQuery, update, bulkUpdate, deleteById, deleteByQuery


ID Decorators

@AutoGeneratedId

Marks a field as a server-generated ID. The field type must be string | null since the ID is null before the entity is saved.

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

@Entity()
export class Product {
    @AutoGeneratedId
    id: string | null = null
}

@Id

Marks a field as a manually-assigned ID. The field type is string since the caller is responsible for providing the value.

import { Entity, Id } from '@kinotic-ai/persistence'

@Entity()
export class Product {
    @Id
    sku: string = ''
}

Field Decorators

@NotNull

Marks a field as required. The persistence layer will reject entities where this field is missing or null.

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

@Entity()
export class Product {
    @AutoGeneratedId
    id: string | null = null

    @NotNull
    name: string = ''
}

@Text

Enables full-text search indexing on a string field. By default, string fields are indexed as keywords (exact match only). Adding @Text enables tokenized search.

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

@Entity()
export class Article {
    @AutoGeneratedId
    id: string | null = null

    @Text
    body: string = ''
}

@Precision(PrecisionType)

Sets the numeric precision for a number field. Controls how the value is stored in Elasticsearch.

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

@Entity()
export class Measurement {
    @AutoGeneratedId
    id: string | null = null

    @Precision(PrecisionType.DOUBLE)
    value: number = 0

    @Precision(PrecisionType.LONG)
    timestamp: number = 0
}

Precision types: PrecisionType.INT, PrecisionType.SHORT, PrecisionType.LONG, PrecisionType.FLOAT, PrecisionType.DOUBLE

@NotIndexed

Excludes a field from Elasticsearch indexing. The field is still stored and returned in queries, but cannot be searched or filtered on.

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

@Entity()
export class Document {
    @AutoGeneratedId
    id: string | null = null

    @NotIndexed
    rawData: string = ''
}

@Flattened

Uses Elasticsearch flattened mapping for an object field. All values in the object are indexed as keywords, enabling filtering without the overhead of dynamic field mappings.

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

@Entity()
export class Event {
    @AutoGeneratedId
    id: string | null = null

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

@Nested

Uses Elasticsearch nested mapping for an array of objects. Preserves the relationship between fields within each object, enabling accurate queries across object boundaries.

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

@Entity()
export class Order {
    @AutoGeneratedId
    id: string | null = null

    @Nested
    lineItems: LineItem[] = []
}

Relationship

@Discriminator(propertyName)

Marks a field as a polymorphic type discriminator. Used when a field can contain different types and the system needs to determine the concrete type during deserialization.

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

@Entity()
export class Notification {
    @AutoGeneratedId
    id: string | null = null

    @Discriminator('type')
    payload: EmailPayload | SmsPayload | null = null
}

Parameters:

  • propertyName — The name of the property within the object that identifies its type

Multi-tenancy

@TenantId

Marks a field as the tenant identifier. Used with MultiTenancyType.SHARED entities to partition data by tenant.

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

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

    @TenantId
    tenantId: string = ''
}

Versioning

@Version

Enables optimistic locking for the entity. The field type must be string | null. The persistence layer uses this field to detect concurrent modifications.

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

@Entity()
export class Product {
    @AutoGeneratedId
    id: string | null = null

    @Version
    version: string | null = null

    name: string = ''
}

Time Series

@TimeReference

Marks a field as the time reference for data stream entities. Used with EntityType.DATA_STREAM to identify the timestamp field.

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

@Entity(undefined, EntityType.DATA_STREAM)
export class SensorReading {
    @AutoGeneratedId
    id: string | null = null

    @TimeReference
    timestamp: Date = new Date()

    value: number = 0
}

Query

@Query(statement)

Defines a named query on an entity service method. The statement uses the Kinotic query syntax.

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

@Entity()
export class Product {
    @AutoGeneratedId
    id: string | null = null

    name: string = ''
    category: string = ''

    @Query("category == ?0")
    static findByCategory: (category: string) => Promise<Product[]>
}

Entity Service Policy Decorators

These factory functions create decorator instances for use within @EntityServiceDecorators. They are imported from @kinotic-ai/persistence.

$AbacPolicy(expression)

Creates an ABAC policy decorator for entity operations. The expression uses the ABAC expression language.

import { $AbacPolicy } from '@kinotic-ai/persistence'

$AbacPolicy("entity.ownerId == participant.id")
$AbacPolicy("participant.roles contains 'admin'")

$Policy(policies)

Creates a policy decorator with a matrix of policy rules.

import { $Policy } from '@kinotic-ai/persistence'

$Policy([['admin', 'editor'], ['manager']])

$Role(roles)

Creates a role-based access decorator for entity operations.

import { $Role } from '@kinotic-ai/persistence'

$Role(['admin', 'editor'])

Service Decorators

These decorators are imported from @kinotic-ai/core.

@Publish(namespace, name?)

Publishes a class as a remotely accessible service. The service becomes available to clients via the RPC gateway.

import { Publish } from '@kinotic-ai/core'

@Publish('com.example')
class UserService {
    async findUser(id: string): Promise<User> {
        // ...
    }
}

@Publish('com.example', 'CustomName')
class MyService {
    // Published as com.example.CustomName
}

Parameters:

  • namespace — The service namespace (e.g., 'com.example')
  • name — Optional custom service name. Defaults to the class name.

@Version(version)

Sets the semantic version for a published service. Enables versioned service routing.

import { Publish, Version } from '@kinotic-ai/core'

@Publish('com.example')
@Version('2.0.0')
class UserService {
    // ...
}

@Scope

Marks a property as the scope for service routing. Used for multi-tenant service resolution.

import { Publish, Scope } from '@kinotic-ai/core'

@Publish('com.example')
class TenantService {
    @Scope
    tenantId: string = ''
}

@Context()

Injects request context into a method parameter. The parameter receives metadata about the current request.

import { Publish, Context } from '@kinotic-ai/core'

@Publish('com.example')
class AuditService {
    async logAction(action: string, @Context() context: any): Promise<void> {
        // context contains request metadata
    }
}

@AbacPolicy(expression)

Enforces an ABAC policy on a published service method. The policy is evaluated at the gateway before the method is invoked.

import { Publish, AbacPolicy } from '@kinotic-ai/core'

@Publish('com.example')
class AdminService {
    @AbacPolicy("participant.roles contains 'admin'")
    async deleteAllData(): Promise<void> {
        // Only reachable by callers with the 'admin' role
    }
}

See Access Control for detailed policy documentation.

Copyright © 2026