metal-orm 1.0.57 → 1.0.59

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 (46) hide show
  1. package/README.md +23 -13
  2. package/dist/index.cjs +1750 -733
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +244 -157
  5. package/dist/index.d.ts +244 -157
  6. package/dist/index.js +1745 -733
  7. package/dist/index.js.map +1 -1
  8. package/package.json +69 -69
  9. package/src/core/ddl/schema-generator.ts +44 -1
  10. package/src/decorators/bootstrap.ts +186 -113
  11. package/src/decorators/column-decorator.ts +8 -49
  12. package/src/decorators/decorator-metadata.ts +10 -46
  13. package/src/decorators/entity.ts +30 -40
  14. package/src/decorators/relations.ts +30 -56
  15. package/src/orm/entity-hydration.ts +72 -0
  16. package/src/orm/entity-meta.ts +18 -13
  17. package/src/orm/entity-metadata.ts +240 -238
  18. package/src/orm/entity-relation-cache.ts +39 -0
  19. package/src/orm/entity-relations.ts +207 -0
  20. package/src/orm/entity.ts +124 -343
  21. package/src/orm/execute.ts +87 -20
  22. package/src/orm/lazy-batch/belongs-to-many.ts +134 -0
  23. package/src/orm/lazy-batch/belongs-to.ts +108 -0
  24. package/src/orm/lazy-batch/has-many.ts +69 -0
  25. package/src/orm/lazy-batch/has-one.ts +68 -0
  26. package/src/orm/lazy-batch/shared.ts +125 -0
  27. package/src/orm/lazy-batch.ts +4 -309
  28. package/src/orm/relations/belongs-to.ts +2 -2
  29. package/src/orm/relations/has-many.ts +23 -9
  30. package/src/orm/relations/has-one.ts +2 -2
  31. package/src/orm/relations/many-to-many.ts +29 -14
  32. package/src/orm/save-graph-types.ts +2 -2
  33. package/src/orm/save-graph.ts +18 -18
  34. package/src/query-builder/relation-conditions.ts +80 -59
  35. package/src/query-builder/relation-cte-builder.ts +63 -0
  36. package/src/query-builder/relation-filter-utils.ts +159 -0
  37. package/src/query-builder/relation-include-strategies.ts +177 -0
  38. package/src/query-builder/relation-join-planner.ts +80 -0
  39. package/src/query-builder/relation-service.ts +103 -159
  40. package/src/query-builder/relation-types.ts +43 -12
  41. package/src/query-builder/select/projection-facet.ts +23 -23
  42. package/src/query-builder/select/select-operations.ts +145 -0
  43. package/src/query-builder/select.ts +373 -426
  44. package/src/schema/relation.ts +22 -18
  45. package/src/schema/table.ts +22 -9
  46. package/src/schema/types.ts +103 -84
