metal-orm 1.0.15 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +64 -61
  2. package/dist/decorators/index.cjs +490 -175
  3. package/dist/decorators/index.cjs.map +1 -1
  4. package/dist/decorators/index.d.cts +1 -5
  5. package/dist/decorators/index.d.ts +1 -5
  6. package/dist/decorators/index.js +490 -175
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +1044 -483
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +67 -15
  11. package/dist/index.d.ts +67 -15
  12. package/dist/index.js +1033 -482
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-Bkv8g8u_.d.cts → select-BPCn6MOH.d.cts} +486 -32
  15. package/dist/{select-Bkv8g8u_.d.ts → select-BPCn6MOH.d.ts} +486 -32
  16. package/package.json +2 -1
  17. package/src/codegen/naming-strategy.ts +64 -0
  18. package/src/codegen/typescript.ts +48 -53
  19. package/src/core/ast/aggregate-functions.ts +50 -4
  20. package/src/core/ast/expression-builders.ts +22 -15
  21. package/src/core/ast/expression-nodes.ts +6 -0
  22. package/src/core/ddl/introspect/functions/postgres.ts +2 -6
  23. package/src/core/ddl/schema-generator.ts +3 -2
  24. package/src/core/ddl/schema-introspect.ts +1 -1
  25. package/src/core/dialect/abstract.ts +40 -8
  26. package/src/core/dialect/mssql/functions.ts +24 -15
  27. package/src/core/dialect/postgres/functions.ts +33 -24
  28. package/src/core/dialect/sqlite/functions.ts +19 -12
  29. package/src/core/functions/datetime.ts +2 -1
  30. package/src/core/functions/numeric.ts +2 -1
  31. package/src/core/functions/standard-strategy.ts +52 -12
  32. package/src/core/functions/text.ts +2 -1
  33. package/src/core/functions/types.ts +8 -8
  34. package/src/decorators/column.ts +13 -4
  35. package/src/index.ts +13 -5
  36. package/src/orm/domain-event-bus.ts +43 -25
  37. package/src/orm/entity-context.ts +30 -0
  38. package/src/orm/entity-meta.ts +42 -2
  39. package/src/orm/entity-metadata.ts +1 -6
  40. package/src/orm/entity.ts +88 -88
  41. package/src/orm/execute.ts +42 -25
  42. package/src/orm/execution-context.ts +18 -0
  43. package/src/orm/hydration-context.ts +16 -0
  44. package/src/orm/identity-map.ts +4 -0
  45. package/src/orm/interceptor-pipeline.ts +29 -0
  46. package/src/orm/lazy-batch.ts +6 -6
  47. package/src/orm/orm-session.ts +245 -0
  48. package/src/orm/orm.ts +58 -0
  49. package/src/orm/query-logger.ts +15 -0
  50. package/src/orm/relation-change-processor.ts +5 -1
  51. package/src/orm/relations/belongs-to.ts +45 -44
  52. package/src/orm/relations/has-many.ts +44 -43
  53. package/src/orm/relations/has-one.ts +140 -139
  54. package/src/orm/relations/many-to-many.ts +46 -45
  55. package/src/orm/runtime-types.ts +60 -2
  56. package/src/orm/transaction-runner.ts +7 -0
  57. package/src/orm/unit-of-work.ts +7 -1
  58. package/src/query-builder/insert-query-state.ts +13 -3
  59. package/src/query-builder/select-helpers.ts +50 -0
  60. package/src/query-builder/select.ts +616 -18
  61. package/src/query-builder/update-query-state.ts +31 -9
  62. package/src/schema/types.ts +16 -6
  63. package/src/orm/orm-context.ts +0 -159
@@ -348,6 +348,10 @@ interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDe
348
348
  */
349
349
  declare const defineTable: <T extends Record<string, ColumnDef>>(name: string, columns: T, relations?: Record<string, RelationDef>, hooks?: TableHooks, options?: TableOptions) => TableDef<T>;
350
350
 
351
+ /**
352
+ * Resolves a relation definition to its target table type.
353
+ */
354
+ type RelationTargetTable<TRel extends RelationDef> = TRel extends HasManyRelation<infer TTarget> ? TTarget : TRel extends HasOneRelation<infer TTarget> ? TTarget : TRel extends BelongsToRelation<infer TTarget> ? TTarget : TRel extends BelongsToManyRelation<infer TTarget> ? TTarget : never;
351
355
  /**
352
356
  * Maps a ColumnDef to its TypeScript type representation
353
357
  */
@@ -544,6 +548,12 @@ interface FunctionNode {
544
548
  args: OperandNode[];
545
549
  /** Optional alias for the function result */
546
550
  alias?: string;
551
+ /** Optional ORDER BY clause used by aggregations like GROUP_CONCAT */
552
+ orderBy?: OrderByNode[];
553
+ /** Optional separator argument used by GROUP_CONCAT-like functions */
554
+ separator?: OperandNode;
555
+ /** Optional DISTINCT modifier */
556
+ distinct?: boolean;
547
557
  }
548
558
  /**
549
559
  * AST node representing a JSON path expression
@@ -893,6 +903,8 @@ interface HydrationMetadata {
893
903
  interface FunctionRenderContext {
894
904
  node: FunctionNode;
895
905
  compiledArgs: string[];
906
+ /** Helper to compile additional operands (e.g., separators or ORDER BY columns) */
907
+ compileOperand: (operand: OperandNode) => string;
896
908
  }
897
909
  type FunctionRenderer = (ctx: FunctionRenderContext) => string;
