# 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.

```typescript
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:

```typescript
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](./3.table-modifiers.md).

## 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.

```typescript
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

| Option  | Type     | Description                                     |
| ------- | -------- | ----------------------------------------------- |
| `group` | `string` | Assign the field to a named compound index group. |

### Compound Indexes

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

```typescript
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.

```typescript
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.

```typescript
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

| Option    | Type                | Description                                                            |
| --------- | ------------------- | ---------------------------------------------------------------------- |
| `to`      | `() => typeof Table` | Thunk returning the target table class (lazy to allow forward references). |
| `toField` | `string`            | Target field name. Defaults to the target table's primary key.         |
| `many`    | `boolean`           | The 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.

```typescript
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.

```typescript
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

```typescript
@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:

```typescript
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.

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

await RegisterSchema("myapp");
```

### Parameters

| Parameter  | Type     | Description                                                       |
| ---------- | -------- | ----------------------------------------------------------------- |
| `schemaId` | `string` | Schema id matching the `@RegisterTable(_, schemaId)` declarations. |

`RegisterSchema` returns `Promise<void>`.
