# Entity Model & Decorators

# Entity Model & Decorators

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [emailsender/src/domain/entities/email_config_entity.ts](emailsender/src/domain/entities/email_config_entity.ts)
- [emailsender/src/domain/entities/email_template_entity.ts](emailsender/src/domain/entities/email_template_entity.ts)
- [emailsender/src/domain/entities/entity-decorators.ts](emailsender/src/domain/entities/entity-decorators.ts)
- [emailsender/src/domain/entities/iauditable_entity.ts](emailsender/src/domain/entities/iauditable_entity.ts)
- [emailsender/src/domain/entities/ideletable_entity.ts](emailsender/src/domain/entities/ideletable_entity.ts)
- [emailsender/src/domain/entities/registry.ts](emailsender/src/domain/entities/registry.ts)

</details>



The Primebrick v3 Data Layer utilizes a custom TypeScript decorator-based system to define database schemas directly within the domain entities. This system bridges the gap between TypeScript classes and PostgreSQL tables, providing metadata for schema migration, DDL generation, and Data Access Layer (DAL) operations.

## Decorator System Architecture

The core of the entity model is a **WeakMap-based metadata registry** defined in [emailsender/src/domain/entities/entity-decorators.ts:99-108](). Unlike standard ORMs that might store metadata on the class prototype directly, this system uses a private `META` WeakMap to store `ClassEntityMeta` objects, ensuring that metadata is encapsulated and keyed by the class constructor [emailsender/src/domain/entities/entity-decorators.ts:99-99]().

### Metadata Storage Flow

The system discovers entity structures through a combination of explicit decorators and implicit reflection via `reflect-metadata`.

1.  **Registration**: When a class is decorated with `@Entity`, it is registered in the `META` registry [emailsender/src/domain/entities/entity-decorators.ts:158-164]().
2.  **Property Discovery**: Property decorators like `@Column`, `@Key`, and `@Unique` populate the `columns` Map within the metadata [emailsender/src/domain/entities/entity-decorators.ts:110-118]().
3.  **Type Inference**: The system uses `design:type` metadata to infer PostgreSQL types (e.g., TS `Date` maps to `timestamptz`) and nullability [emailsender/src/domain/entities/entity-decorators.ts:143-151]().

### Mapping Natural Language to Code Entities

The following diagram illustrates how conceptual database requirements are translated into specific TypeScript code constructs.

**Diagram: Requirement to Code Mapping**
```mermaid
graph TD
    subgraph "Natural Language Concepts"
        A["'This class represents a Table'"]
        B["'This property is the Primary Key'"]
        C["'This field must be Unique'"]
        D["'This field is for internal logic only'"]
        E["'Track who created this record'"]
    end

    subgraph "Code Entities (Decorators & Interfaces)"
        A1["@Entity('table_name')"]
        B1["@Key()"]
        C1["@Unique()"]
        D1["@IsNotColumn()"]
        E1["@AuditableField(AuditableFieldType.CREATED_BY)"]
        F1["IAuditableEntity"]
    end

    A --> A1
    B --> B1
    C --> C1
    D --> D1
    E --> E1
    E1 -.-> F1
```
**Sources:** [emailsender/src/domain/entities/entity-decorators.ts:18-22](), [emailsender/src/domain/entities/entity-decorators.ts:158-164](), [emailsender/src/domain/entities/iauditable_entity.ts:1-10]()

## Core Decorators

| Decorator | Purpose | Implementation Detail |
| :--- | :--- | :--- |
| `@Entity(name?)` | Defines the table name. | Defaults to class name if `name` is omitted [emailsender/src/domain/entities/entity-decorators.ts:161-161](). |
| `@Key()` | Marks the Primary Key. | Supports single-column PKs; defaults to `identity` generation [emailsender/src/domain/entities/entity-decorators.ts:52-53](). |
| `@Unique()` | Adds a unique constraint. | Used by DDL patch tools to generate `UNIQUE` indexes [emailsender/src/domain/entities/entity-decorators.ts:20-20](). |
| `@Column(opts)` | Configures SQL specifics. | Allows overriding `sqlName`, `pgType`, `length`, `precision`, and `nullable` [emailsender/src/domain/entities/entity-decorators.ts:69-86](). |
| `@IsNotColumn()` | Excludes property. | Prevents the property from being included in database snapshots or DAL queries [emailsender/src/domain/entities/entity-decorators.ts:21-21](). |

**Sources:** [emailsender/src/domain/entities/entity-decorators.ts:8-22](), [emailsender/src/domain/entities/entity-decorators.ts:69-86]()

## Auditing and Soft Deletion

The system enforces standardized tracking for record lifecycles through specific interfaces and field decorators.

### IAuditableEntity
Entities implementing `IAuditableEntity` must include fields for creation and update tracking [emailsender/src/domain/entities/iauditable_entity.ts:3-9](). These are mapped to database columns using the `@AuditableField` decorator.

*   `created_at`: `AuditableFieldType.CREATED_AT`
*   `created_by`: `AuditableFieldType.CREATED_BY`
*   `updated_at`: `AuditableFieldType.UPDATED_AT`
*   `updated_by`: `AuditableFieldType.UPDATED_BY`
*   `version`: `AuditableFieldType.VERSION` (used for optimistic locking)

### IDeletableEntity
Provides support for soft-delete patterns [emailsender/src/domain/entities/ideletable_entity.ts:1-5]().
*   `deleted_at`: `DeletableFieldType.DELETED_AT`
*   `deleted_by`: `DeletableFieldType.DELETED_BY`

**Sources:** [emailsender/src/domain/entities/iauditable_entity.ts:1-10](), [emailsender/src/domain/entities/ideletable_entity.ts:1-5](), [emailsender/src/domain/entities/entity-decorators.ts:26-37]()

## Entity Registry

The `ENTITY_REGISTRY` serves as the central manifest for the database patch tooling. Every new entity class must be added to this array to be included in schema introspection and migration generation [emailsender/src/domain/entities/registry.ts:1-15]().

**Diagram: Metadata Extraction Flow**
```mermaid
flowchart LR
    subgraph "Registry"
        REG["ENTITY_REGISTRY"]
    end

    subgraph "Entity Classes"
        E1["EmailConfigEntity"]
        E2["EmailTemplateEntity"]
    end

    subgraph "Metadata Registry (WeakMap)"
        WM["META WeakMap"]
    end

    subgraph "Database Tooling"
        DT["Schema Snapshot / Migration"]
    end

    REG --> E1 & E2
    E1 & E2 -- "Decorators populate" --> WM
    DT -- "Scans" --> REG
    DT -- "Reads Metadata" --> WM
```
**Sources:** [emailsender/src/domain/entities/registry.ts:11-14](), [emailsender/src/domain/entities/entity-decorators.ts:99-108]()

## Implementation Example: EmailConfigEntity

The `EmailConfigEntity` demonstrates the full usage of the decorator system, combining identity, uniqueness, custom column types, and auditing [emailsender/src/domain/entities/email_config_entity.ts:11-51]().

```typescript
@Entity("email_config")
export class EmailConfigEntity implements IAuditableEntity {
  @Key()
  id: number; // Primary Key

  @Unique()
  uuid: string; // Unique Constraint

  @Column({ length: 50, nullable: false })
  provider: string; // Varchar(50) NOT NULL

  @AuditableField(AuditableFieldType.CREATED_AT)
  created_at: Date; // Tracked timestamp
  
  // ... other fields
}
```

**Sources:** [emailsender/src/domain/entities/email_config_entity.ts:11-51]()

---
