title: API Reference description: Complete API reference for @primebrick/dal-pg — every exported symbol.
API Reference
Every exported symbol from @primebrick/dal-pg, rendered mechanically from the
TypeDoc extraction. This page is regenerated from docs/dev-guide/_extracted/api.json
on every pnpm extract-docs run — do not edit by hand.
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
| Property | Type | Description |
|---|---|---|
| id | bigint | |
| entity_id | bigint | |
| entity_uuid | string | |
| action | string | |
| changed_at | Date | |
| changed_by | string | |
| version | number | |
| delta | Record<string, { old: unknown; new: unknown }> |
BulkTimeoutError
Thrown when a bulk write exceeds its wall-clock budget
(DalConfig.bulkTimeoutMs or BulkOptions.timeoutMs). The surrounding
transaction is rolled back — no partial writes survive.
Code: ERR06. TS-originated (the JS deadline fires between
statements; a slow single statement is bounded by SET LOCAL statement_timeout → PG 57014 query_canceled). HTTP 408.
| Property | Type | Description |
|---|---|---|
| code | "ERR06" |
BulkTimeoutError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
ConfigEntityBase
ConfigEntityBase — standard dictionary-style config table entity.
Every Primebrick config table (BE auth_configurations, microservice config)
extends this base class to get the standard column set without copy-paste.
Columns: key varchar(100) NOT NULL UNIQUE — stable snake_case setting key value text nullable — raw TEXT; null = "not set" type varchar(50) NOT NULL — ConfigType (drives SDK coercion + FE widget) type_config text nullable — JSONB-text extra per-type config (badge values, list API URL, etc.) label_key varchar(100) nullable — i18n key for the setting title description_key varchar(100) nullable — i18n key for the explanatory text reserved boolean NOT NULL DEFAULT false — if true: editable but not deletable group_key varchar(100) nullable — UI grouping key (null/empty = ungrouped, top of list)
Plus standard audit columns (created_at/by, updated_at/by, version, deleted_at/by).
The consumer creates a concrete subclass: @Entity("config", "public") export class ConfigEntryEntity extends ConfigEntityBase {}
This class is DB-agnostic — it does NOT import from @primebrick/sdk. The SDK's IConfigEntity interface mirrors the field names for port-level use.
| Property | Type | Description |
|---|---|---|
| id | bigint | |
| uuid | string | |
| key | string | Unique config key (e.g. "oidc_issuer_url", "enable_mfa"). Never renamed after release. |
| value | string | null | Raw TEXT value. null means "the row exists but the value is not set". |
| type | string | Config value type — drives SDK coercion and FE widget selection. |
| type_config | string | null | JSONB-text extra per-type configuration (e.g. badge inline values, list API URL). |
| label_key | string | i18n key for the setting title. |
| description_key | string | i18n key for the explanatory description. |
| reserved | boolean | If true, the row is system-critical: editable but not deletable. |
| group_key | string | null | Optional grouping key for UI display. null/empty = ungrouped (top of list). |
| created_at | Date | |
| created_by | string | |
| updated_at | Date | |
| updated_by | string | |
| version | number | |
| deleted_at | Date | |
| deleted_by | string |
Dal
| Property | Type | Description |
|---|---|---|
| config | Required<Pick<DalConfig, "connectionString" | "schemas" | "max" | "statementTimeoutMs" | "bulkTimeoutMs" | "connectionTimeoutMillis" | "idleTimeoutMillis" | "applicationName">> & Pick<DalConfig, "sharedTables" | "maxUses" | "repoDecorator"> | The resolved configuration (defaults merged with user-provided config). |
Dal(config)
| Parameter | Type | Description |
|---|---|---|
| config | DalConfig |
Dal.getPool(): Pool
The underlying pg.Pool. Exposed for snapshot/migration tooling that needs raw access.
Dal.close(timeoutMs): 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.
| Parameter | Type | Description |
|---|---|---|
| timeoutMs | number | Maximum time to wait for pool.end() to complete. Default: 10000. |
Dal.findById(entity, id, options): Promise<TResult \| null>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| id | string | bigint | |
| options | FindByIdOptions |
Dal.findByUUID(entity, uuid, options): Promise<TResult \| null>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| uuid | string | |
| options | FindByUUIDOptions |
Dal.find(entity, fields, options): Promise<TResult \| null>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
Dal.findAll(entity, fields, options): Promise<AsyncIterable<TResult, any, any> \| TResult[]>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
Dal.findByPage(entity, page, recordsPerPage, fields, options): Promise<PaginatedEntity<TResult>>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| page | number | |
| recordsPerPage | number | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
Dal.count(entity): Promise<bigint>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass |
Dal.vectorSearch(entity, vectorField, queryVector, options): Promise<TResult & { similarity: number; distance: number }[]>
pgvector nearest-neighbour search — see Repository.vectorSearch.
ORDER BY <vectorField> <op> $n::vector LIMIT <topK> with the query
vector bound as a parameter (HNSW/ivfflat-safe). similarity score for
cosine (<=>), raw distance for other operators.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| vectorField | FieldRef<TEntity, keyof TEntity & string> | |
| queryVector | string | number[] | |
| options | VectorSearchOptions<TEntity> |
Dal.add(entity, row, options): Promise<TResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| row | Partial<Record<keyof TEntity & string, unknown>> | |
| options | AuditableWriteOptions<TEntity> |
Dal.update(entity, updates, options): Promise<TResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| updates | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Dal.delete(entity, match, options): Promise<TResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Dal.restore(entity, match, options): Promise<TResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Dal.hardDelete(entity, match, options): Promise<TResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Dal.addMany(entity, rows, options): Promise<BulkResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| rows | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & BulkOptions |
Dal.hardDeleteMany(entity, matches, options): Promise<BulkResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| matches | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> & BulkOptions |
Dal.restoreMany(entity, matches, options): Promise<BulkResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| matches | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> & BulkOptions |
Dal.updateMany(entity, updates, options): Promise<BulkResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| updates | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> & BulkOptions |
Dal.deleteMany(entity, matches, options): Promise<BulkResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| matches | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Dal.entityService(cfg): EntityService<TEntity>
The public path to the generic entity-service worker. The gateway
injects its own (schema-domain-guarded, pool-scoped) Repository — the
consumer never sees it. cfg.repo exists only as a decorator seam
(e.g. BE withCache): leave it unset for the standard wiring.
| Parameter | Type | Description |
|---|---|---|
| cfg | EntityServiceConfig<TEntity> |
Dal.tableAuditPort(): AuditPort
The standard {table}_audit writer port, bound to the gateway
Repository. Use for adapters that need an AuditPort without exposing
the Repository itself.
Dal.serverVersion(): Promise<{ server_version: string; version: string }>
Server version + connectivity probe in one call. A successful response
already proves the connection is alive — there is deliberately no
separate ping() (a dedicated SELECT 1 would be a redundant round-trip).
Throws on connectivity/timeout failure.
Dal.transaction(fn, options): Promise<TResult>
Atomic multi-statement work — BEGIN/COMMIT/ROLLBACK around a
tx-scoped Repository. Use for cascades, multi-write units, and any
sequence that must commit or fail as one. Post-commit side effects
(cache invalidation, events) belong AFTER this resolves, never inside.
| Parameter | Type | Description |
|---|---|---|
| fn | (txRepo: Repository) => Promise<TResult> | |
| options | TimeoutOverrideOptions |
Dal.beginTransaction(options): DeferredTransaction
Deferred fluent transaction — buffer repository ops (tx.add, tx.update,
tx.find, …) without executing, then tx.commit() compiles and runs them
as ONE data-modifying CTE statement. Atomicity is PostgreSQL's
single-statement guarantee — no BEGIN/COMMIT/ROLLBACK and no rollback
path exist in this mode. Inter-op values flow via Deferred.ref();
conditional TS logic on mid-flow results stays in transaction(fn).
| Parameter | Type | Description |
|---|---|---|
| options | TimeoutOverrideOptions |
Dal.truncate(entity, options): Promise<void>
Physical table reset — delegates to Repository.truncate (entity-resolved,
schema-domain guarded). For auditable tables prefer soft-delete; TRUNCATE
is for caches, KB stores, and test teardown.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| options | { restartIdentity: boolean; cascade: boolean } |
Dal.partitionMaintenance(entities, options): Promise<PartitionMaintenanceReport>
pg_partman retention executor — metadata-driven, identical for every
service. Purges @PartitionChildOf children of expired parents (before
the partition drop), removes expired strays from the default partition,
then runs partman.run_maintenance_proc(). Called by the service's
jobs.due.system.<svc>.partition-maintenance consumer.
| Parameter | Type | Description |
|---|---|---|
| entities | readonly EntityClass[] | the service's entity registry (only @PartitionField |
| entities participate; everything else is ignored) | ||
| options | TimeoutOverrideOptions |
DalError
Generic DAL error with a stable code field.
| Property | Type | Description |
|---|---|---|
| code | string |
DalError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
Decimal
DecimalError
Errors raised by @primebrick/decimal.
Deferred
Handle for a buffered operation's future result. NOT a Promise — awaiting
it pre-commit would deadlock (commit is never reached), so it deliberately
exposes no then. Read .value only after await tx.commit().
Deferred.ref(field): DeferredFieldRef<T[K]>
Reference a RETURNING/SELECT column of this op for use in a LATER op.
| Parameter | Type | Description |
|---|---|---|
| field | K |
DeferredFieldRef
Opaque marker produced by Deferred.ref("field") — embeddable in a later
op's payload/match values. At compile time the $n it would occupy is
rewritten to (SELECT "field" FROM "__rN") over the source op's RETURNING
branch. Never a bound parameter — survives jsValueToPgParam untouched.
DeferredTransaction
DeferredTransaction.add(entity, row, options): Deferred<TResult>
Buffer an insert — see Repository.add. options.audit is rejected.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| row | Partial<Record<keyof TEntity & string, unknown>> | |
| options | AuditableWriteOptions<TEntity> |
DeferredTransaction.update(entity, updates, options): Deferred<TResult>
Buffer an update — see Repository.update. options.audit is rejected.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| updates | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
DeferredTransaction.delete(entity, match, options): Deferred<TResult>
Buffer a soft-delete — see Repository.delete. options.audit is rejected.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
DeferredTransaction.restore(entity, match, options): Deferred<TResult>
Buffer a restore — see Repository.restore. options.audit is rejected.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
DeferredTransaction.hardDelete(entity, match, options): Deferred<TResult>
Buffer a hard delete — see Repository.hardDelete. options.audit is rejected.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
DeferredTransaction.find(entity, fields, options): Deferred<TResult \| null>
Buffer a single-row find — see Repository.find.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
DeferredTransaction.findByUUID(entity, uuid, options): Deferred<TResult \| null>
Buffer a find-by-uuid — see Repository.findByUUID.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| uuid | string | |
| options | FindByUUIDOptions |
DeferredTransaction.findById(entity, id, options): Deferred<TResult \| null>
Buffer a find-by-id — see Repository.findById.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| id | string | bigint | |
| options | FindByIdOptions |
DeferredTransaction.findAll(entity, fields, options): Deferred<TResult[]>
Buffer a findAll — see Repository.findAll (stream rejected).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
DeferredTransaction.findByPage(entity, page, recordsPerPage, fields, options): Deferred<PaginatedEntity<TResult>>
Buffer a paged find — see Repository.findByPage.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| page | number | |
| recordsPerPage | number | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
DeferredTransaction.count(entity, options): Deferred<bigint>
Buffer a count — see Repository.count.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| options | { tableName: string } |
DeferredTransaction.vectorSearch(entity, vectorField, queryVector, options): Deferred<TResult & { similarity: number; distance: number }[]>
Buffer a pgvector search — see Repository.vectorSearch.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| vectorField | FieldRef<TEntity, keyof TEntity & string> | |
| queryVector | string | number[] | |
| options | VectorSearchOptions<TEntity> |
DeferredTransaction.commit(): Promise<void>
Compile every buffered op into ONE statement and execute it. Atomicity
is the statement's own: a failure anywhere (constraint, pg_raise guard,
abort branch, timeout) rolls back every branch — no rollback code exists
because none is needed. Resolves when all Deferred handles are
materialized; rejects with the first failure.
DeferredTransaction.discard()
Abandon the buffer without executing anything. Nothing has run yet by design — this simply invalidates the transaction and its Deferred handles.
DeletedRecordConflictError
Unique-constraint conflict on a soft-deleted row — the row exists with
deleted_at set and must be restored, never duplicated.
PG-originated via pg_raise('ERR05', ...); the existing row's uuid
travels in the error detail so consumers can offer a direct restore.
This class is provided for ergonomic instanceof checks.
Code: ERR05. HTTP 409.
| Property | Type | Description |
|---|---|---|
| code | "ERR05" |
DeletedRecordConflictError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
DomainService
The contract every entity service must satisfy — enforced on the router.
| Property | Type | Description |
|---|---|---|
| cfg | EntityServiceConfig<TEntity> |
DomainService(cfg)
| Parameter | Type | Description |
|---|---|---|
| cfg | EntityServiceConfig<TEntity> |
DomainService.buildConfig(): EntityServiceConfig<TEntity>
Subclass seam for config enrichment (auditPort / actor / userEntity
injection). Runs once, inside the lazy svc resolution — this.dal
is available here.
DomainService.list(query): Promise<EntityListResult<TEntity>>
| Parameter | Type | Description |
|---|---|---|
| query | EntityListQuery |
DomainService.get(uuid): Promise<TEntity>
| Parameter | Type | Description |
|---|---|---|
| uuid | string |
DomainService.create(body, tx): Promise<TEntity>
| Parameter | Type | Description |
|---|---|---|
| body | Record<string, unknown> | |
| tx | Repository |
DomainService.update(uuid, body, tx): Promise<TEntity>
| Parameter | Type | Description |
|---|---|---|
| uuid | string | |
| body | Record<string, unknown> & { version: number } | |
| tx | Repository |
DomainService.delete(uuid, version): Promise<TEntity>
| Parameter | Type | Description |
|---|---|---|
| uuid | string | |
| version | number |
DomainService.restore(uuid, version): Promise<TEntity>
| Parameter | Type | Description |
|---|---|---|
| uuid | string | |
| version | number |
DomainService.purge(uuid, version): Promise<TEntity>
| Parameter | Type | Description |
|---|---|---|
| uuid | string | |
| version | number |
DomainService.duplicate(uuids): Promise<DuplicateResult>
| Parameter | Type | Description |
|---|---|---|
| uuids | string[] |
DomainService.bulkDelete(items): Promise<unknown>
| Parameter | Type | Description |
|---|---|---|
| items | BulkItem[] |
DomainService.bulkRestore(items): Promise<unknown>
| Parameter | Type | Description |
|---|---|---|
| items | BulkItem[] |
DomainService.audit(uuid, page, limit): Promise<unknown>
| Parameter | Type | Description |
|---|---|---|
| uuid | string | |
| page | number | |
| limit | number |
DomainService.stream(query): AsyncGenerator<TEntity>
| Parameter | Type | Description |
|---|---|---|
| query | EntityListQuery |
DuplicateRecordError
Unique-constraint conflict on a live row.
Normally PG-originated: the add() conflict-reporting CTE calls
pg_raise('ERR04', ...), and node-postgres propagates it as a
DatabaseError with err.code === 'ERR04' and a jsonb err.detail
({ entity, table, uuid, constraint }). The DAL throws this class only
when the conflict cannot be attributed to any identifiable row (unique
group whose attempted values are all DB-generated, e.g. a payload-less
uuid). Provided in both cases for ergonomic instanceof checks.
Code: ERR04. HTTP 409.
| Property | Type | Description |
|---|---|---|
| code | "ERR04" |
DuplicateRecordError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
EntityBase
Composition root — empty on purpose. extends Mixin(EntityBase).
ManifestError
| Property | Type | Description |
|---|---|---|
| code | string |
ManifestError(code, message)
| Parameter | Type | Description |
|---|---|---|
| code | string | |
| message | string |
MissingVersionError
Thrown when an auditable-entity write (update/upsert-ON-CONFLICT/delete/restore/hardDelete)
is attempted without a version field in the payload.
Code: ERR02. TS-originated. HTTP 400.
| Property | Type | Description |
|---|---|---|
| code | "ERR02" | |
| detail | unknown | Structured per-row detail for bulk ops (entity, table, missing count, rows[]). |
MissingVersionError(message, detail)
| Parameter | Type | Description |
|---|---|---|
| message | string | |
| detail | unknown |
MultipleRowsError
Thrown when a single-row finder (findById, find) returns more than one row.
| Property | Type | Description |
|---|---|---|
| code | "MULTIPLE_ROWS" |
MultipleRowsError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
NotFoundError
Thrown when a finder returns zero rows and throwIfNotFound is true (the default).
| Property | Type | Description |
|---|---|---|
| code | "NOT_FOUND" |
NotFoundError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
OptimisticLockError
TS wrapper for the PG-originated ERR01 optimistic concurrency violation.
The DAL does NOT throw this class in the happy/conflict path — PostgreSQL
raises RAISE EXCEPTION ... USING ERRCODE = 'ERR01' and node-postgres
propagates it as a DatabaseError with err.code === 'ERR01'. This class
is provided only for ergonomic instanceof checks if a consumer wants to
normalize PG errors into TS errors at a boundary.
Code: ERR01. PG-originated. HTTP 409.
| Property | Type | Description |
|---|---|---|
| code | "ERR01" |
OptimisticLockError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
RecordVanishedError
Thrown when an auditable-entity write matches zero rows AND a disambiguation SELECT confirms the row no longer exists (was hard-deleted by another writer).
Code: ERR03. TS-originated. HTTP 404.
Distinct from NotFoundError (which is for finders): ERR03 specifically
means "the row existed when you read it but is now gone".
| Property | Type | Description |
|---|---|---|
| code | "ERR03" |
RecordVanishedError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
Repository
Repository(db, token, bulkTimeoutMs)
| Parameter | Type | Description |
|---|---|---|
| db | Queryable | |
| token | typeof REPO_INTERNAL | |
| bulkTimeoutMs | number | Whole-operation wall-clock budget (ms) for every |
| *Many method — the transaction must complete within this bound or it is | ||
aborted and rolled back. 0/undefined disables the budget. | ||
Per-call override: BulkOptions.timeoutMs. |
Repository.findById(entity, id, options): Promise<TResult \| null>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| id | string | bigint | |
| options | FindByIdOptions |
Repository.findByUUID(entity, uuid, options): Promise<TResult \| null>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| uuid | string | |
| options | FindByUUIDOptions |
Repository.find(entity, fields, options): Promise<TResult \| null>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
Repository.findAll(entity, fields, options): Promise<AsyncIterable<TResult, any, any> \| TResult[]>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
Repository.vectorSearch(entity, vectorField, queryVector, options): Promise<TResult & { similarity: number; distance: number }[]>
pgvector nearest-neighbour search — the DAL-native replacement for raw
<=>-style similarity queries.
Emits ORDER BY <vectorField> <op> $n::vector LIMIT <topK> with the
query vector always bound as a parameter (required for HNSW/ivfflat
index usage — never interpolated). Entity-generic: schema, tableName
override, filters, projections and soft-delete scoping behave exactly
like findAll.
The result carries a similarity score column when distance is the
default "<=>" (cosine — 1 - distance, higher = closer). For other
operators the projected column is distance (raw distance, lower =
closer).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| vectorField | FieldRef<TEntity, keyof TEntity & string> | |
| queryVector | string | number[] | |
| options | VectorSearchOptions<TEntity> |
Repository.findByPage(entity, page, recordsPerPage, fields, options): Promise<PaginatedEntity<TResult>>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| page | number | |
| recordsPerPage | number | |
| fields | FieldProjector[] | null | |
| options | FindOptions |
Repository.count(entity, options): Promise<bigint>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| options | { tableName: string } |
Repository.truncate(entity, options): Promise<void>
Physical table reset — TRUNCATE TABLE <schema>.<table> resolved through
entity metadata, like every other entity op: the schema-domain guard
applies (entities outside the declared domain throw before any SQL).
For auditable tables prefer soft-delete; TRUNCATE is for caches, KB
stores, and test teardown.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| options | { restartIdentity: boolean; cascade: boolean } |
Repository.add(entity, row, options): Promise<TResult>
Add — auditable entity (actor required).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| row | Partial<Record<keyof TEntity & string, unknown>> | |
| options | AuditableWriteOptions<TEntity> |
Repository.update(entity, updates, options): Promise<TResult>
Update — auditable entity (actor required).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| updates | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Repository.delete(entity, match, options): Promise<TResult>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Repository.restore(entity, match, options): Promise<TResult>
Restore — auditable+deletable entity (actor required).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Repository.hardDelete(entity, match, options): Promise<TResult>
Hard-delete — auditable entity (actor required for audit log).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| match | Partial<Record<keyof TEntity & string, unknown>> | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Repository.clone(entity, sourceUuid, options): 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)
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| sourceUuid | string | |
| options | AuditableWriteOptions |
Repository.addMany(entity, rows, options): Promise<BulkResult>
Bulk add — auditable entity (actor required).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| rows | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & BulkOptions |
Repository.deleteMany(entity, matches, options): Promise<BulkResult>
Bulk soft-delete — auditable+deletable entity (actor required).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| matches | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> |
Repository.hardDeleteMany(entity, matches, options): Promise<BulkResult>
Bulk hard-delete — auditable entity (actor required for audit).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| matches | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> & BulkOptions |
Repository.restoreMany(entity, matches, options): Promise<BulkResult>
Bulk restore — auditable+deletable entity (actor required).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| matches | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> & BulkOptions |
Repository.updateMany(entity, updates, options): Promise<BulkResult>
Bulk update — auditable entity (actor required).
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass & () => TEntity | |
| updates | Partial<Record<keyof TEntity & string, unknown>>[] | |
| options | WriteOptions<Record<string, unknown>> & { actor: string } & MatchByOptions<TEntity> & BulkOptions |
SchemaDomainViolationError
Schema sovereignty domain — the set of PostgreSQL schemas a service is
allowed to touch, declared via DATABASE_SCHEMA and pushed here by the
Dal constructor (getDal({ schemas })).
Enforcement points:
- boot:
assertEntitySchemaDomain(schema-domain-assert.ts) — every registered
| Property | Type | Description |
|---|---|---|
| code | "SCHEMA_DOMAIN_VIOLATION" | |
| details | { entity: string; schema: string; allowed: string[] } |
SchemaDomainViolationError(message, details)
| Parameter | Type | Description |
|---|---|---|
| message | string | |
| details | { entity: string; schema: string; allowed: string[] } |
TranslationEntityBase
TranslationEntityBase — standard i18n translations table entity.
Schema = module boundary. Each module creates a concrete subclass with its own schema. The DAL's Repository resolves the schema natively via getQualifiedTableName(entity) — no raw SQL, no string interpolation.
BE creates entity classes for all modules it manages: @Entity("translations", "public") export class AppTranslationEntity extends TranslationEntityBase {}
@Entity("translations", "system") export class SystemTranslationEntity extends TranslationEntityBase {}
@Entity("translations", "emailsender") export class EmailsenderTranslationEntity extends TranslationEntityBase {}
The BE's central CRUD handler maps module code → entity class → Repository. US microservices do NOT create entity classes — the BE manages their schemas.
Columns: key varchar(255) NOT NULL — full dot-path (e.g. 'app.auth.login.title') language varchar(10) NOT NULL — BCP 47 tag (e.g. 'it-IT') value text NOT NULL — translated string
Composite unique: (key, language) — non-partial index: a soft-deleted row still reserves the key; recreating it surfaces a conflict (ERR05 → restore), never a deleted+live duplicate.
Plus standard audit columns (created_at/by, updated_at/by, version, deleted_at/by).
| Property | Type | Description |
|---|---|---|
| created_at | Date | |
| created_by | string | |
| updated_at | Date | |
| updated_by | string | |
| version | number | |
| deleted_at | Date | |
| deleted_by | string | |
| id | bigint | |
| uuid | string | |
| key | string | Full dot-path translation key (e.g. 'app.auth.login.title'). |
| language | string | BCP 47 language tag (e.g. 'it-IT', 'en-GB'). |
| value | string | Translated string value. |
UnknownColumnError
Thrown when a write operation (add, update) receives a property not in entity metadata.
| Property | Type | Description |
|---|---|---|
| code | "UNKNOWN_COLUMN" |
UnknownColumnError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
ValidationError
Thrown when a validation check fails (e.g. empty updates object, missing actor).
| Property | Type | Description |
|---|---|---|
| code | "VALIDATION" |
ValidationError(message)
| Parameter | Type | Description |
|---|---|---|
| message | string |
Vector
Vector — runtime-identifiable number[] for pgvector vector(N) columns.
A real class (not a brand) so the DAL can detect it with instanceof —
array subclasses ARE number[]-assignable but carry runtime identity.
That identity is load-bearing: vector params bind as the '[v1,v2,…]'
literal, while plain number[] binds as a Postgres array '{v1,v2,…}'.
In entities, embedding: Vector maps to vector; @Column({ length: N })
sets the dimension (vector(N)).
Vector.toString(): string
'[1,2,3]' — the pgvector text input/output literal.
Vector.from(v): Vector
Parse the pgvector literal '[v1,v2,…]' (or a plain number array).
| Parameter | Type | Description |
|---|---|---|
| v | string | readonly number[] | Vector |
Vector.fromNumbers(v): Vector
| Parameter | Type | Description |
|---|---|---|
| v | readonly number[] |
Interfaces
AdvancedFilter
One advanced-filter entry (filters sheet / filters[i][...] URL params).
| Field | Type | Description |
|---|---|---|
| id | string | |
| field | string | |
| operator | FilterOperator | |
| value | unknown |
AggregateDecl
Declarative aggregate rollup projected into list rows.
| Field | Type | Description |
|---|---|---|
| name | string | Output column name, e.g. "user_count". |
| expr | string | Aggregate SQL expression over the join alias, e.g. "COUNT(u.id)". |
| cast | string | Optional result cast — emitted as CAST(<expr> [FILTER...] AS <cast>). |
| join | { entity: EntityClass; alias: string; base: string; joined: string; extra: string } | LEFT join feeding the aggregate. |
AuditPageOptions
| Field | Type | Description |
|---|---|---|
| tableName | string | e.g. "customers_audit" — the partition parent table name. |
| entityUuid | string | |
| page | number | |
| limit | number |
AuditPageResult
| Field | Type | Description |
|---|---|---|
| data | AuditRow[] | |
| pagination | { page: number; limit: number; total: bigint; hasMore: boolean } |
AuditPort
Audit port — consumers inject their own audit writer.
The DAL calls writeAudit fire-and-forget (.catch(logger?.error ?? noop)).
AuditRow
| Field | Type | Description |
|---|---|---|
| id | bigint | |
| entity_id | bigint | |
| entity_uuid | string | |
| action | string | |
| changed_at | string | |
| changed_by | string | |
| changed_by_display_name | string | null | |
| changed_by_idp_code | string | null | |
| version | number | |
| delta | Record<string, unknown> |
BulkItem
| Field | Type | Description |
|---|---|---|
| uuid | string | |
| version | number |
CollaborationMeta
Collaboration fragment injected by assembleMeta at serve time.
| Field | Type | Description |
|---|---|---|
| enabled | boolean | |
| expose_editing_value | boolean |
DalConfig
Configuration for the Dal gateway.
| Field | Type | Description |
|---|---|---|
| connectionString | string | PostgreSQL connection string. Required. |
| schemas | string[] | Declared schema domain — the ONLY PostgreSQL schemas this service may |
touch (from DATABASE_SCHEMA). schemas[0] is the owned/primary schema | ||
| (patch registry, config_entries live here). Entity operations resolving | ||
| outside this set throw SchemaDomainViolationError. Required. | ||
| sharedTables | string[] | Shared table names exempt from the schema-domain check — governed |
| cross-schema table contracts where every module schema carries the | ||
| same table and a designated manager reaches all of them. Today only | ||
translations (the BE i18n gateway manages <module>.translations | ||
| for every registered module). The entity's schema pin still applies — | ||
| only the domain check is bypassed, for that table name only. | ||
| max | number | Maximum pool size. Default: 10. |
| Formula: max ≤ (PG max_connections − reserved) / service_instances. | ||
| The lib cannot pick this for you, but it documents it. | ||
| statementTimeoutMs | number | Per-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). | ||
| bulkTimeoutMs | number | Maximum wall-clock budget in ms for a single *Many operation |
| (addMany/upsertMany/updateMany/deleteMany). The whole transaction must | ||
| complete within this budget — on expiry the work is aborted and the | ||
| transaction rolled back (no partial writes). | ||
Default: 1800000 (30 min). Per-call override: BulkOptions.timeoutMs. | ||
| Set to 0 to disable. | ||
| connectionTimeoutMillis | number | Time 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 | number | How long an idle connection is kept before closing. Default: 30000 (pg default). |
| maxUses | number | Optional: recycle connections after N uses to clear per-session state. |
| Default: undefined (off). | ||
| applicationName | string | Optional application_name for PG logging/observability. Default: "primebrick-dal". |
| repoDecorator | (repo: Repository) => Repository | Optional decorator applied to the Dal's internal root Repository at |
| construction — the governed seam for cross-cutting behavior such as | ||
entity caching (withCache). The decorated repo backs dal.entityService, | ||
dal.tableAuditPort, and every entity proxy on this instance, so the | ||
| decoration applies uniformly without consumers building their own | ||
repositories. Tx-scoped repositories handed to dal.transaction(fn) | ||
| callbacks are NOT decorated — writes inside an open transaction must | ||
| not trigger cache writes/invalidation before commit. |
DuplicateResult
| Field | Type | Description |
|---|---|---|
| uuids | string[] | |
| errors | { uuid: string; error: string }[] |
EntityActionEndpoint
Backing route of an EntityAction — emitted by the BE route scan.
| Field | Type | Description |
|---|---|---|
| method | string | HTTP method of the backing route (GET, POST, PUT, DELETE, ...). |
| path | string | Full registered API path with :param placeholders verbatim |
(e.g. /api/v1/auth/users/:uuid/restore). Consumers substitute | ||
placeholders from the row (:uuid ← meta.uid). |
EntityListQuery
| Field | Type | Description |
|---|---|---|
| search | string | |
| search_in | string[] | |
| sort_key | string | |
| sort_dir | "asc" | "desc" | |
| page | number | |
| page_size | number | |
| filters | ListFilterCondition[] | |
| connector | "AND" | "OR" | |
| deleted_records | "EXCLUDED" | "ONLY" | "INCLUDED" |
EntityListResult
| Field | Type | Description |
|---|---|---|
| rows | TEntity[] | |
| page | number | |
| page_size | number | |
| total | bigint |
EntityMeta
Static entity meta — the shape every *.meta.ts file MUST satisfy.
The schema is CLOSED for authored metas: undeclared properties are
compile errors, so new meta props require extending this type first.
| Field | Type | Description |
|---|---|---|
| entity | string | Entity name, snake_case singular (e.g. user_profile). |
| translation_key | string | i18n prefix, snake_case singular — used to build dynamic keys. |
| entities_ns | string | Namespace OWNING this entity's label keys — the module's own namespace |
(job → job.entities.<translation_key>.*). Absent → system | ||
(BE/core-owned entities keep system.entities.*). | ||
| This is a READ-side reference declared by the owning module — the | ||
namespace write boundary (see translation-keys.ts) guarantees the | ||
keys actually live in that module's <code>.translations schema. | ||
| title_key | string | Optional i18n key overriding the canonical page title. |
| When absent, list/create/edit titles are built from the generic | ||
system.entities.page_title.{list|create|edit} templates interpolated | ||
with system.entities.<translation_key>.{plural|singular}. | ||
| Set only for custom pages needing a bespoke title — CRUD entity metas | ||
| must not declare it. | ||
| uid | string | Field key holding the entity primary key (usually uuid). |
| display_field | string | Canonical display field — the column key identifying the entity's |
| human-readable label. Drives first-column/sticky table identity and | ||
| default display resolution. | ||
| display_name | string | Display expression template (${field} syntax, dot-paths allowed). |
OPTIONAL here: assembleMeta materializes it as | ||
"${" + display_field + "}" when absent — it is always present in the | ||
| served response. Used automatically for edit-page titles; reusable for | ||
| comboboxes, lists, chips. | ||
| actions_overrides | ActionsOverrides | Per-op enable overrides — may ONLY toggle enabled on route-backed |
ops; a missing route already produces enabled: false. | ||
| columns | MetaColumn[] | Entity field dictionary (root-level, transversal). |
| table | TableMeta | Table options — omit when the entity has no table page |
| (e.g. a self-service form meta). |
EntityService
The contract every entity service must satisfy — enforced on the router.
EntityServiceConfig
| Field | Type | Description |
|---|---|---|
| entity | EntityClass & () => object | Newable entity class (DB row shape). |
| repo | Repository | Repository — INTERNAL injection point only. dal.entityService(cfg) |
| supplies the gateway-owned instance; callers of the free | ||
makeEntityService (tests, decorators such as BE withCache) must | ||
| pass one explicitly. Consumer configs MUST NOT set it — a missing | ||
repo is a hard error, not a fallback. | ||
| auditPort | AuditPort | Audit port — defaults to makeTableAuditPort(repo) (the standard |
{table}_audit writer). Override only for ports with extra side | ||
| effects (e.g. the BE entity-changed marker publisher). | ||
| actor | () => string | Actor supplier for audit stamping (e.g. SDK requireActor). |
| userEntity | EntityClass | Optional auditable display-name join target (BE: UserProfileEntity). |
| auditTableName | string | Audit trail table override — default ${tableName}_audit. |
| list | { searchableKeys: readonly string[]; filterableKeys: ReadonlySet<string>; defaultSort: { key: string; dir: "asc" | "desc" }; extraFilters: (q: EntityListQuery) => FilterExpr[]; aggregates: AggregateDecl[] } | |
| hooks | { afterWrite: (op: EntityAction, entity: TEntity) => void | Promise<void>; beforeCreate: (body: Record<string, unknown>) => Record<string, unknown> | Promise<Record<string, unknown>>; beforeUpdate: (uuid: string, body: Record<string, unknown>) => Record<string, unknown> | Promise<Record<string, unknown>> } |
IAuditableEntity
Entity has audit stamps (created_at/by, updated_at/by, version).
Does NOT imply soft-delete — auditable and deletable are independent
capabilities; compose with IAuditableEntity & IDeletableEntity where
both are required (the Dal write-path signatures already do this).
| Field | Type | Description |
|---|---|---|
| created_at | Date | |
| created_by | string | |
| updated_at | Date | |
| updated_by | string | |
| version | number |
IClonableEntity
Entity supports cloning (cloned_from stores UUID of source record).
| Field | Type | Description |
|---|---|---|
| cloned_from | string |
IDeletableEntity
Entity supports soft-delete (deleted_at / deleted_by).
| Field | Type | Description |
|---|---|---|
| deleted_at | Date | |
| deleted_by | string |
IExposableEntity
Entity has a public UUID safe to expose outside the system.
| Field | Type | Description |
|---|---|---|
| uuid | string |
ListFilterParamsOptions
| Field | Type | Description |
|---|---|---|
| filterValues | Record<string, unknown> | Toolbar quick-filter values keyed by column key. |
| columns | readonly MetaColumn[] | Entity columns (needed to map filterValues to the right operator). |
| advancedFilters | readonly AdvancedFilter[] | FiltersPanel conditions. |
| connector | string | Global connector for advanced filters (AND |
ListResponse
The paged list response returned by every entity list endpoint.
total is a bigint — parse JSON responses with a bigint-aware parser
(extJsonParse from @primebrick/sdk), never JSON.parse.
| Field | Type | Description |
|---|---|---|
| rows | TRow[] | |
| page | number | |
| page_size | number | |
| total | bigint |
LoggerPort
Logger port — consumers inject their own logger.
PartitionMaintenanceReport
| Field | Type | Description |
|---|---|---|
| parents | PartitionParentReport[] | |
| maintenance_ran | boolean | Whether partman.run_maintenance_proc() ran. |
PartitionParentReport
| Field | Type | Description |
|---|---|---|
| table | string | "schema"."table" of the partitioned parent. |
| partition_column | string | |
| retention | string | null | Effective retention interval actually applied (part_config wins). |
| children_purged | Record<string, number> | "schema"."child" → rows deleted for expired parents. |
| strays_deleted | number | Expired rows removed from the default partition (never dropped). |
| partitions_before | number | Live partition count before/after run_maintenance_proc(). |
| partitions_after | number | |
| skipped | string | Set when the parent was skipped — reason string. |
RowCustomAction
UI configuration for a non-standard row CTA (route-backed bare op).
| Field | Type | Description |
|---|---|---|
| action_name | string | Action/op name — matches the bare op derived from the route |
(e.g. change_password). | ||
| translation_key | string | i18n key for the CTA label. |
| icon | string | Icon name (Lucide in the reference FE). |
| text_color | string | Optional CSS color class for the label. |
| disabled_when_deleted | boolean | Disable the CTA on soft-deleted rows. |
| required_permission | string | string[] | Permission required to see/use the action (filtered client-side |
| against the user's permission set). |
SnapshotQueryable
Minimal queryable shape — pg.Pool, pg.PoolClient, or any adapter.
TableMeta
Table options — present only on entities with a table page.
| Field | Type | Description |
|---|---|---|
| default_view | ViewName | Initial view (default "table"). |
| default_sort | { key: string; dir: SortDir } | |
| default_page_size | number | |
| page_size_options | number[] | |
| row_custom_actions | RowCustomAction[] | UI config for non-standard row actions (e.g. change password). |
| Standard ops (edit/delete/duplicate/preview) are derived from | ||
meta.actions — never declared here. | ||
| filter_presets | readonly FilterPreset[] | Mutually-exclusive preset WHERE filters — each rendered as its own |
| toolbar control; the active option's conditions AND into every list | ||
| request (see FilterPreset). |
TimeoutOverrideOptions
Per-operation timeout override for dedicated-client work
(transaction, partitionMaintenance).
| Field | Type | Description |
|---|---|---|
| timeoutMs | number | Override statement_timeout (ms). Transaction-scoped for transaction |
| (SET LOCAL, auto-resets at COMMIT/ROLLBACK); connection-scoped with | ||
session-default restore for partitionMaintenance. |
Types & Enums
AuditableFieldType
| Member | Value |
|---|---|
| CREATED_AT | "CREATED_AT" |
| CREATED_BY | "CREATED_BY" |
| UPDATED_AT | "UPDATED_AT" |
| UPDATED_BY | "UPDATED_BY" |
| VERSION | "VERSION" |
AuditAction
Audit action enum (mirrors BE's AuditAction).
| Member | Value |
|---|---|
| INSERT | "INSERT" |
| UPDATE | "UPDATE" |
| SOFT_DELETE | "SOFT_DELETE" |
| HARD_DELETE | "HARD_DELETE" |
| RESTORE | "RESTORE" |
| CLONE | "CLONE" |
DeletableFieldType
| Member | Value |
|---|---|
| DELETED_AT | "DELETED_AT" |
| DELETED_BY | "DELETED_BY" |
SynchronizableFieldType
| Member | Value |
|---|---|
| LAST_SYNCED_AT | "LAST_SYNCED_AT" |
ActionsOverrides
Per-op enable overrides — may ONLY toggle enabled on route-backed ops.
Type: Record<string, { enabled: boolean }>
AuditableWriteOptions
Write options for auditable entities — actor is required.
Type: WriteOptions<TEntity> & { actor: string }
AuditParams
Parameters passed to AuditPort.writeAudit.
BulkOptions
Bulk operation options (batch size, timeout).
BulkResult
Result summary of a bulk write (addMany/upsertMany/updateMany/deleteMany).
ColumnOptions
ColumnPgPersistenceHints
DalErrorCode
Type: typeof DalErrorCodes[keyof typeof DalErrorCodes]
DecimalInput
Anything coercion functions accept: Decimal, native number, bigint, or a decimal string.
Type: Decimal \| number \| bigint \| string
DeletionFilterMode
Soft-deletion visibility mode — maps to the deleted_records list param
on the wire (non_deleted → EXCLUDED, deleted → ONLY,
all → INCLUDED; absent param means the BE default, currently
EXCLUDED).
Type: "non_deleted" \| "deleted" \| "all"
EntityAction
Type: "meta" \| "list" \| "export" \| "create" \| "duplicate" \| "bulkDelete" \| "bulkRestore" \| "get" \| "update" \| "delete" \| "purge" \| "restore" \| "audit"
EntityActionSentinel
Sentinel gates a route may declare instead of concrete permissions.
Values mirror the Permission enum in @primebrick/sdk.
Type: "_public" \| "_authenticated_user" \| "_authenticated_admin"
EntityAnnotationInfo
Per-property type facts extracted from source.
EntityAnnotationMap
Result of extractEntityAnnotations — keyed by class name.
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.
Type: (args: any[]) => object
EntityColumnTypeHints
EntityCtor
Entity capability mixins — declare shared audit/deletable columns ONCE, compose them per-entity instead of copy-pasting decorated fields.
Auditable and deletable are ORTHOGONAL capabilities:
- audit-only (hard delete):
class ApiKey extends Auditable(EntityBase) - delete-only:
class Tag extends Deletable(EntityBase) - both (soft delete):
class Customer extends Deletable(Auditable(EntityBase)) - neither:
class Telemetry extends EntityBase
The concrete entity still owns @Entity(table) and the opt-in
@AuditTrail() (audit-log table — separate decision from audit columns).
Field decorators on each anonymous mixin class register on that
constructor; getEntityPersistenceMeta merges the whole prototype chain
parent-first (see collectMetaChain), so subclass fields always win.
Extra per-entity capabilities (IExposableEntity, IClonableEntity, …)
keep their implements on the concrete class — they are pure type
contracts, not column sets.
Type: (args: any[]) => object
EntityMetaResponse
The served GET /api/v1/entities/{entity}/meta response:
static meta + runtime-injected display_name, actions, collaboration.
Type: EntityMeta & { display_name: string; actions: EntityAction[]; collaboration: CollaborationMeta }
EntityPersistenceMeta
Serializable persistence metadata (for JSON compare with DB introspection).
EntityTypeWarning
Advisory warning — never fails a build, printed by primebrick-db.
ExprOperand
A parameterized SQL operand for Filter.expr — ? markers inside sql
are replaced by $n bound parameters in order of appearance.
sql is a trusted literal (never interpolated user input); params
carries the only dynamic data. Example:
{ sql: "to_tsvector(?, d.content)", params: ["simple"] }
FieldProjector
Type: { kind: "field"; field: FieldRef<any, any>; alias: string } \| { kind: "expr"; expr: string; alias: string; params: unknown[] }
FieldRef
FilterCondition
One WHERE condition of a filter preset — serialized verbatim as a
filters[i] entry on the /list query string (same vocabulary as
AdvancedFilter conditions: field/op/value).
FilterExpr
Type: { 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: "expr"; left: ExprOperand; op: SqlOperator; right: ExprOperand; operand: SqlExpressionOperand } \| { kind: "group"; filters: FilterExpr[]; operand: SqlExpressionOperand; connector: SqlExpressionOperand }
FilterOperator
Filter operators available for advanced filters.
Type: "=" \| "!=" \| ">" \| "<" \| ">=" \| "<=" \| "contains" \| "startsWith" \| "endsWith" \| "BETWEEN"
FilterPreset
A mutually-exclusive preset filter group rendered as its own control in
the table toolbar (tandem with the deletion-filter group). Exactly one
option is always active — there is no "clear" affordance. Declared in
meta.table.filter_presets; example: a schedule_type scope selector
(recurring / once / all) on a jobs table.
FilterPresetOption
A single selectable option of a table filter preset.
FindByIdOptions
Options for findById.
FindByUUIDOptions
Options for findByUUID.
FindOptions
Options for find, findAll, findByPage.
ForeignKeyAction
Type: "restrict" \| "cascade" \| "set_null" \| "set_default" \| "no_action"
ForeignKeyOptions
Options for @ForeignKey() — REFERENCES target entity column.
GroupByOperand
GROUP BY operand — either an entity field reference or a parameterized
SQL expression (? markers bind params in order). Expressions are
required for grouping over computed values like date_trunc(?, created_at).
Non-aggregate field projections are auto-added to GROUP BY by the
builder; expression projections must be listed here explicitly when they
are the grouping key.
Type: FieldRef<any, any> \| { kind: "expr"; sql: string; params: unknown[] }
HostApiFn
ctx.components.hostApi — the host's authenticated full-path fetch
(apiFetch): reaches BE-owned /api/v1/… endpoints that ctx.api
(ws-bound to the owning service) cannot. Remote pages bind it through
bindRemoteCtx(ctx) → getServiceApi('host').
Type: (path: string, init: RequestInit) => Promise<Response>
HostMountHandle
Handle returned by ModulePageHost.mount_host — imperative channel to a
host-mounted component root.
IndexMethod
Type: "btree" \| "hash" \| "gin" \| "gist" \| "spgist" \| "brin" \| "hnsw"
IndexOptions
Options for @Index() — plain (non-unique) secondary indexes of any PG access method.
ISODate
Type: string & { [isoDateBrand]: "ISODate" }
ISOTime
Type: string & { [isoTimeBrand]: "ISOTime" }
JoinExpr
KeyOptions
LikelyRename
ListConnector
Global connector joining the advanced-filter group.
Type: "AND" \| "OR"
ListFilterCondition
ListFilterOptions
MatchByOptions
Options for match-by operations (update, delete, restore, hardDelete, *Many).
MetaColumn
Entity field descriptor — the root-level columns dictionary.
Transversal to every page type: table cells, form tooltips, labels.
Declared as a type alias (not interface): object literal types get an
implicit index signature, keeping MetaColumn assignable to
Record<string, unknown> — host/remotes pass columns through generic
cell-snippet args typed as Record<string, unknown>.
MetaColumnType
UI column renderer type. NOTE: this is the UI type, not the DB type —
e.g. roles is "text" here but jsonb on disk (never ILIKE-searchable).
Type: "text" \| "badge" \| "boolean" \| "color" \| "date" \| "datetime" \| "number" \| "sparkline"
MfaStepUpFn
ctx.components.mfaStepUp — host-bound step-up MFA bridge. The remote
calls it exactly like the host's useMfaStepUp().executeWithToken:
requestFn runs once with token = null; on a 403 response carrying
mfa_step_up_required the host shows ITS OWN step-up dialog (host root,
host runtime — nothing crosses the boundary), awaits verification, then
retries requestFn with the action-authorization token. The promise
resolves with the final Response — success or failure.
Type: (requestFn: (token: string \| null) => Promise<Response>, context: { action: string; target_resource: string }) => Promise<Response>
MigrationEngineOptions
Migration engine — apply side. Generation side lives in schema-diff/.
MigrationMode
Migration engine — apply side. Generation side lives in schema-diff/.
Type: "apply" \| "check" \| "off"
MigrationRunResult
Migration engine — apply side. Generation side lives in schema-diff/.
ModuleHostBase
Host-side context base handed to EVERY remote mount — pages
(mountPage) and sheets (mountSheet) alike. Versioned via
host_version — remote chunks can refuse incompatible hosts.
HARD CONSTRAINT — plain values and functions ONLY: Svelte rune state
($state/$derived/$effect) is bundle-local and cannot cross this
boundary. UI building blocks come from @primebrick/ui bundled inside
the remote chunk, not from ctx; components is reserved for the few
host-coupled cases (see components doc).
ModuleHostComponents
ctx.components — the reserved well-known keys plus open caller-provided
entries. remote is assigned by the host loader after the chunk
resolves; mfaStepUp/openSheet/hostApi are built-ins the host
always provides (a caller may override them in tests).
ModuleNavDeclaration
A module's self-described navigation declaration — the payload a service
publishes in service.register (endpoints.nav) so the FE can render
the module's sidebar nav and the census can resolve its routes WITHOUT
the BE hardcoding another module's pages. This is the wiring that lets
each module present its own nav — a remote page is owned by the service
that ships it, never declared inside a host module's registry.
route_prefixes drive active-module resolution (longest-prefix match —
a page under a shared prefix like /system/jobs resolves to the owning
module, not to the module owning the broader /system prefix).
ModuleNavLink
One sidebar navigation link contributed by a module. children is the
collapsible-group mechanism (the shell renders children under the parent).
ModuleNotifyInput
Notification payload accepted by ctx.notify — the minimal shape of the
host's pushNotification input. Plain values only.
ModulePageHost
Host ctx handed to a remote page's mountPage(el, ctx) — the shared
ModuleHostBase plus the page's own route axis (nav/meta).
Type: ModuleHostBase & { nav: PageRouteDeclaration; meta: EntityMeta }
ModuleSheetDecl
A remote sheet panel declared by a service inside endpoints.nav.sheets
— the sheet analogue of a remote PageRouteDeclaration: the host
owns the sheet ENGINE (open/close/chrome/state), the owning service owns
the CONTENT — an esm-mount chunk exporting mountSheet(el, ctx),
mounted at runtime into the host's global sheet surface.
key is the open-sheet address, <module>.<name> namespaced so a
declared key can never collide across services (enforced at enrollment
by the nav-declaration validator). Anyone holding the key can open it —
host openSheet, ctx.components.openSheet — visibility is gated by
access, never by import reachability.
ModuleSheetDefaults
Chrome defaults a sheet declaration may suggest. The caller's openSheet
options always win over these — they are a hint, not a policy.
content_class maps to the host engine's contentClass option.
ModuleSheetHost
Host ctx handed to a remote sheet's mountSheet(el, ctx) — the shared
ModuleHostBase plus the sheet control surface: the declared
key, the caller's props (opaque at the boundary — the owning module
knows their shape), the current chrome, and the commands to mutate the
host-owned frame. No nav/meta — a sheet is not a route; domain
context arrives through sheet.props.
Type: ModuleHostBase & { sheet: { key: string; props: Record<string, unknown>; side: ModuleSheetSide; modal: boolean; close: () => void; replace: (props: Record<string, unknown>) => void; setExpanded: (expanded: boolean) => void } }
ModuleSheetSide
Sheet side — the two chrome slots the host sheet engine owns.
Type: "left" \| "right"
MountPageFn
The esm-mount chunk's entry contract — export function mountPage(el, ctx).
May return the mount() result (disposed via unmount()), a custom dispose
function, or a promise of either.
Type: (el: HTMLElement, ctx: ModulePageHost) => unknown
MountSectionFn
A chunk's section-mount export — same host ctx as mountPage, plus the
section's own declaration (id, props, placement) as third argument.
Type: (el: HTMLElement, ctx: ModulePageHost, section: PageSectionDecl) => unknown
MountSheetFn
The sheet chunk's entry contract — export function mountSheet(el, ctx).
The chunk is declared in endpoints.nav.sheets[] (ModuleSheetDecl)
and mounted inside the host's global sheet surface. Same dispose rules as
MountPageFn.
Type: (el: HTMLElement, ctx: ModuleSheetHost) => unknown
OnConflictMode
Insert conflict semantics for add().
Type: "raise" \| "ignore"
OpenSheetFn
ctx.components.openSheet — opens a sheet panel by key: a host-registered
panel (shell.*/entity.*/config.*) or a remote-declared sheet
(<module>.<name> from nav.sheets[], mounted at runtime). The panel
registry, remote declarations and sheet state all live in the host — a
remote page requests the panel, it never ships the engine. props are
plain values (callback fns are allowed — they cross the boundary);
options are the host's sheet options (side, contentClass, modal,
keepMountedState). Unknown keys are rejected with a host notification —
the remote cannot smuggle an undeclared panel.
Type: (panelKey: string, props: Record<string, unknown>, options: Record<string, unknown>) => void
PageLayoutDecl
Spatial arrangement of a page's sections — ONE archetype: CSS grid.
A vertical stack is the degenerate case (columns defaults to "1fr",
sections auto-flow in declaration order); a split is columns: "280px 1fr"; a dashboard is columns: "repeat(3, 1fr)" + per-section span.
New container classes, when genuinely needed, arrive as new optional
fields — the contract never grows a second placement vocabulary.
PageRouteComponentFormat
Remote component delivery format. Extensible — new literals are additive
and non-breaking. esm-mount: a precompiled ESM chunk that exports
mountPage(el, ctx) (or a default component as fallback).
Type: "esm-mount"
PageRouteDeclaration
One declared frontend route owned by a module. Modules MUST declare every
FE path they own that is not deducible from nav links or entity
conventions — the AI route census (derived from the consolidated
GET /api/v1/modules discovery payload) depends on it.
param marks dynamic segments using the FE convention ([uuid], [code]).
PageRouteKind
Page archetype vocabulary — what the route renders, regardless of delivery.
Type: "list" \| "detail" \| "create" \| "page"
PageRouteProps
page_props — free-form per-route metadata with a typed layout axis.
PageSectionDecl
One mountable block inside a layout — placement is grid-cell based.
PageSectionSource
Section mount target — remote:<export> = a named mount export of the
page's own chunk (mod.mountModels(el, ctx, section)); host:<key> = a
component registered in the host's section registry. The remote: form is
the default for module-owned blocks; host: composes host-owned building
blocks without shipping a chunk at all.
Type: templateLiteral \| templateLiteral
PaginatedEntity
Paginated result wrapper.
PartitionChildOfOptions
Options for @PartitionChildOf() — declares membership in a partitioned
parent's atomic delete/retention unit.
PartitionFieldOptions
Options for @PartitionField() — the RANGE partition key declaration.
PatchManifest
PatchRegistryRow
PatchSegment
PatchStatus
Type: "pending" \| "applied" \| "failed" \| "pending_review" \| "approved" \| "resolved_manual"
PgColumnType
pgType values legal in @Column({ pgType }).
Type: PgScalarType \| templateLiteral \| templateLiteral \| "vector"
PgScalarType
PgColumnType — the canonical PostgreSQL column type vocabulary for
@Column({ pgType }) and the entity type contract.
A closed union, not a free string: aliases like
"timestamp with time zone" (write timestamptz) or "character varying"
(write varchar) are compile errors, so the diff/snapshot pipeline never
sees spelling variants.
Type modifiers are NEVER written inside pgType: varchar(N) comes from
length, numeric(p,s) from precision/scale, vector(N) from
length on a Vector prop. pgType carries the BASE name only
(vector(N) literal is allowed for readability but length wins).
Type: "text" \| "varchar" \| "char" \| "citext" \| "uuid" \| "smallint" \| "int2" \| "integer" \| "int" \| "int4" \| "bigint" \| "int8" \| "real" \| "float4" \| "double precision" \| "float8" \| "numeric" \| "decimal" \| "boolean" \| "bool" \| "date" \| "time" \| "timetz" \| "timestamp" \| "timestamptz" \| "interval" \| "inet" \| "cidr" \| "macaddr" \| "macaddr8" \| "json" \| "jsonb" \| "bytea" \| "xml" \| "tsvector"
RemoteDepsManifest
<chunk>.deps.json — emitted next to each remote chunk at build time,
declaring the vendor specifiers/versions it was compiled against.
RenameAmbiguity
RenameHeuristicResult
RoundingMode
Type: "UP" \| "DOWN" \| "CEILING" \| "FLOOR" \| "HALF_UP" \| "HALF_DOWN" \| "HALF_EVEN"
SchemaColumnMeta
Shared shapes for entity vs database schema snapshots (used by compare + heuristics).
SchemaDomain
SchemaMetaDiffV1
Type: SchemaMetaDiffV2
SchemaMetaDiffV2
SchemaSnapshot
Schema-diff: canonical entity-vs-database snapshot machinery. Generation side of the migration engine (migrations/ is the apply side).
SchemaTableMeta
Schema-diff: canonical entity-vs-database snapshot machinery. Generation side of the migration engine (migrations/ is the apply side).
SelectQueryInput
SnakeCaseSingular
Branded type that enforces snake_case singular (no uppercase letters).
Used for translation_key in entity meta — the i18n key prefix.
The brand is applied via asSnakeCaseSingular(), which performs a
runtime check rejecting strings containing A-Z. This catches camelCase
(userProfile), PascalCase (RoleMapping), and UPPER_CASE
(USER_PROFILE) at both compile time and runtime.
Type: string & { __snakeCaseSingularBrand: unique symbol }
SortDir
Sort direction for server-side list queries and header UI.
Type: "asc" \| "desc"
SortingExpr
Type: { field: FieldRef<any, any>; dir: SqlSortDirection } \| { kind: "alias"; alias: string; dir: SqlSortDirection } \| { kind: "expr"; sql: string; params: unknown[]; dir: SqlSortDirection }
SqlExpressionOperand
Type: "AND" \| "OR"
SqlJoinType
Type: "INNER" \| "LEFT" \| "RIGHT"
SqlOperator
Type: "=" \| "!=" \| "<>" \| "<" \| "<=" \| ">" \| ">=" \| "ILIKE" \| "LIKE" \| "IN" \| "NOT IN" \| "BETWEEN" \| "IS" \| "IS NOT" \| "<=>" \| "<->" \| "<#>" \| "<+>" \| "<~>" \| "<%>" \| "@@"
SqlQuery
SqlSortDirection
Type: "ASC" \| "DESC"
StandardOp
Type: typeof STANDARD_OPS[number]
TooltipPriority
Tooltip visual severity — drives icon and title color in priority tooltip renderers.
Type: "INFORMATION" \| "WARNING" \| "ERROR" \| "QUESTION" \| "HINT" \| "SUCCESS"
TrustedKey
UniqueOptions
Unique constraint options for composite unique indexes.
UpsertOptions
Upsert-specific options.
UUID
Type: string & { [uuidBrand]: "UUID" }
VectorDistanceOp
pgvector distance operator for vectorSearch — <=> cosine, <-> L2, <#> inner product, <+> L1.
Type: "<=>" \| "<->" \| "<#>" \| "<+>"
VectorHybridInput
VectorSearchOptions
Options for Repository.vectorSearch — entity-generic like FindOptions.
VendorManifest
Host vendor-manifest.json — specifier → published vendor asset.
Type: Record<string, { url: string; version: string }>
VendorMismatch
Type: { specifier: string; kind: "missing"; required: string } \| { specifier: string; kind: "version"; required: string; provided: string }
VendorResolution
Type: "external" \| "reject" \| "bundle"
VendorSpecifier
Type: typeof VENDOR_SPECIFIERS[number]
ViewName
Table view names supported by entity list pages.
Type: "table" \| "cards" \| "cards_list"
WithAuditableDisplayNames
Adds display name fields to a row type for auditable entities. Use this to type the result of queries that include auditable joins.
Type: 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).
Type: T & { created_by_name: string }
WithDeletedRecords
Controls how soft-deleted rows (deleted_at IS NOT NULL) are handled in finders.
Type: "EXCLUDED" \| "ONLY" \| "INCLUDED"
WithUpdaterDisplayName
Adds only updater display name (for cases where you only need updated_by).
Type: T & { updated_by_name: string }
WriteOptions
Base write options — no actor (for non-auditable entities).
Constants
DalErrorCodes
Stable error codes for DAL optimistic concurrency control.
These codes are used as PostgreSQL SQLSTATE values (via RAISE EXCEPTION USING ERRCODE = 'ERR01') and as TS DalError.code values. Consumers (BE,
US, FE) branch on the string literal (e.g. err.code === 'ERR01') so that
PG-originated errors and TS-originated errors share the same code.
Convention: ERR + 2 digits. The ER class is outside the SQL-standard
SQLSTATE classes (00–99), so PostgreSQL accepts it as a custom code.
Type: { ERR01: "ERR01"; ERR02: "ERR02"; ERR03: "ERR03"; ERR04: "ERR04"; ERR05: "ERR05"; ERR06: "ERR06"; ERR07: "ERR07"; ERR08: "ERR08"; ERR09: "ERR09"; ERR10: "ERR10" }
| Field | Value |
|---|---|
| ERR01 | "ERR01" |
| ERR02 | "ERR02" |
| ERR03 | "ERR03" |
| ERR04 | "ERR04" |
| ERR05 | "ERR05" |
| ERR06 | "ERR06" |
| ERR07 | "ERR07" |
| ERR08 | "ERR08" |
| ERR09 | "ERR09" |
| ERR10 | "ERR10" |
decimalFromPG
Alias of dec() — parse a PostgreSQL numeric/decimal text value.
Type: typeof dec
Filter
Type: { fieldValue: ; fieldField: ; raw: ; expr: ; group: }
| Field | Value |
|---|---|
| fieldValue | "" |
| fieldField | "" |
| raw | "" |
| expr | "" |
| group | "" |
fromString
Type: typeof dec
fromWire
Alias of dec() — tolerates the "…d" wire suffix.
Type: typeof dec
GroupBy
Type: { expr: }
| Field | Value |
|---|---|
| expr | "" |
Join
Type: { on: }
| Field | Value |
|---|---|
| on | "" |
KEYS_FILENAME
Type: "keys.json"
MANIFEST_FILENAME
Type: "MANIFEST.json"
NUMERIC_MIN_SIG_DIGITS
Minimum significant digits preserved by automatic div scale — mirrors
PostgreSQL NUMERIC_MIN_SIG_DIGITS (16). See pgDivScale.
Type: 16
ONE
Type: Decimal
PATCH_REGISTRY_TABLE
Per-service-schema patch registry (v2).
Each service owns <svc_schema>.primebrick_database_patches — the registry is
domain data of the owning microservice, not a shared global table.
The DDL is self-bootstrapping: the engine runs it unconditionally before any
read, so an empty database upgrades itself.
Type: "primebrick_database_patches"
Project
Type: { field: ; expr: }
| Field | Value |
|---|---|
| field | "" |
| expr | "" |
RENAME_HEURISTIC_AGENT_INSTRUCTION
Type: "renameHeuristicUserReviewRequired is true: ambiguous rename candidates were detected. You MUST ask the user which renames (if any) to apply before running suggested ALTER ... RENAME COLUMN or generating migrations from likelyRenames."
RENAME_MATCH_RULE_LABELS
Ordered strict → loose; documented for consumers of diff-entities-vs-database.json.
Type: readonly string[]
Sort
Type: { by: ; byAlias: ; byExpr: }
| Field | Value |
|---|---|
| by | "" |
| byAlias | "" |
| byExpr | "" |
STANDARD_OPS
The canonical vocabulary of standard entity ops. Every op is always
present in meta.actions — ops whose route is not registered are emitted
with enabled: false (explicitly unavailable) instead of being omitted.
Type: readonly ["list", "meta", "get", "create.single", "update.single", "delete.single", "purge.single", "restore.single", "read.audit", "export", "delete.bulk", "restore.bulk", "duplicate.bulk"]
TEN
Type: Decimal
VENDOR_BLOCKED_PACKAGES
Packages that MUST NOT be imported raw inside a remote chunk — they are
already served through a sanctioned vendor specifier (e.g. transformers is
vendored behind @primebrick/ui/vendor/transformers). A raw import would bundle
a second runtime copy (split caches, split env config) — reject it.
Type: readonly ["@huggingface/transformers", "clsx", "tailwind-merge", "tailwind-variants", "@lucide/svelte", "bits-ui"]
VENDOR_SPECIFIERS
Closed allowlist of bare specifiers remote chunks may import. A
package's specifiers normally union into ONE bundle file so the browser
dedupes by URL — a single runtime instance is guaranteed. Exception:
svelte's public subpaths (events/reactivity/store/attachments) get
their own files — their export names collide with the internal signal
API (get/derived exist in both), and a flat union module cannot hold
both. Shared internals still dedupe through the bundler's shared chunks.
Type: readonly ["svelte", "svelte/internal/client", "svelte/internal/disclose-version", "svelte/internal/flags/legacy", "svelte/events", "svelte/reactivity", "svelte/store", "svelte/attachments", "svelte/motion", "svelte/easing", "@primebrick/core", "@primebrick/ui", "@primebrick/ui/vendor/transformers", "@primebrick/ui/vendor/clsx", "@primebrick/ui/vendor/tailwind-merge", "@primebrick/ui/vendor/tailwind-variants", "@primebrick/ui/vendor/lucide", "@primebrick/ui/vendor/bits-ui"]
ZERO
Type: Decimal
Functions
abs(d): Decimal
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
add(a, b): Decimal
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
allowedKeyNamespaces(moduleCode): ReadonlySet<string>
Namespaces a module's meta/nav declarations may REFERENCE — the module's
own namespace plus the CORE vocabularies (app, system).
| Parameter | Type | Description |
|---|---|---|
| moduleCode | string |
appendListFilterParams(params, opts, startIdx): number
| Parameter | Type | Description |
|---|---|---|
| params | URLSearchParams | |
| opts | ListFilterParamsOptions | |
| startIdx | number |
approvePendingReview(pool, schema, patchName, actor, note): Promise<boolean>
pending_review → approved for ONE named patch: the engine treats an
approved row as review-cleared and applies the file on the next run.
| Parameter | Type | Description |
|---|---|---|
| pool | Pool | |
| schema | string | |
| patchName | string | |
| actor | string | |
| note | string |
assertEntitySchemaDomain(entities, schemas, sharedTables): void
Boot-time check: every registered entity must resolve inside schemas
(an explicit
| Parameter | Type | Description |
|---|---|---|
| entities | readonly unknown[] | |
| schemas | readonly string[] | |
| sharedTables | readonly string[] |
assertPgTypeCompatible(annotation, explicitPgType, propertyKey): void
Throws when an explicit pgType is incompatible with the declared TS
annotation family (e.g. UUID + pgType:"text", number + pgType: "int8"). Unmappable families pass — the explicit type is their contract.
| Parameter | Type | Description |
|---|---|---|
| annotation | EntityAnnotationInfo | |
| explicitPgType | string | |
| propertyKey | string |
asSnakeCaseSingular(value): SnakeCaseSingular
Branded constructor for SnakeCaseSingular. Throws if the value contains uppercase letters (camelCase/PascalCase/UPPER_CASE).
| Parameter | Type | Description |
|---|---|---|
| value | string |
Auditable(Base): { prototype: AuditableEntity<any> } & TBase
Adds created_at / created_by / updated_at / updated_by / version
(optimistic-lock column). Does NOT add soft-delete — compose Deletable
when the entity needs it.
| Parameter | Type | Description |
|---|---|---|
| Base | TBase |
AuditableField(what): PropertyDecorator
Marks a field as auditable (created_at, created_by, updated_at, updated_by, version).
| Parameter | Type | Description |
|---|---|---|
| what | AuditableFieldType |
AuditTrail(): ClassDecorator
Marks an entity as having an audit trail table.
AuditTrailEntity(options): 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").
| Parameter | Type | Description |
|---|---|---|
| options | { changedByColumn: string } |
buildAuditableJoins(entity, userEntity): 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".
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | The entity class implementing IAuditableEntity |
| userEntity | EntityClass | The user entity class (e.g. UserProfileEntity) that has a uuid and display_name column |
buildAuditableJoinsSelective(entity, userEntity, options): 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.
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | The entity class implementing IAuditableEntity |
| userEntity | EntityClass | The user entity class (e.g. UserProfileEntity) |
| options | { includeCreator: boolean; includeUpdater: boolean; includeDeleter: boolean } | Configuration for which joins to include |
buildAuditTrailJoins(auditEntity, userEntity): { 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-]{36}$') 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).
| Parameter | Type | Description |
|---|---|---|
| auditEntity | EntityClass | The audit trail entity class (e.g., AuditLogEntity) |
| userEntity | EntityClass | The user entity class (e.g., UserProfileEntity) with uuid, display_name, idp_code columns |
buildDatabaseSnapshot(db, tables, generatedAt): Promise<SchemaSnapshot>
Introspect given tables into the same SchemaSnapshot shape as entities.
Uses pg_attribute / pg_type / format_type (pg-diff-api CatalogApi style) so PostGIS
and other UDTs surface with real typname / typcategory, not only information_schema.data_type.
The caller owns the connection: pass a Pool (read-only fan-out) or a reserved client.
| Parameter | Type | Description |
|---|---|---|
| db | SnapshotQueryable | |
| tables | { schema: string; name: string }[] | |
| generatedAt | string |
buildEntitySnapshot(registry, opts, generatedAt): SchemaSnapshot
Canonical entity-intent snapshot for a service's entity registry. Parameterized on the registry — no service-specific imports live here.
| Parameter | Type | Description |
|---|---|---|
| registry | readonly EntityClass[] | |
| opts | BuildEntitySnapshotOptions | |
| generatedAt | string |
buildPatchFilename(diff, d): string
| Parameter | Type | Description |
|---|---|---|
| diff | SchemaMetaDiffV2 | |
| d | Date |
buildSelectQuery(input): SqlQuery
| Parameter | Type | Description |
|---|---|---|
| input | SelectQueryInput |
buildSqlPatchFromMetaDiff(entitySnap, diff): string
Best-effort SQL to move TARGET database toward entity intent. Destructive changes (DROP) are never emitted — DB-only objects are WARN comments.
| Parameter | Type | Description |
|---|---|---|
| entitySnap | SchemaSnapshot | |
| diff | SchemaMetaDiffV2 |
buildVectorSearchQuery(input): SqlQuery
| Parameter | Type | Description |
|---|---|---|
| input | VectorHybridInput |
calculateDelta(oldEntity, newEntity): Record<string, { old: unknown; new: unknown }>
Calculate delta between old and new records for audit.
| Parameter | Type | Description |
|---|---|---|
| oldEntity | Record<string, unknown> | |
| newEntity | Record<string, unknown> |
calculateDeltaWithForcedFields(oldEntity, newEntity, forceFields): Record<string, { old: unknown; new: unknown }>
Calculate delta and force include specific fields even when unchanged.
| Parameter | Type | Description |
|---|---|---|
| oldEntity | Record<string, unknown> | |
| newEntity | Record<string, unknown> | |
| forceFields | string[] |
canonicalJson(value): string
Stable JSON: object keys sorted recursively so signatures are deterministic.
| Parameter | Type | Description |
|---|---|---|
| value | unknown |
canonicalPgType(t): string
Fold alias spellings to canonical names (integer → int4, …).
| Parameter | Type | Description |
|---|---|---|
| t | string |
ceil(d): Decimal
Smallest integer >= d.
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
checkDrift(registry, db, opts): Promise<SchemaMetaDiffV2>
| Parameter | Type | Description |
|---|---|---|
| registry | readonly EntityClass[] | |
| db | SnapshotQueryable | |
| opts | BuildEntitySnapshotOptions |
classifyRenamePair(eMeta, dMeta): { matchTier: number; reasons: string[] } \| null
Assigns the single strictest tier that applies, or null if no rule matches.
| Parameter | Type | Description |
|---|---|---|
| eMeta | SchemaColumnMeta | |
| dMeta | SchemaColumnMeta |
CloneField(): PropertyDecorator
Marks a field as clone tracking (cloned_from). Stores UUID of the source record.
cmp(a, b): -1 \| 0 \| 1
Numeric comparison ignoring scale: cmp(1.0, 1.00) === 0. Returns -1 | 0 | 1.
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
collectEntityTypeWarnings(registry, annotations): EntityTypeWarning[]
Advisory authoring warnings across a registry — *_uuid columns that do
not resolve to uuid, and pgType declarations that restate the inferred
default. Requires the static annotation map; warnings never fail a gate.
| Parameter | Type | Description |
|---|---|---|
| registry | readonly EntityClass[] | |
| annotations | EntityAnnotationMap |
Column(sqlName): PropertyDecorator
Override SQL name / pgType / nullable only; otherwise the property is already a column by convention.
| Parameter | Type | Description |
|---|---|---|
| sqlName | string |
columnHintsFromMetaColumn(col): ColumnPgPersistenceHints
| Parameter | Type | Description |
|---|---|---|
| col | { propertyKey: string; sqlName: string; isKey: boolean; isUnique: boolean; uniqueIndexName: string; uniqueIndexOrder: number; nullable: boolean; pgType: string; jsType: "vector" | "decimal" | "instant"; 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; isPartition: boolean; partitionOpts: PartitionFieldOptions } |
columnTypeWarnings(entityName, h, resolved): EntityTypeWarning[]
Authoring warnings for one column:
uuid-name— a*_uuid/uuidcolumn resolving to a non-uuid type. The name SAYS uuid; either the column should beuuid(retype the prop toUUIDor setpgType:"uuid") or the name lies.redundant-pgType— explicitpgTypeequal to what the annotation already infers; drop it (we never spell out the default).
| Parameter | Type | Description |
|---|---|---|
| entityName | string | |
| h | EntityColumnTypeHints | |
| resolved | string |
comparablePgType(meta): string
Build a stable string for equality checks across entity hints and catalog introspection.
| Parameter | Type | Description |
|---|---|---|
| meta | Pick<SchemaColumnMeta, "typname" | "typcategory" | "dataType" | "formatType"> |
compareSnapshots(entitySnap, dbSnap): SchemaMetaDiffV2
| Parameter | Type | Description |
|---|---|---|
| entitySnap | SchemaSnapshot | |
| dbSnap | SchemaSnapshot |
configureSchemaDomain(schemas, sharedTables): SchemaDomain
Called once by the Dal constructor. Re-calls replace the domain (tests).
| Parameter | Type | Description |
|---|---|---|
| schemas | string[] | |
| sharedTables | string[] |
createStream(db, text, values): AsyncIterable<TResult>
Creates an AsyncIterable from a SQL query using pg-query-stream.
| Parameter | Type | Description |
|---|---|---|
| db | Queryable | The pg Pool or PoolClient |
| text | string | SQL query text |
| values | unknown[] | Parameter values |
dec(input): Decimal
Decimal — pass-through. string — parsed (PG text form or "…d" wire form). number — via shortest round-trip toString so 0.1 stays "0.1". bigint — scale 0.
| Parameter | Type | Description |
|---|---|---|
| input | DecimalInput |
decimalToPG(d): string
PostgreSQL parameter form — plain canonical decimal string, no d suffix.
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
defaultSearchGate(trimmed): boolean
search-gate — canonical "should this search query hit the server" predicate.
Mirrors the backend list-search gate: ≥3 "real" characters, or an escaped
wildcard (\* / \?) with ≥1 real char. Prevents per-keystroke queries
while still allowing single-char wildcard searches.
Canonical home for both the host FE and remote module pages — the gate must match the server-side rule byte-for-byte.
| Parameter | Type | Description |
|---|---|---|
| trimmed | string | the search string, already .trim()ed by the caller |
defaultVisibleColumnKeys(columns): string[]
Keys visible by default — from column flags.
| Parameter | Type | Description |
|---|---|---|
| columns | MetaColumn[] |
Deletable(Base): { prototype: DeletableEntity<any> } & TBase
Adds deleted_at / deleted_by — soft-delete markers.
| Parameter | Type | Description |
|---|---|---|
| Base | TBase |
DeletableField(what): PropertyDecorator
Marks a field as deletable (deleted_at, deleted_by).
| Parameter | Type | Description |
|---|---|---|
| what | DeletableFieldType |
diffVendorRequirements(requires, manifest): VendorMismatch[]
Vendor compatibility check — exact-match policy. A remote chunk compiled
against a different version of a vendored package is incompatible:
svelte/internal/* is not a stable API and each union bundle's export set
may change between versions. The remedy is rebuilding the remote chunk —
a semver-tolerant handshake would only defer an opaque import failure.
| Parameter | Type | Description |
|---|---|---|
| requires | Record<string, string> | |
| manifest | VendorManifest |
div(a, b, opts): Decimal
a / b. Without scale, the result uses the PostgreSQL numeric
division rule (pgDivScale — e.g. 1/3 → scale 20, 10/4 → 16), so
Decimal↔DB computations compare equal digit-for-digit. Rounding defaults
to HALF_UP. When the true quotient does not terminate at the target
scale the result is flagged periodic (isPeriodic(d) → true).
div(1, 3) // 0.33333333333333333333 — periodic div(10, 4) // 2.5000000000000000 div(1, 3, 2) // 0.33 div(a, b, { scale: 6, rounding: "HALF_EVEN" })
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput | |
| opts | number | { scale: number; rounding: RoundingMode } |
effectivePgStorageType(h): string
Effective storage type in PostgreSQL (explicit pgType wins over inference).
| Parameter | Type | Description |
|---|---|---|
| h | ColumnPgPersistenceHints |
Entity(tableName, schema): (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.
| Parameter | Type | Description |
|---|---|---|
| tableName | string | |
| schema | string |
entityDateToApiIso(value): string
| Parameter | Type | Description |
|---|---|---|
| value | Date |
eq(a, b): boolean
Numeric equality ignoring scale — eq(1.0, 1.00) is true.
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
extJsonParse(text): T
Parse an Ext-JSON string.
ALL integers are returned as native bigint (via reviver).
Floats (values with decimal point or scientific notation) are number.
Strings, booleans, null are unaffected.
| Parameter | Type | Description |
|---|---|---|
| text | string |
extJsonStringify(data): string
Serialize a value to an Ext-JSON string. BigInt values serialize as JSON numbers (42n → "42"); floats stay numbers.
Use for request bodies carrying bigint values — the BE's ext-json body
parser revives them to native bigint.
| Parameter | Type | Description |
|---|---|---|
| data | unknown |
extractEntityAnnotations(entryFile): Promise<EntityAnnotationMap>
Build the annotation map for every class reachable from entryFile
(usually the entity registry module). compilerOptions are taken from the
nearest tsconfig.json so path aliases resolve correctly.
| Parameter | Type | Description |
|---|---|---|
| entryFile | string |
field(entity, key): FieldRef<TEntity, K>
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| key | K |
findAuditPage(repo, opts): Promise<AuditPageResult>
Page through an entity audit table, newest first.
userEntity — optional auditable-display-name join target (BE:
UserProfileEntity). Without it, display-name columns are null.
| Parameter | Type | Description |
|---|---|---|
| repo | AuditQueryable | |
| opts | AuditPageOptions & { userEntity: EntityClass } |
findLikelyRenames(schema, table, entityOnly, databaseOnly, entityColumns, databaseColumns): RenameHeuristicResult
Greedy 1:1 matching: process tiers 0→n, within each tier stable order, no floats. Uses ordinal indexing to avoid scanning all DB-only columns for every entity-only column.
| Parameter | Type | Description |
|---|---|---|
| schema | string | |
| table | string | |
| entityOnly | string[] | |
| databaseOnly | string[] | |
| entityColumns | Record<string, SchemaColumnMeta> | |
| databaseColumns | Record<string, SchemaColumnMeta> |
floor(d): Decimal
Largest integer <= d.
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
ForeignKey(target, opts): PropertyDecorator
Declares a FOREIGN KEY constraint referencing another entity's column.
target is a lazy thunk (() => CustomerEntity) so circular entity
references resolve at meta-read time, not class-eval time.
Minimal form @ForeignKey(() => CustomerEntity) references the target's
@Key() column with ON DELETE RESTRICT / ON UPDATE NO ACTION —
the zero-option path is the safest behavior.
Note: a partitioned parent (@PartitionField) cannot be a plain FK target
unless the referenced unique constraint includes the partition key —
meta validation throws and points to @PartitionChildOf for that shape.
| Parameter | Type | Description |
|---|---|---|
| target | () => EntityClass | |
| opts | ForeignKeyOptions |
fromBigInt(v, scale): Decimal
| Parameter | Type | Description |
|---|---|---|
| v | bigint | |
| scale | number |
fromNumber(n): Decimal
| Parameter | Type | Description |
|---|---|---|
| n | number |
getColumnName(ctor, propertyKey): string
| Parameter | Type | Description |
|---|---|---|
| ctor | EntityClass | |
| propertyKey | string | symbol |
getDal(config): 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).
| Parameter | Type | Description |
|---|---|---|
| config | DalConfig |
getEntityName(ctor): string
Logical entity name: the class name (e.g. CustomerEntity).
| Parameter | Type | Description |
|---|---|---|
| ctor | EntityClass |
getEntityPersistenceMeta(ctor, tableSchema): EntityPersistenceMeta
Snapshot fragment for one
| Parameter | Type | Description |
|---|---|---|
| ctor | EntityClass | |
| tableSchema | string |
getOperatorsForColumnType(columnType): FilterOperator[]
Operators available for a given column UI type.
| Parameter | Type | Description |
|---|---|---|
| columnType | string |
getPrimaryKeyColumn(ctor): string
| Parameter | Type | Description |
|---|---|---|
| ctor | EntityClass |
getQualifiedTableName(ctor): 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).
| Parameter | Type | Description |
|---|---|---|
| ctor | EntityClass |
getSchemaDomain(): SchemaDomain \| null
getTableName(ctor): string
| Parameter | Type | Description |
|---|---|---|
| ctor | EntityClass |
hydrateEntityDateFieldsFromJson(instance, meta): void
After Object.assign from JSON, restore column-typed values on the
entity: instant → Date, decimal → Decimal (wire "N.Nd" or a
bare numeric string), vector → Vector.
| Parameter | Type | Description |
|---|---|---|
| instance | T | |
| meta | EntityPersistenceMeta |
Index(): PropertyDecorator
Declares a secondary (non-unique) index. Bare @Index() → single-column
btree auto-named <table>_<col>_idx. Same name on multiple columns →
composite index ordered by order. Supports every PG access method:
@Index({ using: 'hnsw', opclass: 'vector_cosine_ops' }),
@Index({ where: 'deleted_at IS NULL' }) for partial indexes.
Unique indexes stay on @Unique().
isDecimal(v): v is Decimal
| Parameter | Type | Description |
|---|---|---|
| v | unknown |
isDriftClean(diff): boolean
True when the diff contains only database-only objects (extras we never drop) — i.e. no unapplied entity intent remains.
| Parameter | Type | Description |
|---|---|---|
| diff | SchemaMetaDiffV2 |
isEntityClass(value): value is EntityClass
| Parameter | Type | Description |
|---|---|---|
| value | unknown |
isEntityOpEnabled(actions, op): boolean
Pure enablement check — true when op exists in the served actions
array and carries enabled: true. FAIL-CLOSED: when actions is absent
(meta without actions — contract violation) the op is not enabled.
This deliberately does NOT evaluate user permissions — that step lives in
the consumer (e.g. FE isEntityOpAllowed composes this with the session
permission check).
| Parameter | Type | Description |
|---|---|---|
| actions | readonly EntityAction[] | undefined | |
| op | string |
isISODate(v): v is ISODate
| Parameter | Type | Description |
|---|---|---|
| v | unknown |
isISOTime(v): v is ISOTime
| Parameter | Type | Description |
|---|---|---|
| v | unknown |
isLogicalJsDateColumn(h): boolean
Column carries a Date-valued property — an audit/deletable/sync *_AT
field, an instant codec hint, or an explicit timestamptz/timestamp
pgType. date/time/timetz columns are ISODate/ISOTime strings —
NOT Dates — by contract.
| Parameter | Type | Description |
|---|---|---|
| h | ColumnPgPersistenceHints |
IsNotColumn(): PropertyDecorator
Excludes the property from meta schema / migration and from future DAL queries.
isoDateFromUTCDate(d): ISODate
Date → ISODate using the date's UTC calendar day.
| Parameter | Type | Description |
|---|---|---|
| d | Date |
isPeriodic(d): boolean
true when the value was produced by a truncated non-terminating division.
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
isSnakeCaseSingular(value): value is SnakeCaseSingular
Runtime validator for SnakeCaseSingular — rejects strings with uppercase letters. Use in meta-loading code to catch BE meta that violates the convention.
| Parameter | Type | Description |
|---|---|---|
| value | string |
isUUID(v): v is UUID
Type guard — validates RFC 4122 layout (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, hex).
| Parameter | Type | Description |
|---|---|---|
| v | unknown |
jsValueToPgParam(value, h): unknown
Value to pass to node-pg query parameters.
Date → passthrough (timestamptz) or YYYY-MM-DD (SQL date);
Decimal → plain numeric string; Vector/number[] → '[…]' literal;
jsonb payloads → JSON string (nested bigint → number — jsonb numerics are
doubles anyway and BigInt breaks JSON.stringify).
| Parameter | Type | Description |
|---|---|---|
| value | unknown | |
| h | ColumnPgPersistenceHints |
Key(): PropertyDecorator
Marks the single-column primary key.
keyNamespaceOf(key): string \| null
First dotted segment of a translation key — job.entities.x → job.
| Parameter | Type | Description |
|---|---|---|
| key | string |
listEntityPersistencePropertyKeys(ctor): string[]
Property keys that map to SQL columns (implicit + decorated).
| Parameter | Type | Description |
|---|---|---|
| ctor | EntityClass |
loadKeyring(keysPath): TrustedKey[]
| Parameter | Type | Description |
|---|---|---|
| keysPath | string |
loadManifest(manifestPath): PatchManifest \| null
| Parameter | Type | Description |
|---|---|---|
| manifestPath | string |
lookupEntityAnnotation(map, className, prop): EntityAnnotationInfo \| undefined
Walk the extends chain (subclass first — wins on conflicts, matching the
decorator-merge semantics of getEntityPersistenceMeta). Returns the
annotation info for prop on className, or undefined when the chain
declares no such property.
| Parameter | Type | Description |
|---|---|---|
| map | EntityAnnotationMap | |
| className | string | |
| prop | string |
makeEntityService(cfg): EntityService<TEntity>
| Parameter | Type | Description |
|---|---|---|
| cfg | EntityServiceConfig<TEntity> |
makeTableAuditPort(repo): AuditPort
makeTableAuditPort — writes audit log rows to {tableName}_audit via the
given repository. This is the service-side counterpart of the BE's
EntityAuditPort, minus the Redis/NATS entity-changed markers (those
belong to gateway collaboration infra). The audit row write itself is
always performed.
| Parameter | Type | Description |
|---|---|---|
| repo | Repository |
manifestPaths(dbMetaDir): { manifestPath: string; keysPath: string }
Resolve manifest + keyring paths for a service's db-meta dir.
| Parameter | Type | Description |
|---|---|---|
| dbMetaDir | string |
max(a, b): Decimal
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
min(a, b): Decimal
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
mod(a, b): Decimal
a mod b — remainder of truncated division at the common scale.
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
mul(a, b): Decimal
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
neg(d): Decimal
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
normalize(d): Decimal
Strip trailing fractional zeros — 1.230 → 1.23, 12.000 → 12.
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
normalizePatchEol(body): string
Patch integrity hashes are EOL-insensitive: a Windows checkout may materialize CRLF while the committed blob and the signed MANIFEST are LF. Normalize before hashing so manifest verification and the patch registry are platform-stable.
| Parameter | Type | Description |
|---|---|---|
| body | string |
orderedColumns(columns): MetaColumn[]
Columns in display order: sticky group → normal group → audited group,
each sorted by order.
| Parameter | Type | Description |
|---|---|---|
| columns | readonly MetaColumn[] | null | undefined |
parseDecimal(input): Decimal
Parse a decimal string into unscaled form.
Accepts: "12", "-0.5", ".5", "5.", "1.5e3", "1E-3", "+4".
Rejects: NaN, Infinity, empty strings, hex, non-numeric garbage.
Scale is preserved as written ("1.230" → scale 3).
| Parameter | Type | Description |
|---|---|---|
| input | string |
parsePatchPragmas(raw): { requiresReview: boolean; noTransaction: boolean }
Parse the -- pb:* pragma header of a patch file.
| Parameter | Type | Description |
|---|---|---|
| raw | string |
parsePatchSegments(raw): PatchSegment[]
Split a patch file into execution segments. Default content is transactional
(tx); statements inside -- pb:begin-no-transaction … -- pb:end-no-transaction
run per-statement in autocommit (for CREATE INDEX CONCURRENTLY & friends).
Whole-file -- pb:no-transaction is equivalent to wrapping everything.
| Parameter | Type | Description |
|---|---|---|
| raw | string |
PartitionChildOf(opts): ClassDecorator
Declares this entity a logical child of a @PartitionField-partitioned
parent: it joins the parent's atomic delete and retention purge unit.
Needed because a partitioned parent cannot host a plain FOREIGN KEY
(unique constraints must contain the partition key) — the relationship
is application-level, enforced by the repository cascade and the
partition-maintenance purge. Entities that merely REFERENCE a parent
(telemetry, logs) simply don't declare this.
| Parameter | Type | Description |
|---|---|---|
| opts | PartitionChildOfOptions |
PartitionField(opts): PropertyDecorator
Marks a column as the RANGE partition key of the table (pg_partman,
monthly/daily/…). Exactly ONE per entity. The column must be NOT NULL and
date/timestamptz-typed; every unique group and the primary key emitted in
DDL must include it (PostgreSQL requirement) — getEntityPersistenceMeta
validates this and throws otherwise, so a partitioned entity can never
produce an invalid table definition.
| Parameter | Type | Description |
|---|---|---|
| opts | PartitionFieldOptions |
patchNameFromFilename(filename): string
The registry identity of a patch is its filename minus the .sql extension.
| Parameter | Type | Description |
|---|---|---|
| filename | string |
patchRegistryDdl(schema): string
| Parameter | Type | Description |
|---|---|---|
| schema | string |
patchSlugFromDiff(diff): string
| Parameter | Type | Description |
|---|---|---|
| diff | SchemaMetaDiffV2 |
pgDivScale(a, b): number
PostgreSQL-faithful result scale for x / y (mirrors select_div_scale):
max(16 - 4·qweight, x.scale, y.scale) — 16 significant digits minimum.
Verified live: 1/3→20, 10/4→16, 1.00/8→20, 2/1→16, 100/3→16.
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
pgTypeFromAnnotation(a): string \| null
Annotation → base pg type. Returns null for unmappable annotations —
the caller decides whether that's an error (schema pipeline) or a
non-authoritative runtime hint.
| Parameter | Type | Description |
|---|---|---|
| a | EntityAnnotationInfo |
pgValueToJsValue(value, h): unknown
Normalise a driver value into the entity-side type: Date for date-like
columns, Decimal for numeric columns, Vector for vector columns.
Driver-native shapes (pg already returns Date/bigint/arrays) pass
through unchanged.
| Parameter | Type | Description |
|---|---|---|
| value | unknown | |
| h | ColumnPgPersistenceHints |
pow10(n): bigint
| Parameter | Type | Description |
|---|---|---|
| n | number |
quoteIdent(ident): string
| Parameter | Type | Description |
|---|---|---|
| ident | string |
registryStatus(pool, schema): Promise<PatchRegistryRow[]>
| Parameter | Type | Description |
|---|---|---|
| pool | Pool | |
| schema | string |
rescale(d, newScale, mode): Decimal
Re-express d at newScale. Growing is exact; shrinking applies mode
(default HALF_UP, matching PostgreSQL round()).
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput | |
| newScale | number | |
| mode | RoundingMode |
resetDal(): Promise<void>
Resets the singleton. Closes the existing instance if any. Intended for tests — call in afterAll to release the pool.
resetSchemaDomain(): void
Test hook — clears the configured domain.
resolveEntitySchema(meta, fallback): string
Resolve the effective schema of an entity: the explicit
| Parameter | Type | Description |
|---|---|---|
| meta | { tableSchema: string; tableName: string } | |
| fallback | string |
resolveManually(pool, schema, patchName, actor, note): Promise<boolean>
Operator escape hatch: mark a failed/pending patch as manually resolved.
| Parameter | Type | Description |
|---|---|---|
| pool | Pool | |
| schema | string | |
| patchName | string | |
| actor | string | |
| note | string |
resolvePgTypeForSchema(h): string
Authoritative resolve for the schema pipeline: explicit pgType, else
semantic decorator pin, else annotation inference. Throws when none can
produce a type — an unmappable entity property must never silently
become text.
| Parameter | Type | Description |
|---|---|---|
| h | EntityColumnTypeHints |
resolvePresetConditions(presets, selections): FilterCondition[]
Flatten the WHERE conditions of every preset's ACTIVE option — the
conditions AND-ed into every /list call. selections maps
preset.id → option id; invalid/absent ids resolve per
resolvePresetSelection.
| Parameter | Type | Description |
|---|---|---|
| presets | readonly FilterPreset[] | undefined | |
| selections | Record<string, string> |
resolvePresetSelection(preset, selected): string
Resolve a preset's active option id — the caller-provided selection when
it names a declared option, otherwise default_option (itself falling
back to the first option when misconfigured, keeping the always-one
invariant rather than failing closed).
| Parameter | Type | Description |
|---|---|---|
| preset | FilterPreset | |
| selected | string | undefined |
resolveVendorSpecifier(specifier): VendorResolution
How a remote chunk's bundler must treat a bare import specifier. Both the host vendor build and every module chunk build derive behavior from this single function so the plane stays deterministic.
| Parameter | Type | Description |
|---|---|---|
| specifier | string |
retryFailedPatches(pool, schema, actor): Promise<number>
failed → pending: next runMigrations retries them (and past them, in order).
| Parameter | Type | Description |
|---|---|---|
| pool | Pool | |
| schema | string | |
| actor | string |
round(d, scale, mode): Decimal
Round to scale fractional digits (default HALF_UP).
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput | |
| scale | number | |
| mode | RoundingMode |
runMigrations(opts): Promise<MigrationRunResult>
| Parameter | Type | Description |
|---|---|---|
| opts | MigrationEngineOptions |
runPartitionMaintenance(client, entities): Promise<PartitionMaintenanceReport>
| Parameter | Type | Description |
|---|---|---|
| client | PoolClient | |
| entities | readonly EntityClass[] |
sanitizeVisibleKeys(visibleKeys, columns): string[]
Drop unknown keys and fall back to defaults when nothing left.
| Parameter | Type | Description |
|---|---|---|
| visibleKeys | string[] | |
| columns | MetaColumn[] |
searchableTextColumns(columns): MetaColumn[]
Text-physical searchable columns — the scope selector + default "all fields" search set.
| Parameter | Type | Description |
|---|---|---|
| columns | MetaColumn[] |
serviceApiBase(listBasePath): string
Service API base of an entity list basePath — strips the trailing
/entities/<entity> segment so service-relative endpoints declared in
meta (e.g. sparkline endpoint: "/actions/job-run-stats") resolve to
/ws/<svc>/api/v1/actions/… or /api/v1/actions/… for BE entities.
| Parameter | Type | Description |
|---|---|---|
| listBasePath | string |
sha256Hex(body): string
| Parameter | Type | Description |
|---|---|---|
| body | string |
signManifest(manifest, privateKeyB64): PatchManifest
Sign a manifest body (entries already updated) with a PEM/DER private key.
| Parameter | Type | Description |
|---|---|---|
| manifest | Omit<PatchManifest, "signature"> | |
| privateKeyB64 | string |
signum(d): -1 \| 0 \| 1
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
slugifyPatchSegment(s): string
| Parameter | Type | Description |
|---|---|---|
| s | string |
specifierTopPackage(specifier): string
Top-level npm package of a specifier ('svelte/internal/client' → 'svelte').
| Parameter | Type | Description |
|---|---|---|
| specifier | string |
splitSqlStatements(sql): string[]
Top-level SQL statement splitter for -- pb:no-transaction segments.
Needed because node-pg's simple query protocol executes a multi-statement string in a single implicit transaction — to get per-statement autocommit (required for CREATE INDEX CONCURRENTLY etc.) statements must be sent separately. Handles: single/double-quoted strings, dollar-quoted bodies ($$…$$, $tag$…$tag$), line comments, block comments.
| Parameter | Type | Description |
|---|---|---|
| sql | string |
strictEq(a, b): boolean
Exact structural equality — value AND scale must match (strictEq(1.0, 1.00) is false).
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
sub(a, b): Decimal
| Parameter | Type | Description |
|---|---|---|
| a | DecimalInput | |
| b | DecimalInput |
SynchronizableField(what): PropertyDecorator
Marks a field as synchronizable (last_synced_at).
| Parameter | Type | Description |
|---|---|---|
| what | SynchronizableFieldType |
syncImplicitEntityColumns(ctor): void
Registers every implicit column + design:type / nullability when not already set by decorators.
| Parameter | Type | Description |
|---|---|---|
| ctor | Function |
tableKey(schema, name): string
| Parameter | Type | Description |
|---|---|---|
| schema | string | |
| name | string |
toISODate(v): ISODate
| Parameter | Type | Description |
|---|---|---|
| v | string |
toISOTime(v): ISOTime
| Parameter | Type | Description |
|---|---|---|
| v | string |
toUUID(v): UUID
Validating constructor — throws on malformed input. Use at system boundaries (request bodies, env, user input).
| Parameter | Type | Description |
|---|---|---|
| v | string |
toWire(d): string
Wire form — "…d" suffixed string.
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
translateFilterConditions(entity, conditions, options): FilterExpr[] \| null
| Parameter | Type | Description |
|---|---|---|
| entity | EntityClass | |
| conditions | ListFilterCondition[] | null | undefined | |
| options | ListFilterOptions |
translationKeyNamespace(schema): string
Owning PG schema → the only translation-key namespace writable there.
| Parameter | Type | Description |
|---|---|---|
| schema | string |
trunc(d): Decimal
Integer part, toward zero.
| Parameter | Type | Description |
|---|---|---|
| d | DecimalInput |
trustedISODate(v): ISODate
Zero-cost cast for trusted sources (DB rows).
| Parameter | Type | Description |
|---|---|---|
| v | string |
trustedISOTime(v): ISOTime
Zero-cost cast for trusted sources (DB rows).
| Parameter | Type | Description |
|---|---|---|
| v | string |
trustedUUID(v): UUID
Zero-cost cast for trusted sources (DB rows, values already validated upstream). Named explicitly so reviews can spot it.
| Parameter | Type | Description |
|---|---|---|
| v | string |
typesCompatibleForRename(a, b): boolean
True if two metas are “same enough” for rename pairing (not for strict migration).
| Parameter | Type | Description |
|---|---|---|
| a | SchemaColumnMeta | |
| b | SchemaColumnMeta |
Unique(): PropertyDecorator
Unique constraint (PostgreSQL: unique index in generated patches).
utcTimestampForFilename(d): string
| Parameter | Type | Description |
|---|---|---|
| d | Date |
verifyManifest(manifest, keyring, allowedTrust): TrustedKey
Verify manifest signature against the keyring (filtered by allowed trust levels).
| Parameter | Type | Description |
|---|---|---|
| manifest | PatchManifest | |
| keyring | TrustedKey[] | |
| allowedTrust | readonly "release" | "dev"[] |
writeManifest(manifestPath, manifest): void
Write manifest (used by compare/sign tooling).
| Parameter | Type | Description |
|---|---|---|
| manifestPath | string | |
| manifest | PatchManifest |