nestjs-query-mikro-orm 0.1.4 → 0.1.5
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/README.md +138 -103
- package/dist/index.cjs +424 -131
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -11
- package/dist/index.d.ts +47 -11
- package/dist/index.mjs +424 -131
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -654,53 +654,81 @@ var RelationQueryBuilder = class {
|
|
|
654
654
|
this.filterQueryBuilder = new FilterQueryBuilder(relationRepo);
|
|
655
655
|
}
|
|
656
656
|
/**
|
|
657
|
-
* Executes a relation select using
|
|
657
|
+
* Executes a relation select using MikroORM native relation population first.
|
|
658
658
|
*/
|
|
659
|
-
async selectAndExecute(entity, query) {
|
|
660
|
-
const
|
|
659
|
+
async selectAndExecute(entity, query, loadOptions) {
|
|
660
|
+
const nativeRelations = await this.tryLoadRelationsNatively(entity, loadOptions?.useDataloader, loadOptions?.strategy);
|
|
661
|
+
if (!nativeRelations) {
|
|
662
|
+
return this.queryByOwnerCondition(entity, query);
|
|
663
|
+
}
|
|
664
|
+
const resolvedRelations = nativeRelations;
|
|
665
|
+
if (!this.hasFilterSortingOrPaging(query)) {
|
|
666
|
+
return resolvedRelations;
|
|
667
|
+
}
|
|
668
|
+
if (!this.hasFilterOrSorting(query)) {
|
|
669
|
+
return this.applyPaging(resolvedRelations, query);
|
|
670
|
+
}
|
|
671
|
+
return this.queryResolvedRelations(resolvedRelations, query);
|
|
672
|
+
}
|
|
673
|
+
async batchSelectAndExecute(entities, query, loadOptions) {
|
|
674
|
+
if (entities.length === 0) {
|
|
675
|
+
return /* @__PURE__ */ new Map();
|
|
676
|
+
}
|
|
677
|
+
const nativeRelationsMap = await this.tryBatchLoadRelationsNatively(entities, loadOptions?.useDataloader, loadOptions?.strategy);
|
|
678
|
+
if (!nativeRelationsMap) {
|
|
679
|
+
const results2 = /* @__PURE__ */ new Map();
|
|
680
|
+
await Promise.all(entities.map(async (entity) => {
|
|
681
|
+
const relations = await this.queryByOwnerCondition(entity, query);
|
|
682
|
+
if (relations.length > 0) {
|
|
683
|
+
results2.set(entity, relations);
|
|
684
|
+
}
|
|
685
|
+
}));
|
|
686
|
+
return results2;
|
|
687
|
+
}
|
|
688
|
+
if (!this.hasFilterSortingOrPaging(query)) {
|
|
689
|
+
return nativeRelationsMap;
|
|
690
|
+
}
|
|
691
|
+
if (!this.hasFilterOrSorting(query)) {
|
|
692
|
+
return this.applyPagingToMap(nativeRelationsMap, query);
|
|
693
|
+
}
|
|
694
|
+
const results = /* @__PURE__ */ new Map();
|
|
695
|
+
await Promise.all(entities.map(async (entity) => {
|
|
696
|
+
const relations = nativeRelationsMap.get(entity) ?? [];
|
|
697
|
+
const queried = await this.queryResolvedRelations(relations, query);
|
|
698
|
+
if (queried.length > 0) {
|
|
699
|
+
results.set(entity, queried);
|
|
700
|
+
}
|
|
701
|
+
}));
|
|
702
|
+
return results;
|
|
703
|
+
}
|
|
704
|
+
async populateEntityRelation(entity, useDataloader, strategy) {
|
|
661
705
|
const em = this.repo.getEntityManager();
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
if (options?.limit !== void 0) findOptions.limit = options.limit;
|
|
674
|
-
if (options?.offset !== void 0) findOptions.offset = options.offset;
|
|
675
|
-
return await em.find(RelationEntity, finalWhere, findOptions);
|
|
706
|
+
const emPopulate = em;
|
|
707
|
+
try {
|
|
708
|
+
await emPopulate.populate([
|
|
709
|
+
entity
|
|
710
|
+
], [
|
|
711
|
+
this.relation
|
|
712
|
+
], this.getNativePopulateOptions(useDataloader, strategy));
|
|
713
|
+
return true;
|
|
714
|
+
} catch {
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
676
717
|
}
|
|
677
718
|
async count(entity, query) {
|
|
678
|
-
const
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
$and: [
|
|
685
|
-
baseWhere,
|
|
686
|
-
filterQuery
|
|
687
|
-
]
|
|
688
|
-
} : baseWhere;
|
|
689
|
-
return em.count(RelationEntity, finalWhere);
|
|
719
|
+
const relations = await this.selectAndExecute(entity, {
|
|
720
|
+
...query,
|
|
721
|
+
paging: void 0,
|
|
722
|
+
sorting: void 0
|
|
723
|
+
});
|
|
724
|
+
return relations.length;
|
|
690
725
|
}
|
|
691
726
|
async aggregate(entity, query, aggregateQuery) {
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
const finalWhere = filterQuery ? {
|
|
698
|
-
$and: [
|
|
699
|
-
baseWhere,
|
|
700
|
-
filterQuery
|
|
701
|
-
]
|
|
702
|
-
} : baseWhere;
|
|
703
|
-
const rows = await em.find(RelationEntity, finalWhere);
|
|
727
|
+
const rows = await this.selectAndExecute(entity, {
|
|
728
|
+
...query,
|
|
729
|
+
paging: void 0,
|
|
730
|
+
sorting: void 0
|
|
731
|
+
});
|
|
704
732
|
const aggs = aggregateQuery;
|
|
705
733
|
const groupBy = aggs.groupBy ?? [];
|
|
706
734
|
const makeAggKey = /* @__PURE__ */ __name((func, field) => `${func}_${field}`, "makeAggKey");
|
|
@@ -811,6 +839,259 @@ var RelationQueryBuilder = class {
|
|
|
811
839
|
}
|
|
812
840
|
return records;
|
|
813
841
|
}
|
|
842
|
+
getRelationMeta() {
|
|
843
|
+
const em = this.repo.getEntityManager();
|
|
844
|
+
const metadata = em.getMetadata().get(this.repo.getEntityName());
|
|
845
|
+
const relationProp = metadata.properties[this.relation];
|
|
846
|
+
if (!relationProp) {
|
|
847
|
+
throw new Error(`Unable to find relation '${this.relation}' on entity`);
|
|
848
|
+
}
|
|
849
|
+
return relationProp;
|
|
850
|
+
}
|
|
851
|
+
get entityIndexColName() {
|
|
852
|
+
return "__nestjsQuery__entityIndex__";
|
|
853
|
+
}
|
|
854
|
+
getRelationPrimaryKeysPropertyNameAndColumnsName() {
|
|
855
|
+
const em = this.repo.getEntityManager();
|
|
856
|
+
const relationMeta = this.getRelationMeta();
|
|
857
|
+
const relationEntityMeta = em.getMetadata().get(relationMeta.type);
|
|
858
|
+
return relationEntityMeta.primaryKeys.map((pk) => {
|
|
859
|
+
const prop = relationEntityMeta.properties[pk];
|
|
860
|
+
return {
|
|
861
|
+
propertyName: pk,
|
|
862
|
+
columnName: prop.fieldNames?.[0] || pk
|
|
863
|
+
};
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
getNativeLoadOptions(useDataloader = false) {
|
|
867
|
+
if (!useDataloader) {
|
|
868
|
+
return void 0;
|
|
869
|
+
}
|
|
870
|
+
return {
|
|
871
|
+
dataloader: true
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
getNativePopulateOptions(useDataloader = false, strategy) {
|
|
875
|
+
const nativeLoadOptions = this.getNativeLoadOptions(useDataloader);
|
|
876
|
+
const options = {};
|
|
877
|
+
if (nativeLoadOptions) {
|
|
878
|
+
options.dataloader = true;
|
|
879
|
+
}
|
|
880
|
+
if (strategy) {
|
|
881
|
+
options.strategy = strategy;
|
|
882
|
+
}
|
|
883
|
+
if (!Object.keys(options).length) {
|
|
884
|
+
return void 0;
|
|
885
|
+
}
|
|
886
|
+
return options;
|
|
887
|
+
}
|
|
888
|
+
async tryBatchLoadRelationsNatively(entities, useDataloader = false, strategy) {
|
|
889
|
+
const em = this.repo.getEntityManager();
|
|
890
|
+
const entityName = this.repo.getEntityName();
|
|
891
|
+
const metadata = em.getMetadata().get(entityName);
|
|
892
|
+
const primaryKey = metadata.primaryKeys[0];
|
|
893
|
+
const entityAndIds = entities.map((entity) => {
|
|
894
|
+
const id = entity[primaryKey];
|
|
895
|
+
return [
|
|
896
|
+
entity,
|
|
897
|
+
id
|
|
898
|
+
];
|
|
899
|
+
});
|
|
900
|
+
const ids = entityAndIds.map(([, id]) => id).filter((id) => id !== void 0 && id !== null);
|
|
901
|
+
if (!ids.length) {
|
|
902
|
+
return /* @__PURE__ */ new Map();
|
|
903
|
+
}
|
|
904
|
+
const where = {
|
|
905
|
+
[primaryKey]: {
|
|
906
|
+
$in: ids
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
const findOptions = {
|
|
910
|
+
...this.getNativePopulateOptions(useDataloader, strategy) ?? {},
|
|
911
|
+
populate: [
|
|
912
|
+
this.relation
|
|
913
|
+
]
|
|
914
|
+
};
|
|
915
|
+
let populatedEntities;
|
|
916
|
+
try {
|
|
917
|
+
populatedEntities = await em.find(entityName, where, findOptions);
|
|
918
|
+
} catch {
|
|
919
|
+
return void 0;
|
|
920
|
+
}
|
|
921
|
+
const relationMeta = this.getRelationMeta();
|
|
922
|
+
const relationsMap = /* @__PURE__ */ new Map();
|
|
923
|
+
const populatedById = /* @__PURE__ */ new Map();
|
|
924
|
+
populatedEntities.forEach((populatedEntity) => {
|
|
925
|
+
const id = populatedEntity[primaryKey];
|
|
926
|
+
if (id !== void 0 && id !== null) {
|
|
927
|
+
populatedById.set(this.serializePrimaryKeyValue(id), populatedEntity);
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
for (const [entity, id] of entityAndIds) {
|
|
931
|
+
if (id === void 0 || id === null) {
|
|
932
|
+
relationsMap.set(entity, []);
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
const resolvedEntity = populatedById.get(this.serializePrimaryKeyValue(id));
|
|
936
|
+
if (!resolvedEntity) {
|
|
937
|
+
relationsMap.set(entity, []);
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
const relations = this.readLoadedRelation(resolvedEntity, relationMeta);
|
|
941
|
+
if (relations === void 0) {
|
|
942
|
+
return void 0;
|
|
943
|
+
}
|
|
944
|
+
relationsMap.set(entity, relations);
|
|
945
|
+
}
|
|
946
|
+
return relationsMap;
|
|
947
|
+
}
|
|
948
|
+
async tryLoadRelationsNatively(entity, useDataloader = false, strategy) {
|
|
949
|
+
const relationsMap = await this.tryBatchLoadRelationsNatively([
|
|
950
|
+
entity
|
|
951
|
+
], useDataloader, strategy);
|
|
952
|
+
if (!relationsMap) {
|
|
953
|
+
return void 0;
|
|
954
|
+
}
|
|
955
|
+
return relationsMap.get(entity) ?? [];
|
|
956
|
+
}
|
|
957
|
+
readLoadedRelation(entity, relationMeta) {
|
|
958
|
+
const entityRecord = entity;
|
|
959
|
+
const propsRecord = entityRecord.props;
|
|
960
|
+
const relationValue = entityRecord[this.relation] !== void 0 ? entityRecord[this.relation] : propsRecord?.[this.relation];
|
|
961
|
+
if (relationMeta.kind === "1:m" || relationMeta.kind === "m:n") {
|
|
962
|
+
if (!relationValue || typeof relationValue !== "object") {
|
|
963
|
+
return void 0;
|
|
964
|
+
}
|
|
965
|
+
const maybeCollection = relationValue;
|
|
966
|
+
if (typeof maybeCollection.getItems === "function") {
|
|
967
|
+
return maybeCollection.getItems(false);
|
|
968
|
+
}
|
|
969
|
+
if (Array.isArray(relationValue)) {
|
|
970
|
+
return relationValue;
|
|
971
|
+
}
|
|
972
|
+
return void 0;
|
|
973
|
+
}
|
|
974
|
+
if (relationValue === null || relationValue === void 0) {
|
|
975
|
+
return [];
|
|
976
|
+
}
|
|
977
|
+
if (typeof relationValue !== "object") {
|
|
978
|
+
return void 0;
|
|
979
|
+
}
|
|
980
|
+
const maybeReference = relationValue;
|
|
981
|
+
if (maybeReference.$ !== void 0) {
|
|
982
|
+
return maybeReference.$ === null ? [] : [
|
|
983
|
+
maybeReference.$
|
|
984
|
+
];
|
|
985
|
+
}
|
|
986
|
+
if (typeof maybeReference.get === "function") {
|
|
987
|
+
try {
|
|
988
|
+
const loaded = maybeReference.get();
|
|
989
|
+
return loaded === null || loaded === void 0 ? [] : [
|
|
990
|
+
loaded
|
|
991
|
+
];
|
|
992
|
+
} catch {
|
|
993
|
+
return void 0;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
if (typeof maybeReference.getEntity === "function") {
|
|
997
|
+
try {
|
|
998
|
+
const loaded = maybeReference.getEntity();
|
|
999
|
+
return loaded === null || loaded === void 0 ? [] : [
|
|
1000
|
+
loaded
|
|
1001
|
+
];
|
|
1002
|
+
} catch {
|
|
1003
|
+
return void 0;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (typeof maybeReference.unwrap === "function") {
|
|
1007
|
+
const loaded = maybeReference.unwrap();
|
|
1008
|
+
return loaded === null || loaded === void 0 ? [] : [
|
|
1009
|
+
loaded
|
|
1010
|
+
];
|
|
1011
|
+
}
|
|
1012
|
+
return [
|
|
1013
|
+
relationValue
|
|
1014
|
+
];
|
|
1015
|
+
}
|
|
1016
|
+
applyPaging(relations, query) {
|
|
1017
|
+
const limit = query.paging?.limit;
|
|
1018
|
+
const offset = query.paging?.offset ?? 0;
|
|
1019
|
+
if (limit === void 0 && offset === 0) {
|
|
1020
|
+
return relations;
|
|
1021
|
+
}
|
|
1022
|
+
if (limit === void 0) {
|
|
1023
|
+
return relations.slice(offset);
|
|
1024
|
+
}
|
|
1025
|
+
return relations.slice(offset, offset + limit);
|
|
1026
|
+
}
|
|
1027
|
+
applyPagingToMap(relationsMap, query) {
|
|
1028
|
+
const mapped = /* @__PURE__ */ new Map();
|
|
1029
|
+
for (const [entity, relations] of relationsMap.entries()) {
|
|
1030
|
+
const paged = this.applyPaging(relations, query);
|
|
1031
|
+
if (paged.length > 0) {
|
|
1032
|
+
mapped.set(entity, paged);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
return mapped;
|
|
1036
|
+
}
|
|
1037
|
+
serializePrimaryKeyValue(value) {
|
|
1038
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
1039
|
+
}
|
|
1040
|
+
hasFilterSortingOrPaging(query) {
|
|
1041
|
+
return this.hasFilterOrSorting(query) || Boolean(query.paging?.limit || query.paging?.offset);
|
|
1042
|
+
}
|
|
1043
|
+
hasFilterOrSorting(query) {
|
|
1044
|
+
return Boolean(query.sorting?.length) || Boolean(query.filter && Object.keys(query.filter).length);
|
|
1045
|
+
}
|
|
1046
|
+
async queryResolvedRelations(resolvedRelations, query) {
|
|
1047
|
+
if (resolvedRelations.length === 0) {
|
|
1048
|
+
return [];
|
|
1049
|
+
}
|
|
1050
|
+
const em = this.repo.getEntityManager();
|
|
1051
|
+
const relationMeta = this.getRelationMeta();
|
|
1052
|
+
const RelationEntity = relationMeta.type;
|
|
1053
|
+
const metadata = em.getMetadata().get(RelationEntity);
|
|
1054
|
+
const primaryKey = metadata.primaryKeys[0];
|
|
1055
|
+
const ids = resolvedRelations.map((r) => r[primaryKey]).filter((v) => v !== void 0 && v !== null);
|
|
1056
|
+
if (!ids.length) {
|
|
1057
|
+
return [];
|
|
1058
|
+
}
|
|
1059
|
+
const idFilter = {
|
|
1060
|
+
[primaryKey]: {
|
|
1061
|
+
$in: ids
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
const { filterQuery, options } = this.filterQueryBuilder.buildFindOptions(query);
|
|
1065
|
+
const finalWhere = filterQuery ? {
|
|
1066
|
+
$and: [
|
|
1067
|
+
idFilter,
|
|
1068
|
+
filterQuery
|
|
1069
|
+
]
|
|
1070
|
+
} : idFilter;
|
|
1071
|
+
const findOptions = {};
|
|
1072
|
+
if (options?.orderBy) findOptions.orderBy = options.orderBy;
|
|
1073
|
+
if (options?.limit !== void 0) findOptions.limit = options.limit;
|
|
1074
|
+
if (options?.offset !== void 0) findOptions.offset = options.offset;
|
|
1075
|
+
return em.find(RelationEntity, finalWhere, findOptions);
|
|
1076
|
+
}
|
|
1077
|
+
async queryByOwnerCondition(entity, query) {
|
|
1078
|
+
const relationMeta = this.getRelationMeta();
|
|
1079
|
+
const em = this.repo.getEntityManager();
|
|
1080
|
+
const RelationEntity = relationMeta.type;
|
|
1081
|
+
const baseWhere = this.buildWhereCondition(entity, relationMeta);
|
|
1082
|
+
const { filterQuery, options } = this.filterQueryBuilder.buildFindOptions(query);
|
|
1083
|
+
const finalWhere = filterQuery ? {
|
|
1084
|
+
$and: [
|
|
1085
|
+
baseWhere,
|
|
1086
|
+
filterQuery
|
|
1087
|
+
]
|
|
1088
|
+
} : baseWhere;
|
|
1089
|
+
const findOptions = {};
|
|
1090
|
+
if (options?.orderBy) findOptions.orderBy = options.orderBy;
|
|
1091
|
+
if (options?.limit !== void 0) findOptions.limit = options.limit;
|
|
1092
|
+
if (options?.offset !== void 0) findOptions.offset = options.offset;
|
|
1093
|
+
return em.find(RelationEntity, finalWhere, findOptions);
|
|
1094
|
+
}
|
|
814
1095
|
buildWhereCondition(entity, relationMeta) {
|
|
815
1096
|
const em = this.repo.getEntityManager();
|
|
816
1097
|
const entityMeta = em.getMetadata().get(this.repo.getEntityName());
|
|
@@ -882,16 +1163,14 @@ var RelationQueryBuilder = class {
|
|
|
882
1163
|
return {
|
|
883
1164
|
[relationPrimaryKey]: fkValue
|
|
884
1165
|
};
|
|
885
|
-
} else {
|
|
886
|
-
return {
|
|
887
|
-
[relationMeta.mappedBy]: entityId
|
|
888
|
-
};
|
|
889
1166
|
}
|
|
1167
|
+
return {
|
|
1168
|
+
[relationMeta.mappedBy]: entityId
|
|
1169
|
+
};
|
|
890
1170
|
}
|
|
891
1171
|
if (relationMeta.kind === "1:m") {
|
|
892
|
-
const mappedBy = relationMeta.mappedBy;
|
|
893
1172
|
return {
|
|
894
|
-
[mappedBy]: entityId
|
|
1173
|
+
[relationMeta.mappedBy]: entityId
|
|
895
1174
|
};
|
|
896
1175
|
}
|
|
897
1176
|
if (relationMeta.kind === "m:n") {
|
|
@@ -899,40 +1178,15 @@ var RelationQueryBuilder = class {
|
|
|
899
1178
|
return {
|
|
900
1179
|
[relationMeta.inversedBy]: entityId
|
|
901
1180
|
};
|
|
902
|
-
} else {
|
|
903
|
-
return {
|
|
904
|
-
[relationMeta.mappedBy]: entityId
|
|
905
|
-
};
|
|
906
1181
|
}
|
|
1182
|
+
return {
|
|
1183
|
+
[relationMeta.mappedBy]: entityId
|
|
1184
|
+
};
|
|
907
1185
|
}
|
|
908
1186
|
return {
|
|
909
1187
|
[entityPrimaryKey]: entityId
|
|
910
1188
|
};
|
|
911
1189
|
}
|
|
912
|
-
getRelationMeta() {
|
|
913
|
-
const em = this.repo.getEntityManager();
|
|
914
|
-
const metadata = em.getMetadata().get(this.repo.getEntityName());
|
|
915
|
-
const relationProp = metadata.properties[this.relation];
|
|
916
|
-
if (!relationProp) {
|
|
917
|
-
throw new Error(`Unable to find relation '${this.relation}' on entity`);
|
|
918
|
-
}
|
|
919
|
-
return relationProp;
|
|
920
|
-
}
|
|
921
|
-
get entityIndexColName() {
|
|
922
|
-
return "__nestjsQuery__entityIndex__";
|
|
923
|
-
}
|
|
924
|
-
getRelationPrimaryKeysPropertyNameAndColumnsName() {
|
|
925
|
-
const em = this.repo.getEntityManager();
|
|
926
|
-
const relationMeta = this.getRelationMeta();
|
|
927
|
-
const relationEntityMeta = em.getMetadata().get(relationMeta.type);
|
|
928
|
-
return relationEntityMeta.primaryKeys.map((pk) => {
|
|
929
|
-
const prop = relationEntityMeta.properties[pk];
|
|
930
|
-
return {
|
|
931
|
-
propertyName: pk,
|
|
932
|
-
columnName: prop.fieldNames?.[0] || pk
|
|
933
|
-
};
|
|
934
|
-
});
|
|
935
|
-
}
|
|
936
1190
|
};
|
|
937
1191
|
var AGG_REGEXP = /^(AVG|SUM|COUNT|MAX|MIN|GROUP_BY|group_by|groupBy|avg|sum|count|max|min)_(.*)$/i;
|
|
938
1192
|
var AggregateBuilder = class _AggregateBuilder {
|
|
@@ -1171,17 +1425,25 @@ var RelationQueryService = class {
|
|
|
1171
1425
|
static {
|
|
1172
1426
|
__name(this, "RelationQueryService");
|
|
1173
1427
|
}
|
|
1428
|
+
relationLoadingStrategy;
|
|
1429
|
+
nativeLoadUseDataloader;
|
|
1430
|
+
constructor(opts) {
|
|
1431
|
+
this.relationLoadingStrategy = opts?.relationLoading?.strategy;
|
|
1432
|
+
this.nativeLoadUseDataloader = opts?.relationLoading?.useDataloader ?? false;
|
|
1433
|
+
}
|
|
1174
1434
|
async queryRelations(RelationClass, relationName, dto, query) {
|
|
1175
1435
|
if (Array.isArray(dto)) {
|
|
1176
1436
|
return this.batchQueryRelations(RelationClass, relationName, dto, query);
|
|
1177
1437
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
}
|
|
1182
|
-
const assembler = AssemblerFactory.getAssembler(RelationClass, this.getRelationEntity(relationName));
|
|
1438
|
+
const bypassAssembler = this.isRelationClassIdentity(RelationClass, relationName);
|
|
1439
|
+
const assembler = bypassAssembler ? void 0 : AssemblerFactory.getAssembler(RelationClass, this.getRelationEntity(relationName));
|
|
1440
|
+
const convertedQuery = assembler ? assembler.convertQuery(query) : query;
|
|
1183
1441
|
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1184
|
-
|
|
1442
|
+
const relations = await relationQueryBuilder.selectAndExecute(dto, convertedQuery, this.getRelationLoadOptions());
|
|
1443
|
+
if (bypassAssembler) {
|
|
1444
|
+
return relations;
|
|
1445
|
+
}
|
|
1446
|
+
return assembler.convertToDTOs(relations);
|
|
1185
1447
|
}
|
|
1186
1448
|
async aggregateRelations(RelationClass, relationName, dto, filter, aggregate) {
|
|
1187
1449
|
if (Array.isArray(dto)) {
|
|
@@ -1219,7 +1481,7 @@ var RelationQueryService = class {
|
|
|
1219
1481
|
paging: {
|
|
1220
1482
|
limit: 1
|
|
1221
1483
|
}
|
|
1222
|
-
});
|
|
1484
|
+
}, this.getRelationLoadOptions());
|
|
1223
1485
|
return relations2[0];
|
|
1224
1486
|
}
|
|
1225
1487
|
const assembler = AssemblerFactory.getAssembler(RelationClass, this.getRelationEntity(relationName));
|
|
@@ -1229,7 +1491,7 @@ var RelationQueryService = class {
|
|
|
1229
1491
|
paging: {
|
|
1230
1492
|
limit: 1
|
|
1231
1493
|
}
|
|
1232
|
-
});
|
|
1494
|
+
}, this.getRelationLoadOptions());
|
|
1233
1495
|
const relationEntity = relations[0];
|
|
1234
1496
|
return relationEntity ? assembler.convertToDTO(relationEntity) : void 0;
|
|
1235
1497
|
}
|
|
@@ -1247,19 +1509,24 @@ var RelationQueryService = class {
|
|
|
1247
1509
|
if (!this.foundAllRelations(relationIds, relations)) {
|
|
1248
1510
|
throw new Error(`Unable to find all ${relationName} to add to ${this.EntityClass.name}`);
|
|
1249
1511
|
}
|
|
1250
|
-
|
|
1512
|
+
const collection = entity[relationName];
|
|
1513
|
+
if (collection && typeof collection.add === "function") {
|
|
1514
|
+
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1515
|
+
const populated = await relationQueryBuilder.populateEntityRelation(entity, this.nativeLoadUseDataloader, this.relationLoadingStrategy);
|
|
1516
|
+
if (!populated) {
|
|
1517
|
+
await collection.init();
|
|
1518
|
+
}
|
|
1251
1519
|
for (const relation of relations) {
|
|
1252
|
-
|
|
1253
|
-
[meta.mappedBy]: entity
|
|
1254
|
-
});
|
|
1520
|
+
collection.add(relation);
|
|
1255
1521
|
}
|
|
1256
1522
|
await this.repo.getEntityManager().flush();
|
|
1257
1523
|
return entity;
|
|
1258
1524
|
}
|
|
1259
|
-
|
|
1260
|
-
if (collection && typeof collection.add === "function") {
|
|
1525
|
+
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1261
1526
|
for (const relation of relations) {
|
|
1262
|
-
|
|
1527
|
+
wrap(relation).assign({
|
|
1528
|
+
[meta.mappedBy]: entity
|
|
1529
|
+
});
|
|
1263
1530
|
}
|
|
1264
1531
|
await this.repo.getEntityManager().flush();
|
|
1265
1532
|
}
|
|
@@ -1283,9 +1550,20 @@ var RelationQueryService = class {
|
|
|
1283
1550
|
throw new Error(`Unable to find all ${relationName} to set on ${this.EntityClass.name}`);
|
|
1284
1551
|
}
|
|
1285
1552
|
}
|
|
1553
|
+
const collection = entity[relationName];
|
|
1554
|
+
if (collection && typeof collection.set === "function") {
|
|
1555
|
+
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1556
|
+
const populated = await relationQueryBuilder.populateEntityRelation(entity, this.nativeLoadUseDataloader, this.relationLoadingStrategy);
|
|
1557
|
+
if (!populated) {
|
|
1558
|
+
await collection.init();
|
|
1559
|
+
}
|
|
1560
|
+
collection.set(relations);
|
|
1561
|
+
await this.repo.getEntityManager().flush();
|
|
1562
|
+
return entity;
|
|
1563
|
+
}
|
|
1286
1564
|
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1287
1565
|
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1288
|
-
const currentRelations = await relationQueryBuilder.selectAndExecute(entity, {});
|
|
1566
|
+
const currentRelations = await relationQueryBuilder.selectAndExecute(entity, {}, this.getRelationLoadOptions());
|
|
1289
1567
|
const nextSet = new Set(relations.map((r) => wrap(r).getPrimaryKey()));
|
|
1290
1568
|
for (const currentRelation of currentRelations) {
|
|
1291
1569
|
const currentPk = wrap(currentRelation).getPrimaryKey();
|
|
@@ -1301,13 +1579,6 @@ var RelationQueryService = class {
|
|
|
1301
1579
|
});
|
|
1302
1580
|
}
|
|
1303
1581
|
await this.repo.getEntityManager().flush();
|
|
1304
|
-
return entity;
|
|
1305
|
-
}
|
|
1306
|
-
const collection = entity[relationName];
|
|
1307
|
-
if (collection && typeof collection.set === "function") {
|
|
1308
|
-
await collection.init();
|
|
1309
|
-
collection.set(relations);
|
|
1310
|
-
await this.repo.getEntityManager().flush();
|
|
1311
1582
|
}
|
|
1312
1583
|
return entity;
|
|
1313
1584
|
}
|
|
@@ -1347,20 +1618,24 @@ var RelationQueryService = class {
|
|
|
1347
1618
|
if (!this.foundAllRelations(relationIds, relations)) {
|
|
1348
1619
|
throw new Error(`Unable to find all ${relationName} to remove from ${this.EntityClass.name}`);
|
|
1349
1620
|
}
|
|
1350
|
-
|
|
1621
|
+
const collection = entity[relationName];
|
|
1622
|
+
if (collection && typeof collection.remove === "function") {
|
|
1623
|
+
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1624
|
+
const populated = await relationQueryBuilder.populateEntityRelation(entity, this.nativeLoadUseDataloader, this.relationLoadingStrategy);
|
|
1625
|
+
if (!populated) {
|
|
1626
|
+
await collection.init();
|
|
1627
|
+
}
|
|
1351
1628
|
for (const relation of relations) {
|
|
1352
|
-
|
|
1353
|
-
[meta.mappedBy]: null
|
|
1354
|
-
});
|
|
1629
|
+
collection.remove(relation);
|
|
1355
1630
|
}
|
|
1356
1631
|
await this.repo.getEntityManager().flush();
|
|
1357
1632
|
return entity;
|
|
1358
1633
|
}
|
|
1359
|
-
|
|
1360
|
-
if (collection && typeof collection.remove === "function") {
|
|
1361
|
-
await collection.init();
|
|
1634
|
+
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1362
1635
|
for (const relation of relations) {
|
|
1363
|
-
|
|
1636
|
+
wrap(relation).assign({
|
|
1637
|
+
[meta.mappedBy]: null
|
|
1638
|
+
});
|
|
1364
1639
|
}
|
|
1365
1640
|
await this.repo.getEntityManager().flush();
|
|
1366
1641
|
}
|
|
@@ -1384,29 +1659,30 @@ var RelationQueryService = class {
|
|
|
1384
1659
|
const meta = this.getRelationMeta(relationName);
|
|
1385
1660
|
if (meta.kind === "1:1" || meta.kind === "m:1") {
|
|
1386
1661
|
const fkFieldName = `${relationName}Id`;
|
|
1387
|
-
const assignData = {
|
|
1662
|
+
const assignData = {
|
|
1663
|
+
[relationName]: null
|
|
1664
|
+
};
|
|
1388
1665
|
const ownDescriptor = Object.getOwnPropertyDescriptor(entity, fkFieldName);
|
|
1389
1666
|
const protoDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), fkFieldName);
|
|
1390
1667
|
const descriptor = ownDescriptor ?? protoDescriptor;
|
|
1391
1668
|
const canAssignFk = fkFieldName in entity && (!descriptor || Boolean(descriptor.set) || descriptor.writable === true);
|
|
1392
1669
|
if (canAssignFk) {
|
|
1393
1670
|
assignData[fkFieldName] = null;
|
|
1394
|
-
} else {
|
|
1395
|
-
assignData[relationName] = null;
|
|
1396
1671
|
}
|
|
1397
1672
|
wrap(entity).assign(assignData);
|
|
1398
1673
|
} else {
|
|
1399
|
-
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1400
|
-
wrap(relation).assign({
|
|
1401
|
-
[meta.mappedBy]: null
|
|
1402
|
-
});
|
|
1403
|
-
await this.repo.getEntityManager().flush();
|
|
1404
|
-
return entity;
|
|
1405
|
-
}
|
|
1406
1674
|
const collection = entity[relationName];
|
|
1407
1675
|
if (collection && typeof collection.remove === "function") {
|
|
1408
|
-
|
|
1676
|
+
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1677
|
+
const populated = await relationQueryBuilder.populateEntityRelation(entity, this.nativeLoadUseDataloader, this.relationLoadingStrategy);
|
|
1678
|
+
if (!populated) {
|
|
1679
|
+
await collection.init();
|
|
1680
|
+
}
|
|
1409
1681
|
collection.remove(relation);
|
|
1682
|
+
} else if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1683
|
+
wrap(relation).assign({
|
|
1684
|
+
[meta.mappedBy]: null
|
|
1685
|
+
});
|
|
1410
1686
|
}
|
|
1411
1687
|
}
|
|
1412
1688
|
await this.repo.getEntityManager().flush();
|
|
@@ -1427,15 +1703,18 @@ var RelationQueryService = class {
|
|
|
1427
1703
|
const assembler = bypassAssembler ? void 0 : AssemblerFactory.getAssembler(RelationClass, this.getRelationEntity(relationName));
|
|
1428
1704
|
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1429
1705
|
const convertedQuery = assembler ? assembler.convertQuery(query) : query;
|
|
1430
|
-
const
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1706
|
+
const relationsMap = await relationQueryBuilder.batchSelectAndExecute(entities, convertedQuery, this.getRelationLoadOptions());
|
|
1707
|
+
if (bypassAssembler) {
|
|
1708
|
+
return relationsMap;
|
|
1709
|
+
}
|
|
1710
|
+
const dtoMap = /* @__PURE__ */ new Map();
|
|
1711
|
+
for (const [entity, relations] of relationsMap.entries()) {
|
|
1712
|
+
const relationDtos = await assembler.convertToDTOs(relations);
|
|
1434
1713
|
if (relationDtos.length > 0) {
|
|
1435
|
-
|
|
1714
|
+
dtoMap.set(entity, relationDtos);
|
|
1436
1715
|
}
|
|
1437
|
-
}
|
|
1438
|
-
return
|
|
1716
|
+
}
|
|
1717
|
+
return dtoMap;
|
|
1439
1718
|
}
|
|
1440
1719
|
/**
|
|
1441
1720
|
* Query for an array of relations for multiple dtos.
|
|
@@ -1504,6 +1783,12 @@ var RelationQueryService = class {
|
|
|
1504
1783
|
const relationEntity = this.getRelationEntity(relationName);
|
|
1505
1784
|
return RelationClass === relationEntity || RelationClass.name === relationEntity.name;
|
|
1506
1785
|
}
|
|
1786
|
+
getRelationLoadOptions() {
|
|
1787
|
+
return {
|
|
1788
|
+
strategy: this.relationLoadingStrategy,
|
|
1789
|
+
useDataloader: this.nativeLoadUseDataloader
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1507
1792
|
getRelationMeta(relationName) {
|
|
1508
1793
|
const em = this.repo.getEntityManager();
|
|
1509
1794
|
const metadata = em.getMetadata().get(this.repo.getEntityName());
|
|
@@ -1562,7 +1847,9 @@ var MikroOrmQueryService = class extends RelationQueryService {
|
|
|
1562
1847
|
filterQueryBuilder;
|
|
1563
1848
|
useSoftDelete;
|
|
1564
1849
|
constructor(repo, opts) {
|
|
1565
|
-
super(
|
|
1850
|
+
super({
|
|
1851
|
+
relationLoading: opts?.relationLoading
|
|
1852
|
+
}), this.repo = repo;
|
|
1566
1853
|
this.filterQueryBuilder = opts?.filterQueryBuilder ?? new FilterQueryBuilder(this.repo);
|
|
1567
1854
|
this.useSoftDelete = opts?.useSoftDelete ?? false;
|
|
1568
1855
|
const serializer = getAssemblerSerializer(this.EntityClass);
|
|
@@ -1583,7 +1870,11 @@ var MikroOrmQueryService = class extends RelationQueryService {
|
|
|
1583
1870
|
return data;
|
|
1584
1871
|
})(this.EntityClass);
|
|
1585
1872
|
AssemblerDeserializer((d) => {
|
|
1586
|
-
const entity = this.repo.getEntityManager().
|
|
1873
|
+
const entity = this.repo.getEntityManager().create(this.EntityClass, d, {
|
|
1874
|
+
managed: true,
|
|
1875
|
+
convertCustomTypes: true,
|
|
1876
|
+
partial: true
|
|
1877
|
+
});
|
|
1587
1878
|
return entity;
|
|
1588
1879
|
})(this.EntityClass);
|
|
1589
1880
|
}
|
|
@@ -2080,12 +2371,12 @@ var MikroOrmQueryService = class extends RelationQueryService {
|
|
|
2080
2371
|
};
|
|
2081
2372
|
|
|
2082
2373
|
// src/lib/providers.ts
|
|
2083
|
-
function createMikroOrmQueryServiceProvider(EntityClass, contextName) {
|
|
2374
|
+
function createMikroOrmQueryServiceProvider(EntityClass, contextName, opts) {
|
|
2084
2375
|
return {
|
|
2085
2376
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2086
2377
|
provide: getQueryServiceToken(EntityClass),
|
|
2087
2378
|
useFactory(repo) {
|
|
2088
|
-
return new MikroOrmQueryService(repo);
|
|
2379
|
+
return new MikroOrmQueryService(repo, opts);
|
|
2089
2380
|
},
|
|
2090
2381
|
inject: [
|
|
2091
2382
|
getRepositoryToken(EntityClass, contextName)
|
|
@@ -2093,15 +2384,17 @@ function createMikroOrmQueryServiceProvider(EntityClass, contextName) {
|
|
|
2093
2384
|
};
|
|
2094
2385
|
}
|
|
2095
2386
|
__name(createMikroOrmQueryServiceProvider, "createMikroOrmQueryServiceProvider");
|
|
2096
|
-
var createMikroOrmQueryServiceProviders = /* @__PURE__ */ __name((entities, contextName) => entities.map((entity) => createMikroOrmQueryServiceProvider(entity, contextName)), "createMikroOrmQueryServiceProviders");
|
|
2387
|
+
var createMikroOrmQueryServiceProviders = /* @__PURE__ */ __name((entities, contextName, opts) => entities.map((entity) => createMikroOrmQueryServiceProvider(entity, contextName, opts)), "createMikroOrmQueryServiceProviders");
|
|
2097
2388
|
|
|
2098
2389
|
// src/lib/nest-query-mikro-orm.module.ts
|
|
2099
2390
|
var NestjsQueryMikroOrmModule = class _NestjsQueryMikroOrmModule {
|
|
2100
2391
|
static {
|
|
2101
2392
|
__name(this, "NestjsQueryMikroOrmModule");
|
|
2102
2393
|
}
|
|
2103
|
-
static forFeature(entities,
|
|
2104
|
-
const
|
|
2394
|
+
static forFeature(entities, contextNameOrOptions) {
|
|
2395
|
+
const contextName = typeof contextNameOrOptions === "string" ? contextNameOrOptions : contextNameOrOptions?.contextName;
|
|
2396
|
+
const queryServiceOpts = typeof contextNameOrOptions === "string" ? void 0 : contextNameOrOptions?.queryServiceOpts;
|
|
2397
|
+
const queryServiceProviders = createMikroOrmQueryServiceProviders(entities, contextName, queryServiceOpts);
|
|
2105
2398
|
const mikroOrmModule = MikroOrmModule.forFeature(entities, contextName);
|
|
2106
2399
|
return {
|
|
2107
2400
|
imports: [
|