PrimebrickPrimebrick
  • Primebrick.dev
  • GitHub
  • Documentation
  • Services
  • Libraries
  • API Catalog
Resources
  • Landing Page
  • API Catalog
  • GitHub
PrimebrickPrimebrick

© 2026 Primebrick. MIT License.

github
DAL Library
    AI Agent Rules and SkillsAudit and Soft-Delete SubsystemsAudit Port and Delta TrackingAuditable Joins and Display NamesBulk OperationsCI/CD and Release ProcessConnection Pool and Session ConfigurationCore ArchitectureDal GatewayEntity Metadata SystemError HandlingGetting StartedGitFlow and Branching RulesGlossaryKey Design DecisionsOverviewQuery DSL and SQL BuilderRead OperationsRepository: CRUD and FindersStreaming Large Result SetsTest Infrastructure and EntitiesTest Suite CoverageTestingTimeout Management and withClientType Coercion: JS ↔ PostgreSQLWrite OperationsREADME
SDK Library
powered by Zudoku
DAL Library

Entity Metadata System

Entity Metadata System

Relevant source files

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

  • src/meta/entity-decorators.ts
  • src/meta/entity-meta.ts
  • src/meta/entity-ts-to-pg.ts

The Entity Metadata System is the foundational layer of the @primebrick/dal-pg package. It uses TypeScript decorators and the reflect-metadata API to bridge the gap between JavaScript class definitions and PostgreSQL relational structures src/meta/entity-decorators.ts:1-23.

The system is designed with a "convention over configuration" philosophy: every own enumerable property of an entity class is implicitly treated as a database column unless explicitly excluded src/meta/entity-decorators.ts:11-13.

Metadata Storage and Retrieval

Metadata is stored using a WeakMap where the keys are the class constructors (functions) and the values are ClassEntityMeta objects src/meta/entity-decorators.ts:106-115. This ensures that metadata does not leak memory and is scoped strictly to the entity classes.

Core Metadata Functions

FunctionPurpose
ensureMeta(ctor)Retrieves or initializes the ClassEntityMeta for a given class src/meta/entity-decorators.ts:108-115.
touchColumn(ctor, key)Ensures a ColumnRegistration exists for a specific property, defaulting the sqlName to the property name src/meta/entity-decorators.ts:117-125.
syncImplicitEntityColumns(ctor)Discovers all instance properties and applies type inference to those not explicitly decorated src/meta/entity-decorators.ts:134-155.
getEntityPersistenceMeta(ctor)The primary public API to retrieve the complete, resolved metadata for an entity src/meta/entity-meta.ts:24.

Metadata Data Flow

The following diagram illustrates how a class definition is transformed into a persistence metadata object used by the Repository.

Entity Metadata Extraction Flow

Code
graph TD classDef["@Entity Class Definition"] --> decorator["Decorators (@Column, @Key, etc.)"] decorator --> ensureMeta["ensureMeta(ctor)"] ensureMeta --> weakMap["WeakMap Storage"] subgraph "Inference Pipeline" sync["syncImplicitEntityColumns(ctor)"] discover["discoverInstancePropertyKeys(ctor)"] reflect["Reflect.getMetadata('design:type')"] infer["inferPgTypeFromEntityColumn"] end weakMap --> sync sync --> discover sync --> reflect reflect --> infer infer --> finalMeta["EntityPersistenceMeta"] finalMeta --> repo["Repository / Query Builder"]

Sources: src/meta/entity-decorators.ts:106-155, src/meta/entity-ts-to-pg.ts:137-143

Decorator API

The DAL provides a rich set of decorators to define table structure and behavior.

Table and Column Definition

  • @Entity(tableName?, schema?): Maps a class to a table. If tableName is omitted, it defaults to the class name src/meta/entity-decorators.ts:161-168.
  • @Column(opts): Overrides default naming or type inference. Required only for specifying pgType, length, precision, or nullable src/meta/entity-decorators.ts:188-204.
  • @Key(opts?): Marks a property as the Primary Key. Supports identity (default) or manual generation src/meta/entity-decorators.ts:223-231.
  • @Unique(): Marks a column as having a unique constraint src/meta/entity-decorators.ts:234-239.
  • @IsNotColumn(): Explicitly excludes a property from persistence src/meta/entity-decorators.ts:242-247.

