[data-reveal]{opacity:1!important;transform:none!important}
Database Decorators

Table Definitions

The Database Decorators package provides a class-based approach to defining database tables. You extend the Table base class, declare each field with TypeScript's declare keyword and the @Field decorator, and use further decorators to configure indexes, relations, and initial data.

The Table Class

The Table class serves as the base class for all table definitions. Every table automatically includes an _id field as the primary key.

import { Table, Field } from "@antelopejs/interface-database-decorators";

class User extends Table {
  @Field("string")
  declare name: string;

  @Field("string")
  declare email: string;
}

Extend with Modifiers

The Table.with() static method incorporates modifier mixins into the table class, adding capabilities like encryption, hashing, or localization:

import { Table, Field, EncryptionModifier, Encrypted } from "@antelopejs/interface-database-decorators";

class SensitiveData extends Table.with(EncryptionModifier) {
  @Field("string")
  declare publicContent: string;

  @Encrypted({ secretKey: process.env.SECRET_KEY || "default-key" })
  @Field("string")
  declare secureContent: string;
}

For detailed information about modifiers, see Table Modifiers.

The Index Decorator

The Index decorator marks a field as a database index. Indexed fields enable efficient lookups through getAll() and between() on the underlying AQL table.

import { Table, Field, Index } from "@antelopejs/interface-database-decorators";

class User extends Table {
  @Index()
  @Field("string")
  declare email: string;

  @Field("string")
  declare name: string;
}

Options

OptionTypeDescription
groupstringAssign the field to a named compound index group.

Compound Indexes

Assign multiple fields to the same index group to create a compound index:

import { Table, Field, Index, Relation } from "@antelopejs/interface-database-decorators";

class User extends Table {
  @Field("string")
  declare name: string;
}

class UserActivity extends Table {
  @Index({ group: "user_action" })
  @Field("string")
  @Relation({ to: () => User })
  declare userId: string;

  @Index({ group: "user_action" })
  @Field("string")
  declare action: string;

  @Field("date")
  declare timestamp: Date;
}

The Field Decorator

@Field(type) declares the field type for a property. The type is forwarded verbatim into the TableDefinition.fields map handed to the adapter. It accepts the full FieldType union -- primitive tokens ("string", "number", ...), arrays, nested records, or an io-ts codec.

import * as t from "io-ts";
import { Table, Field, Index, RegisterTable } from "@antelopejs/interface-database-decorators";

@RegisterTable("orders", "shop")
class Order extends Table {
  @Field("string")
  declare id: string;

  @Field(t.union([t.literal("open"), t.literal("closed")]))
  declare status: "open" | "closed";

  @Index()
  @Field("number")
  declare total: number;
}

Properties without @Field are omitted from fields. @Field stacks freely with @Index.

The Relation Decorator

The Relation decorator declares a link from a field to another table. It is declarative metadata only: database implementations do not enforce it (no foreign key constraint, no referential validation). Introspection tooling consumes it to expose the links between tables — for example to render schema diagrams or navigate related records.

import { Table, Field, Index, Relation } from "@antelopejs/interface-database-decorators";

class Comment extends Table {
  @Index()
  @Field("string")
  @Relation({ to: () => Post })
  declare postId: string;

  @Field("string")
  @Relation({ to: () => Tag, many: true })
  declare tagIds: string[];
}

Options

OptionTypeDescription
to() => typeof TableThunk returning the target table class (lazy to allow forward references).
toFieldstringTarget field name. Defaults to the target table's primary key.
manybooleanThe decorated field holds multiple target keys (many targets per source record).

@Relation stacks freely with @Field and @Index.

The RegisterTable Decorator

The RegisterTable class decorator associates a table class with a specific table name and schema. This registration is used by RegisterSchema to build the schema definition automatically.

import { Table, Field, Index, RegisterTable } from "@antelopejs/interface-database-decorators";

@RegisterTable("users", "myapp")
class User extends Table {
  @Index()
  @Field("string")
  declare email: string;

  @Field("string")
  declare name: string;
}

The first argument is the table name in the database, and the second is the schema name.

The Fixture Decorator

The Fixture decorator defines default data to insert when a table is first created. It receives a generator function that produces initial records.

import { Table, Field, Fixture } from "@antelopejs/interface-database-decorators";

@Fixture(() => [
  { _id: "admin", name: "Administrator" },
  { _id: "user", name: "Standard User" },
  { _id: "guest", name: "Guest" },
])
class UserRole extends Table {
  @Field("string")
  declare name: string;
}

The generator function:

  • Receives the table class as its parameter.
  • Can return a single object, an array of objects, or a Promise resolving to either.
  • Runs only when the table is empty, preventing duplicate inserts on subsequent starts.

Async Generators

@Fixture(async () => {
  const defaults = await loadDefaultConfig();
  return defaults.map((cfg) => ({
    _id: cfg.key,
    value: cfg.value,
  }));
})
class SystemConfig extends Table {
  @Field("string")
  declare value: string;
}

Inheritance

Tables support standard class inheritance. Define a base table with common fields and extend it for specific use cases:

import { Table, Field, Index, Relation } from "@antelopejs/interface-database-decorators";

class BaseEntity extends Table {
  @Field("date")
  declare createdAt: Date;

  @Field("date")
  declare updatedAt: Date;
}

class User extends BaseEntity {
  @Index()
  @Field("string")
  declare email: string;

  @Field("string")
  declare firstName: string;

  @Field("string")
  declare lastName: string;
}

class Post extends BaseEntity {
  @Index()
  @Field("string")
  @Relation({ to: () => User })
  declare authorId: string;

  @Field("string")
  declare title: string;

  @Field("string")
  declare content: string;
}

Register a Schema

The RegisterSchema function builds a SchemaDefinition from all tables registered for the given schema id (via @RegisterTable), constructs the Schema (which the adapter provisions), then inserts any fixture data for tables that are empty.

import { RegisterSchema } from "@antelopejs/interface-database-decorators";

await RegisterSchema("myapp");

Parameters

ParameterTypeDescription
schemaIdstringSchema id matching the @RegisterTable(_, schemaId) declarations.

RegisterSchema returns Promise<void>.