Skip to main content

@Entity

@Entity is the class decorator that registers a class as an ORM entity mapped to a database table. See Defining Models for the full guide.

function Entity(options?: EntityOptions | string): ClassDecorator;
  • @Entity('table_name') — shorthand that only sets the table name.
  • @Entity({ tableName?, schema?, comment? }) — the full EntityOptions form.
  • @Entity() — table name defaults to the class name (ctor.name, used verbatim, no case conversion).
import { BaseEntity, Column, Entity, PrimaryKey } from '@sqb/connect';

@Entity('countries')
export class Country extends BaseEntity {
@PrimaryKey()
@Column()
declare code: string;

@Column()
declare name: string;
}

Static helpers

The Entity function also carries a namespace of static helpers for introspecting and composing entity metadata at runtime. These are not documented in the @sqb/connect README, but are part of the public API (exported from @sqb/connect).

Entity.getMetadata() / Entity.getOwnMetadata()

function getMetadata(ctor: Type): Maybe<EntityMetadata>;
function getOwnMetadata(ctor: Type): Maybe<EntityMetadata>;

Returns the class's EntityMetadata, or undefined if ctor isn't (yet) an entity. getMetadata (aliased from EntityMetadata.get) looks up the prototype chain and returns inherited metadata; getOwnMetadata (aliased from EntityMetadata.getOwn) returns only metadata defined directly on ctor itself.

Entity.getField()

function getField<T>(ctor: Type<T>, key: keyof T | string): Maybe<AnyFieldMetadata>;

Returns the metadata for any field (column, embedded, or association) by property name.

Entity.getColumnField()

function getColumnField<T>(ctor: Type<T>, key: keyof T | string): Maybe<ColumnFieldMetadata>;

Returns the field's ColumnFieldMetadata (see ColumnFieldOptions for its options shape); throws if the field exists but isn't a @Column field.

Entity.getEmbeddedField()

function getEmbeddedField<T>(ctor: Type<T>, key: keyof T | string): Maybe<EmbeddedFieldMetadata>;

Returns embedded-field metadata; throws if the field exists but isn't an @Embedded field.

Entity.getAssociationField()

function getAssociationField<T>(ctor: Type<T>, key: keyof T | string): Maybe<AssociationFieldMetadata>;

Returns association-field metadata; throws if the field exists but isn't a @Link field.

Entity.getColumnFieldByFieldName()

function getColumnFieldByFieldName(ctor: Type, fieldName: string): Maybe<ColumnFieldMetadata>;

Looks a column up by its database field name instead of its property name.

Entity.find()

function find(ctor: Type, predicate: (el: AnyFieldMetadata) => boolean): Maybe<AnyFieldMetadata>;

Returns the first field matching predicate.

Field-name lists

function getFieldNames(ctor: Type, filter?: (el: AnyFieldMetadata) => boolean): string[];
function getColumnFieldNames(ctor: Type): string[];
function getEmbeddedFieldNames(ctor: Type): string[];
function getAssociationFieldNames(ctor: Type): string[];
function getNonAssociationFieldNames(ctor: Type): string[];
function getInsertColumnNames(ctor: Type): string[];
function getUpdateColumnNames(ctor: Type): string[];

All property (not database) names, narrowed by field kind. getInsertColumnNames/ getUpdateColumnNames further filter to columns that participate in INSERT/UPDATE (i.e. not marked noInsert/noUpdate — see ColumnFieldOptions). Every one of these returns [] (rather than throwing) when ctor isn't an entity.

Entity.getPrimaryIndex() / Entity.getPrimaryIndexColumns()

function getPrimaryIndex(ctor: Type): Maybe<IndexMetadata>;
function getPrimaryIndexColumns(ctor: Type): ColumnFieldMetadata[];

The entity's primary-key index (see Primary Keys) and the resolved ColumnFieldMetadata[] making up that key, in index-column order.

Entity.mixin()

function mixin<A, B>(derivedCtor: Type<A>, baseB: Type<B>): Type<A & B>;
// ...overloads up to 5 base classes

Merges one or more base entities' columns, embedded fields, associations, indexes, foreign keys, and event listeners onto derivedCtor — mutating its own entity metadata in place and returning it (typed as the intersection of all classes involved). See Entity Composition.

Entity.mixin(Customer, Timestamps);

Entity.Pick()

function Pick<T, K extends keyof T>(
classRef: Type<T>,
keys: readonly K[],
): Type<Pick<T, K>>;

Builds a new class containing only the named keys from classRef (case-insensitive key match) — see Entity Composition.

const CustomerSummary = Entity.Pick(Customer, ['id', 'givenName', 'familyName']);

Entity.Omit()

function Omit<T, K extends keyof T>(
classRef: Type<T>,
keys: readonly K[],
): Type<Omit<T, K>>;

The inverse of Pick — a new class with everything except the named keys. See Entity Composition.

const CustomerWithoutAudit = Entity.Omit(Customer, ['createdAt', 'updatedAt']);

Entity.Union()

function Union<A, B>(baseA: Type<A>, baseB: Type<B>): Type<A & B>;
// ...overloads up to 6 base classes

Combines two or more entities' fields and prototype members into a brand-new class — like mixin, but building a fresh class instead of mutating an existing one. See Entity Composition.

const CustomerWithTimestamps = Entity.Union(Customer, Timestamps);

See also