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.cjs +163 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +163 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/orm/entity-relations.ts +19 -19
- package/src/orm/entity.ts +74 -47
- package/src/orm/execute.ts +23 -19
- package/src/orm/relation-preload.ts +82 -0
- package/src/query-builder/relation-include-tree.ts +98 -0
- package/src/query-builder/select.ts +108 -64
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?:
|
|
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?:
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
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
|