metal-orm 1.0.71 → 1.0.73

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.
package/dist/index.d.cts CHANGED
@@ -2661,6 +2661,18 @@ interface SelectQueryBuilderEnvironment {
2661
2661
  readonly deps: SelectQueryBuilderDependencies;
2662
2662
  }
2663
2663
 
2664
+ type RelationIncludeInput<TTable extends TableDef> = {
2665
+ [K in keyof RelationMap<TTable> & string]?: true | RelationIncludeNodeInput<TTable['relations'][K]>;
2666
+ };
2667
+ type RelationIncludeNodeInput<TRel extends RelationDef> = TypedRelationIncludeOptions<TRel> & {
2668
+ include?: RelationIncludeInput<RelationTargetTable<TRel>>;
2669
+ };
2670
+ type NormalizedRelationIncludeNode = {
2671
+ options?: RelationIncludeOptions;
2672
+ include?: NormalizedRelationIncludeTree;
2673
+ };
2674
+ type NormalizedRelationIncludeTree = Record<string, NormalizedRelationIncludeNode>;
2675
+
2664
2676
  type QueryResult = {
2665
2677
  columns: string[];
2666
2678
  values: unknown[][];
@@ -3795,6 +3807,7 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
3795
3807
  private readonly lazyRelations;
3796
3808
  private readonly lazyRelationOptions;
3797
3809
  private readonly entityConstructor?;
3810
+ private readonly includeTree;
3798
3811
  /**
3799
3812
  * Creates a new SelectQueryBuilder instance
3800
3813
  * @param table - Table definition to query
@@ -3802,7 +3815,7 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
3802
3815
  * @param hydration - Optional hydration manager
3803
3816
  * @param dependencies - Optional query builder dependencies
3804
3817
  */
3805
- constructor(table: TTable, state?: SelectQueryState, hydration?: HydrationManager, dependencies?: Partial<SelectQueryBuilderDependencies>, lazyRelations?: Set<string>, lazyRelationOptions?: Map<string, RelationIncludeOptions>, entityConstructor?: EntityConstructor);
3818
+ constructor(table: TTable, state?: SelectQueryState, hydration?: HydrationManager, dependencies?: Partial<SelectQueryBuilderDependencies>, lazyRelations?: Set<string>, lazyRelationOptions?: Map<string, RelationIncludeOptions>, entityConstructor?: EntityConstructor, includeTree?: NormalizedRelationIncludeTree);
3806
3819
  /**
3807
3820
  * Creates a new SelectQueryBuilder instance with updated context and lazy relations
3808
3821
  * @param context - Updated query context
@@ -4057,8 +4070,11 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
4057
4070
  * columns: ['id', 'title'],
4058
4071
  * where: eq(postTable.columns.published, true)
4059
4072
  * });
4073
+ * @example
4074
+ * qb.include({ posts: { include: { author: true } } });
4060
4075
  */
4061
- include<K extends keyof TTable['relations'] & string>(relationName: K, options?: TypedRelationIncludeOptions<TTable['relations'][K]>): SelectQueryBuilder<T, TTable>;
4076
+ include<K extends keyof TTable['relations'] & string>(relationName: K, options?: RelationIncludeNodeInput<TTable['relations'][K]>): SelectQueryBuilder<T, TTable>;
4077
+ include(relations: RelationIncludeInput<TTable>): SelectQueryBuilder<T, TTable>;
4062
4078
  /**
4063
4079
  * Includes a relation lazily in the query results
4064
4080
  * @param relationName - Name of the relation to include lazily
@@ -4098,6 +4114,10 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
4098
4114
  * @returns Map of relation names to include options
4099
4115
  */
4100
4116
  getLazyRelationOptions(): Map<string, RelationIncludeOptions>;
4117
+ /**
4118
+ * Gets normalized nested include information for runtime preloading.
4119
+ */
4120
+ getIncludeTree(): NormalizedRelationIncludeTree;
4101
4121
  /**
4102
4122
  * Gets the table definition for this query builder
4103
4123
  * @returns Table definition
package/dist/index.d.ts CHANGED
@@ -2661,6 +2661,18 @@ interface SelectQueryBuilderEnvironment {
2661
2661
  readonly deps: SelectQueryBuilderDependencies;
2662
2662
  }
2663
2663
 
2664
+ type RelationIncludeInput<TTable extends TableDef> = {
2665
+ [K in keyof RelationMap<TTable> & string]?: true | RelationIncludeNodeInput<TTable['relations'][K]>;
2666
+ };
2667
+ type RelationIncludeNodeInput<TRel extends RelationDef> = TypedRelationIncludeOptions<TRel> & {
2668
+ include?: RelationIncludeInput<RelationTargetTable<TRel>>;
2669
+ };
2670
+ type NormalizedRelationIncludeNode = {
2671
+ options?: RelationIncludeOptions;
2672
+ include?: NormalizedRelationIncludeTree;
2673
+ };
2674
+ type NormalizedRelationIncludeTree = Record<string, NormalizedRelationIncludeNode>;
2675
+
2664
2676
  type QueryResult = {
2665
2677
  columns: string[];
2666
2678
  values: unknown[][];
@@ -3795,6 +3807,7 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
3795
3807
  private readonly lazyRelations;
3796
3808
  private readonly lazyRelationOptions;
3797
3809
  private readonly entityConstructor?;
3810
+ private readonly includeTree;
3798
3811
  /**
3799
3812
  * Creates a new SelectQueryBuilder instance
3800
3813
  * @param table - Table definition to query
@@ -3802,7 +3815,7 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
3802
3815
  * @param hydration - Optional hydration manager
3803
3816
  * @param dependencies - Optional query builder dependencies
3804
3817
  */
3805
- constructor(table: TTable, state?: SelectQueryState, hydration?: HydrationManager, dependencies?: Partial<SelectQueryBuilderDependencies>, lazyRelations?: Set<string>, lazyRelationOptions?: Map<string, RelationIncludeOptions>, entityConstructor?: EntityConstructor);
3818
+ constructor(table: TTable, state?: SelectQueryState, hydration?: HydrationManager, dependencies?: Partial<SelectQueryBuilderDependencies>, lazyRelations?: Set<string>, lazyRelationOptions?: Map<string, RelationIncludeOptions>, entityConstructor?: EntityConstructor, includeTree?: NormalizedRelationIncludeTree);
3806
3819
  /**
3807
3820
  * Creates a new SelectQueryBuilder instance with updated context and lazy relations
3808
3821
  * @param context - Updated query context
@@ -4057,8 +4070,11 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
4057
4070
  * columns: ['id', 'title'],
4058
4071
  * where: eq(postTable.columns.published, true)
4059
4072
  * });
4073
+ * @example
4074
+ * qb.include({ posts: { include: { author: true } } });
4060
4075
  */
4061
- include<K extends keyof TTable['relations'] & string>(relationName: K, options?: TypedRelationIncludeOptions<TTable['relations'][K]>): SelectQueryBuilder<T, TTable>;
4076
+ include<K extends keyof TTable['relations'] & string>(relationName: K, options?: RelationIncludeNodeInput<TTable['relations'][K]>): SelectQueryBuilder<T, TTable>;
4077
+ include(relations: RelationIncludeInput<TTable>): SelectQueryBuilder<T, TTable>;
4062
4078
  /**
4063
4079
  * Includes a relation lazily in the query results
4064
4080
  * @param relationName - Name of the relation to include lazily
@@ -4098,6 +4114,10 @@ declare class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Ta
4098
4114
  * @returns Map of relation names to include options
4099
4115
  */
4100
4116
  getLazyRelationOptions(): Map<string, RelationIncludeOptions>;
4117
+ /**
4118
+ * Gets normalized nested include information for runtime preloading.
4119
+ */
4120
+ getIncludeTree(): NormalizedRelationIncludeTree;
4101
4121
  /**
4102
4122
  * Gets the table definition for this query builder
4103
4123
  * @returns Table definition
package/dist/index.js CHANGED
@@ -4618,6 +4618,58 @@ var resolveSelectQueryBuilderDependencies = (overrides = {}) => {
4618
4618
  };
4619
4619
  var defaultSelectQueryBuilderDependencies = resolveSelectQueryBuilderDependencies();
4620
4620
 
4621
+ // src/query-builder/relation-include-tree.ts
4622
+ var isObject = (value) => Boolean(value && typeof value === "object");
4623
+ var normalizeRelationIncludeNode = (value) => {
4624
+ if (!value || value === true) {
4625
+ return {};
4626
+ }
4627
+ if (!isObject(value)) {
4628
+ return {};
4629
+ }
4630
+ const { include, ...rest } = value;
4631
+ const options = Object.keys(rest).length ? rest : void 0;
4632
+ const normalizedInclude = isObject(include) ? normalizeRelationInclude(include) : void 0;
4633
+ if (normalizedInclude && Object.keys(normalizedInclude).length > 0) {
4634
+ return { options, include: normalizedInclude };
4635
+ }
4636
+ return { options };
4637
+ };
4638
+ var normalizeRelationInclude = (input) => {
4639
+ if (!input) return {};
4640
+ const tree = {};
4641
+ for (const [key, value] of Object.entries(input)) {
4642
+ tree[key] = normalizeRelationIncludeNode(value);
4643
+ }
4644
+ return tree;
4645
+ };
4646
+ var mergeRelationIncludeTrees = (base, next) => {
4647
+ const merged = { ...base };
4648
+ for (const [key, node] of Object.entries(next)) {
4649
+ const existing = merged[key];
4650
+ if (!existing) {
4651
+ merged[key] = node;
4652
+ continue;
4653
+ }
4654
+ const include = existing.include && node.include ? mergeRelationIncludeTrees(existing.include, node.include) : node.include ?? existing.include;
4655
+ merged[key] = {
4656
+ options: node.options ?? existing.options,
4657
+ ...include ? { include } : {}
4658
+ };
4659
+ }
4660
+ return merged;
4661
+ };
4662
+ var cloneRelationIncludeTree = (tree) => {
4663
+ const cloned = {};
4664
+ for (const [key, node] of Object.entries(tree)) {
4665
+ cloned[key] = {
4666
+ options: node.options,
4667
+ ...node.include ? { include: cloneRelationIncludeTree(node.include) } : {}
4668
+ };
4669
+ }
4670
+ return cloned;
4671
+ };
4672
+
4621
4673
  // src/orm/hydration.ts
4622
4674
  var hydrateRows = (rows, plan) => {
4623
4675
  if (!plan || !rows.length) return rows;
@@ -5750,14 +5802,14 @@ var getRelationWrapper = (meta, relationName, owner, createEntity) => {
5750
5802
  };
5751
5803
  var instantiateWrapper = (meta, relationName, relation, owner, createEntity) => {
5752
5804
  const metaBase = meta;
5753
- const lazyOptions = meta.lazyRelationOptions.get(relationName);
5754
5805
  const loadCached = (factory) => relationLoaderCache(metaBase, relationName, factory);
5806
+ const resolveOptions = () => meta.lazyRelationOptions.get(relationName);
5755
5807
  switch (relation.type) {
5756
5808
  case RelationKinds.HasOne: {
5757
5809
  const hasOne2 = relation;
5758
5810
  const localKey = hasOne2.localKey || findPrimaryKey(meta.table);
5759
5811
  const loader = () => loadCached(
5760
- () => loadHasOneRelation(meta.ctx, meta.table, relationName, hasOne2, lazyOptions)
5812
+ () => loadHasOneRelation(meta.ctx, meta.table, relationName, hasOne2, resolveOptions())
5761
5813
  );
5762
5814
  return new DefaultHasOneReference(
5763
5815
  meta.ctx,
@@ -5775,7 +5827,7 @@ var instantiateWrapper = (meta, relationName, relation, owner, createEntity) =>
5775
5827
  const hasMany2 = relation;
5776
5828
  const localKey = hasMany2.localKey || findPrimaryKey(meta.table);
5777
5829
  const loader = () => loadCached(
5778
- () => loadHasManyRelation(meta.ctx, meta.table, relationName, hasMany2, lazyOptions)
5830
+ () => loadHasManyRelation(meta.ctx, meta.table, relationName, hasMany2, resolveOptions())
5779
5831
  );
5780
5832
  return new DefaultHasManyCollection(
5781
5833
  meta.ctx,
@@ -5793,7 +5845,7 @@ var instantiateWrapper = (meta, relationName, relation, owner, createEntity) =>
5793
5845
  const belongsTo2 = relation;
5794
5846
  const targetKey = belongsTo2.localKey || findPrimaryKey(belongsTo2.target);
5795
5847
  const loader = () => loadCached(
5796
- () => loadBelongsToRelation(meta.ctx, meta.table, relationName, belongsTo2, lazyOptions)
5848
+ () => loadBelongsToRelation(meta.ctx, meta.table, relationName, belongsTo2, resolveOptions())
5797
5849
  );
5798
5850
  return new DefaultBelongsToReference(
5799
5851
  meta.ctx,
@@ -5811,7 +5863,7 @@ var instantiateWrapper = (meta, relationName, relation, owner, createEntity) =>
5811
5863
  const many = relation;
5812
5864
  const localKey = many.localKey || findPrimaryKey(meta.table);
5813
5865
  const loader = () => loadCached(
5814
- () => loadBelongsToManyRelation(meta.ctx, meta.table, relationName, many, lazyOptions)
5866
+ () => loadBelongsToManyRelation(meta.ctx, meta.table, relationName, many, resolveOptions())
5815
5867
  );
5816
5868
  return new DefaultManyToManyCollection(
5817
5869
  meta.ctx,
@@ -5831,6 +5883,10 @@ var instantiateWrapper = (meta, relationName, relation, owner, createEntity) =>
5831
5883
  };
5832
5884
 
5833
5885
  // src/orm/entity.ts
5886
+ var isRelationWrapperLoaded = (value) => {
5887
+ if (!value || typeof value !== "object") return false;
5888
+ return Boolean(value.loaded);
5889
+ };
5834
5890
  var createEntityProxy = (ctx, table, row, lazyRelations = [], lazyRelationOptions = /* @__PURE__ */ new Map()) => {
5835
5891
  const target = { ...row };
5836
5892
  const meta = {
@@ -5843,6 +5899,19 @@ var createEntityProxy = (ctx, table, row, lazyRelations = [], lazyRelationOption
5843
5899
  relationWrappers: /* @__PURE__ */ new Map()
5844
5900
  };
5845
5901
  const createRelationEntity = (relationTable, relationRow) => createEntityFromRow(meta.ctx, relationTable, relationRow);
5902
+ const buildJson = (self) => {
5903
+ const json = {};
5904
+ for (const key of Object.keys(target)) {
5905
+ json[key] = self[key];
5906
+ }
5907
+ for (const [relationName, wrapper] of meta.relationWrappers) {
5908
+ if (Object.prototype.hasOwnProperty.call(json, relationName)) continue;
5909
+ if (isRelationWrapperLoaded(wrapper)) {
5910
+ json[relationName] = wrapper;
5911
+ }
5912
+ }
5913
+ return json;
5914
+ };
5846
5915
  Object.defineProperty(target, ENTITY_META, {
5847
5916
  value: meta,
5848
5917
  enumerable: false,
@@ -5862,6 +5931,12 @@ var createEntityProxy = (ctx, table, row, lazyRelations = [], lazyRelationOption
5862
5931
  return void 0;
5863
5932
  };
5864
5933
  }
5934
+ if (prop === "toJSON") {
5935
+ if (prop in targetObj) {
5936
+ return Reflect.get(targetObj, prop, receiver);
5937
+ }
5938
+ return () => buildJson(receiver);
5939
+ }
5865
5940
  if (typeof prop === "string" && table.relations[prop]) {
5866
5941
  return getRelationWrapper(meta, prop, receiver, createRelationEntity);
5867
5942
  }
@@ -5895,6 +5970,58 @@ var createEntityFromRow = (ctx, table, row, lazyRelations = [], lazyRelationOpti
5895
5970
  return entity;
5896
5971
  };
5897
5972
 
5973
+ // src/orm/relation-preload.ts
5974
+ var collectEntities = (value) => {
5975
+ if (!value) return [];
5976
+ if (Array.isArray(value)) {
5977
+ return value.filter((item) => item && typeof item === "object");
5978
+ }
5979
+ if (typeof value === "object") {
5980
+ return [value];
5981
+ }
5982
+ return [];
5983
+ };
5984
+ var loadRelation = async (entity, relationName) => {
5985
+ const wrapper = entity[relationName];
5986
+ if (!wrapper) return [];
5987
+ if (typeof wrapper.load === "function") {
5988
+ const loaded = await wrapper.load();
5989
+ return collectEntities(loaded);
5990
+ }
5991
+ if (typeof wrapper.getItems === "function") {
5992
+ return collectEntities(wrapper.getItems());
5993
+ }
5994
+ if (typeof wrapper.get === "function") {
5995
+ return collectEntities(wrapper.get());
5996
+ }
5997
+ return collectEntities(wrapper);
5998
+ };
5999
+ var setLazyOptionsIfEmpty = (entity, relationName, options) => {
6000
+ if (!options) return;
6001
+ const meta = getEntityMeta(entity);
6002
+ if (!meta || meta.lazyRelationOptions.has(relationName)) return;
6003
+ meta.lazyRelationOptions.set(relationName, options);
6004
+ };
6005
+ var preloadRelationIncludes = async (entities, includeTree, depth = 0) => {
6006
+ if (!entities.length) return;
6007
+ const entries = Object.entries(includeTree);
6008
+ if (!entries.length) return;
6009
+ for (const [relationName, node] of entries) {
6010
+ const shouldLoad = depth > 0 || Boolean(node.include);
6011
+ if (!shouldLoad) continue;
6012
+ for (const entity of entities) {
6013
+ setLazyOptionsIfEmpty(entity, relationName, node.options);
6014
+ }
6015
+ const loaded = await Promise.all(
6016
+ entities.map((entity) => loadRelation(entity, relationName))
6017
+ );
6018
+ const relatedEntities = loaded.flat();
6019
+ if (node.include && relatedEntities.length) {
6020
+ await preloadRelationIncludes(relatedEntities, node.include, depth + 1);
6021
+ }
6022
+ }
6023
+ };
6024
+
5898
6025
  // src/orm/execute.ts
5899
6026
  var flattenResults = (results) => {
5900
6027
  const rows = [];
@@ -5917,14 +6044,17 @@ var executeWithContexts = async (execCtx, entityCtx, qb) => {
5917
6044
  const rows = flattenResults(executed);
5918
6045
  const lazyRelations = qb.getLazyRelations();
5919
6046
  const lazyRelationOptions = qb.getLazyRelationOptions();
6047
+ const includeTree = qb.getIncludeTree();
5920
6048
  if (ast.setOps && ast.setOps.length > 0) {
5921
6049
  const proxies = rows.map((row) => createEntityProxy(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
5922
6050
  await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
6051
+ await preloadRelationIncludes(proxies, includeTree);
5923
6052
  return proxies;
5924
6053
  }
5925
6054
  const hydrated = hydrateRows(rows, qb.getHydrationPlan());
5926
6055
  const entities = hydrated.map((row) => createEntityFromRow(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
5927
6056
  await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
6057
+ await preloadRelationIncludes(entities, includeTree);
5928
6058
  return entities;
5929
6059
  };
5930
6060
  var executePlainWithContexts = async (execCtx, qb) => {
@@ -6551,6 +6681,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6551
6681
  lazyRelations;
6552
6682
  lazyRelationOptions;
6553
6683
  entityConstructor;
6684
+ includeTree;
6554
6685
  /**
6555
6686
  * Creates a new SelectQueryBuilder instance
6556
6687
  * @param table - Table definition to query
@@ -6558,7 +6689,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6558
6689
  * @param hydration - Optional hydration manager
6559
6690
  * @param dependencies - Optional query builder dependencies
6560
6691
  */
6561
- constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions, entityConstructor) {
6692
+ constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions, entityConstructor, includeTree) {
6562
6693
  const deps = resolveSelectQueryBuilderDependencies(dependencies);
6563
6694
  this.env = { table, deps };
6564
6695
  const createAstService = (nextState) => deps.createQueryAstService(table, nextState);
@@ -6571,6 +6702,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6571
6702
  this.lazyRelations = new Set(lazyRelations ?? []);
6572
6703
  this.lazyRelationOptions = new Map(lazyRelationOptions ?? []);
6573
6704
  this.entityConstructor = entityConstructor;
6705
+ this.includeTree = includeTree ?? {};
6574
6706
  this.columnSelector = deps.createColumnSelector(this.env);
6575
6707
  const relationManager = deps.createRelationManager(this.env);
6576
6708
  this.fromFacet = new SelectFromFacet(this.env, createAstService);
@@ -6587,7 +6719,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6587
6719
  * @param lazyRelations - Updated lazy relations set
6588
6720
  * @returns New SelectQueryBuilder instance
6589
6721
  */
6590
- clone(context = this.context, lazyRelations = new Set(this.lazyRelations), lazyRelationOptions = new Map(this.lazyRelationOptions)) {
6722
+ clone(context = this.context, lazyRelations = new Set(this.lazyRelations), lazyRelationOptions = new Map(this.lazyRelationOptions), includeTree = this.includeTree) {
6591
6723
  return new _SelectQueryBuilder(
6592
6724
  this.env.table,
6593
6725
  context.state,
@@ -6595,7 +6727,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6595
6727
  this.env.deps,
6596
6728
  lazyRelations,
6597
6729
  lazyRelationOptions,
6598
- this.entityConstructor
6730
+ this.entityConstructor,
6731
+ includeTree
6599
6732
  );
6600
6733
  }
6601
6734
  /**
@@ -6883,24 +7016,22 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6883
7016
  const nextContext = this.relationFacet.joinRelation(this.context, relationName, joinKind, extraCondition);
6884
7017
  return this.clone(nextContext);
6885
7018
  }
6886
- /**
6887
- * Includes related data in the query results
6888
- * @param relationName - Name of the relationship to include
6889
- * @param options - Optional include options
6890
- * @returns New query builder instance with the relationship inclusion
6891
- * @example
6892
- * qb.include('posts');
6893
- * @example
6894
- * qb.include('posts', { columns: ['id', 'title', 'published'] });
6895
- * @example
6896
- * qb.include('posts', {
6897
- * columns: ['id', 'title'],
6898
- * where: eq(postTable.columns.published, true)
6899
- * });
6900
- */
6901
- include(relationName, options) {
6902
- const nextContext = this.relationFacet.include(this.context, relationName, options);
6903
- return this.clone(nextContext);
7019
+ include(relationNameOrRelations, options) {
7020
+ if (typeof relationNameOrRelations === "object" && relationNameOrRelations !== null) {
7021
+ const normalized = normalizeRelationInclude(relationNameOrRelations);
7022
+ let nextContext2 = this.context;
7023
+ for (const [relationName2, node] of Object.entries(normalized)) {
7024
+ nextContext2 = this.relationFacet.include(nextContext2, relationName2, node.options);
7025
+ }
7026
+ const nextTree2 = mergeRelationIncludeTrees(this.includeTree, normalized);
7027
+ return this.clone(nextContext2, void 0, void 0, nextTree2);
7028
+ }
7029
+ const relationName = relationNameOrRelations;
7030
+ const normalizedNode = normalizeRelationIncludeNode(options);
7031
+ const nextContext = this.relationFacet.include(this.context, relationName, normalizedNode.options);
7032
+ const shouldStore = Boolean(normalizedNode.include || normalizedNode.options);
7033
+ const nextTree = shouldStore ? mergeRelationIncludeTrees(this.includeTree, { [relationName]: normalizedNode }) : this.includeTree;
7034
+ return this.clone(nextContext, void 0, void 0, nextTree);
6904
7035
  }
6905
7036
  /**
6906
7037
  * Includes a relation lazily in the query results
@@ -6984,6 +7115,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6984
7115
  getLazyRelationOptions() {
6985
7116
  return new Map(this.lazyRelationOptions);
6986
7117
  }
7118
+ /**
7119
+ * Gets normalized nested include information for runtime preloading.
7120
+ */
7121
+ getIncludeTree() {
7122
+ return cloneRelationIncludeTree(this.includeTree);
7123
+ }
6987
7124
  /**
6988
7125
  * Gets the table definition for this query builder
6989
7126
  * @returns Table definition