nestjs-query-mikro-orm 0.1.0 → 0.1.2
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 +90 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +91 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -342,6 +342,7 @@ declare abstract class RelationQueryService<Entity extends object> {
|
|
|
342
342
|
* @param query - A query to filter, page or sort relations.
|
|
343
343
|
*/
|
|
344
344
|
private batchFindRelations;
|
|
345
|
+
private isRelationClassIdentity;
|
|
345
346
|
private getRelationMeta;
|
|
346
347
|
private getRelationEntity;
|
|
347
348
|
private getRelations;
|
package/dist/index.d.ts
CHANGED
|
@@ -342,6 +342,7 @@ declare abstract class RelationQueryService<Entity extends object> {
|
|
|
342
342
|
* @param query - A query to filter, page or sort relations.
|
|
343
343
|
*/
|
|
344
344
|
private batchFindRelations;
|
|
345
|
+
private isRelationClassIdentity;
|
|
345
346
|
private getRelationMeta;
|
|
346
347
|
private getRelationEntity;
|
|
347
348
|
private getRelations;
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { MikroOrmModule, getRepositoryToken } from '@mikro-orm/nestjs';
|
|
2
|
-
import { getFilterFields, AssemblerFactory,
|
|
2
|
+
import { getFilterFields, AssemblerFactory, getQueryServiceToken } from '@ptc-org/nestjs-query-core';
|
|
3
3
|
import { raw, wrap } from '@mikro-orm/core';
|
|
4
|
-
import { getAssemblerSerializer } from '@ptc-org/nestjs-query-core/src/assemblers/assembler.serializer';
|
|
5
4
|
import { BadRequestException, NotFoundException, MethodNotAllowedException } from '@nestjs/common';
|
|
6
|
-
import { instanceToPlain } from 'class-transformer';
|
|
7
5
|
import merge from 'lodash.merge';
|
|
8
6
|
|
|
9
7
|
var __defProp = Object.defineProperty;
|
|
@@ -834,7 +832,14 @@ var RelationQueryBuilder = class {
|
|
|
834
832
|
const entityKeys = Object.keys(entityAsRecord);
|
|
835
833
|
const matchingKey = entityKeys.find((key) => {
|
|
836
834
|
const keyLower = key.toLowerCase();
|
|
837
|
-
|
|
835
|
+
if (keyLower === "id" || !keyLower.endsWith("id")) {
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
const base = keyLower.replace(/id$/, "");
|
|
839
|
+
if (!base) {
|
|
840
|
+
return false;
|
|
841
|
+
}
|
|
842
|
+
return relationNameLower.includes(base);
|
|
838
843
|
});
|
|
839
844
|
if (matchingKey) {
|
|
840
845
|
fkValue = entityAsRecord[matchingKey];
|
|
@@ -1168,6 +1173,10 @@ var RelationQueryService = class {
|
|
|
1168
1173
|
if (Array.isArray(dto)) {
|
|
1169
1174
|
return this.batchQueryRelations(RelationClass, relationName, dto, query);
|
|
1170
1175
|
}
|
|
1176
|
+
if (this.isRelationClassIdentity(RelationClass, relationName)) {
|
|
1177
|
+
const relationQueryBuilder2 = this.getRelationQueryBuilder(relationName);
|
|
1178
|
+
return await relationQueryBuilder2.selectAndExecute(dto, query);
|
|
1179
|
+
}
|
|
1171
1180
|
const assembler = AssemblerFactory.getAssembler(RelationClass, this.getRelationEntity(relationName));
|
|
1172
1181
|
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1173
1182
|
return assembler.convertToDTOs(await relationQueryBuilder.selectAndExecute(dto, assembler.convertQuery(query)));
|
|
@@ -1201,6 +1210,16 @@ var RelationQueryService = class {
|
|
|
1201
1210
|
if (Array.isArray(dto)) {
|
|
1202
1211
|
return this.batchFindRelations(RelationClass, relationName, dto, opts);
|
|
1203
1212
|
}
|
|
1213
|
+
if (this.isRelationClassIdentity(RelationClass, relationName)) {
|
|
1214
|
+
const relationQueryBuilder2 = this.getRelationQueryBuilder(relationName);
|
|
1215
|
+
const relations2 = await relationQueryBuilder2.selectAndExecute(dto, {
|
|
1216
|
+
filter: opts?.filter,
|
|
1217
|
+
paging: {
|
|
1218
|
+
limit: 1
|
|
1219
|
+
}
|
|
1220
|
+
});
|
|
1221
|
+
return relations2[0];
|
|
1222
|
+
}
|
|
1204
1223
|
const assembler = AssemblerFactory.getAssembler(RelationClass, this.getRelationEntity(relationName));
|
|
1205
1224
|
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1206
1225
|
const relations = await relationQueryBuilder.selectAndExecute(dto, {
|
|
@@ -1221,10 +1240,20 @@ var RelationQueryService = class {
|
|
|
1221
1240
|
*/
|
|
1222
1241
|
async addRelations(relationName, id, relationIds, opts) {
|
|
1223
1242
|
const entity = await this.getById(id, opts);
|
|
1243
|
+
const meta = this.getRelationMeta(relationName);
|
|
1224
1244
|
const relations = await this.getRelations(relationName, relationIds, opts?.relationFilter);
|
|
1225
1245
|
if (!this.foundAllRelations(relationIds, relations)) {
|
|
1226
1246
|
throw new Error(`Unable to find all ${relationName} to add to ${this.EntityClass.name}`);
|
|
1227
1247
|
}
|
|
1248
|
+
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1249
|
+
for (const relation of relations) {
|
|
1250
|
+
wrap(relation).assign({
|
|
1251
|
+
[meta.mappedBy]: entity
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
await this.repo.getEntityManager().flush();
|
|
1255
|
+
return entity;
|
|
1256
|
+
}
|
|
1228
1257
|
const collection = entity[relationName];
|
|
1229
1258
|
if (collection && typeof collection.add === "function") {
|
|
1230
1259
|
for (const relation of relations) {
|
|
@@ -1245,12 +1274,33 @@ var RelationQueryService = class {
|
|
|
1245
1274
|
*/
|
|
1246
1275
|
async setRelations(relationName, id, relationIds, opts) {
|
|
1247
1276
|
const entity = await this.getById(id, opts);
|
|
1277
|
+
const meta = this.getRelationMeta(relationName);
|
|
1248
1278
|
const relations = await this.getRelations(relationName, relationIds, opts?.relationFilter);
|
|
1249
1279
|
if (relationIds.length) {
|
|
1250
1280
|
if (!this.foundAllRelations(relationIds, relations)) {
|
|
1251
1281
|
throw new Error(`Unable to find all ${relationName} to set on ${this.EntityClass.name}`);
|
|
1252
1282
|
}
|
|
1253
1283
|
}
|
|
1284
|
+
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1285
|
+
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1286
|
+
const currentRelations = await relationQueryBuilder.selectAndExecute(entity, {});
|
|
1287
|
+
const nextSet = new Set(relations.map((r) => wrap(r).getPrimaryKey()));
|
|
1288
|
+
for (const currentRelation of currentRelations) {
|
|
1289
|
+
const currentPk = wrap(currentRelation).getPrimaryKey();
|
|
1290
|
+
if (!nextSet.has(currentPk)) {
|
|
1291
|
+
wrap(currentRelation).assign({
|
|
1292
|
+
[meta.mappedBy]: null
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
for (const relation of relations) {
|
|
1297
|
+
wrap(relation).assign({
|
|
1298
|
+
[meta.mappedBy]: entity
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
await this.repo.getEntityManager().flush();
|
|
1302
|
+
return entity;
|
|
1303
|
+
}
|
|
1254
1304
|
const collection = entity[relationName];
|
|
1255
1305
|
if (collection && typeof collection.set === "function") {
|
|
1256
1306
|
await collection.init();
|
|
@@ -1290,10 +1340,20 @@ var RelationQueryService = class {
|
|
|
1290
1340
|
*/
|
|
1291
1341
|
async removeRelations(relationName, id, relationIds, opts) {
|
|
1292
1342
|
const entity = await this.getById(id, opts);
|
|
1343
|
+
const meta = this.getRelationMeta(relationName);
|
|
1293
1344
|
const relations = await this.getRelations(relationName, relationIds, opts?.relationFilter);
|
|
1294
1345
|
if (!this.foundAllRelations(relationIds, relations)) {
|
|
1295
1346
|
throw new Error(`Unable to find all ${relationName} to remove from ${this.EntityClass.name}`);
|
|
1296
1347
|
}
|
|
1348
|
+
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1349
|
+
for (const relation of relations) {
|
|
1350
|
+
wrap(relation).assign({
|
|
1351
|
+
[meta.mappedBy]: null
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
await this.repo.getEntityManager().flush();
|
|
1355
|
+
return entity;
|
|
1356
|
+
}
|
|
1297
1357
|
const collection = entity[relationName];
|
|
1298
1358
|
if (collection && typeof collection.remove === "function") {
|
|
1299
1359
|
await collection.init();
|
|
@@ -1322,14 +1382,25 @@ var RelationQueryService = class {
|
|
|
1322
1382
|
const meta = this.getRelationMeta(relationName);
|
|
1323
1383
|
if (meta.kind === "1:1" || meta.kind === "m:1") {
|
|
1324
1384
|
const fkFieldName = `${relationName}Id`;
|
|
1325
|
-
const assignData = {
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1385
|
+
const assignData = {};
|
|
1386
|
+
const ownDescriptor = Object.getOwnPropertyDescriptor(entity, fkFieldName);
|
|
1387
|
+
const protoDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), fkFieldName);
|
|
1388
|
+
const descriptor = ownDescriptor ?? protoDescriptor;
|
|
1389
|
+
const canAssignFk = fkFieldName in entity && (!descriptor || Boolean(descriptor.set) || descriptor.writable === true);
|
|
1390
|
+
if (canAssignFk) {
|
|
1329
1391
|
assignData[fkFieldName] = null;
|
|
1392
|
+
} else {
|
|
1393
|
+
assignData[relationName] = null;
|
|
1330
1394
|
}
|
|
1331
1395
|
wrap(entity).assign(assignData);
|
|
1332
1396
|
} else {
|
|
1397
|
+
if (meta.kind === "1:m" && meta.mappedBy) {
|
|
1398
|
+
wrap(relation).assign({
|
|
1399
|
+
[meta.mappedBy]: null
|
|
1400
|
+
});
|
|
1401
|
+
await this.repo.getEntityManager().flush();
|
|
1402
|
+
return entity;
|
|
1403
|
+
}
|
|
1333
1404
|
const collection = entity[relationName];
|
|
1334
1405
|
if (collection && typeof collection.remove === "function") {
|
|
1335
1406
|
await collection.init();
|
|
@@ -1350,13 +1421,14 @@ var RelationQueryService = class {
|
|
|
1350
1421
|
* @param query - A query to filter, page or sort relations.
|
|
1351
1422
|
*/
|
|
1352
1423
|
async batchQueryRelations(RelationClass, relationName, entities, query) {
|
|
1353
|
-
const
|
|
1424
|
+
const bypassAssembler = this.isRelationClassIdentity(RelationClass, relationName);
|
|
1425
|
+
const assembler = bypassAssembler ? void 0 : AssemblerFactory.getAssembler(RelationClass, this.getRelationEntity(relationName));
|
|
1354
1426
|
const relationQueryBuilder = this.getRelationQueryBuilder(relationName);
|
|
1355
|
-
const convertedQuery = assembler.convertQuery(query);
|
|
1427
|
+
const convertedQuery = assembler ? assembler.convertQuery(query) : query;
|
|
1356
1428
|
const results = /* @__PURE__ */ new Map();
|
|
1357
1429
|
await Promise.all(entities.map(async (entity) => {
|
|
1358
1430
|
const relations = await relationQueryBuilder.selectAndExecute(entity, convertedQuery);
|
|
1359
|
-
const relationDtos = await assembler.convertToDTOs(relations);
|
|
1431
|
+
const relationDtos = bypassAssembler ? relations : await assembler.convertToDTOs(relations);
|
|
1360
1432
|
if (relationDtos.length > 0) {
|
|
1361
1433
|
results.set(entity, relationDtos);
|
|
1362
1434
|
}
|
|
@@ -1426,6 +1498,10 @@ var RelationQueryService = class {
|
|
|
1426
1498
|
});
|
|
1427
1499
|
return results;
|
|
1428
1500
|
}
|
|
1501
|
+
isRelationClassIdentity(RelationClass, relationName) {
|
|
1502
|
+
const relationEntity = this.getRelationEntity(relationName);
|
|
1503
|
+
return RelationClass === relationEntity || RelationClass.name === relationEntity.name;
|
|
1504
|
+
}
|
|
1429
1505
|
getRelationMeta(relationName) {
|
|
1430
1506
|
const em = this.repo.getEntityManager();
|
|
1431
1507
|
const metadata = em.getMetadata().get(this.repo.getEntityName());
|
|
@@ -1436,12 +1512,14 @@ var RelationQueryService = class {
|
|
|
1436
1512
|
return {
|
|
1437
1513
|
kind: relationMeta.kind,
|
|
1438
1514
|
type: relationMeta.type,
|
|
1439
|
-
entity: relationMeta.entity
|
|
1515
|
+
entity: relationMeta.entity,
|
|
1516
|
+
mappedBy: relationMeta.mappedBy
|
|
1440
1517
|
};
|
|
1441
1518
|
}
|
|
1442
1519
|
getRelationEntity(relationName) {
|
|
1443
1520
|
const relationMeta = this.getRelationMeta(relationName);
|
|
1444
|
-
|
|
1521
|
+
const entity = relationMeta.entity();
|
|
1522
|
+
return entity && "class" in entity ? entity.class : entity;
|
|
1445
1523
|
}
|
|
1446
1524
|
async getRelations(relationName, ids, filter) {
|
|
1447
1525
|
const em = this.repo.getEntityManager();
|
|
@@ -1485,28 +1563,6 @@ var MikroOrmQueryService = class extends RelationQueryService {
|
|
|
1485
1563
|
super(), this.repo = repo;
|
|
1486
1564
|
this.filterQueryBuilder = opts?.filterQueryBuilder ?? new FilterQueryBuilder(this.repo);
|
|
1487
1565
|
this.useSoftDelete = opts?.useSoftDelete ?? false;
|
|
1488
|
-
const serializer = getAssemblerSerializer(this.EntityClass);
|
|
1489
|
-
if (!serializer) {
|
|
1490
|
-
AssemblerSerializer((e) => {
|
|
1491
|
-
const json = instanceToPlain(e, {
|
|
1492
|
-
enableImplicitConversion: true,
|
|
1493
|
-
excludeExtraneousValues: true,
|
|
1494
|
-
exposeDefaultValues: true
|
|
1495
|
-
});
|
|
1496
|
-
const jsonWithRemovedEmptyObjects = Object.fromEntries(Object.entries(json).filter(([, value]) => !(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0)));
|
|
1497
|
-
const wrapped = wrap(e, true);
|
|
1498
|
-
const ormJson = "toObject" in wrapped ? wrapped.toObject() : {};
|
|
1499
|
-
const data = {
|
|
1500
|
-
...ormJson,
|
|
1501
|
-
...jsonWithRemovedEmptyObjects
|
|
1502
|
-
};
|
|
1503
|
-
return data;
|
|
1504
|
-
})(this.EntityClass);
|
|
1505
|
-
AssemblerDeserializer((d) => {
|
|
1506
|
-
const entity = this.repo.getEntityManager().create(this.EntityClass, instanceToPlain(d));
|
|
1507
|
-
return entity;
|
|
1508
|
-
})(this.EntityClass);
|
|
1509
|
-
}
|
|
1510
1566
|
}
|
|
1511
1567
|
get EntityClass() {
|
|
1512
1568
|
const em = this.repo.getEntityManager();
|