import { TableBuilder, PartitioningConfig } from '../schema/table-builder'; import { ColumnBuilder } from '../schema/column-builder'; /** * Unique symbol for DbEntity type branding * @internal */ declare const __entityBrandSymbol: unique symbol; /** * Base class for all entities */ export declare abstract class DbEntity { /** @internal - Type brand to distinguish DbEntity from plain objects in the type system */ readonly [__entityBrandSymbol]: true; /** @internal */ static readonly __isEntity = true; /** @internal */ static __tableName?: string; /** @internal */ static __tableBuilder?: TableBuilder; } /** * DbEntity constructor type */ export type EntityConstructor = new () => T; /** * DbEntity metadata for a single entity */ export interface EntityMetadata { entityClass: EntityConstructor; tableName: string; schemaName?: string; properties: Map; navigations: Map>; indexes: IndexMetadata[]; /** Extended-statistics objects (`CREATE STATISTICS`), set via `.hasStatistics()`. */ statistics?: StatisticsMetadata[]; /** Declarative table partitioning (parent `PARTITION BY`), set via `.hasPartitioning()`. */ partitioning?: PartitioningConfig; } /** * Property metadata */ export interface PropertyMetadata { propertyKey: keyof any; columnName: string; columnBuilder: ColumnBuilder; isPrimaryKey?: boolean; isRequired?: boolean; isUnique?: boolean; defaultValue?: any; /** * Set when the column participates in an {@link ixNormalized} index. A * transferable hint that the column has an accent/case-insensitive index, so * normalized query helpers can be applied against it efficiently. */ hasNormalizedIndex?: boolean; } /** * Foreign key action type */ export type ForeignKeyAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default'; /** * Navigation metadata */ export interface NavigationMetadata { propertyKey: keyof any; targetEntity: () => EntityConstructor; relationType: 'one' | 'many'; foreignKeys: string[]; principalKeys: string[]; isRequired?: boolean; onDelete?: ForeignKeyAction; onUpdate?: ForeignKeyAction; constraintName?: string; /** * If true, this is an inverse navigation (the FK constraint is defined on the other side). * No FK constraint will be created for this navigation. */ isInverseNavigation?: boolean; } export type IndexMethod = 'btree' | 'gin' | 'gist' | 'hash' | 'brin' | 'spgist'; /** * Index expression helpers — wrap entity property references inside hasIndex selectors. * Composable: ixLower(ixUnaccent(e.name)) → lower(unaccent("name")) * * @example * entity.hasIndex('idx_name', e => [ixLower(ixUnaccent(e.name))]) */ export interface IndexColumnRef { __indexColumn: true; columnName: string; expression?: string; /** * Set by {@link ixNormalized}. Signals that this index entry uses * `public.search_normalize()`, so the migration must create the `unaccent` * extension and the `search_normalize` function before building the index. */ __requiresSearchNormalize?: boolean; /** * Set by `ixNormalized(ref, { gin: true })`. Signals that the index should be * a trigram GIN index (`USING gin (... gin_trgm_ops)`), which also requires * the `pg_trgm` extension. */ __gin?: boolean; } export declare function ixLower(ref: T): T; export declare function ixUnaccent(ref: T): T; /** * Index expression helper that wraps a column in `public.search_normalize()`, * producing an accent- and case-insensitive expression index. Composable with * the other `ix*` helpers. * * Pass `{ gin: true }` to build a trigram GIN index (best for substring / * `normalizedLike('%x%')` searches); omit it for a plain btree expression index * (best for `normalizedEq` / `normalizedStartsWith` and unique constraints). * * Declaring any `ixNormalized` index automatically makes the migration create * the `unaccent` extension + `search_normalize` function (and `pg_trgm` when * `gin` is used) before the index is built. * * @example * // unique normalized lookup (btree) * entity.hasIndex('user_admin_query', e => [ixNormalized(e.email), e.hash]).isUnique(); * * // fuzzy substring search (trigram GIN) * entity.hasIndex('user_name_search', e => [ixNormalized(e.username, { gin: true })]); */ export declare function ixNormalized(ref: T, options?: { gin?: boolean; }): T; /** * Index metadata */ export interface IndexMetadata { name: string; columns: string[]; isUnique?: boolean; using?: IndexMethod; operatorClass?: string; /** * If true, the index is created with `CREATE INDEX CONCURRENTLY`, which avoids * holding a long write lock on the table. The statement must run outside of a * transaction — PostgreSQL will raise an error otherwise. */ concurrent?: boolean; /** Raw SQL expressions for expression-based index columns (e.g., 'lower(unaccent(name))') */ expressions?: string[]; /** Raw SQL WHERE clause for partial indexes (e.g., 'active = true') */ where?: string; /** * Opt-in `NULLS NOT DISTINCT` (PostgreSQL 15+) for a UNIQUE index: treat NULLs * as equal so at most one row may hold NULL in the indexed column(s). Only * meaningful on unique indexes; ignored when the index is not unique. */ nullsNotDistinct?: boolean; /** * Set when the index contains an {@link ixNormalized} expression. The schema * manager uses this to create the `unaccent` extension + `search_normalize` * function (and `pg_trgm` when `using === 'gin'`) before building the index. */ requiresSearchNormalize?: boolean; } /** * Extended-statistics metadata (`CREATE STATISTICS … ON FROM `), * declared via `entity.hasStatistics()`. Entries are raw SQL — quoted column * references collected through the selector proxy and/or parenthesized * expressions supplied through `withExpression()`. Reconciled by NAME only: * the schema manager creates a missing object and never drops or rebuilds one * (rename to change a definition). */ export interface StatisticsMetadata { name: string; /** Raw SQL entries of the `ON` list, in declaration order. */ expressions: string[]; /** * Optional multivariate kinds. Must stay unset for a single-expression * declaration — PostgreSQL builds univariate expression statistics there * and rejects an explicit kinds list. */ kinds?: Array<'ndistinct' | 'dependencies' | 'mcv'>; } /** * Global entity metadata store */ export declare class EntityMetadataStore { private static metadata; static getMetadata(entityClass: EntityConstructor): EntityMetadata | undefined; static setMetadata(entityClass: EntityConstructor, metadata: EntityMetadata): void; static hasMetadata(entityClass: EntityConstructor): boolean; static getOrCreateMetadata(entityClass: EntityConstructor): EntityMetadata; } export {}; //# sourceMappingURL=entity-base.d.ts.map