898
910
  interface FunctionStrategy {
@@ -1023,6 +1035,12 @@ declare abstract class Dialect implements SelectCompiler, InsertCompiler, Update
1023
1035
  private readonly operandCompilers;
1024
1036
  protected readonly functionStrategy: FunctionStrategy;
1025
1037
  protected constructor(functionStrategy?: FunctionStrategy);
1038
+ /**
1039
+ * Creates a new Dialect instance (for testing purposes)
1040
+ * @param functionStrategy - Optional function strategy
1041
+ * @returns New Dialect instance
1042
+ */
1043
+ static create(functionStrategy?: FunctionStrategy): Dialect;
1026
1044
  /**
1027
1045
  * Registers an expression compiler for a specific node type
1028
1046
  * @param type - Expression node type
@@ -1577,21 +1595,48 @@ interface SimpleQueryRunner {
1577
1595
  */
1578
1596
  declare function createExecutorFromQueryRunner(runner: SimpleQueryRunner): DbExecutor;
1579
1597
 
1598
+ type EntityConstructor = new (...args: any[]) => any;
1599
+ type EntityOrTableTarget = EntityConstructor | TableDef;
1600
+ type EntityOrTableTargetResolver = EntityOrTableTarget | (() => EntityOrTableTarget);
1601
+
1602
+ /**
1603
+ * Entity status enum representing the lifecycle state of an entity
1604
+ */
1580
1605
  declare enum EntityStatus {
1606
+ /** Entity is newly created and not yet persisted */
1581
1607
  New = "new",
1608
+ /** Entity is managed by the ORM and synchronized with the database */
1582
1609
  Managed = "managed",
1610
+ /** Entity has been modified but not yet persisted */
1583
1611
  Dirty = "dirty",
1612
+ /** Entity has been marked for removal */
1584
1613
  Removed = "removed",
1614
+ /** Entity is detached from the ORM context */
1585
1615
  Detached = "detached"
1586
1616
  }
1617
+ /**
1618
+ * Represents an entity being tracked by the ORM
1619
+ */
1587
1620
  interface TrackedEntity {
1621
+ /** The table definition this entity belongs to */
1588
1622
  table: TableDef;
1623
+ /** The actual entity instance */
1589
1624
  entity: any;
1625
+ /** Primary key value of the entity */
1590
1626
  pk: string | number | null;
1627
+ /** Current status of the entity */
1591
1628
  status: EntityStatus;
1629
+ /** Original values of the entity when it was loaded */
1592
1630
  original: Record<string, any> | null;
1593
1631
  }
1632
+ /**
1633
+ * Type representing a key for relation navigation
1634
+ */
1594
1635
  type RelationKey = string;
1636
+ /**
1637
+ * Represents a change operation on a relation
1638
+ * @typeParam T - Type of the related entity
1639
+ */
1595
1640
  type RelationChange<T> = {
1596
1641
  kind: 'add';
1597
1642
  entity: T;
@@ -1605,63 +1650,306 @@ type RelationChange<T> = {
1605
1650
  kind: 'detach';
1606
1651
  entity: T;
1607
1652
  };
1608
- interface HasDomainEvents {
1609
- domainEvents?: any[];
1653
+ /**
1654
+ * Represents a relation change entry in the unit of work
1655
+ */
1656
+ interface RelationChangeEntry {
1657
+ /** Root entity that owns the relation */
1658
+ root: any;
1659
+ /** Key of the relation being changed */
1660
+ relationKey: RelationKey;
1661
+ /** Table definition of the root entity */
1662
+ rootTable: TableDef;
1663
+ /** Name of the relation */
1664
+ relationName: string;
1665
+ /** Relation definition */
1666
+ relation: RelationDef;
1667
+ /** The change being applied */
1668
+ change: RelationChange<any>;
1669
+ }
1670
+ /**
1671
+ * Represents a domain event that can be emitted by entities
1672
+ * @typeParam TType - Type of the event (string literal)
1673
+ */
1674
+ interface DomainEvent<TType extends string = string> {
1675
+ /** Type identifier for the event */
1676
+ readonly type: TType;
1677
+ /** Timestamp when the event occurred */
1678
+ readonly occurredAt?: Date;
1679
+ }
1680
+ /**
1681
+ * Type representing any domain event
1682
+ */
1683
+ type AnyDomainEvent = DomainEvent<string>;
1684
+ /**
1685
+ * Type representing ORM-specific domain events
1686
+ */
1687
+ type OrmDomainEvent = AnyDomainEvent;
1688
+ /**
1689
+ * Interface for entities that can emit domain events
1690
+ * @typeParam E - Type of domain events this entity can emit
1691
+ */
1692
+ interface HasDomainEvents<E extends DomainEvent = AnyDomainEvent> {
1693
+ /** Array of domain events emitted by this entity */
1694
+ domainEvents?: E[];
1610
1695
  }
1611
1696
 
1612
- type DomainEventHandler$1<Context> = (event: any, ctx: Context) => Promise<void> | void;
1613
- declare const addDomainEvent: (entity: HasDomainEvents, event: any) => void;
1697
+ /**
1698
+ * Strategy interface for converting database names to TypeScript identifiers
1699
+ */
1700
+ interface NamingStrategy {
1701
+ /**
1702
+ * Converts a table name to a TypeScript symbol name
1703
+ * @param table - Table node, function table node, or name
1704
+ * @returns Valid TypeScript identifier
1705
+ */
1706
+ tableToSymbol(table: TableNode | FunctionTableNode | string): string;
1707
+ /**
1708
+ * Converts a column reference to a property name
1709
+ * @param column - Column node
1710
+ * @returns Valid TypeScript property name
1711
+ */
1712
+ columnToProperty(column: ColumnNode): string;
1713
+ }
1714
+
1715
+ interface QueryContext {
1716
+ sql: string;
1717
+ params: unknown[];
1718
+ }
1719
+ type QueryInterceptor = (ctx: QueryContext, next: () => Promise<QueryResult[]>) => Promise<QueryResult[]>;
1720
+ declare class InterceptorPipeline {
1721
+ private interceptors;
1722
+ use(interceptor: QueryInterceptor): void;
1723
+ run(ctx: QueryContext, executor: DbExecutor): Promise<QueryResult[]>;
1724
+ }
1725
+
1726
+ interface OrmOptions<E extends DomainEvent = OrmDomainEvent> {
1727
+ dialect: Dialect;
1728
+ executorFactory: DbExecutorFactory;
1729
+ interceptors?: InterceptorPipeline;
1730
+ namingStrategy?: NamingStrategy;
1731
+ }
1732
+ interface DbExecutorFactory {
1733
+ createExecutor(options?: {
1734
+ tx?: ExternalTransaction;
1735
+ }): DbExecutor;
1736
+ createTransactionalExecutor(): DbExecutor;
1737
+ }
1738
+ interface ExternalTransaction {
1739
+ }
1740
+ declare class Orm<E extends DomainEvent = OrmDomainEvent> {
1741
+ readonly dialect: Dialect;
1742
+ readonly interceptors: InterceptorPipeline;
1743
+ readonly namingStrategy: NamingStrategy;
1744
+ private readonly executorFactory;
1745
+ constructor(opts: OrmOptions<E>);
1746
+ createSession(options?: {
1747
+ tx?: ExternalTransaction;
1748
+ }): OrmSession<E>;
1749
+ transaction<T>(fn: (session: OrmSession<E>) => Promise<T>): Promise<T>;
1750
+ }
1751
+
1752
+ declare class IdentityMap {
1753
+ private readonly buckets;
1754
+ get bucketsMap(): Map<string, Map<string, TrackedEntity>>;
1755
+ getEntity(table: TableDef, pk: string | number): any | undefined;
1756
+ register(tracked: TrackedEntity): void;
1757
+ remove(tracked: TrackedEntity): void;
1758
+ getEntitiesForTable(table: TableDef): TrackedEntity[];
1759
+ clear(): void;
1760
+ private toIdentityKey;
1761
+ }
1762
+
1763
+ declare class UnitOfWork {
1764
+ private readonly dialect;
1765
+ private readonly executor;
1766
+ private readonly identityMap;
1767
+ private readonly hookContext;
1768
+ private readonly trackedEntities;
1769
+ constructor(dialect: Dialect, executor: DbExecutor, identityMap: IdentityMap, hookContext: () => unknown);
1770
+ get identityBuckets(): Map<string, Map<string, TrackedEntity>>;
1771
+ getTracked(): TrackedEntity[];
1772
+ getEntity(table: TableDef, pk: string | number): any | undefined;
1773
+ getEntitiesForTable(table: TableDef): TrackedEntity[];
1774
+ findTracked(entity: any): TrackedEntity | undefined;
1775
+ setEntity(table: TableDef, pk: string | number, entity: any): void;
1776
+ trackNew(table: TableDef, entity: any, pk?: string | number): void;
1777
+ trackManaged(table: TableDef, pk: string | number, entity: any): void;
1778
+ markDirty(entity: any): void;
1779
+ markRemoved(entity: any): void;
1780
+ flush(): Promise<void>;
1781
+ reset(): void;
1782
+ private flushInsert;
1783
+ private flushUpdate;
1784
+ private flushDelete;
1785
+ private runHook;
1786
+ private computeChanges;
1787
+ private extractColumns;
1788
+ private executeCompiled;
1789
+ private getReturningColumns;
1790
+ private applyReturningResults;
1791
+ private normalizeColumnName;
1792
+ private registerIdentity;
1793
+ private createSnapshot;
1794
+ private getPrimaryKeyValue;
1795
+ }
1796
+
1797
+ type EventOfType<E extends DomainEvent, TType extends E['type']> = Extract<E, {
1798
+ type: TType;
1799
+ }>;
1800
+ type DomainEventHandler<E extends DomainEvent, Context> = (event: E, ctx: Context) => Promise<void> | void;
1801
+ type InitialHandlers<E extends DomainEvent, Context> = {
1802
+ [K in E['type']]?: DomainEventHandler<EventOfType<E, K>, Context>[];
1803
+ };
1804
+ declare class DomainEventBus<E extends DomainEvent, Context> {
1805
+ private readonly handlers;
1806
+ constructor(initialHandlers?: InitialHandlers<E, Context>);
1807
+ on<TType extends E['type']>(type: TType, handler: DomainEventHandler<EventOfType<E, TType>, Context>): void;
1808
+ register<TType extends E['type']>(type: TType, handler: DomainEventHandler<EventOfType<E, TType>, Context>): void;
1809
+ dispatch(trackedEntities: Iterable<TrackedEntity>, ctx: Context): Promise<void>;
1810
+ }
1811
+ declare const addDomainEvent: <E extends DomainEvent>(entity: HasDomainEvents<E>, event: E) => void;
1812
+
1813
+ declare class RelationChangeProcessor {
1814
+ private readonly unitOfWork;
1815
+ private readonly dialect;
1816
+ private readonly executor;
1817
+ private readonly relationChanges;
1818
+ constructor(unitOfWork: UnitOfWork, dialect: Dialect, executor: DbExecutor);
1819
+ registerChange(entry: RelationChangeEntry): void;
1820
+ reset(): void;
1821
+ process(): Promise<void>;
1822
+ private handleHasManyChange;
1823
+ private handleHasOneChange;
1824
+ private handleBelongsToChange;
1825
+ private handleBelongsToManyChange;
1826
+ private assignHasManyForeignKey;
1827
+ private detachHasManyChild;
1828
+ private assignHasOneForeignKey;
1829
+ private detachHasOneChild;
1830
+ private insertPivotRow;
1831
+ private deletePivotRow;
1832
+ private resolvePrimaryKeyValue;
1833
+ }
1614
1834
 
1835
+ /**
1836
+ * Represents a single SQL query log entry
1837
+ */
1615
1838
  interface QueryLogEntry {
1839
+ /** The SQL query that was executed */
1616
1840
  sql: string;
1841
+ /** Parameters used in the query */
1617
1842
  params?: unknown[];
1618
1843
  }
1844
+ /**
1845
+ * Function type for query logging callbacks
1846
+ * @param entry - The query log entry to process
1847
+ */
1619
1848
  type QueryLogger = (entry: QueryLogEntry) => void;
1849
+ /**
1850
+ * Creates a wrapped database executor that logs all SQL queries
1851
+ * @param executor - Original database executor to wrap
1852
+ * @param logger - Optional logger function to receive query log entries
1853
+ * @returns Wrapped executor that logs queries before execution
1854
+ */
1855
+ declare const createQueryLoggingExecutor: (executor: DbExecutor, logger?: QueryLogger) => DbExecutor;
1620
1856
 
1621
- interface OrmInterceptor {
1622
- beforeFlush?(ctx: OrmContext): Promise<void> | void;
1623
- afterFlush?(ctx: OrmContext): Promise<void> | void;
1857
+ /**
1858
+ * Context for SQL query execution
1859
+ */
1860
+ interface ExecutionContext {
1861
+ /** Database dialect to use for SQL generation */
1862
+ dialect: Dialect;
1863
+ /** Database executor for running SQL queries */
1864
+ executor: DbExecutor;
1865
+ /** Interceptor pipeline for query processing */
1866
+ interceptors: InterceptorPipeline;
1624
1867
  }
1625
- type DomainEventHandler = DomainEventHandler$1<OrmContext>;
1626
- interface OrmContextOptions {
1868
+
1869
+ interface EntityContext {
1627
1870
  dialect: Dialect;
1628
1871
  executor: DbExecutor;
1629
- interceptors?: OrmInterceptor[];
1630
- domainEventHandlers?: Record<string, DomainEventHandler[]>;
1631
- queryLogger?: QueryLogger;
1872
+ getEntity(table: TableDef, pk: any): any;
1873
+ setEntity(table: TableDef, pk: any, entity: any): void;
1874
+ trackNew(table: TableDef, entity: any, pk?: any): void;
1875
+ trackManaged(table: TableDef, pk: any, entity: any): void;
1876
+ markDirty(entity: any): void;
1877
+ markRemoved(entity: any): void;
1878
+ getEntitiesForTable(table: TableDef): TrackedEntity[];
1879
+ registerRelationChange(root: any, relationKey: RelationKey, rootTable: TableDef, relationName: string, relation: RelationDef, change: RelationChange<any>): void;
1632
1880
  }
1633
- declare class OrmContext {
1634
- private readonly options;
1635
- private readonly identityMap;
1636
- private readonly executorWithLogging;
1637
- private readonly unitOfWork;
1638
- private readonly relationChanges;
1881
+
1882
+ interface HydrationContext<E extends DomainEvent = AnyDomainEvent> {
1883
+ identityMap: IdentityMap;
1884
+ unitOfWork: UnitOfWork;
1885
+ domainEvents: DomainEventBus<E, OrmSession<E>>;
1886
+ relationChanges: RelationChangeProcessor;
1887
+ entityContext: EntityContext;
1888
+ }
1889
+
1890
+ interface OrmInterceptor {
1891
+ beforeFlush?(ctx: EntityContext): Promise<void> | void;
1892
+ afterFlush?(ctx: EntityContext): Promise<void> | void;
1893
+ }
1894
+ interface OrmSessionOptions<E extends DomainEvent = OrmDomainEvent> {
1895
+ orm: Orm<E>;
1896
+ executor: DbExecutor;
1897
+ queryLogger?: QueryLogger;
1898
+ interceptors?: OrmInterceptor[];
1899
+ domainEventHandlers?: InitialHandlers<E, OrmSession<E>>;
1900
+ }
1901
+ declare class OrmSession<E extends DomainEvent = OrmDomainEvent> implements EntityContext {
1902
+ readonly orm: Orm<E>;
1903
+ readonly executor: DbExecutor;
1904
+ readonly identityMap: IdentityMap;
1905
+ readonly unitOfWork: UnitOfWork;
1906
+ readonly domainEvents: DomainEventBus<E, OrmSession<E>>;
1907
+ readonly relationChanges: RelationChangeProcessor;
1639
1908
  private readonly interceptors;
1640
- private readonly domainEvents;
1641
- constructor(options: OrmContextOptions);
1909
+ constructor(opts: OrmSessionOptions<E>);
1642
1910
  get dialect(): Dialect;
1643
- get executor(): DbExecutor;
1644
1911
  get identityBuckets(): Map<string, Map<string, TrackedEntity>>;
1645
1912
  get tracked(): TrackedEntity[];
1646
- getEntity(table: TableDef, pk: string | number): any | undefined;
1647
- setEntity(table: TableDef, pk: string | number, entity: any): void;
1648
- trackNew(table: TableDef, entity: any, pk?: string | number): void;
1649
- trackManaged(table: TableDef, pk: string | number, entity: any): void;
1913
+ getEntity(table: TableDef, pk: any): any | undefined;
1914
+ setEntity(table: TableDef, pk: any, entity: any): void;
1915
+ trackNew(table: TableDef, entity: any, pk?: any): void;
1916
+ trackManaged(table: TableDef, pk: any, entity: any): void;
1650
1917
  markDirty(entity: any): void;
1651
1918
  markRemoved(entity: any): void;
1652
- registerRelationChange(root: any, relationKey: RelationKey, rootTable: TableDef, relationName: string, relation: RelationDef, change: RelationChange<any>): void;
1653
- registerInterceptor(interceptor: OrmInterceptor): void;
1654
- registerDomainEventHandler(name: string, handler: DomainEventHandler): void;
1655
- saveChanges(): Promise<void>;
1919
+ registerRelationChange: (root: any, relationKey: RelationKey, rootTable: TableDef, relationName: string, relation: RelationDef, change: RelationChange<any>) => void;
1656
1920
  getEntitiesForTable(table: TableDef): TrackedEntity[];
1921
+ registerInterceptor(interceptor: OrmInterceptor): void;
1922
+ registerDomainEventHandler<TType extends E['type']>(type: TType, handler: DomainEventHandler<Extract<E, {
1923
+ type: TType;
1924
+ }>, OrmSession<E>>): void;
1925
+ find<TTable extends TableDef>(entityClass: EntityConstructor, id: any): Promise<Entity<TTable> | null>;
1926
+ findOne<TTable extends TableDef>(qb: SelectQueryBuilder<any, TTable>): Promise<Entity<TTable> | null>;
1927
+ findMany<TTable extends TableDef>(qb: SelectQueryBuilder<any, TTable>): Promise<Entity<TTable>[]>;
1928
+ persist(entity: object): Promise<void>;
1929
+ remove(entity: object): Promise<void>;
1930
+ flush(): Promise<void>;
1931
+ commit(): Promise<void>;
1932
+ rollback(): Promise<void>;
1933
+ getExecutionContext(): ExecutionContext;
1934
+ getHydrationContext(): HydrationContext<E>;
1657
1935
  }
1658
1936
 
1659
1937
  type SelectDialectInput = Dialect | DialectKey;
1660
1938
 
1939
+ type ColumnSelectionValue = ColumnDef | FunctionNode | CaseExpressionNode | WindowFunctionNode;
1940
+ type DeepSelectConfig<TTable extends TableDef> = {
1941
+ root?: (keyof TTable['columns'] & string)[];
1942
+ } & {
1943
+ [K in keyof TTable['relations'] & string]?: (keyof RelationTargetTable<TTable['relations'][K]>['columns'] & string)[];
1944
+ };
1661
1945
  /**
1946
+
1662
1947
  * Main query builder class for constructing SQL SELECT queries
1948
+
1663
1949
  * @typeParam T - Result type for projections (unused)
1950
+
1664
1951
  * @typeParam TTable - Table definition being queried
1952
+
1665
1953
  */
1666
1954
  declare class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
1667
1955
  private readonly env;
@@ -1670,11 +1958,17 @@ declare class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
1670
1958
  private readonly relationManager;
1671
1959
  private readonly lazyRelations;
1672
1960
  /**
1961
+
1673
1962
  * Creates a new SelectQueryBuilder instance
1963
+
1674
1964
  * @param table - Table definition to query
1965
+
1675
1966
  * @param state - Optional initial query state
1967
+
1676
1968
  * @param hydration - Optional hydration manager
1969
+
1677
1970
  * @param dependencies - Optional query builder dependencies
1971
+
1678
1972
  */
1679
1973
  constructor(table: TTable, state?: SelectQueryState, hydration?: HydrationManager, dependencies?: Partial<SelectQueryBuilderDependencies>, lazyRelations?: Set<string>);
1680
1974
  private clone;
@@ -1684,215 +1978,375 @@ declare class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
1684
1978
  private applyJoin;
1685
1979
  private applySetOperation;
1686
1980
  /**
1981
+
1687
1982
  * Selects specific columns for the query
1983
+
1688
1984
  * @param columns - Record of column definitions, function nodes, case expressions, or window functions
1985
+
1689
1986
  * @returns New query builder instance with selected columns
1987
+
1988
+ */
1989
+ select(columns: Record<string, ColumnSelectionValue>): SelectQueryBuilder<T, TTable>;
1990
+ /**
1991
+ * Selects columns from the root table by name (typed).
1992
+ * @param cols - Column names on the root table
1690
1993
  */
1691
- select(columns: Record<string, ColumnDef | FunctionNode | CaseExpressionNode | WindowFunctionNode>): SelectQueryBuilder<T, TTable>;
1994
+ selectColumns<K extends keyof TTable['columns'] & string>(...cols: K[]): SelectQueryBuilder<T, TTable>;
1692
1995
  /**
1996
+
1693
1997
  * Selects raw column expressions
1998
+
1694
1999
  * @param cols - Column expressions as strings
2000
+
1695
2001
  * @returns New query builder instance with raw column selections
2002
+
1696
2003
  */
1697
2004
  selectRaw(...cols: string[]): SelectQueryBuilder<T, TTable>;
1698
2005
  /**
2006
+
1699
2007
  * Adds a Common Table Expression (CTE) to the query
2008
+
1700
2009
  * @param name - Name of the CTE
2010
+
1701
2011
  * @param query - Query builder or query node for the CTE
2012
+
1702
2013
  * @param columns - Optional column names for the CTE
2014
+
1703
2015
  * @returns New query builder instance with the CTE
2016
+
1704
2017
  */
1705
2018
  with(name: string, query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode, columns?: string[]): SelectQueryBuilder<T, TTable>;
1706
2019
  /**
2020
+
1707
2021
  * Adds a recursive Common Table Expression (CTE) to the query
2022
+
1708
2023
  * @param name - Name of the CTE
2024
+
1709
2025
  * @param query - Query builder or query node for the CTE
2026
+
1710
2027
  * @param columns - Optional column names for the CTE
2028
+
1711
2029
  * @returns New query builder instance with the recursive CTE
2030
+
1712
2031
  */
1713
2032
  withRecursive(name: string, query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode, columns?: string[]): SelectQueryBuilder<T, TTable>;
1714
2033
  /**
2034
+
1715
2035
  * Selects a subquery as a column
2036
+
1716
2037
  * @param alias - Alias for the subquery column
2038
+
1717
2039
  * @param sub - Query builder or query node for the subquery
2040
+
1718
2041
  * @returns New query builder instance with the subquery selection
2042
+
1719
2043
  */
1720
2044
  selectSubquery(alias: string, sub: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
1721
2045
  /**
2046
+
1722
2047
  * Adds an INNER JOIN to the query
2048
+
1723
2049
  * @param table - Table to join
2050
+
1724
2051
  * @param condition - Join condition expression
2052
+
1725
2053
  * @returns New query builder instance with the INNER JOIN
2054
+
1726
2055
  */
1727
2056
  innerJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable>;
1728
2057
  /**
2058
+
1729
2059
  * Adds a LEFT JOIN to the query
2060
+
1730
2061
  * @param table - Table to join
2062
+
1731
2063
  * @param condition - Join condition expression
2064
+
1732
2065
  * @returns New query builder instance with the LEFT JOIN
2066
+
1733
2067
  */
1734
2068
  leftJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable>;
1735
2069
  /**
2070
+
1736
2071
  * Adds a RIGHT JOIN to the query
2072
+
1737
2073
  * @param table - Table to join
2074
+
1738
2075
  * @param condition - Join condition expression
2076
+
1739
2077
  * @returns New query builder instance with the RIGHT JOIN
2078
+
1740
2079
  */
1741
2080
  rightJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable>;
1742
2081
  /**
2082
+
1743
2083
  * Matches records based on a relationship
2084
+
1744
2085
  * @param relationName - Name of the relationship to match
2086
+
1745
2087
  * @param predicate - Optional predicate expression
2088
+
1746
2089
  * @returns New query builder instance with the relationship match
2090
+
1747
2091
  */
1748
2092
  match(relationName: string, predicate?: ExpressionNode): SelectQueryBuilder<T, TTable>;
1749
2093
  /**
2094
+
1750
2095
  * Joins a related table
2096
+
1751
2097
  * @param relationName - Name of the relationship to join
2098
+
1752
2099
  * @param joinKind - Type of join (defaults to INNER)
2100
+
1753
2101
  * @param extraCondition - Optional additional join condition
2102
+
1754
2103
  * @returns New query builder instance with the relationship join
2104
+
1755
2105
  */
1756
2106
  joinRelation(relationName: string, joinKind?: JoinKind, extraCondition?: ExpressionNode): SelectQueryBuilder<T, TTable>;
1757
2107
  /**
2108
+
1758
2109
  * Includes related data in the query results
2110
+
1759
2111
  * @param relationName - Name of the relationship to include
2112
+
1760
2113
  * @param options - Optional include options
2114
+
1761
2115
  * @returns New query builder instance with the relationship inclusion
2116
+
1762
2117
  */
1763
2118
  include(relationName: string, options?: RelationIncludeOptions): SelectQueryBuilder<T, TTable>;
1764
2119
  includeLazy<K extends keyof RelationMap<TTable>>(relationName: K): SelectQueryBuilder<T, TTable>;
2120
+ /**
2121
+ * Selects columns for a related table in a single hop.
2122
+ */
2123
+ selectRelationColumns<K extends keyof TTable['relations'] & string, TRel extends RelationDef = TTable['relations'][K], TTarget extends TableDef = RelationTargetTable<TRel>, C extends keyof TTarget['columns'] & string = keyof TTarget['columns'] & string>(relationName: K, ...cols: C[]): SelectQueryBuilder<T, TTable>;
2124
+ /**
2125
+ * Convenience alias for selecting specific columns from a relation.
2126
+ */
2127
+ includePick<K extends keyof TTable['relations'] & string, TRel extends RelationDef = TTable['relations'][K], TTarget extends TableDef = RelationTargetTable<TRel>, C extends keyof TTarget['columns'] & string = keyof TTarget['columns'] & string>(relationName: K, cols: C[]): SelectQueryBuilder<T, TTable>;
2128
+ /**
2129
+ * Selects columns for the root table and relations from a single config object.
2130
+ */
2131
+ selectColumnsDeep(config: DeepSelectConfig<TTable>): SelectQueryBuilder<T, TTable>;
1765
2132
  getLazyRelations(): (keyof RelationMap<TTable>)[];
1766
2133
  getTable(): TTable;
1767
- execute(ctx: OrmContext): Promise<Entity<TTable>[]>;
2134
+ execute(ctx: OrmSession): Promise<Entity<TTable>[]>;
2135
+ executeWithContexts(execCtx: ExecutionContext, hydCtx: HydrationContext): Promise<Entity<TTable>[]>;
1768
2136
  /**
2137
+
1769
2138
  * Adds a WHERE condition to the query
2139
+
1770
2140
  * @param expr - Expression for the WHERE clause
2141
+
1771
2142
  * @returns New query builder instance with the WHERE condition
2143
+
1772
2144
  */
1773
2145
  where(expr: ExpressionNode): SelectQueryBuilder<T, TTable>;
1774
2146
  /**
2147
+
1775
2148
  * Adds a GROUP BY clause to the query
2149
+
1776
2150
  * @param col - Column definition or column node to group by
2151
+
1777
2152
  * @returns New query builder instance with the GROUP BY clause
2153
+
1778
2154
  */
1779
2155
  groupBy(col: ColumnDef | ColumnNode): SelectQueryBuilder<T, TTable>;
1780
2156
  /**
2157
+
1781
2158
  * Adds a HAVING condition to the query
2159
+
1782
2160
  * @param expr - Expression for the HAVING clause
2161
+
1783
2162
  * @returns New query builder instance with the HAVING condition
2163
+
1784
2164
  */
1785
2165
  having(expr: ExpressionNode): SelectQueryBuilder<T, TTable>;
1786
2166
  /**
2167
+
1787
2168
  * Adds an ORDER BY clause to the query
2169
+
1788
2170
  * @param col - Column definition or column node to order by
2171
+
1789
2172
  * @param direction - Order direction (defaults to ASC)
2173
+
1790
2174
  * @returns New query builder instance with the ORDER BY clause
2175
+
1791
2176
  */
1792
2177
  orderBy(col: ColumnDef | ColumnNode, direction?: OrderDirection): SelectQueryBuilder<T, TTable>;
1793
2178
  /**
2179
+
1794
2180
  * Adds a DISTINCT clause to the query
2181
+
1795
2182
  * @param cols - Columns to make distinct
2183
+
1796
2184
  * @returns New query builder instance with the DISTINCT clause
2185
+
1797
2186
  */
1798
2187
  distinct(...cols: (ColumnDef | ColumnNode)[]): SelectQueryBuilder<T, TTable>;
1799
2188
  /**
2189
+
1800
2190
  * Adds a LIMIT clause to the query
2191
+
1801
2192
  * @param n - Maximum number of rows to return
2193
+
1802
2194
  * @returns New query builder instance with the LIMIT clause
2195
+
1803
2196
  */
1804
2197
  limit(n: number): SelectQueryBuilder<T, TTable>;
1805
2198
  /**
2199
+
1806
2200
  * Adds an OFFSET clause to the query
2201
+
1807
2202
  * @param n - Number of rows to skip
2203
+
1808
2204
  * @returns New query builder instance with the OFFSET clause
2205
+
1809
2206
  */
1810
2207
  offset(n: number): SelectQueryBuilder<T, TTable>;
1811
2208
  /**
2209
+
1812
2210
  * Combines this query with another using UNION
2211
+
1813
2212
  * @param query - Query to union with
2213
+
1814
2214
  * @returns New query builder instance with the set operation
2215
+
1815
2216
  */
1816
2217
  union(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
1817
2218
  /**
2219
+
1818
2220
  * Combines this query with another using UNION ALL
2221
+
1819
2222
  * @param query - Query to union with
2223
+
1820
2224
  * @returns New query builder instance with the set operation
2225
+
1821
2226
  */
1822
2227
  unionAll(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
1823
2228
  /**
2229
+
1824
2230
  * Combines this query with another using INTERSECT
2231
+
1825
2232
  * @param query - Query to intersect with
2233
+
1826
2234
  * @returns New query builder instance with the set operation
2235
+
1827
2236
  */
1828
2237
  intersect(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
1829
2238
  /**
2239
+
1830
2240
  * Combines this query with another using EXCEPT
2241
+
1831
2242
  * @param query - Query to subtract
2243
+
1832
2244
  * @returns New query builder instance with the set operation
2245
+
1833
2246
  */
1834
2247
  except(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
1835
2248
  /**
2249
+
1836
2250
  * Adds a WHERE EXISTS condition to the query
2251
+
1837
2252
  * @param subquery - Subquery to check for existence
2253
+
1838
2254
  * @returns New query builder instance with the WHERE EXISTS condition
2255
+
1839
2256
  */
1840
2257
  whereExists(subquery: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
1841
2258
  /**
2259
+
1842
2260
  * Adds a WHERE NOT EXISTS condition to the query
2261
+
1843
2262
  * @param subquery - Subquery to check for non-existence
2263
+
1844
2264
  * @returns New query builder instance with the WHERE NOT EXISTS condition
2265
+
1845
2266
  */
1846
2267
  whereNotExists(subquery: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
1847
2268
  /**
2269
+
1848
2270
  * Adds a WHERE EXISTS condition based on a relationship
2271
+
1849
2272
  * @param relationName - Name of the relationship to check
2273
+
1850
2274
  * @param callback - Optional callback to modify the relationship query
2275
+
1851
2276
  * @returns New query builder instance with the relationship existence check
2277
+
1852
2278
  */
1853
2279
  whereHas(relationName: string, callback?: <TChildTable extends TableDef>(qb: SelectQueryBuilder<any, TChildTable>) => SelectQueryBuilder<any, TChildTable>): SelectQueryBuilder<T, TTable>;
1854
2280
  /**
2281
+
1855
2282
  * Adds a WHERE NOT EXISTS condition based on a relationship
2283
+
1856
2284
  * @param relationName - Name of the relationship to check
2285
+
1857
2286
  * @param callback - Optional callback to modify the relationship query
2287
+
1858
2288
  * @returns New query builder instance with the relationship non-existence check
2289
+
1859
2290
  */
1860
2291
  whereHasNot(relationName: string, callback?: <TChildTable extends TableDef>(qb: SelectQueryBuilder<any, TChildTable>) => SelectQueryBuilder<any, TChildTable>): SelectQueryBuilder<T, TTable>;
1861
2292
  /**
2293
+
1862
2294
  * Compiles the query to SQL for a specific dialect
2295
+
1863
2296
  * @param dialect - Database dialect to compile for
2297
+
1864
2298
  * @returns Compiled query with SQL and parameters
2299
+
1865
2300
  */
1866
2301
  compile(dialect: SelectDialectInput): CompiledQuery;
1867
2302
  /**
2303
+
1868
2304
  * Converts the query to SQL string for a specific dialect
2305
+
1869
2306
  * @param dialect - Database dialect to generate SQL for
2307
+
1870
2308
  * @returns SQL string representation of the query
2309
+
1871
2310
  */
1872
2311
  toSql(dialect: SelectDialectInput): string;
1873
2312
  /**
2313
+
1874
2314
  * Gets the hydration plan for the query
2315
+
1875
2316
  * @returns Hydration plan or undefined if none exists
2317
+
1876
2318
  */
1877
2319
  getHydrationPlan(): HydrationPlan | undefined;
1878
2320
  /**
2321
+
1879
2322
  * Gets the Abstract Syntax Tree (AST) representation of the query
2323
+
1880
2324
  * @returns Query AST with hydration applied
2325
+
1881
2326
  */
1882
2327
  getAST(): SelectQueryNode;
1883
2328
  }
1884
2329
  /**
2330
+
1885
2331
  * Creates a column node for use in expressions
2332
+
1886
2333
  * @param table - Table name
2334
+
1887
2335
  * @param name - Column name
2336
+
1888
2337
  * @returns ColumnNode with the specified table and name
2338
+
1889
2339
  */
1890
2340
  declare const createColumn: (table: string, name: string) => ColumnNode;
1891
2341
  /**
2342
+
1892
2343
  * Creates a literal value node for use in expressions
2344
+
1893
2345
  * @param val - Literal value (string or number)
2346
+
1894
2347
  * @returns LiteralNode with the specified value
2348
+
1895
2349
  */
1896
2350
  declare const createLiteral: (val: string | number) => LiteralNode;
1897
2351
 
1898
- export { type RawDefaultValue as $, type BelongsToManyRelation as A, type BinaryExpressionNode as B, type ColumnRef as C, Dialect as D, type ExpressionNode as E, type FunctionNode as F, type HasManyCollection as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type BelongsToReference as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, SelectQueryBuilder as P, type CheckConstraint as Q, type RelationMap as R, type SelectQueryNode as S, type TableRef as T, type UpdateQueryNode as U, type TableOptions as V, type WindowFunctionNode as W, type TableHooks as X, defineTable as Y, type ColumnType as Z, type ReferentialAction as _, type ColumnNode as a, type DefaultValue as a0, col as a1, RelationKinds as a2, type RelationType as a3, type CascadeMode as a4, type RelationDef as a5, hasMany as a6, hasOne as a7, belongsTo as a8, belongsToMany as a9, createExecutorFromQueryRunner as aA, type ColumnToTs as aa, type InferRow as ab, type HasOneReference as ac, createColumn as ad, createLiteral as ae, isOperandNode as af, isFunctionNode as ag, isCaseExpressionNode as ah, isWindowFunctionNode as ai, isExpressionSelectionNode as aj, type HydrationPivotPlan as ak, type HydrationRelationPlan as al, type HydrationMetadata as am, addDomainEvent as an, EntityStatus as ao, type QueryResult as ap, type RelationKey as aq, type RelationChange as ar, type HasDomainEvents as as, type OrmInterceptor as at, type DomainEventHandler as au, type OrmContextOptions as av, type QueryLogEntry as aw, type QueryLogger as ax, rowsToQueryResult as ay, type SimpleQueryRunner as az, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type ColumnDef as h, type TableDef as i, type InsertQueryNode as j, type InsertCompiler as k, type CompiledQuery as l, type DialectKey as m, type UpdateCompiler as n, type DeleteQueryNode as o, type DeleteCompiler as p, type CompilerContext as q, type ForeignKeyReference as r, type IndexColumn as s, type IndexDef as t, type DbExecutor as u, OrmContext as v, type Entity as w, type HasManyRelation as x, type HasOneRelation as y, type BelongsToRelation as z };
2352
+ export { type TableHooks as $, type BelongsToRelation as A, type BinaryExpressionNode as B, type ColumnRef as C, Dialect as D, type ExpressionNode as E, type FunctionNode as F, type BelongsToManyRelation as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type HasManyCollection as K, type LiteralNode as L, type BelongsToReference as M, type NullExpressionNode as N, type OperandNode as O, type ManyToManyCollection as P, OrmSession as Q, type RelationMap as R, type SelectQueryNode as S, type TableRef as T, type UpdateQueryNode as U, SelectQueryBuilder as V, type WindowFunctionNode as W, type ExecutionContext as X, type HydrationContext as Y, type CheckConstraint as Z, type TableOptions as _, type ColumnNode as a, defineTable as a0, type ColumnType as a1, type ReferentialAction as a2, type RawDefaultValue as a3, type DefaultValue as a4, col as a5, RelationKinds as a6, type RelationType as a7, type CascadeMode as a8, type RelationDef as a9, DomainEventBus as aA, addDomainEvent as aB, EntityStatus as aC, type TrackedEntity as aD, type RelationKey as aE, type RelationChange as aF, type RelationChangeEntry as aG, type DomainEvent as aH, type AnyDomainEvent as aI, type OrmDomainEvent as aJ, type HasDomainEvents as aK, type QueryLogEntry as aL, type QueryLogger as aM, createQueryLoggingExecutor as aN, type QueryResult as aO, rowsToQueryResult as aP, type SimpleQueryRunner as aQ, createExecutorFromQueryRunner as aR, type EntityOrTableTargetResolver as aS, type EntityConstructor as aT, hasMany as aa, hasOne as ab, belongsTo as ac, belongsToMany as ad, type RelationTargetTable as ae, type ColumnToTs as af, type InferRow as ag, type HasOneReference as ah, createColumn as ai, createLiteral as aj, isOperandNode as ak, isFunctionNode as al, isCaseExpressionNode as am, isWindowFunctionNode as an, isExpressionSelectionNode as ao, type HydrationPivotPlan as ap, type HydrationRelationPlan as aq, type HydrationMetadata as ar, type OrmInterceptor as as, type OrmSessionOptions as at, type OrmOptions as au, type DbExecutorFactory as av, type ExternalTransaction as aw, Orm as ax, type DomainEventHandler as ay, type InitialHandlers as az, type LogicalExpressionNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type ColumnDef as h, type TableDef as i, type InsertQueryNode as j, type InsertCompiler as k, type CompiledQuery as l, type DialectKey as m, type UpdateCompiler as n, type DeleteQueryNode as o, type DeleteCompiler as p, type CompilerContext as q, type ForeignKeyReference as r, type IndexColumn as s, type IndexDef as t, type DbExecutor as u, type NamingStrategy as v, type EntityContext as w, type Entity as x, type HasManyRelation as y, type HasOneRelation as z };