[data-reveal]{opacity:1!important;transform:none!important}
Define tables and work with models
Database Decorators

Define tables and work with models

Overview

Use @antelopejs/interface-database-decorators to describe tables with TypeScript classes and work with converted records through models. It builds on AQL (@antelopejs/interface-database) and adds field modifiers and API model injection.

From a table class to a stored record

  1. Describe the table. Extend Table, declare fields and indexes, and register the class with @RegisterTable("users", "myapp"). See table definitions.
  2. Bind the schema. Import the table declarations, then call await RegisterSchema("myapp") from their declaring module. This requires a configured database provider and can provision tables and insert fixtures; it is not a read-only metadata operation.
  3. Create the model. Use BasicDataModel(User) and a SchemaInstance, or GetModel after the table has been bound. See data models.
  4. Write and read through the model. Model operations apply conversion and modifier events. Use model.table when you need to compose an AQL query yourself.

Keep schema IDs and instance IDs distinct: myapp identifies the table definitions; an instance ID selects the database instance used by a model. A table class without a schema binding cannot be resolved by GetModel.

Save and retrieve a note

In a module with a configured database provider, import this declaration before calling tryNote() during initialization. Use a disposable development database: RegisterSchema provisions the schema, and insert writes data.

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

@RegisterTable("notes", "notes-demo")
class Note extends Table {
  @Field("string")
  declare title: string;
}

class NoteModel extends BasicDataModel(Note) {}

export async function tryNote() {
  await RegisterSchema("notes-demo");
  const notes = GetModel(NoteModel);
  const [id] = await notes.insert({ title: "Learn models" });
  const saved = await notes.get(id);
  if (!saved) throw new Error("The inserted note was not found");
  return saved.title; // "Learn models"
}

The model uses the default instance of the schema bound to Note. Keep the inserted ID when extending this exercise with update or delete; each successful run inserts a new note. In an application, register the schema once during initialization rather than on each request.

Choose the layer for your task

TaskLayerImportant boundary
Describe storage fields and indexesTable definitionsDeclaring a class is separate from registering its schema.
Encrypt, hash, or localize fieldsTable modifiersConversion events determine when transformations run.
Read or write converted recordsData modelsReads return converted records, not chainable queries.
Select a model in an HTTP requestParameter decorationThe instance ID selects a binding; it does not authorize access.

Start without modifiers until the schema and model work together. Add validation explicitly: string-token @Field declarations describe storage, while codec validation requires codecs and the model's validation options.

Dependencies

This package depends on the following:

Documentation

  • Table Definitions - Define database tables with the Table class, Index decorator, and Fixture decorator
  • Table Modifiers - Apply encryption, hashing, and localization modifiers to table fields, or create custom modifiers
  • Data Models - Create data models with BasicDataModel for CRUD operations and data conversion
  • Parameter Decoration - Inject model instances into API controller methods with the Model decorator