Specialized Field Decorators

These decorators mark fields for internal DAL subsystems like Audit and Soft-Delete.

  • @AuditableField(type): Links a property to CREATED_AT, CREATED_BY, UPDATED_AT, UPDATED_BY, or VERSION src/meta/entity-decorators.ts:250-258.
  • @DeletableField(type): Links a property to DELETED_AT or DELETED_BY for soft-delete logic src/meta/entity-decorators.ts:265-273.
  • @SynchronizableField(type): Marks fields for sync tracking, e.g., LAST_SYNCED_AT src/meta/entity-decorators.ts:280-288.
  • @CloneField(): Marks a field for tracking the source of a cloned record src/meta/entity-decorators.ts:295-300.
  • @AuditTrail(): Indicates that the entity has a corresponding audit trail table src/meta/entity-decorators.ts:303-308.

Sources: src/meta/entity-decorators.ts:161-308, src/meta/entity-meta.ts:4-17

Type Inference Pipeline

The entity-ts-to-pg.ts module handles the mapping from TypeScript types and naming heuristics to PostgreSQL base types. This is critical when emitDecoratorMetadata is active or when developers rely on naming conventions.

Inference Logic

  1. Explicit Type: If @Column({ pgType: '...' }) is used, it always wins src/meta/entity-ts-to-pg.ts:139.
  2. Design Type: Uses design:type metadata (e.g., Number → integer, Date → timestamptz) src/meta/entity-ts-to-pg.ts:92-118.
  3. Naming Heuristics: If types are ambiguous (like Object in some transpilation setups), it looks at the property name:
    • Ends in _at or _on → timestamptz src/meta/entity-ts-to-pg.ts:76-85.
    • Named uuid → uuid src/meta/entity-ts-to-pg.ts:64-66.
    • Named id and is a Key → bigint src/meta/entity-ts-to-pg.ts:67-69.

Type Modifiers

The system applies modifiers for length, precision, and scale. For example, text with length: 20 becomes varchar(20) src/meta/entity-ts-to-pg.ts:25-58.

TS to PG Type Mapping Matrix

TS Property / TypeHeuristic / MetaPG Type
id: number@Key()bigint
version: numberName matchinteger
createdAt: DateName *_attimestamptz
bio: stringDefaulttext
price: numberprecision: 10, scale: 2numeric(10,2)

Sources: src/meta/entity-ts-to-pg.ts:60-143

System Interaction Diagram

This diagram shows how the metadata system connects the high-level TypeScript Entity definitions to the low-level PostgreSQL requirements.

Metadata Pipeline: TS Space to PG Space

Code
graph LR subgraph "TypeScript Space (Natural Language)" Class["class UserEntity"] Prop["@Column() email: string"] PK["@Key() id: number"] end subgraph "Code Entity Space (Metadata)" sync["syncImplicitEntityColumns"] infer["inferPgTypeFromEntityColumn"] MetaObj["EntityPersistenceMeta"] end subgraph "PostgreSQL Space" Table["TABLE users"] Col1["email TEXT NOT NULL"] Col2["id BIGINT PRIMARY KEY"] end Class -- "reflects" --> sync Prop -- "extracts" --> MetaObj PK -- "extracts" --> MetaObj MetaObj -- "informs" --> infer infer -- "generates SQL for" --> Table MetaObj -- "maps to" --> Col1 MetaObj -- "maps to" --> Col2

Sources: src/meta/entity-decorators.ts:134-155, src/meta/entity-ts-to-pg.ts:137-143, src/meta/entity-meta.ts:24-30


Last modified on July 13, 2026
Dal GatewayError Handling
On this page
  • Metadata Storage and Retrieval
    • Core Metadata Functions
    • Metadata Data Flow
  • Decorator API
    • Table and Column Definition
    • Specialized Field Decorators
  • Type Inference Pipeline
    • Inference Logic
    • Type Modifiers
  • System Interaction Diagram