PrimeBrickPrimeBrick
  • Docs
  • Contact
  • MIT License
  • Documentation
  • MCP Server
  • API Catalog
  • Services
  • Libraries
PrimeBrickPrimeBrick

© 2026 PrimeBrick. MIT License. v3.8.0

github
DAL Library
    Getting startedArchitectureEntities & decoratorsQuery DSLRepositoryConnections & transactionsAudit trailOptimistic Locking & ConcurrencyCloneChangelogAPI reference
SDK Library
powered by Zudoku
DAL Library

API reference

<!-- AUTO-GENERATED -->

> This page is mechanically generated from docs/user-guide/_extracted/api.json. > Do not edit by hand — run pnpm extract-docs and re-render.

Enumerations

AuditableFieldType

MemberValue
CREATED_AT"CREATED_AT"
CREATED_BY"CREATED_BY"
UPDATED_AT"UPDATED_AT"
UPDATED_BY"UPDATED_BY"
VERSION"VERSION"

DeletableFieldType

MemberValue
DELETED_AT"DELETED_AT"
DELETED_BY"DELETED_BY"

SynchronizableFieldType

MemberValue
LAST_SYNCED_AT"LAST_SYNCED_AT"

AuditAction

Audit action enum (mirrors BE's AuditAction).

MemberValue
INSERT"INSERT"
UPDATE"UPDATE"
SOFT_DELETE"SOFT_DELETE"
HARD_DELETE"HARD_DELETE"
RESTORE"RESTORE"

Classes

AuditLogEntity

AuditLogEntity — generic audit trail entity.

Maps to any audit table (customers_audit, organizations_audit, user_profiles_audit, etc.) via the tableName override option on finders/writers.

All audit tables share the same column structure: id bigint identity PK entity_id bigint (the audited entity's ID) entity_uuid uuid (the audited entity's UUID) action text (INSERT, UPDATE, SOFT_DELETE, HARD_DELETE, RESTORE) changed_at timestamptz changed_by text (actor UUID or "system") version integer delta jsonb (field-level old/new diff)

This entity has NO

Constructor: new AuditLogEntity()

PropertyTypeFlags
idbigint
entity_idbigint
entity_uuidstring
actionstring
changed_atDate
changed_bystring
versionnumber
deltaRecord<string, { old: unknown; new: unknown }>optional

Dal

Constructor: new Dal(config: DalConfig)

PropertyTypeFlags
configRequired<Pick<DalConfig, "connectionString""max"

getPool(): Pool

The underlying pg.Pool. Exposed for snapshot/migration tooling that needs raw access.

close(timeoutMs: number): Promise<void>

Graceful shutdown — drains the pool with a timeout deadline.

  • Re-entrant: concurrent calls return immediately (the first call wins).
  • Timeout: if pool.end() doesn't complete within timeoutMs, the promise resolves anyway (the pool is left to be reaped by the OS/TCP stack).
  • Error containment: if pool.end() throws, the error is logged and swallowed.
  • Does NOT install process.on() handlers — that is a consumer-side concern.
ParameterTypeDescription
timeoutMsnumberMaximum time to wait for pool.end() to complete. Default: 10000.

findById(entity: EntityClass, id: string | bigint, options: FindByIdOptions): Promise<TResult | null>

ParameterTypeDescription
entityEntityClass
idstringbigint
optionsFindByIdOptions

findByUUID(entity: EntityClass, uuid: string, options: FindByUUIDOptions): Promise<TResult | null>

ParameterTypeDescription
entityEntityClass
uuidstring
optionsFindByUUIDOptions

find(entity: EntityClass, fields: FieldProjector[] | null, options: FindOptions): Promise<TResult | null>

ParameterTypeDescription
entityEntityClass
fieldsFieldProjector[]null
optionsFindOptions

findAll(entity: EntityClass, fields: FieldProjector[] | null, options: FindOptions): Promise<AsyncIterable<TResult, any, any> | TResult[]>

ParameterTypeDescription
entityEntityClass
fieldsFieldProjector[]null
optionsFindOptions

findByPage(entity: EntityClass, page: number, recordsPerPage: number, fields: FieldProjector[] | null, options: FindOptions): Promise<PaginatedEntity<TResult>>

ParameterTypeDescription
entityEntityClass
pagenumber
recordsPerPagenumber
fieldsFieldProjector[]null
optionsFindOptions

count(entity: EntityClass): Promise<bigint>

ParameterTypeDescription
entityEntityClass

add(entity: EntityClass & () => TEntity, row: Partial<Record<any & string, unknown>>, options: AuditableWriteOptions): Promise<TEntity>

ParameterTypeDescription
entityEntityClass & () => TEntity
rowPartial<Record<any & string, unknown>>
optionsAuditableWriteOptions

upsert(entity: EntityClass & () => TEntity, row: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & UpsertOptions): Promise<TEntity>

ParameterTypeDescription
entityEntityClass & () => TEntity
rowPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & UpsertOptions

update(entity: EntityClass & () => TEntity, updates: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity>

ParameterTypeDescription
entityEntityClass & () => TEntity
updatesPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

delete(entity: EntityClass & () => TEntity, match: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity>

ParameterTypeDescription
entityEntityClass & () => TEntity
matchPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

restore(entity: EntityClass & () => TEntity, match: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity>

ParameterTypeDescription
entityEntityClass & () => TEntity
matchPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

hardDelete(entity: EntityClass & () => TEntity, match: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<void>

ParameterTypeDescription
entityEntityClass & () => TEntity
matchPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

addMany(entity: EntityClass & () => TEntity, rows: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & BulkOptions): Promise<TEntity[]>

ParameterTypeDescription
entityEntityClass & () => TEntity
rowsPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & BulkOptions

upsertMany(entity: EntityClass & () => TEntity, rows: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & BulkOptions & UpsertOptions): Promise<TEntity[]>

ParameterTypeDescription
entityEntityClass & () => TEntity
rowsPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & BulkOptions & UpsertOptions

updateMany(entity: EntityClass & () => TEntity, updates: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & MatchByOptions<TEntity> & BulkOptions): Promise<TEntity[]>

ParameterTypeDescription
entityEntityClass & () => TEntity
updatesPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity> & BulkOptions

deleteMany(entity: EntityClass & () => TEntity, matches: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity[]>

ParameterTypeDescription
entityEntityClass & () => TEntity
matchesPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

rawSql(text: string, values: unknown[]): Promise<TResult[]>

ParameterTypeDescription
textstring
valuesunknown[]

withClient(fn: (client: PoolClient) => Promise<TResult>, options: WithClientOptions): Promise<TResult>

Acquires a dedicated client from the pool, optionally sets a per-connection statement_timeout, runs fn(client), and releases the client (resetting the timeout to the session default).

Use for:

  • Transactions (BEGIN/COMMIT inside fn).
  • Ad-hoc long queries with a timeoutMs override.
  • Constructing a Repository backed by a specific client for tx participation: dal.withClient(async (client) =&gt; &#123; const repo = new Repository(client); ... &#125;).
ParameterTypeDescription
fn(client: PoolClient) => Promise<TResult>
optionsWithClientOptions

DalError

Generic DAL error with a stable code field.

Constructor: new DalError(message: string)

PropertyTypeFlags
codestringreadonly
stackTraceLimitnumberstatic
causeunknownoptional
namestring
messagestring
stackstringoptional

captureStackTrace(targetObject: object, constructorOpt: Function): void

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

Code
const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack`

The first line of the trace will be prefixed with $&#123;myObject.name&#125;: $&#123;myObject.message&#125;.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

Code
function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a();
ParameterTypeDescription
targetObjectobject
constructorOptFunction

prepareStackTrace(err: Error, stackTraces: CallSite[]): any

ParameterTypeDescription
errError
stackTracesCallSite[]

NotFoundError

Thrown when a finder returns zero rows and throwIfNotFound is true (the default).

Constructor: new NotFoundError(message: string)

PropertyTypeFlags
code"NOT_FOUND"readonly
stackTraceLimitnumberstatic
causeunknownoptional
namestring
messagestring
stackstringoptional

captureStackTrace(targetObject: object, constructorOpt: Function): void

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

Code
const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack`

The first line of the trace will be prefixed with $&#123;myObject.name&#125;: $&#123;myObject.message&#125;.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

Code
function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a();
ParameterTypeDescription
targetObjectobject
constructorOptFunction

prepareStackTrace(err: Error, stackTraces: CallSite[]): any

ParameterTypeDescription
errError
stackTracesCallSite[]

MultipleRowsError

Thrown when a single-row finder (findById, find) returns more than one row.

Constructor: new MultipleRowsError(message: string)

PropertyTypeFlags
code"MULTIPLE_ROWS"readonly
stackTraceLimitnumberstatic
causeunknownoptional
namestring
messagestring
stackstringoptional

captureStackTrace(targetObject: object, constructorOpt: Function): void

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

Code
const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack`

The first line of the trace will be prefixed with $&#123;myObject.name&#125;: $&#123;myObject.message&#125;.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

Code
function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a();
ParameterTypeDescription
targetObjectobject
constructorOptFunction

prepareStackTrace(err: Error, stackTraces: CallSite[]): any

ParameterTypeDescription
errError
stackTracesCallSite[]

UnknownColumnError

Thrown when a write operation (add, update) receives a property not in entity metadata.

Constructor: new UnknownColumnError(message: string)

PropertyTypeFlags
code"UNKNOWN_COLUMN"readonly
stackTraceLimitnumberstatic
causeunknownoptional
namestring
messagestring
stackstringoptional

captureStackTrace(targetObject: object, constructorOpt: Function): void

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

Code
const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack`

The first line of the trace will be prefixed with $&#123;myObject.name&#125;: $&#123;myObject.message&#125;.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

Code
function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a();
ParameterTypeDescription
targetObjectobject
constructorOptFunction

prepareStackTrace(err: Error, stackTraces: CallSite[]): any

ParameterTypeDescription
errError
stackTracesCallSite[]

ValidationError

Thrown when a validation check fails (e.g. empty updates object, missing actor).

Constructor: new ValidationError(message: string)

PropertyTypeFlags
code"VALIDATION"readonly
stackTraceLimitnumberstatic
causeunknownoptional
namestring
messagestring
stackstringoptional

captureStackTrace(targetObject: object, constructorOpt: Function): void

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

Code
const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack`

The first line of the trace will be prefixed with $&#123;myObject.name&#125;: $&#123;myObject.message&#125;.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

Code
function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a();
ParameterTypeDescription
targetObjectobject
constructorOptFunction

prepareStackTrace(err: Error, stackTraces: CallSite[]): any

ParameterTypeDescription
errError
stackTracesCallSite[]

Repository

Constructor: new Repository(db: Queryable)

findById(entity: EntityClass, id: string | bigint, options: FindByIdOptions): Promise<TResult | null>

ParameterTypeDescription
entityEntityClass
idstringbigint
optionsFindByIdOptions

findByUUID(entity: EntityClass, uuid: string, options: FindByUUIDOptions): Promise<TResult | null>

ParameterTypeDescription
entityEntityClass
uuidstring
optionsFindByUUIDOptions

find(entity: EntityClass, fields: FieldProjector[] | null, options: FindOptions): Promise<TResult | null>

ParameterTypeDescription
entityEntityClass
fieldsFieldProjector[]null
optionsFindOptions

findAll(entity: EntityClass, fields: FieldProjector[] | null, options: FindOptions): Promise<AsyncIterable<TResult, any, any> | TResult[]>

ParameterTypeDescription
entityEntityClass
fieldsFieldProjector[]null
optionsFindOptions

findByPage(entity: EntityClass, page: number, recordsPerPage: number, fields: FieldProjector[] | null, options: FindOptions): Promise<PaginatedEntity<TResult>>

ParameterTypeDescription
entityEntityClass
pagenumber
recordsPerPagenumber
fieldsFieldProjector[]null
optionsFindOptions

count(entity: EntityClass, options: { tableName?: string }): Promise<bigint>

ParameterTypeDescription
entityEntityClass
options{ tableName?: string }

add(entity: EntityClass & () => TEntity, row: Partial<Record<any & string, unknown>>, options: AuditableWriteOptions): Promise<TEntity>

Add — auditable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
rowPartial<Record<any & string, unknown>>
optionsAuditableWriteOptions

upsert(entity: EntityClass & () => TEntity, row: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & UpsertOptions): Promise<TEntity>

Upsert — auditable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
rowPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & UpsertOptions

update(entity: EntityClass & () => TEntity, updates: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity>

Update — auditable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
updatesPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

delete(entity: EntityClass & () => TEntity, match: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity>

ParameterTypeDescription
entityEntityClass & () => TEntity
matchPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

restore(entity: EntityClass & () => TEntity, match: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity>

Restore — auditable+deletable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
matchPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

hardDelete(entity: EntityClass & () => TEntity, match: Partial<Record<any & string, unknown>>, options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<void>

Hard-delete — auditable entity (actor required for audit log).

ParameterTypeDescription
entityEntityClass & () => TEntity
matchPartial<Record<any & string, unknown>>
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

clone(entity: EntityClass & () => TEntity, sourceUuid: string, options: AuditableWriteOptions): Promise<TEntity>

Clone an entity record by UUID.

Fetches the source record (including soft-deleted), builds a new row with:

  • PK column excluded (DB auto-generates)
  • Unique columns excluded (including uuid — a new uuid is generated)
ParameterTypeDescription
entityEntityClass & () => TEntity
sourceUuidstring
optionsAuditableWriteOptions

addMany(entity: EntityClass & () => TEntity, rows: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & BulkOptions): Promise<TEntity[]>

Bulk add — auditable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
rowsPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & BulkOptions

upsertMany(entity: EntityClass & () => TEntity, rows: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & BulkOptions & UpsertOptions): Promise<TEntity[]>

Bulk upsert — auditable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
rowsPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & BulkOptions & UpsertOptions

deleteMany(entity: EntityClass & () => TEntity, matches: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & MatchByOptions<TEntity>): Promise<TEntity[]>

Bulk soft-delete — auditable+deletable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
matchesPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity>

updateMany(entity: EntityClass & () => TEntity, updates: Partial<Record<any & string, unknown>>[], options: WriteOptions & { actor: string } & MatchByOptions<TEntity> & BulkOptions): Promise<TEntity[]>

Bulk update — auditable entity (actor required).

ParameterTypeDescription
entityEntityClass & () => TEntity
updatesPartial<Record<any & string, unknown>>[]
optionsWriteOptions & { actor: string } & MatchByOptions<TEntity> & BulkOptions

rawSql(text: string, values: unknown[]): Promise<TResult[]>

ParameterTypeDescription
textstring
valuesunknown[]

Interfaces

DalConfig

Configuration for the Dal gateway.

FieldTypeDescription
connectionStringstringPostgreSQL connection string. Required.
schema?stringSchema to set as search_path on every connection. Default: undefined (uses DB default).
max?numberMaximum pool size. Default: 10.
Formula: max ≤ (PG max_connections − reserved) / service_instances.
The lib cannot pick this for you, but it documents it.
statementTimeoutMs?numberPer-statement timeout in ms, set via SET statement_timeout on every connection.
Default: 30000. Set to 0 to disable.
This is the full wall-clock (command arrival → server completion → all rows transmitted).
connectionTimeoutMillis?numberTime to wait when acquiring a connection from the pool before erroring.
Default: 5000. Fail fast when pool exhausted — don't let requests queue forever.
idleTimeoutMillis?numberHow long an idle connection is kept before closing. Default: 30000 (pg default).
maxUses?numberOptional: recycle connections after N uses to clear per-session state.
Default: undefined (off).
applicationName?stringOptional application_name for PG logging/observability. Default: "primebrick-dal".

WithClientOptions

Options for withClient — per-connection timeout override.

FieldTypeDescription
timeoutMs?numberOverride statement_timeout (ms) for this client. Resets to session default on release.

IExposableEntity

Entity has a public UUID safe to expose outside the system.

FieldTypeDescription
uuidstring

IDeletableEntity

Entity supports soft-delete (deleted_at / deleted_by).

FieldTypeDescription
deleted_at?Date
deleted_by?string

IAuditableEntity

Entity has full audit trail (created_at/by, updated_at/by, version) + soft-delete.

FieldTypeDescription
deleted_at?Date
deleted_by?string
created_atDate
created_bystring
updated_atDate
updated_bystring
versionnumber

IClonableEntity

Entity supports cloning (cloned_from stores UUID of source record).

FieldTypeDescription
cloned_from?string

AuditPort

Audit port — consumers inject their own audit writer. The DAL calls writeAudit fire-and-forget (.catch(logger?.error ?? noop)).

LoggerPort

Logger port — consumers inject their own logger.

Type Aliases

WithAuditableDisplayNames

Adds display name fields to a row type for auditable entities. Use this to type the result of queries that include auditable joins.

Code
type WithAuditableDisplayNames = T & { created_by_name?: string; updated_by_name?: string; deleted_by_name?: string };

WithCreatorDisplayName

Adds only creator display name (for cases where you only need created_by).

Code
type WithCreatorDisplayName = T & { created_by_name?: string };

WithUpdaterDisplayName

Adds only updater display name (for cases where you only need updated_by).

Code
type WithUpdaterDisplayName = T & { updated_by_name?: string };

ColumnPgPersistenceHints

EntityClass

Entity metadata via legacy TypeScript decorators (WeakMap "reflection").

Convention: every "data" property on the class prototype is a SQL column with a name equal to the property name (snake_case). @Column() is only needed for: sqlName / pgType / nullable, or a short alias for the column name.

  • @Entity() — table name; optional argument if different from class name.
  • @Key() — primary key (one column only).
  • @Unique() — unique index (DDL patch).
  • @IsNotColumn() — excludes the property from persistence meta & DAL queries.
  • @AuditableField(type) — marks a field as audit (created_at, created_by, etc.).
  • @DeletableField(type) — marks a field as soft-delete (deleted_at, deleted_by).
  • @CloneField() — marks a field as clone tracking (cloned_from).
  • @AuditTrail() — marks the entity as having an audit trail table.
Code
type EntityClass = (args: any[]) => object;

ColumnOptions

KeyOptions

EntityPersistenceMeta

Serializable persistence metadata (for JSON compare with DB introspection).

SqlOperator

Code
type SqlOperator = "=" | "!=" | "<>" | "<" | "<=" | ">" | ">=" | "ILIKE" | "LIKE" | "IN" | "NOT IN" | "BETWEEN" | "IS" | "IS NOT";

SqlSortDirection

Code
type SqlSortDirection = "ASC" | "DESC";

SqlJoinType

Code
type SqlJoinType = "INNER" | "LEFT" | "RIGHT";

SqlExpressionOperand

Code
type SqlExpressionOperand = "AND" | "OR";

FieldRef

FilterExpr

Code
type FilterExpr = { kind: "field_value"; left: FieldRef<any, any>; op: SqlOperator; right: unknown; operand: SqlExpressionOperand } | { kind: "field_field"; left: FieldRef<any, any>; op: SqlOperator; right: FieldRef<any, any>; operand: SqlExpressionOperand } | { kind: "raw"; left: string; op: SqlOperator; right: string; operand: SqlExpressionOperand } | { kind: "group"; filters: FilterExpr[]; operand: SqlExpressionOperand };

SortingExpr

JoinExpr

FieldProjector

Code
type FieldProjector = { kind: "field"; field: FieldRef<any, any>; alias?: string } | { kind: "expr"; expr: string; alias: string };

SqlQuery

SelectQueryInput

WithDeletedRecords

Controls how soft-deleted rows (deleted_at IS NOT NULL) are handled in finders.

Code
type WithDeletedRecords = "EXCLUDED" | "ONLY" | "INCLUDED";

FindByIdOptions

Options for findById.

FindOptions

Options for find, findAll, findByPage.

FindByUUIDOptions

Options for findByUUID.

PaginatedEntity

Paginated result wrapper.

WriteOptions

Base write options — no actor (for non-auditable entities).

AuditableWriteOptions

Write options for auditable entities — actor is required.

Code
type AuditableWriteOptions = WriteOptions & { actor: string };

MatchByOptions

Options for match-by operations (update, delete, restore, hardDelete).

BulkOptions

Bulk operation options (batch size, timeout).

UpsertOptions

Upsert-specific options.

AuditParams

Parameters passed to AuditPort.writeAudit.

Variables

Filter

Type: { fieldValue: any; fieldField: any; raw: any; group: any }

Sort

Type: { by: any }

Join

Type: { on: any }

Project

Type: { field: any; expr: any }

Functions

buildAuditableJoins(entity: EntityClass, userEntity: EntityClass): JoinExpr[]

Standard join configuration for auditable entities. Automatically adds LEFT JOINs to the user entity table for created_by, updated_by, deleted_by fields.

Uses regex guardrail pattern to only join when the field contains a valid UUID. This prevents errors when the field contains non-UUID values like "system".

ParameterTypeDescription
entityEntityClassThe entity class implementing IAuditableEntity
userEntityEntityClassThe user entity class (e.g. UserProfileEntity) that has a uuid and display_name column

buildAuditableJoinsSelective(entity: EntityClass, userEntity: EntityClass, options: { includeCreator?: boolean; includeUpdater?: boolean; includeDeleter?: boolean }): JoinExpr[]

Enhanced version that allows selective joins (e.g., only creator and updater). Useful when you only need specific audit fields to reduce query overhead.

ParameterTypeDescription
entityEntityClassThe entity class implementing IAuditableEntity
userEntityEntityClassThe user entity class (e.g. UserProfileEntity)
options{ includeCreator?: boolean; includeUpdater?: boolean; includeDeleter?: boolean }Configuration for which joins to include

buildAuditTrailJoins(auditEntity: EntityClass, userEntity: EntityClass): { joins: JoinExpr[]; projections: FieldProjector[] }

Build LEFT JOIN + projections for audit trail entities (AuditLogEntity).

Audit trail entities have a single changed_by column (not created_by/updated_by/deleted_by). This function joins the user entity to resolve changed_by into display_name and idp_code.

Uses castRightTo: "uuid" + castLeftTo: "uuid" to trigger the regex guardrail (changed_by ~ '^[0-9a-fA-F-]&#123;36&#125;$') automatically in renderJoins(). This prevents errors when changed_by contains non-UUID values like "system".

Distinct from buildAuditableJoins() which uses castRightTo: "text" (no guardrail, text = text). buildAuditTrailJoins() uses castRightTo: "uuid" + castLeftTo: "uuid" (guardrail + uuid = uuid).

ParameterTypeDescription
auditEntityEntityClassThe audit trail entity class (e.g., AuditLogEntity)
userEntityEntityClassThe user entity class (e.g., UserProfileEntity) with uuid, display_name, idp_code columns

calculateDelta(oldEntity: Record<string, unknown>, newEntity: Record<string, unknown>): Record<string, { old: unknown; new: unknown }>

Calculate delta between old and new records for audit.

ParameterTypeDescription
oldEntityRecord<string, unknown>
newEntityRecord<string, unknown>

calculateDeltaWithForcedFields(oldEntity: Record<string, unknown>, newEntity: Record<string, unknown>, forceFields: string[]): Record<string, { old: unknown; new: unknown }>

Calculate delta and force include specific fields even when unchanged.

ParameterTypeDescription
oldEntityRecord<string, unknown>
newEntityRecord<string, unknown>
forceFieldsstring[]

getDal(config: DalConfig): Dal

Returns the process-wide singleton Dal instance. Creates it on first call.

  • First call: requires config, creates the singleton.
  • Subsequent calls with NO config: returns the existing instance.
  • Subsequent calls with the SAME connectionString: returns the existing instance.
  • Subsequent calls with a DIFFERENT connectionString: throws (prevents accidental double-init with wrong params).

For multi-DB: construct new Dal(config) directly (bypasses the singleton).

ParameterTypeDescription
configDalConfig

resetDal(): Promise<void>

Resets the singleton. Closes the existing instance if any. Intended for tests — call in afterAll to release the pool.

columnHintsFromMetaColumn(col: { propertyKey: string; sqlName: string; isKey: boolean; isUnique: boolean; nullable?: boolean; pgType?: string; tsDesignTypeCtorName?: string; defaultSql?: string; length?: number; precision?: number; scale?: number; inferredPgType: string; usePostgresIdentity: boolean; isAuditable?: boolean; auditableType?: AuditableFieldType; isDeletable?: boolean; deletableType?: DeletableFieldType; isSynchronizable?: boolean; synchronizableType?: SynchronizableFieldType; isClone?: boolean; castInJoin?: string }): ColumnPgPersistenceHints

ParameterTypeDescription
col{ propertyKey: string; sqlName: string; isKey: boolean; isUnique: boolean; nullable?: boolean; pgType?: string; tsDesignTypeCtorName?: string; defaultSql?: string; length?: number; precision?: number; scale?: number; inferredPgType: string; usePostgresIdentity: boolean; isAuditable?: boolean; auditableType?: AuditableFieldType; isDeletable?: boolean; deletableType?: DeletableFieldType; isSynchronizable?: boolean; synchronizableType?: SynchronizableFieldType; isClone?: boolean; castInJoin?: string }

effectivePgStorageType(h: ColumnPgPersistenceHints): string

Effective storage type in PostgreSQL (explicit pgType wins over inference).

ParameterTypeDescription
hColumnPgPersistenceHints

isLogicalJsDateColumn(h: ColumnPgPersistenceHints): boolean

Column represents an instant / calendar point stored via Date in the entity.

ParameterTypeDescription
hColumnPgPersistenceHints

jsValueToPgParam(value: unknown, h: ColumnPgPersistenceHints): unknown

Value to pass to node-pg query parameters (or similar drivers). Date → timestamptz / timestamp as Date; SQL date as YYYY-MM-DD string.

ParameterTypeDescription
valueunknown
hColumnPgPersistenceHints

pgValueToJsValue(value: unknown, h: ColumnPgPersistenceHints): unknown

Normalise a driver value (often ISO string) into Date on the entity when the column is date-like.

ParameterTypeDescription
valueunknown
hColumnPgPersistenceHints

entityDateToApiIso(value: Date): string

ParameterTypeDescription
valueDate

hydrateEntityDateFieldsFromJson(instance: T, meta: EntityPersistenceMeta): void

After Object.assign from JSON, coerce ISO strings into Date for date-like columns.

ParameterTypeDescription
instanceT
metaEntityPersistenceMeta

syncImplicitEntityColumns(ctor: Function): void

Registers every implicit column + design:type / nullability when not already set by decorators.

ParameterTypeDescription
ctorFunction

Entity(tableName: string, schema: string): (ctor: T) => T

Maps the class to a DB table. Optional argument overrides the table name; if omitted, the table name equals the class name.

ParameterTypeDescription
tableNamestring
schemastring

Column(sqlName: string): PropertyDecorator

Override SQL name / pgType / nullable only; otherwise the property is already a column by convention.

ParameterTypeDescription
sqlNamestring

IsNotColumn(): PropertyDecorator

Excludes the property from meta schema / migration and from future DAL queries.

Unique(): PropertyDecorator

Unique constraint (PostgreSQL®: unique index in generated patches).

Key(): PropertyDecorator

Marks the single-column primary key.

AuditableField(what: AuditableFieldType): PropertyDecorator

Marks a field as auditable (created_at, created_by, updated_at, updated_by, version).

ParameterTypeDescription
whatAuditableFieldType

DeletableField(what: DeletableFieldType): PropertyDecorator

Marks a field as deletable (deleted_at, deleted_by).

ParameterTypeDescription
whatDeletableFieldType

SynchronizableField(what: SynchronizableFieldType): PropertyDecorator

Marks a field as synchronizable (last_synced_at).

ParameterTypeDescription
whatSynchronizableFieldType

CloneField(): PropertyDecorator

Marks a field as clone tracking (cloned_from). Stores UUID of the source record.

AuditTrail(): ClassDecorator

Marks an entity as having an audit trail table.

AuditTrailEntity(options: { changedByColumn?: string }): ClassDecorator

Marks a class as BEING an audit trail entity (e.g., AuditLogEntity). Distinct from @AuditTrail() which marks an entity as HAVING an audit trail. The changedByColumn specifies which property holds the actor (default: "changed_by").

ParameterTypeDescription
options{ changedByColumn?: string }

isEntityClass(value: unknown): value is EntityClass

ParameterTypeDescription
valueunknown

getTableName(ctor: EntityClass): string

ParameterTypeDescription
ctorEntityClass

getQualifiedTableName(ctor: EntityClass): string

Returns a schema-qualified table reference for SQL generation. When the entity has an explicit @Entity("table", "schema") override, returns "schema"."table". Otherwise returns just "table" (relies on search_path).

ParameterTypeDescription
ctorEntityClass

getEntityName(ctor: EntityClass): string

Logical entity name: the class name (e.g. CustomerEntity).

ParameterTypeDescription
ctorEntityClass

getColumnName(ctor: EntityClass, propertyKey: string | symbol): string

ParameterTypeDescription
ctorEntityClass
propertyKeystringsymbol

getPrimaryKeyColumn(ctor: EntityClass): string

ParameterTypeDescription
ctorEntityClass

listEntityPersistencePropertyKeys(ctor: EntityClass): string[]

Property keys that map to SQL columns (implicit + decorated).

ParameterTypeDescription
ctorEntityClass

getEntityPersistenceMeta(ctor: EntityClass, tableSchema: string): EntityPersistenceMeta

Snapshot fragment for one

ParameterTypeDescription
ctorEntityClass
tableSchemastring

field(entity: EntityClass, key: K): FieldRef<TEntity, K>

ParameterTypeDescription
entityEntityClass
keyK

quoteIdent(ident: string): string

ParameterTypeDescription
identstring

buildSelectQuery(input: SelectQueryInput): SqlQuery

ParameterTypeDescription
inputSelectQueryInput

createStream(db: Queryable, text: string, values: unknown[]): AsyncIterable<TResult>

Creates an AsyncIterable from a SQL query using pg-query-stream.

ParameterTypeDescription
dbQueryableThe pg Pool or PoolClient
textstringSQL query text
valuesunknown[]Parameter values

<!-- END -->

Last modified on July 26, 2026
ChangelogOverview
On this page
  • Enumerations
    • AuditableFieldType
    • DeletableFieldType
    • SynchronizableFieldType
    • AuditAction
  • Classes
    • AuditLogEntity
    • Dal
    • DalError
    • NotFoundError
    • MultipleRowsError
    • UnknownColumnError
    • ValidationError
    • Repository
  • Interfaces
    • DalConfig
    • WithClientOptions
    • IExposableEntity
    • IDeletableEntity
    • IAuditableEntity
    • IClonableEntity
    • AuditPort
    • LoggerPort
  • Type Aliases
    • WithAuditableDisplayNames
    • WithCreatorDisplayName
    • WithUpdaterDisplayName
    • ColumnPgPersistenceHints
    • EntityClass
    • ColumnOptions
    • KeyOptions
    • EntityPersistenceMeta
    • SqlOperator
    • SqlSortDirection
    • SqlJoinType
    • SqlExpressionOperand
    • FieldRef
    • FilterExpr
    • SortingExpr
    • JoinExpr
    • FieldProjector
    • SqlQuery
    • SelectQueryInput
    • WithDeletedRecords
    • FindByIdOptions
    • FindOptions
    • FindByUUIDOptions
    • PaginatedEntity
    • WriteOptions
    • AuditableWriteOptions
    • MatchByOptions
    • BulkOptions
    • UpsertOptions
    • AuditParams
  • Variables
    • Filter
    • Sort
    • Join
    • Project
  • Functions
    • buildAuditableJoins(entity: EntityClass, userEntity: EntityClass): JoinExpr[]
    • buildAuditableJoinsSelective(entity: EntityClass, userEntity: EntityClass, options: { includeCreator?: boolean; includeUpdater?: boolean; includeDeleter?: boolean }): JoinExpr[]
    • buildAuditTrailJoins(auditEntity: EntityClass, userEntity: EntityClass): { joins: JoinExpr[]; projections: FieldProjector[] }
    • calculateDelta(oldEntity: Record<string, unknown>, newEntity: Record<string, unknown>): Record<string, { old: unknown; new: unknown }>
    • calculateDeltaWithForcedFields(oldEntity: Record<string, unknown>, newEntity: Record<string, unknown>, forceFields: string[]): Record<string, { old: unknown; new: unknown }>
    • getDal(config: DalConfig): Dal
    • resetDal(): Promise<void>
    • columnHintsFromMetaColumn(col: { propertyKey: string; sqlName: string; isKey: boolean; isUnique: boolean; nullable?: boolean; pgType?: string; tsDesignTypeCtorName?: string; defaultSql?: string; length?: number; precision?: number; scale?: number; inferredPgType: string; usePostgresIdentity: boolean; isAuditable?: boolean; auditableType?: AuditableFieldType; isDeletable?: boolean; deletableType?: DeletableFieldType; isSynchronizable?: boolean; synchronizableType?: SynchronizableFieldType; isClone?: boolean; castInJoin?: string }): ColumnPgPersistenceHints
    • effectivePgStorageType(h: ColumnPgPersistenceHints): string
    • isLogicalJsDateColumn(h: ColumnPgPersistenceHints): boolean
    • jsValueToPgParam(value: unknown, h: ColumnPgPersistenceHints): unknown
    • pgValueToJsValue(value: unknown, h: ColumnPgPersistenceHints): unknown
    • entityDateToApiIso(value: Date): string
    • hydrateEntityDateFieldsFromJson(instance: T, meta: EntityPersistenceMeta): void
    • syncImplicitEntityColumns(ctor: Function): void
    • Entity(tableName: string, schema: string): (ctor: T) => T
    • Column(sqlName: string): PropertyDecorator
    • IsNotColumn(): PropertyDecorator
    • Unique(): PropertyDecorator
    • Key(): PropertyDecorator
    • AuditableField(what: AuditableFieldType): PropertyDecorator
    • DeletableField(what: DeletableFieldType): PropertyDecorator
    • SynchronizableField(what: SynchronizableFieldType): PropertyDecorator
    • CloneField(): PropertyDecorator
    • AuditTrail(): ClassDecorator
    • AuditTrailEntity(options: { changedByColumn?: string }): ClassDecorator
    • isEntityClass(value: unknown): value is EntityClass
    • getTableName(ctor: EntityClass): string
    • getQualifiedTableName(ctor: EntityClass): string
    • getEntityName(ctor: EntityClass): string
    • getColumnName(ctor: EntityClass, propertyKey: string | symbol): string
    • getPrimaryKeyColumn(ctor: EntityClass): string
    • listEntityPersistencePropertyKeys(ctor: EntityClass): string[]
    • getEntityPersistenceMeta(ctor: EntityClass, tableSchema: string): EntityPersistenceMeta
    • field(entity: EntityClass, key: K): FieldRef<TEntity, K>
    • quoteIdent(ident: string): string
    • buildSelectQuery(input: SelectQueryInput): SqlQuery
    • createStream(db: Queryable, text: string, values: unknown[]): AsyncIterable<TResult>
Javascript
Javascript
Javascript
Javascript
Javascript
Javascript
Javascript
Javascript
Javascript
Javascript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
columnHintsFromMetaColumn(col: { propertyKey: string; sqlName: string; isKey: boolean; isUnique: boolean; nullable?: boolean; pgType?: string; tsDesignTypeCtorName?: string; defaultSql?: string; length?: number; precision?: number; scale?: number; inferredPgType: string; usePostgresIdentity: boolean; isAuditable?: boolean; auditableType?: AuditableFieldType; isDeletable?: boolean; deletableType?: DeletableFieldType; isSynchronizable?: boolean; synchronizableType?: SynchronizableFieldType; isClone?: boolean; castInJoin?: string }): ColumnPgPersistenceHints