package/dist/index.d.ts CHANGED
@@ -251,10 +251,10 @@ interface BelongsToRelation<TTarget extends TableDef = TableDef> {
251
251
  /**
252
252
  * Many-to-many relationship definition with rich pivot metadata
253
253
  */
254
- interface BelongsToManyRelation<TTarget extends TableDef = TableDef> {
254
+ interface BelongsToManyRelation<TTarget extends TableDef = TableDef, TPivot extends TableDef = TableDef> {
255
255
  type: typeof RelationKinds.BelongsToMany;
256
256
  target: TTarget;
257
- pivotTable: TableDef;
257
+ pivotTable: TPivot;
258
258
  pivotForeignKeyToRoot: string;
259
259
  pivotForeignKeyToTarget: string;
260
260
  localKey?: string;
@@ -308,7 +308,7 @@ declare const belongsTo: <TTarget extends TableDef>(target: TTarget, foreignKey:
308
308
  * @param options - Pivot metadata configuration
309
309
  * @returns BelongsToManyRelation definition
310
310
  */
311
- declare const belongsToMany: <TTarget extends TableDef>(target: TTarget, pivotTable: TableDef, options: {
311
+ declare const belongsToMany: <TTarget extends TableDef, TPivot extends TableDef = TableDef>(target: TTarget, pivotTable: TPivot, options: {
312
312
  pivotForeignKeyToRoot: string;
313
313
  pivotForeignKeyToTarget: string;
314
314
  localKey?: string;
@@ -316,7 +316,7 @@ declare const belongsToMany: <TTarget extends TableDef>(target: TTarget, pivotTa
316
316
  pivotPrimaryKey?: string;
317
317
  defaultPivotColumns?: string[];
318
318
  cascade?: CascadeMode;
319
- }) => BelongsToManyRelation<TTarget>;
319
+ }) => BelongsToManyRelation<TTarget, TPivot>;
320
320
 
321
321
  interface IndexColumn {
322
322
  column: string;
@@ -397,6 +397,12 @@ interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDe
397
397
  * ```
398
398
  */
399
399
  declare const defineTable: <T extends Record<string, ColumnDef>>(name: string, columns: T, relations?: Record<string, RelationDef>, hooks?: TableHooks, options?: TableOptions) => TableDef<T>;
400
+ /**
401
+ * Assigns relations to a table definition while preserving literal typing.
402
+ */
403
+ declare function setRelations<TTable extends TableDef, TRelations extends Record<string, RelationDef>>(table: TTable, relations: TRelations): asserts table is TTable & {
404
+ relations: TRelations;
405
+ };
400
406
  type DirectColumnKeys<T extends TableDef> = Exclude<keyof T["columns"] & string, keyof T | "$">;
401
407
  type TableRef$1<T extends TableDef> = T & {
402
408
  [K in DirectColumnKeys<T>]: T["columns"][K];
@@ -438,7 +444,7 @@ declare function getColumn<T extends TableDef>(table: T, key: string): ColumnDef
438
444
  /**
439
445
  * Resolves a relation definition to its target table type.
440
446
  */
441
- 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;
447
+ 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, TableDef> ? TTarget : never;
442
448
  type NormalizedColumnType<T extends ColumnDef> = Lowercase<T['type'] & string>;
443
449
  /**
444
450
  * Maps a ColumnDef to its TypeScript type representation
@@ -452,8 +458,8 @@ type ColumnToTs<T extends ColumnDef> = [
452
458
  type InferRow<TTable extends TableDef> = {
453
459
  [K in keyof TTable['columns']]: ColumnToTs<TTable['columns'][K]>;
454
460
  };
455
- type RelationResult$1<T extends RelationDef> = T extends HasManyRelation<infer TTarget> ? InferRow<TTarget>[] : T extends HasOneRelation<infer TTarget> ? InferRow<TTarget> | null : T extends BelongsToRelation<infer TTarget> ? InferRow<TTarget> | null : T extends BelongsToManyRelation<infer TTarget> ? (InferRow<TTarget> & {
456
- _pivot?: unknown;
461
+ type RelationResult$1<T extends RelationDef> = T extends HasManyRelation<infer TTarget> ? InferRow<TTarget>[] : T extends HasOneRelation<infer TTarget> ? InferRow<TTarget> | null : T extends BelongsToRelation<infer TTarget> ? InferRow<TTarget> | null : T extends BelongsToManyRelation<infer TTarget, TableDef> ? (InferRow<TTarget> & {
462
+ _pivot?: Record<string, unknown>;
457
463
  })[] : never;
458
464
  /**
459
465
  * Maps relation names to the expected row results
@@ -461,7 +467,14 @@ type RelationResult$1<T extends RelationDef> = T extends HasManyRelation<infer T
461
467
  type RelationMap<TTable extends TableDef> = {
462
468
  [K in keyof TTable['relations']]: RelationResult$1<TTable['relations'][K]>;
463
469
  };
470
+ type RelationWrapper$1<TRel extends RelationDef> = TRel extends HasManyRelation<infer TTarget> ? HasManyCollection<EntityInstance<TTarget>> & ReadonlyArray<EntityInstance<TTarget>> : TRel extends HasOneRelation<infer TTarget> ? HasOneReference<EntityInstance<TTarget>> : TRel extends BelongsToManyRelation<infer TTarget> ? ManyToManyCollection<EntityInstance<TTarget> & {
471
+ _pivot?: Record<string, unknown>;
472
+ }> & ReadonlyArray<EntityInstance<TTarget> & {
473
+ _pivot?: Record<string, unknown>;
474
+ }> : TRel extends BelongsToRelation<infer TTarget> ? BelongsToReference<EntityInstance<TTarget>> : never;
464
475
  interface HasManyCollection<TChild> {
476
+ length: number;
477
+ [Symbol.iterator](): Iterator<TChild>;
465
478
  load(): Promise<TChild[]>;
466
479
  getItems(): TChild[];
467
480
  add(data: Partial<TChild>): TChild;
@@ -469,28 +482,39 @@ interface HasManyCollection<TChild> {
469
482
  remove(entity: TChild): void;
470
483
  clear(): void;
471
484
  }
472
- interface BelongsToReference<TParent> {
485
+ interface BelongsToReferenceApi<TParent extends object = object> {
473
486
  load(): Promise<TParent | null>;
474
487
  get(): TParent | null;
475
488
  set(data: Partial<TParent> | TParent | null): TParent | null;
476
489
  }
477
- interface HasOneReference<TChild> {
490
+ type BelongsToReference<TParent extends object = object> = BelongsToReferenceApi<TParent> & Partial<TParent>;
491
+ interface HasOneReferenceApi<TChild extends object = object> {
478
492
  load(): Promise<TChild | null>;
479
493
  get(): TChild | null;
480
494
  set(data: Partial<TChild> | TChild | null): TChild | null;
481
495
  }
482
- interface ManyToManyCollection<TTarget> {
496
+ type HasOneReference<TChild extends object = object> = HasOneReferenceApi<TChild> & Partial<TChild>;
497
+ interface ManyToManyCollection<TTarget, TPivot extends object | undefined = undefined> {
498
+ length: number;
499
+ [Symbol.iterator](): Iterator<TTarget>;
483
500
  load(): Promise<TTarget[]>;
484
501
  getItems(): TTarget[];
485
502
  attach(target: TTarget | number | string): void;
486
503
  detach(target: TTarget | number | string): void;
487
504
  syncByIds(ids: (number | string)[]): Promise<void>;
505
+ /** @internal Type-level marker for the related pivot entity */
506
+ readonly __pivotType?: TPivot;
488
507
  }
489
508
  type EntityInstance<TTable extends TableDef, TRow = InferRow<TTable>> = TRow & {
490
- [K in keyof RelationMap<TTable>]: TTable['relations'][K] extends HasManyRelation<infer TTarget> ? HasManyCollection<EntityInstance<TTarget>> : TTable['relations'][K] extends HasOneRelation<infer TTarget> ? HasOneReference<EntityInstance<TTarget>> : TTable['relations'][K] extends BelongsToManyRelation<infer TTarget> ? ManyToManyCollection<EntityInstance<TTarget>> : TTable['relations'][K] extends BelongsToRelation<infer TTarget> ? BelongsToReference<EntityInstance<TTarget>> : never;
509
+ [K in keyof RelationMap<TTable>]: RelationWrapper$1<TTable['relations'][K]>;
491
510
  } & {
492
511
  $load<K extends keyof RelationMap<TTable>>(relation: K): Promise<RelationMap<TTable>[K]>;
493
512
  };
513
+ type Primitive = string | number | boolean | Date | bigint | Buffer | null | undefined;
514
+ type IsAny<T> = 0 extends (1 & T) ? true : false;
515
+ type SelectableKeys<T> = {
516
+ [K in keyof T]-?: IsAny<T[K]> extends true ? never : NonNullable<T[K]> extends Primitive ? K : never;
517
+ }[keyof T];
494
518
 
495
519
  /**
496
520
  * SQL operators used in query conditions
@@ -2136,15 +2160,30 @@ type RelationIncludeJoinKind = typeof JOIN_KINDS.LEFT | typeof JOIN_KINDS.INNER;
2136
2160
  * Options for including a relation in a query
2137
2161
  */
2138
2162
  interface RelationIncludeOptions {
2139
- columns?: string[];
2163
+ columns?: readonly string[];
2140
2164
  aliasPrefix?: string;
2141
2165
  filter?: ExpressionNode;
2142
2166
  joinKind?: RelationIncludeJoinKind;
2143
2167
  pivot?: {
2144
- columns?: string[];
2168
+ columns?: readonly string[];
2145
2169
  aliasPrefix?: string;
2146
2170
  };
2147
2171
  }
2172
+ type ColumnKeys$1<T> = T extends {
2173
+ columns: infer Columns;
2174
+ } ? keyof Columns & string : string;
2175
+ type PivotColumnKeys<TPivot> = ColumnKeys$1<TPivot> extends never ? string : ColumnKeys$1<TPivot>;
2176
+ type RelationTargetColumns<TRel extends RelationDef> = ColumnKeys$1<RelationTargetTable<TRel>>;
2177
+ type BelongsToManyPivotColumns<TRel extends RelationDef> = TRel extends BelongsToManyRelation<TableDef, infer TPivot> ? PivotColumnKeys<TPivot> : never;
2178
+ type TypedRelationIncludeOptions<TRel extends RelationDef> = TRel extends BelongsToManyRelation ? Omit<RelationIncludeOptions, 'columns' | 'pivot'> & {
2179
+ columns?: readonly RelationTargetColumns<TRel>[];
2180
+ pivot?: {
2181
+ columns?: readonly BelongsToManyPivotColumns<TRel>[];
2182
+ aliasPrefix?: string;
2183
+ };
2184
+ } : Omit<RelationIncludeOptions, 'columns' | 'pivot'> & {
2185
+ columns?: readonly RelationTargetColumns<TRel>[];
2186
+ };
2148
2187
 
2149
2188
  /**
2150
2189
  * Service for handling relation operations (joins, includes, etc.)
@@ -2155,6 +2194,8 @@ declare class RelationService {
2155
2194
  private readonly hydration;
2156
2195
  private readonly createQueryAstService;
2157
2196
  private readonly projectionHelper;
2197
+ private readonly joinPlanner;
2198
+ private readonly cteBuilder;
2158
2199
  /**
2159
2200
  * Creates a new RelationService instance
2160
2201
  * @param table - Table definition
@@ -2169,7 +2210,7 @@ declare class RelationService {
2169
2210
  * @param extraCondition - Additional join condition
2170
2211
  * @returns Relation result with updated state and hydration
2171
2212
  */
2172
- joinRelation(relationName: string, joinKind: JoinKind, extraCondition?: ExpressionNode): RelationResult;
2213
+ joinRelation(relationName: string, joinKind: JoinKind, extraCondition?: ExpressionNode, tableSource?: TableSourceNode): RelationResult;
2173
2214
  /**
2174
2215
  * Matches records based on a relation with an optional predicate
2175
2216
  * @param relationName - Name of the relation to match
@@ -2191,15 +2232,6 @@ declare class RelationService {
2191
2232
  * @returns Modified query AST with relation correlation
2192
2233
  */
2193
2234
  applyRelationCorrelation(relationName: string, ast: SelectQueryNode, additionalCorrelation?: ExpressionNode): SelectQueryNode;
2194
- /**
2195
- * Creates a join node for a relation
2196
- * @param state - Current query state
2197
- * @param relationName - Name of the relation
2198
- * @param joinKind - Type of join to use
2199
- * @param extraCondition - Additional join condition
2200
- * @returns Updated query state with join
2201
- */
2202
- private withJoin;
2203
2235
  /**
2204
2236
  * Selects columns for a relation
2205
2237
  * @param state - Current query state
@@ -2208,6 +2240,7 @@ declare class RelationService {
2208
2240
  * @returns Relation result with updated state and hydration
2209
2241
  */
2210
2242
  private selectColumns;
2243
+ private combineWithAnd;
2211
2244
  /**
2212
2245
  * Gets a relation definition by name
2213
2246
  * @param relationName - Name of the relation
@@ -2447,8 +2480,9 @@ type EntityConstructor<T = object> = new (...args: never[]) => T;
2447
2480
  type EntityOrTableTarget = EntityConstructor | TableDef;
2448
2481
  /**
2449
2482
  * Resolver for entity or table target, can be direct or function.
2483
+ * @typeParam T - Specific target type that should be resolved
2450
2484
  */
2451
- type EntityOrTableTargetResolver = EntityOrTableTarget | (() => EntityOrTableTarget);
2485
+ type EntityOrTableTargetResolver<T extends EntityOrTableTarget = EntityOrTableTarget> = T | (() => T);
2452
2486
  /**
2453
2487
  * Simplified column definition structure used during metadata registration.
2454
2488
  * @template T - Concrete column definition type being extended
@@ -2472,7 +2506,7 @@ interface HasManyRelationMetadata extends BaseRelationMetadata {
2472
2506
  /** The relation kind */
2473
2507
  kind: typeof RelationKinds.HasMany;
2474
2508
  /** The foreign key */
2475
- foreignKey: string;
2509
+ foreignKey?: string;
2476
2510
  /** Optional local key */
2477
2511
  localKey?: string;
2478
2512
  }
@@ -2483,7 +2517,7 @@ interface HasOneRelationMetadata extends BaseRelationMetadata {
2483
2517
  /** The relation kind */
2484
2518
  kind: typeof RelationKinds.HasOne;
2485
2519
  /** The foreign key */
2486
- foreignKey: string;
2520
+ foreignKey?: string;
2487
2521
  /** Optional local key */
2488
2522
  localKey?: string;
2489
2523
  }
@@ -2507,9 +2541,9 @@ interface BelongsToManyRelationMetadata extends BaseRelationMetadata {
2507
2541
  /** The pivot table */
2508
2542
  pivotTable: EntityOrTableTargetResolver;
2509
2543
  /** The pivot foreign key to root */
2510
- pivotForeignKeyToRoot: string;
2544
+ pivotForeignKeyToRoot?: string;
2511
2545
  /** The pivot foreign key to target */
2512
- pivotForeignKeyToTarget: string;
2546
+ pivotForeignKeyToTarget?: string;
2513
2547
  /** Optional local key */
2514
2548
  localKey?: string;
2515
2549
  /** Optional target key */
@@ -2557,7 +2591,7 @@ interface TrackedEntity {
2557
2591
  /**
2558
2592
  * Type representing a key for relation navigation
2559
2593
  */
2560
- type RelationKey = string;
2594
+ type RelationKey$1 = string;
2561
2595
  /**
2562
2596
  * Represents a change operation on a relation
2563
2597
  * @typeParam T - Type of the related entity
@@ -2582,7 +2616,7 @@ interface RelationChangeEntry {
2582
2616
  /** Root entity that owns the relation */
2583
2617
  root: unknown;
2584
2618
  /** Key of the relation being changed */
2585
- relationKey: RelationKey;
2619
+ relationKey: RelationKey$1;
2586
2620
  /** Table definition of the root entity */
2587
2621
  rootTable: TableDef;
2588
2622
  /** Name of the relation */
@@ -3170,7 +3204,7 @@ interface EntityContext {
3170
3204
  * @param relation - The relation definition
3171
3205
  * @param change - The relation change
3172
3206
  */
3173
- registerRelationChange(root: unknown, relationKey: RelationKey, rootTable: TableDef, relationName: string, relation: RelationDef, change: RelationChange<unknown>): void;
3207
+ registerRelationChange(root: unknown, relationKey: RelationKey$1, rootTable: TableDef, relationName: string, relation: RelationDef, change: RelationChange<unknown>): void;
3174
3208
  }
3175
3209
 
3176
3210
  /**
@@ -3207,14 +3241,14 @@ interface SaveGraphOptions {
3207
3241
 
3208
3242
  type AnyId = number | string;
3209
3243
  type AnyFn = (...args: unknown[]) => unknown;
3210
- type RelationWrapper = HasManyCollection<unknown> | HasOneReference<unknown> | BelongsToReference<unknown> | ManyToManyCollection<unknown>;
3244
+ type RelationWrapper = HasManyCollection<unknown> | HasOneReference | BelongsToReference | ManyToManyCollection<unknown>;
3211
3245
  type FunctionKeys<T> = {
3212
3246
  [K in keyof T & string]-?: T[K] extends AnyFn ? K : never;
3213
3247
  }[keyof T & string];
3214
- type RelationKeys<T> = {
3248
+ type RelationKeys$1<T> = {
3215
3249
  [K in keyof T & string]-?: NonNullable<T[K]> extends RelationWrapper ? K : never;
3216
3250
  }[keyof T & string];
3217
- type ColumnKeys<T> = Exclude<keyof T & string, FunctionKeys<T> | RelationKeys<T>>;
3251
+ type ColumnKeys<T> = Exclude<keyof T & string, FunctionKeys<T> | RelationKeys$1<T>>;
3218
3252
  type SaveGraphJsonScalar<T> = T extends Date ? string : T;
3219
3253
  /**
3220
3254
  * Input scalar type for `OrmSession.saveGraph` payloads.
@@ -3227,7 +3261,7 @@ type ColumnInput$1<TEntity> = {
3227
3261
  };
3228
3262
  type RelationInputValue<T> = T extends HasManyCollection<infer C> ? Array<SaveGraphInputPayload<C> | AnyId> : T extends HasOneReference<infer C> ? SaveGraphInputPayload<C> | AnyId | null : T extends BelongsToReference<infer P> ? SaveGraphInputPayload<P> | AnyId | null : T extends ManyToManyCollection<infer Tgt> ? Array<SaveGraphInputPayload<Tgt> | AnyId> : never;
3229
3263
  type RelationInput<TEntity> = {
3230
- [K in RelationKeys<TEntity>]?: RelationInputValue<NonNullable<TEntity[K]>>;
3264
+ [K in RelationKeys$1<TEntity>]?: RelationInputValue<NonNullable<TEntity[K]>>;
3231
3265
  };
3232
3266
  /**
3233
3267
  * Typed payload accepted by `OrmSession.saveGraph`:
@@ -3353,7 +3387,7 @@ declare class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Enti
3353
3387
  * @param relation - The relation definition
3354
3388
  * @param change - The relation change
3355
3389
  */
3356
- registerRelationChange: (root: unknown, relationKey: RelationKey, rootTable: TableDef, relationName: string, relation: RelationDef, change: RelationChange<unknown>) => void;
3390
+ registerRelationChange: (root: unknown, relationKey: RelationKey$1, rootTable: TableDef, relationName: string, relation: RelationDef, change: RelationChange<unknown>) => void;
3357
3391
  /**
3358
3392
  * Gets all tracked entities for a specific table.
3359
3393
  * @param table - The table definition
@@ -3453,6 +3487,11 @@ declare class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Enti
3453
3487
  getHydrationContext(): HydrationContext<E>;
3454
3488
  }
3455
3489
 
3490
+ type WhereHasOptions = {
3491
+ correlate?: ExpressionNode;
3492
+ };
3493
+ type RelationCallback = <TChildTable extends TableDef>(qb: SelectQueryBuilder<unknown, TChildTable>) => SelectQueryBuilder<unknown, TChildTable>;
3494
+
3456
3495
  type SelectDialectInput = Dialect | DialectKey;
3457
3496
 
3458
3497
  type ColumnSelectionValue = ColumnDef | FunctionNode | CaseExpressionNode | WindowFunctionNode;
@@ -3465,10 +3504,6 @@ type DeepSelectEntry<TTable extends TableDef> = {
3465
3504
  columns: string[];
3466
3505
  };
3467
3506
  type DeepSelectConfig<TTable extends TableDef> = DeepSelectEntry<TTable>[];
3468
- type WhereHasOptions = {
3469
- correlate?: ExpressionNode;
3470
- };
3471
- type RelationCallback = <TChildTable extends TableDef>(qb: SelectQueryBuilder<unknown, TChildTable>) => SelectQueryBuilder<unknown, TChildTable>;
3472
3507
  /**
3473
3508
  * Main query builder class for constructing SQL SELECT queries
3474
3509
  * @typeParam T - Result type for projections (unused)
@@ -3478,8 +3513,15 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3478
3513
  private readonly env;
3479
3514
  private readonly context;
3480
3515
  private readonly columnSelector;
3481
- private readonly relationManager;
3516
+ private readonly fromFacet;
3517
+ private readonly joinFacet;
3518
+ private readonly projectionFacet;
3519
+ private readonly predicateFacet;
3520
+ private readonly cteFacet;
3521
+ private readonly setOpFacet;
3522
+ private readonly relationFacet;
3482
3523
  private readonly lazyRelations;
3524
+ private readonly lazyRelationOptions;
3483
3525
  /**
3484
3526
  * Creates a new SelectQueryBuilder instance
3485
3527
  * @param table - Table definition to query
@@ -3487,7 +3529,7 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3487
3529
  * @param hydration - Optional hydration manager
3488
3530
  * @param dependencies - Optional query builder dependencies
3489
3531
  */
3490
- constructor(table: TTable, state?: SelectQueryState, hydration?: HydrationManager, dependencies?: Partial<SelectQueryBuilderDependencies>, lazyRelations?: Set<string>);
3532
+ constructor(table: TTable, state?: SelectQueryState, hydration?: HydrationManager, dependencies?: Partial<SelectQueryBuilderDependencies>, lazyRelations?: Set<string>, lazyRelationOptions?: Map<string, RelationIncludeOptions>);
3491
3533
  /**
3492
3534
  * Creates a new SelectQueryBuilder instance with updated context and lazy relations
3493
3535
  * @param context - Updated query context
@@ -3513,22 +3555,6 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3513
3555
  * @returns New SelectQueryBuilder instance for the child table
3514
3556
  */
3515
3557
  private createChildBuilder;
3516
- /**
3517
- * Applies an AST mutation using the query AST service
3518
- * @param context - Current query context
3519
- * @param mutator - Function that mutates the AST
3520
- * @returns Updated query context
3521
- */
3522
- private applyAst;
3523
- /**
3524
- * Applies a join to the query context
3525
- * @param context - Current query context
3526
- * @param table - Table to join
3527
- * @param condition - Join condition
3528
- * @param kind - Join kind
3529
- * @returns Updated query context with join applied
3530
- */
3531
- private applyJoin;
3532
3558
  /**
3533
3559
  * Applies a set operation to the query
3534
3560
  * @param operator - Set operation kind
@@ -3661,21 +3687,18 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3661
3687
  * @param options - Optional include options
3662
3688
  * @returns New query builder instance with the relationship inclusion
3663
3689
  */
3664
- include<K extends keyof TTable['relations'] & string>(relationName: K, options?: RelationIncludeOptions): SelectQueryBuilder<T, TTable>;
3690
+ include<K extends keyof TTable['relations'] & string>(relationName: K, options?: TypedRelationIncludeOptions<TTable['relations'][K]>): SelectQueryBuilder<T, TTable>;
3665
3691
  /**
3666
3692
  * Includes a relation lazily in the query results
3667
3693
  * @param relationName - Name of the relation to include lazily
3694
+ * @param options - Optional include options for lazy loading
3668
3695
  * @returns New query builder instance with lazy relation inclusion
3669
3696
  */
3670
- includeLazy<K extends keyof RelationMap<TTable>>(relationName: K): SelectQueryBuilder<T, TTable>;
3697
+ includeLazy<K extends keyof RelationMap<TTable>>(relationName: K, options?: TypedRelationIncludeOptions<TTable['relations'][K]>): SelectQueryBuilder<T, TTable>;
3671
3698
  /**
3672
- * Selects columns for a related table in a single hop.
3699
+ * Convenience alias for including only specific columns from a relation.
3673
3700
  */
3674
- 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>;
3675
- /**
3676
- * Convenience alias for selecting specific columns from a relation.
3677
- */
3678
- 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>;
3701
+ includePick<K extends keyof TTable['relations'] & string, C extends RelationTargetColumns<TTable['relations'][K]>>(relationName: K, cols: C[]): SelectQueryBuilder<T, TTable>;
3679
3702
  /**
3680
3703
  * Selects columns for the root table and relations from an array of entries
3681
3704
  * @param config - Configuration array for deep column selection
@@ -3687,6 +3710,11 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3687
3710
  * @returns Array of lazy relation names
3688
3711
  */
3689
3712
  getLazyRelations(): (keyof RelationMap<TTable>)[];
3713
+ /**
3714
+ * Gets lazy relation include options
3715
+ * @returns Map of relation names to include options
3716
+ */
3717
+ getLazyRelationOptions(): Map<string, RelationIncludeOptions>;
3690
3718
  /**
3691
3719
  * Gets the table definition for this query builder
3692
3720
  * @returns Table definition
@@ -3698,8 +3726,19 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3698
3726
  * @returns Promise of entity instances
3699
3727
  */
3700
3728
  execute(ctx: OrmSession): Promise<EntityInstance<TTable>[]>;
3701
- private withAst;
3729
+ /**
3730
+ * Executes a count query for the current builder without LIMIT/OFFSET clauses.
3731
+ *
3732
+ * @example
3733
+ * const total = await qb.count(session);
3734
+ */
3702
3735
  count(session: OrmSession): Promise<number>;
3736
+ /**
3737
+ * Executes the query and returns both the paged items and the total.
3738
+ *
3739
+ * @example
3740
+ * const { items, totalItems } = await qb.executePaged(session, { page: 1, pageSize: 20 });
3741
+ */
3703
3742
  executePaged(session: OrmSession, options: {
3704
3743
  page: number;
3705
3744
  pageSize: number;
@@ -3737,6 +3776,9 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3737
3776
  * @param term - Column definition or ordering term to order by
3738
3777
  * @param directionOrOptions - Order direction or options (defaults to ASC)
3739
3778
  * @returns New query builder instance with the ORDER BY clause
3779
+ *
3780
+ * @example
3781
+ * qb.orderBy(userTable.columns.createdAt, 'DESC');
3740
3782
  */
3741
3783
  orderBy(term: ColumnDef | OrderingTerm, directionOrOptions?: OrderDirection | {
3742
3784
  direction?: OrderDirection;
@@ -3802,6 +3844,9 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3802
3844
  * @param relationName - Name of the relationship to check
3803
3845
  * @param callback - Optional callback to modify the relationship query
3804
3846
  * @returns New query builder instance with the relationship existence check
3847
+ *
3848
+ * @example
3849
+ * qb.whereHas('posts', postQb => postQb.where(eq(postTable.columns.published, true)));
3805
3850
  */
3806
3851
  whereHas<K extends keyof TTable['relations'] & string>(relationName: K, callbackOrOptions?: RelationCallback | WhereHasOptions, maybeOptions?: WhereHasOptions): SelectQueryBuilder<T, TTable>;
3807
3852
  /**
@@ -3809,6 +3854,9 @@ declare class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef
3809
3854
  * @param relationName - Name of the relationship to check
3810
3855
  * @param callback - Optional callback to modify the relationship query
3811
3856
  * @returns New query builder instance with the relationship non-existence check
3857
+ *
3858
+ * @example
3859
+ * qb.whereHasNot('posts', postQb => postQb.where(eq(postTable.columns.published, true)));
3812
3860
  */
3813
3861
  whereHasNot<K extends keyof TTable['relations'] & string>(relationName: K, callbackOrOptions?: RelationCallback | WhereHasOptions, maybeOptions?: WhereHasOptions): SelectQueryBuilder<T, TTable>;
3814
3862
  /**
@@ -4549,6 +4597,26 @@ declare const generateCreateTableSql: (table: TableDef, dialect: SchemaDialect)
4549
4597
  * @returns The SQL statements.
4550
4598
  */
4551
4599
  declare const generateSchemaSql: (tables: TableDef[], dialect: SchemaDialect) => string[];
4600
+ /**
4601
+ * Convenience wrapper for generateSchemaSql with rest args.
4602
+ * @param dialect - The schema dialect used to render SQL.
4603
+ * @param tables - The table definitions to create.
4604
+ */
4605
+ declare const generateSchemaSqlFor: (dialect: SchemaDialect, ...tables: TableDef[]) => string[];
4606
+ /**
4607
+ * Generates and executes schema SQL for the provided tables.
4608
+ * @param executor - The database executor to run statements with.
4609
+ * @param tables - The table definitions to create.
4610
+ * @param dialect - The schema dialect used to render SQL.
4611
+ */
4612
+ declare const executeSchemaSql: (executor: DbExecutor, tables: TableDef[], dialect: SchemaDialect) => Promise<void>;
4613
+ /**
4614
+ * Convenience wrapper for executeSchemaSql with rest args.
4615
+ * @param executor - The database executor to run statements with.
4616
+ * @param dialect - The schema dialect used to render SQL.
4617
+ * @param tables - The table definitions to create.
4618
+ */
4619
+ declare const executeSchemaSqlFor: (executor: DbExecutor, dialect: SchemaDialect, ...tables: TableDef[]) => Promise<void>;
4552
4620
 
4553
4621
  /** The kind of schema change. */
4554
4622
  type SchemaChangeKind = 'createTable' | 'dropTable' | 'addColumn' | 'dropColumn' | 'alterColumn' | 'addIndex' | 'dropIndex';
@@ -5438,6 +5506,38 @@ declare class TypeScriptGenerator implements ExpressionVisitor<string>, OperandV
5438
5506
  private mapOp;
5439
5507
  }
5440
5508
 
5509
+ type RelationKey<TTable extends TableDef> = Extract<keyof RelationMap<TTable>, string>;
5510
+ /**
5511
+ * Metadata stored on entity instances for ORM internal use
5512
+ * @typeParam TTable - Table definition type
5513
+ */
5514
+ interface EntityMeta<TTable extends TableDef> {
5515
+ /** Entity context */
5516
+ ctx: EntityContext;
5517
+ /** Table definition */
5518
+ table: TTable;
5519
+ /** Relations that should be loaded lazily */
5520
+ lazyRelations: RelationKey<TTable>[];
5521
+ /** Include options for lazy relations */
5522
+ lazyRelationOptions: Map<string, RelationIncludeOptions>;
5523
+ /** Cache for relation promises */
5524
+ relationCache: Map<string, Promise<unknown>>;
5525
+ /** Hydration data for relations */
5526
+ relationHydration: Map<string, Map<string, unknown>>;
5527
+ /** Relation wrapper instances */
5528
+ relationWrappers: Map<string, unknown>;
5529
+ }
5530
+
5531
+ /**
5532
+ * Caches relation loader results across entities of the same type.
5533
+ * @template T - The cache type
5534
+ * @param meta - The entity metadata
5535
+ * @param relationName - The relation name
5536
+ * @param factory - The factory function to create the cache
5537
+ * @returns Promise with the cached relation data
5538
+ */
5539
+ declare const relationLoaderCache: <TTable extends TableDef, T extends Map<string, unknown>>(meta: EntityMeta<TTable>, relationName: string, factory: () => Promise<T>) => Promise<T>;
5540
+
5441
5541
  /**
5442
5542
  * Creates an entity proxy with lazy loading capabilities.
5443
5543
  * @template TTable - The table type
@@ -5448,7 +5548,7 @@ declare class TypeScriptGenerator implements ExpressionVisitor<string>, OperandV
5448
5548
  * @param lazyRelations - Optional lazy relations
5449
5549
  * @returns The entity instance
5450
5550
  */
5451
- declare const createEntityProxy: <TTable extends TableDef, TLazy extends keyof RelationMap<TTable> = keyof RelationMap<TTable>>(ctx: EntityContext, table: TTable, row: Record<string, unknown>, lazyRelations?: TLazy[]) => EntityInstance<TTable>;
5551
+ declare const createEntityProxy: <TTable extends TableDef, TLazy extends RelationKey<TTable> = RelationKey<TTable>>(ctx: EntityContext, table: TTable, row: Record<string, unknown>, lazyRelations?: TLazy[], lazyRelationOptions?: Map<string, RelationIncludeOptions>) => EntityInstance<TTable>;
5452
5552
  /**
5453
5553
  * Creates an entity instance from a database row.
5454
5554
  * @template TTable - The table type
@@ -5459,12 +5559,13 @@ declare const createEntityProxy: <TTable extends TableDef, TLazy extends keyof R
5459
5559
  * @param lazyRelations - Optional lazy relations
5460
5560
  * @returns The entity instance
5461
5561
  */
5462
- declare const createEntityFromRow: <TTable extends TableDef, TResult extends EntityInstance<TTable> = EntityInstance<TTable>>(ctx: EntityContext, table: TTable, row: Record<string, unknown>, lazyRelations?: (keyof RelationMap<TTable>)[]) => TResult;
5562
+ declare const createEntityFromRow: <TTable extends TableDef, TResult extends EntityInstance<TTable> = EntityInstance<TTable>>(ctx: EntityContext, table: TTable, row: Record<string, unknown>, lazyRelations?: RelationKey<TTable>[], lazyRelationOptions?: Map<string, RelationIncludeOptions>) => TResult;
5463
5563
 
5464
5564
  /**
5465
5565
  * An array of database rows, each represented as a record of string keys to unknown values.
5466
5566
  */
5467
5567
  type Rows$3 = Record<string, unknown>[];
5568
+
5468
5569
  /**
5469
5570
  * Loads related entities for a has-many relation in batch.
5470
5571
  * @param ctx - The entity context.
@@ -5473,7 +5574,8 @@ type Rows$3 = Record<string, unknown>[];
5473
5574
  * @param relation - The has-many relation definition.
5474
5575
  * @returns A promise resolving to a map of root keys to arrays of related rows.
5475
5576
  */
5476
- declare const loadHasManyRelation: (ctx: EntityContext, rootTable: TableDef, _relationName: string, relation: HasManyRelation) => Promise<Map<string, Rows$3>>;
5577
+ declare const loadHasManyRelation: (ctx: EntityContext, rootTable: TableDef, relationName: string, relation: HasManyRelation, options?: RelationIncludeOptions) => Promise<Map<string, Rows$3>>;
5578
+
5477
5579
  /**
5478
5580
  * Loads related entities for a has-one relation in batch.
5479
5581
  * @param ctx - The entity context.
@@ -5482,7 +5584,8 @@ declare const loadHasManyRelation: (ctx: EntityContext, rootTable: TableDef, _re
5482
5584
  * @param relation - The has-one relation definition.
5483
5585
  * @returns A promise resolving to a map of root keys to single related rows.
5484
5586
  */
5485
- declare const loadHasOneRelation: (ctx: EntityContext, rootTable: TableDef, _relationName: string, relation: HasOneRelation) => Promise<Map<string, Record<string, unknown>>>;
5587
+ declare const loadHasOneRelation: (ctx: EntityContext, rootTable: TableDef, relationName: string, relation: HasOneRelation, options?: RelationIncludeOptions) => Promise<Map<string, Record<string, unknown>>>;
5588
+
5486
5589
  /**
5487
5590
  * Loads related entities for a belongs-to relation in batch.
5488
5591
  * @param ctx - The entity context.
@@ -5491,7 +5594,8 @@ declare const loadHasOneRelation: (ctx: EntityContext, rootTable: TableDef, _rel
5491
5594
  * @param relation - The belongs-to relation definition.
5492
5595
  * @returns A promise resolving to a map of foreign keys to single related rows.
5493
5596
  */
5494
- declare const loadBelongsToRelation: (ctx: EntityContext, rootTable: TableDef, _relationName: string, relation: BelongsToRelation) => Promise<Map<string, Record<string, unknown>>>;
5597
+ declare const loadBelongsToRelation: (ctx: EntityContext, rootTable: TableDef, relationName: string, relation: BelongsToRelation, options?: RelationIncludeOptions) => Promise<Map<string, Record<string, unknown>>>;
5598
+
5495
5599
  /**
5496
5600
  * Loads related entities for a belongs-to-many relation in batch, including pivot data.
5497
5601
  * @param ctx - The entity context.
@@ -5500,26 +5604,7 @@ declare const loadBelongsToRelation: (ctx: EntityContext, rootTable: TableDef, _
5500
5604
  * @param relation - The belongs-to-many relation definition.
5501
5605
  * @returns A promise resolving to a map of root keys to arrays of related rows with pivot data.
5502
5606
  */
5503
- declare const loadBelongsToManyRelation: (ctx: EntityContext, rootTable: TableDef, _relationName: string, relation: BelongsToManyRelation) => Promise<Map<string, Rows$3>>;
5504
-
5505
- /**
5506
- * Metadata stored on entity instances for ORM internal use
5507
- * @typeParam TTable - Table definition type
5508
- */
5509
- interface EntityMeta<TTable extends TableDef> {
5510
- /** Entity context */
5511
- ctx: EntityContext;
5512
- /** Table definition */
5513
- table: TTable;
5514
- /** Relations that should be loaded lazily */
5515
- lazyRelations: (keyof RelationMap<TTable>)[];
5516
- /** Cache for relation promises */
5517
- relationCache: Map<string, Promise<unknown>>;
5518
- /** Hydration data for relations */
5519
- relationHydration: Map<string, Map<string, unknown>>;
5520
- /** Relation wrapper instances */
5521
- relationWrappers: Map<string, unknown>;
5522
- }
5607
+ declare const loadBelongsToManyRelation: (ctx: EntityContext, rootTable: TableDef, relationName: string, relation: BelongsToManyRelation, options?: RelationIncludeOptions) => Promise<Map<string, Rows$3>>;
5523
5608
 
5524
5609
  type Rows$2 = Record<string, unknown>[];
5525
5610
  /**
@@ -5563,6 +5648,14 @@ declare class DefaultHasManyCollection<TChild> implements HasManyCollection<TChi
5563
5648
  * @returns Array of child entities
5564
5649
  */
5565
5650
  getItems(): TChild[];
5651
+ /**
5652
+ * Array-compatible length for testing frameworks.
5653
+ */
5654
+ get length(): number;
5655
+ /**
5656
+ * Enables iteration over the collection like an array.
5657
+ */
5658
+ [Symbol.iterator](): Iterator<TChild>;
5566
5659
  /**
5567
5660
  * Adds a new child entity to the collection.
5568
5661
  * @param data - Partial data for the new entity
@@ -5599,7 +5692,7 @@ type Rows$1 = Record<string, unknown>;
5599
5692
  *
5600
5693
  * @template TParent The type of the parent entity.
5601
5694
  */
5602
- declare class DefaultBelongsToReference<TParent> implements BelongsToReference<TParent> {
5695
+ declare class DefaultBelongsToReference<TParent extends object> implements BelongsToReferenceApi<TParent> {
5603
5696
  private readonly ctx;
5604
5697
  private readonly meta;
5605
5698
  private readonly root;
@@ -5639,7 +5732,7 @@ type Rows = Record<string, unknown>[];
5639
5732
  *
5640
5733
  * @template TTarget The type of the target entities in the collection.
5641
5734
  */
5642
- declare class DefaultManyToManyCollection<TTarget> implements ManyToManyCollection<TTarget> {
5735
+ declare class DefaultManyToManyCollection<TTarget, TPivot extends object | undefined = undefined> implements ManyToManyCollection<TTarget, TPivot> {
5643
5736
  private readonly ctx;
5644
5737
  private readonly meta;
5645
5738
  private readonly root;
@@ -5673,6 +5766,14 @@ declare class DefaultManyToManyCollection<TTarget> implements ManyToManyCollecti
5673
5766
  * @returns Array of target entities.
5674
5767
  */
5675
5768
  getItems(): TTarget[];
5769
+ /**
5770
+ * Array-compatible length for testing frameworks.
5771
+ */
5772
+ get length(): number;
5773
+ /**
5774
+ * Enables iteration over the collection like an array.
5775
+ */
5776
+ [Symbol.iterator](): Iterator<TTarget>;
5676
5777
  /**
5677
5778
  * Attaches an entity to the collection.
5678
5779
  * Registers an 'attach' change in the entity context.
@@ -5732,51 +5833,6 @@ type Jsonify<T> = {
5732
5833
  */
5733
5834
  declare const jsonify: <T extends object>(value: T) => Jsonify<T>;
5734
5835
 
5735
- /**
5736
- * Context object provided by standard decorators in newer TypeScript versions.
5737
- */
5738
- interface StandardDecoratorContext {
5739
- kind: string;
5740
- name?: string | symbol;
5741
- metadata?: Record<PropertyKey, unknown>;
5742
- static?: boolean;
5743
- private?: boolean;
5744
- }
5745
- /**
5746
- * Dual-mode property decorator that supports both legacy and standard decorator syntax.
5747
- */
5748
- interface DualModePropertyDecorator {
5749
- (target: object, propertyKey: string | symbol): void;
5750
- (value: unknown, context: StandardDecoratorContext): void;
5751
- }
5752
- /**
5753
- * Dual-mode class decorator that supports both legacy and standard decorator syntax.
5754
- */
5755
- interface DualModeClassDecorator {
5756
- <TFunction extends Function>(value: TFunction): void | TFunction;
5757
- <TFunction extends Function>(value: TFunction, context: StandardDecoratorContext): void | TFunction;
5758
- }
5759
- /**
5760
- * Bag for storing decorator metadata during the decoration phase.
5761
- */
5762
- interface DecoratorMetadataBag {
5763
- columns: Array<{
5764
- propertyName: string;
5765
- column: ColumnDefLike;
5766
- }>;
5767
- relations: Array<{
5768
- propertyName: string;
5769
- relation: RelationMetadata;
5770
- }>;
5771
- }
5772
- /**
5773
- * Public helper to read decorator metadata from a class constructor.
5774
- * Standard decorators only; legacy metadata is intentionally ignored.
5775
- * @param ctor - The entity constructor.
5776
- * @returns The metadata bag if present.
5777
- */
5778
- declare const getDecoratorMetadata: (ctor: object) => DecoratorMetadataBag | undefined;
5779
-
5780
5836
  /**
5781
5837
  * Options for defining an entity.
5782
5838
  */
@@ -5789,7 +5845,7 @@ interface EntityOptions {
5789
5845
  * @param options - Configuration options for the entity.
5790
5846
  * @returns A class decorator that registers the entity metadata.
5791
5847
  */
5792
- declare function Entity(options?: EntityOptions): DualModeClassDecorator;
5848
+ declare function Entity(options?: EntityOptions): <T extends EntityConstructor>(value: T, context: ClassDecoratorContext) => T;
5793
5849
 
5794
5850
  /**
5795
5851
  * Options for defining a column in an entity.
@@ -5811,14 +5867,14 @@ type ColumnInput = ColumnOptions | ColumnDef;
5811
5867
  * @param definition - The column definition or options.
5812
5868
  * @returns A property decorator that registers the column metadata.
5813
5869
  */
5814
- declare function Column(definition: ColumnInput): DualModePropertyDecorator;
5870
+ declare function Column(definition: ColumnInput): (_value: unknown, context: ClassFieldDecoratorContext) => void;
5815
5871
  /**
5816
5872
  * Decorator to define a primary key column on an entity property.
5817
5873
  * Sets the primary flag to true and delegates to Column decorator.
5818
5874
  * @param definition - The column definition or options.
5819
5875
  * @returns A property decorator that registers the primary key column metadata.
5820
5876
  */
5821
- declare function PrimaryKey(definition: ColumnInput): DualModePropertyDecorator;
5877
+ declare function PrimaryKey(definition: ColumnInput): (_value: unknown, context: ClassFieldDecoratorContext) => void;
5822
5878
 
5823
5879
  interface BaseRelationOptions {
5824
5880
  target: EntityOrTableTargetResolver;
@@ -5829,28 +5885,28 @@ interface BaseRelationOptions {
5829
5885
  * Options for HasMany relation.
5830
5886
  */
5831
5887
  interface HasManyOptions extends BaseRelationOptions {
5832
- foreignKey: string;
5888
+ foreignKey?: string;
5833
5889
  }
5834
5890
  /**
5835
5891
  * Options for HasOne relation.
5836
5892
  */
5837
5893
  interface HasOneOptions extends BaseRelationOptions {
5838
- foreignKey: string;
5894
+ foreignKey?: string;
5839
5895
  }
5840
5896
  /**
5841
5897
  * Options for BelongsTo relation.
5842
5898
  */
5843
5899
  interface BelongsToOptions extends BaseRelationOptions {
5844
- foreignKey: string;
5900
+ foreignKey?: string;
5845
5901
  }
5846
5902
  /**
5847
5903
  * Options for BelongsToMany relation.
5848
5904
  */
5849
- interface BelongsToManyOptions {
5850
- target: EntityOrTableTargetResolver;
5851
- pivotTable: EntityOrTableTargetResolver;
5852
- pivotForeignKeyToRoot: string;
5853
- pivotForeignKeyToTarget: string;
5905
+ interface BelongsToManyOptions<TTarget extends EntityOrTableTarget = EntityOrTableTarget, TPivot extends EntityOrTableTarget = EntityOrTableTarget> {
5906
+ target: EntityOrTableTargetResolver<TTarget>;
5907
+ pivotTable: EntityOrTableTargetResolver<TPivot>;
5908
+ pivotForeignKeyToRoot?: string;
5909
+ pivotForeignKeyToTarget?: string;
5854
5910
  localKey?: string;
5855
5911
  targetKey?: string;
5856
5912
  pivotPrimaryKey?: string;
@@ -5862,25 +5918,25 @@ interface BelongsToManyOptions {
5862
5918
  * @param options - The relation options.
5863
5919
  * @returns A property decorator that registers the relation metadata.
5864
5920
  */
5865
- declare function HasMany(options: HasManyOptions): DualModePropertyDecorator;
5921
+ declare function HasMany(options: HasManyOptions): (_value: unknown, context: ClassFieldDecoratorContext) => void;
5866
5922
  /**
5867
5923
  * Decorator to define a HasOne relation on an entity property.
5868
5924
  * @param options - The relation options.
5869
5925
  * @returns A property decorator that registers the relation metadata.
5870
5926
  */
5871
- declare function HasOne(options: HasOneOptions): DualModePropertyDecorator;
5927
+ declare function HasOne(options: HasOneOptions): (_value: unknown, context: ClassFieldDecoratorContext) => void;
5872
5928
  /**
5873
5929
  * Decorator to define a BelongsTo relation on an entity property.
5874
5930
  * @param options - The relation options.
5875
5931
  * @returns A property decorator that registers the relation metadata.
5876
5932
  */
5877
- declare function BelongsTo(options: BelongsToOptions): DualModePropertyDecorator;
5933
+ declare function BelongsTo(options: BelongsToOptions): (_value: unknown, context: ClassFieldDecoratorContext) => void;
5878
5934
  /**
5879
5935
  * Decorator to define a BelongsToMany relation on an entity property.
5880
5936
  * @param options - The relation options.
5881
5937
  * @returns A property decorator that registers the relation metadata.
5882
5938
  */
5883
- declare function BelongsToMany(options: BelongsToManyOptions): DualModePropertyDecorator;
5939
+ declare function BelongsToMany<TTarget extends EntityOrTableTarget = EntityOrTableTarget, TPivot extends EntityOrTableTarget = EntityOrTableTarget>(options: BelongsToManyOptions<TTarget, TPivot>): (_value: unknown, context: ClassFieldDecoratorContext) => void;
5884
5940
 
5885
5941
  /**
5886
5942
  * Bootstraps all entities by building their table definitions and relations.
@@ -5899,14 +5955,45 @@ declare const getTableDefFromEntity: <TTable extends TableDef = TableDef>(ctor:
5899
5955
  * @param ctor - The entity constructor.
5900
5956
  * @returns A select query builder for the entity.
5901
5957
  */
5902
- declare const selectFromEntity: <TTable extends TableDef = TableDef>(ctor: EntityConstructor) => SelectQueryBuilder<unknown, TTable>;
5958
+ type NonFunctionKeys<T> = {
5959
+ [K in keyof T]-?: T[K] extends (...args: unknown[]) => unknown ? never : K;
5960
+ }[keyof T];
5961
+ type RelationKeys<TEntity extends object> = Exclude<NonFunctionKeys<TEntity>, SelectableKeys<TEntity>> & string;
5962
+ type EntityTable<TEntity extends object> = Omit<TableDef<{
5963
+ [K in SelectableKeys<TEntity>]: ColumnDef;
5964
+ }>, 'relations'> & {
5965
+ relations: {
5966
+ [K in RelationKeys<TEntity>]: NonNullable<TEntity[K]> extends HasManyCollection<infer TChild> ? HasManyRelation<EntityTable<NonNullable<TChild> & object>> : NonNullable<TEntity[K]> extends ManyToManyCollection<infer TTarget, infer TPivot> ? BelongsToManyRelation<EntityTable<NonNullable<TTarget> & object>, TPivot extends object ? EntityTable<NonNullable<TPivot> & object> : TableDef> : NonNullable<TEntity[K]> extends HasOneReference<infer TChild> ? HasOneRelation<EntityTable<NonNullable<TChild> & object>> : NonNullable<TEntity[K]> extends BelongsToReference<infer TParent> ? BelongsToRelation<EntityTable<NonNullable<TParent> & object>> : NonNullable<TEntity[K]> extends object ? BelongsToRelation<EntityTable<NonNullable<TEntity[K]> & object>> : never;
5967
+ };
5968
+ };
5969
+ declare const selectFromEntity: <TEntity extends object>(ctor: EntityConstructor<TEntity>) => SelectQueryBuilder<unknown, EntityTable<TEntity>>;
5903
5970
  /**
5904
5971
  * Public API: opt-in ergonomic entity reference (decorator-level).
5905
5972
  *
5906
5973
  * Lazily bootstraps entity metadata (via getTableDefFromEntity) and returns a
5907
5974
  * `tableRef(...)`-style proxy so users can write `u.id` instead of `u.columns.id`.
5908
5975
  */
5909
- declare const entityRef: <TTable extends TableDef = TableDef>(ctor: EntityConstructor) => TableRef$1<TTable>;
5976
+ declare const entityRef: <TEntity extends object>(ctor: EntityConstructor<TEntity>) => TableRef$1<EntityTable<TEntity>>;
5977
+
5978
+ /**
5979
+ * Bag for storing decorator metadata during the decoration phase.
5980
+ */
5981
+ interface DecoratorMetadataBag {
5982
+ columns: Array<{
5983
+ propertyName: string;
5984
+ column: ColumnDefLike;
5985
+ }>;
5986
+ relations: Array<{
5987
+ propertyName: string;
5988
+ relation: RelationMetadata;
5989
+ }>;
5990
+ }
5991
+ /**
5992
+ * Public helper to read decorator metadata from a class constructor.
5993
+ * @param ctor - The entity constructor.
5994
+ * @returns The metadata bag if present.
5995
+ */
5996
+ declare const getDecoratorMetadata: (ctor: object) => DecoratorMetadataBag | undefined;
5910
5997
 
5911
5998
  type PoolOptions = {
5912
5999
  /** Maximum number of live resources (idle + leased). */
@@ -6071,4 +6158,4 @@ type PooledExecutorFactoryOptions<TConn> = {
6071
6158
  */
6072
6159
  declare function createPooledExecutorFactory<TConn>(opts: PooledExecutorFactoryOptions<TConn>): DbExecutorFactory;
6073
6160
 
6074
- export { type AliasRefNode, type AnyDomainEvent, type ArithmeticExpressionNode, type TableRef as AstTableRef, AsyncLocalStorage, BelongsTo, BelongsToMany, type BelongsToManyOptions, type BelongsToManyRelation, type BelongsToOptions, type BelongsToReference, type BelongsToRelation, type BetweenExpressionNode, type BinaryExpressionNode, type BitwiseExpressionNode, type CascadeMode, type CaseExpressionNode, type CastExpressionNode, type CheckConstraint, type CollateExpressionNode, Column, type ColumnDef, type ColumnDiff, type ColumnInput, type ColumnNode, type ColumnOptions, type ColumnRef, type ColumnToTs, type ColumnType, type CreateTediousClientOptions, type DatabaseCheck, type DatabaseColumn, type DatabaseIndex, type DatabaseSchema, type DatabaseTable, type DbExecutor, type DbExecutorFactory, DefaultBelongsToReference, DefaultHasManyCollection, DefaultManyToManyCollection, type DefaultValue, DeleteQueryBuilder, type DialectName, type DomainEvent, DomainEventBus, type DomainEventHandler, Entity, type EntityContext, type EntityInstance, type EntityOptions, EntityStatus, type ExecutionContext, type ExistsExpressionNode, type ExpressionNode, type ExpressionVisitor, type ForeignKeyReference, type FunctionNode, type GroupConcatOptions, type HasDomainEvents, HasMany, type HasManyCollection, type HasManyOptions, type HasManyRelation, HasOne, type HasOneOptions, type HasOneReference, type HasOneRelation, type HydrationContext, type HydrationMetadata, type HydrationPivotPlan, type HydrationPlan, type HydrationRelationPlan, type InExpressionNode, type InExpressionRight, type IndexColumn, type IndexDef, type InferRow, type InitialHandlers, InsertQueryBuilder, type IntrospectOptions, type JsonPathNode, type Jsonify, type JsonifyScalar, type LiteralNode, type LiteralValue, type LogicalExpressionNode, type ManyToManyCollection, type MssqlClientLike, MySqlDialect, type MysqlClientLike, type NullExpressionNode, type OperandNode, type OperandVisitor, Orm, type OrmDomainEvent, type OrmInterceptor, type OrmOptions, OrmSession, type OrmSessionOptions, Pool, type PoolAdapter, type PoolLease, type PoolOptions, type PooledConnectionAdapter, type PostgresClientLike, PostgresDialect, PrimaryKey, type QueryLogEntry, type QueryLogger, type QueryResult, type RawDefaultValue, type ReferentialAction, type RelationChange, type RelationChangeEntry, type RelationDef, type RelationKey, RelationKinds, type RelationMap, type RelationTargetTable, type RelationType, type RenderColumnOptions, STANDARD_COLUMN_TYPES, type SaveGraphInputPayload, type SaveGraphInputScalar, type SaveGraphJsonScalar, type ScalarSubqueryNode, type SchemaChange, type SchemaChangeKind, type SchemaDiffOptions, type SchemaGenerateResult, type SchemaIntrospector, type SchemaPlan, SelectQueryBuilder, type SelectQueryInput, type SimpleQueryRunner, SqlServerDialect, type SqliteClientLike, SqliteDialect, type StandardColumnType, type SynchronizeOptions, type TableDef, type TableHooks, type TableOptions, type TableRef$1 as TableRef, type TediousColumn, type TediousConnectionLike, type TediousModule, type TediousRequest, type TediousRequestCtor, type TediousTypes, type TrackedEntity, TypeScriptGenerator, UpdateQueryBuilder, type ValueOperandInput, type WindowFunctionNode, abs, acos, add, addDomainEvent, age, aliasRef, and, arrayAppend, ascii, asin, atan, atan2, avg, belongsTo, belongsToMany, between, bitAnd, bitLength, bitOr, bitXor, bootstrapEntities, caseWhen, cast, cbrt, ceil, ceiling, char, charLength, chr, clearExpressionDispatchers, clearOperandDispatchers, coalesce, col, collate, columnOperand, concat, concatWs, correlateBy, cos, cot, count, countAll, createEntityFromRow, createEntityProxy, createExecutorFromQueryRunner, createMssqlExecutor, createMysqlExecutor, createPooledExecutorFactory, createPostgresExecutor, createQueryLoggingExecutor, createSqliteExecutor, createTediousExecutor, createTediousMssqlClient, currentDate, currentTime, dateAdd, dateDiff, dateFormat, dateSub, dateTrunc, day, dayOfWeek, defineTable, degrees, denseRank, diffSchema, div, endOfMonth, entityRef, eq, esel, executeHydrated, executeHydratedWithContexts, exists, exp, extract, firstValue, floor, fromUnixTime, generateCreateTableSql, generateSchemaSql, getColumn, getDecoratorMetadata, getSchemaIntrospector, getTableDefFromEntity, greatest, groupConcat, gt, gte, hasMany, hasOne, hour, hydrateRows, ifNull, inList, inSubquery, initcap, instr, introspectSchema, isCaseExpressionNode, isCastExpressionNode, isCollateExpressionNode, isExpressionSelectionNode, isFunctionNode, isNotNull, isNull, isOperandNode, isValueOperandInput, isWindowFunctionNode, jsonArrayAgg, jsonContains, jsonLength, jsonPath, jsonSet, jsonify, lag, lastValue, lead, least, left, length, like, ln, loadBelongsToManyRelation, loadBelongsToRelation, loadHasManyRelation, loadHasOneRelation, localTime, localTimestamp, locate, log, log10, log2, logBase, lower, lpad, lt, lte, ltrim, max, md5, min, minute, mod, month, mul, neq, normalizeColumnType, notBetween, notExists, notInList, notInSubquery, notLike, now, ntile, nullif, octetLength, or, outerRef, pi, position, pow, power, quarter, radians, rand, random, rank, registerExpressionDispatcher, registerOperandDispatcher, registerSchemaIntrospector, renderColumnDefinition, renderTypeWithArgs, repeat, replace, reverse, right, round, rowNumber, rowsToQueryResult, rpad, rtrim, second, sel, selectFromEntity, sha1, sha2, shiftLeft, shiftRight, sign, sin, space, sqrt, stddev, sub, substr, sum, synchronizeSchema, tableRef, tan, toColumnRef, toTableRef, trim, trunc, truncate, unixTimestamp, upper, utcNow, valueToOperand, variance, visitExpression, visitOperand, weekOfYear, windowFunction, year };
6161
+ export { type AliasRefNode, type AnyDomainEvent, type ArithmeticExpressionNode, type TableRef as AstTableRef, AsyncLocalStorage, BelongsTo, BelongsToMany, type BelongsToManyOptions, type BelongsToManyRelation, type BelongsToOptions, type BelongsToReference, type BelongsToReferenceApi, type BelongsToRelation, type BetweenExpressionNode, type BinaryExpressionNode, type BitwiseExpressionNode, type CascadeMode, type CaseExpressionNode, type CastExpressionNode, type CheckConstraint, type CollateExpressionNode, Column, type ColumnDef, type ColumnDiff, type ColumnInput, type ColumnNode, type ColumnOptions, type ColumnRef, type ColumnToTs, type ColumnType, type CreateTediousClientOptions, type DatabaseCheck, type DatabaseColumn, type DatabaseIndex, type DatabaseSchema, type DatabaseTable, type DbExecutor, type DbExecutorFactory, DefaultBelongsToReference, DefaultHasManyCollection, DefaultManyToManyCollection, type DefaultValue, DeleteQueryBuilder, type DialectName, type DomainEvent, DomainEventBus, type DomainEventHandler, Entity, type EntityContext, type EntityInstance, type EntityOptions, EntityStatus, type ExecutionContext, type ExistsExpressionNode, type ExpressionNode, type ExpressionVisitor, type ForeignKeyReference, type FunctionNode, type GroupConcatOptions, type HasDomainEvents, HasMany, type HasManyCollection, type HasManyOptions, type HasManyRelation, HasOne, type HasOneOptions, type HasOneReference, type HasOneReferenceApi, type HasOneRelation, type HydrationContext, type HydrationMetadata, type HydrationPivotPlan, type HydrationPlan, type HydrationRelationPlan, type InExpressionNode, type InExpressionRight, type IndexColumn, type IndexDef, type InferRow, type InitialHandlers, InsertQueryBuilder, type IntrospectOptions, type JsonPathNode, type Jsonify, type JsonifyScalar, type LiteralNode, type LiteralValue, type LogicalExpressionNode, type ManyToManyCollection, type MssqlClientLike, MySqlDialect, type MysqlClientLike, type NullExpressionNode, type OperandNode, type OperandVisitor, Orm, type OrmDomainEvent, type OrmInterceptor, type OrmOptions, OrmSession, type OrmSessionOptions, Pool, type PoolAdapter, type PoolLease, type PoolOptions, type PooledConnectionAdapter, type PostgresClientLike, PostgresDialect, PrimaryKey, type Primitive, type QueryLogEntry, type QueryLogger, type QueryResult, type RawDefaultValue, type ReferentialAction, type RelationChange, type RelationChangeEntry, type RelationDef, type RelationKey$1 as RelationKey, RelationKinds, type RelationMap, type RelationTargetTable, type RelationType, type RenderColumnOptions, STANDARD_COLUMN_TYPES, type SaveGraphInputPayload, type SaveGraphInputScalar, type SaveGraphJsonScalar, type ScalarSubqueryNode, type SchemaChange, type SchemaChangeKind, type SchemaDiffOptions, type SchemaGenerateResult, type SchemaIntrospector, type SchemaPlan, SelectQueryBuilder, type SelectQueryInput, type SelectableKeys, type SimpleQueryRunner, SqlServerDialect, type SqliteClientLike, SqliteDialect, type StandardColumnType, type SynchronizeOptions, type TableDef, type TableHooks, type TableOptions, type TableRef$1 as TableRef, type TediousColumn, type TediousConnectionLike, type TediousModule, type TediousRequest, type TediousRequestCtor, type TediousTypes, type TrackedEntity, TypeScriptGenerator, UpdateQueryBuilder, type ValueOperandInput, type WindowFunctionNode, abs, acos, add, addDomainEvent, age, aliasRef, and, arrayAppend, ascii, asin, atan, atan2, avg, belongsTo, belongsToMany, between, bitAnd, bitLength, bitOr, bitXor, bootstrapEntities, caseWhen, cast, cbrt, ceil, ceiling, char, charLength, chr, clearExpressionDispatchers, clearOperandDispatchers, coalesce, col, collate, columnOperand, concat, concatWs, correlateBy, cos, cot, count, countAll, createEntityFromRow, createEntityProxy, createExecutorFromQueryRunner, createMssqlExecutor, createMysqlExecutor, createPooledExecutorFactory, createPostgresExecutor, createQueryLoggingExecutor, createSqliteExecutor, createTediousExecutor, createTediousMssqlClient, currentDate, currentTime, dateAdd, dateDiff, dateFormat, dateSub, dateTrunc, day, dayOfWeek, defineTable, degrees, denseRank, diffSchema, div, endOfMonth, entityRef, eq, esel, executeHydrated, executeHydratedWithContexts, executeSchemaSql, executeSchemaSqlFor, exists, exp, extract, firstValue, floor, fromUnixTime, generateCreateTableSql, generateSchemaSql, generateSchemaSqlFor, getColumn, getDecoratorMetadata, getSchemaIntrospector, getTableDefFromEntity, greatest, groupConcat, gt, gte, hasMany, hasOne, hour, hydrateRows, ifNull, inList, inSubquery, initcap, instr, introspectSchema, isCaseExpressionNode, isCastExpressionNode, isCollateExpressionNode, isExpressionSelectionNode, isFunctionNode, isNotNull, isNull, isOperandNode, isValueOperandInput, isWindowFunctionNode, jsonArrayAgg, jsonContains, jsonLength, jsonPath, jsonSet, jsonify, lag, lastValue, lead, least, left, length, like, ln, loadBelongsToManyRelation, loadBelongsToRelation, loadHasManyRelation, loadHasOneRelation, localTime, localTimestamp, locate, log, log10, log2, logBase, lower, lpad, lt, lte, ltrim, max, md5, min, minute, mod, month, mul, neq, normalizeColumnType, notBetween, notExists, notInList, notInSubquery, notLike, now, ntile, nullif, octetLength, or, outerRef, pi, position, pow, power, quarter, radians, rand, random, rank, registerExpressionDispatcher, registerOperandDispatcher, registerSchemaIntrospector, relationLoaderCache, renderColumnDefinition, renderTypeWithArgs, repeat, replace, reverse, right, round, rowNumber, rowsToQueryResult, rpad, rtrim, second, sel, selectFromEntity, setRelations, sha1, sha2, shiftLeft, shiftRight, sign, sin, space, sqrt, stddev, sub, substr, sum, synchronizeSchema, tableRef, tan, toColumnRef, toTableRef, trim, trunc, truncate, unixTimestamp, upper, utcNow, valueToOperand, variance, visitExpression, visitOperand, weekOfYear, windowFunction, year };