@goatlab/fluent 0.7.5 → 0.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/BaseConnector.d.ts +8 -31
  2. package/dist/BaseConnector.js +11 -104
  3. package/dist/FluentConnectorInterface.d.ts +17 -0
  4. package/dist/FluentConnectorInterface.js +2 -0
  5. package/dist/TypeOrmConnector/TypeOrmConnector.d.ts +8 -12
  6. package/dist/TypeOrmConnector/TypeOrmConnector.js +183 -546
  7. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoBaseAggregations.d.ts +7 -0
  8. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoBaseAggregations.js +148 -0
  9. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoFindAggregatedQuery.d.ts +6 -0
  10. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoFindAggregatedQuery.js +34 -0
  11. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoSelect.d.ts +4 -0
  12. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoSelect.js +12 -0
  13. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoWhere.d.ts +6 -0
  14. package/dist/TypeOrmConnector/queryBuilder/mongodb/getMongoWhere.js +166 -0
  15. package/dist/TypeOrmConnector/queryBuilder/sql/getQueryBuilderWhere.d.ts +8 -0
  16. package/dist/TypeOrmConnector/queryBuilder/sql/getQueryBuilderWhere.js +200 -0
  17. package/dist/TypeOrmConnector/queryBuilder/sql/getTypeOrmWhere.d.ts +6 -0
  18. package/dist/TypeOrmConnector/queryBuilder/sql/getTypeOrmWhere.js +207 -0
  19. package/dist/TypeOrmConnector/test/basic/goat.entity.d.ts +3 -3
  20. package/dist/TypeOrmConnector/test/basic/goat.entity.js +1 -1
  21. package/dist/TypeOrmConnector/test/docker/docker.d.ts +1 -1
  22. package/dist/TypeOrmConnector/test/docker/docker.js +3 -4
  23. package/dist/TypeOrmConnector/test/docker/mongo.d.ts +16 -0
  24. package/dist/TypeOrmConnector/test/docker/mongo.js +93 -0
  25. package/dist/TypeOrmConnector/test/docker/mysql.js +1 -1
  26. package/dist/TypeOrmConnector/test/mongo/car.mongo.repository.d.ts +4 -2
  27. package/dist/TypeOrmConnector/test/mongo/car.mongo.repository.js +6 -1
  28. package/dist/TypeOrmConnector/test/mongo/roles.mongo.repository.d.ts +3 -2
  29. package/dist/TypeOrmConnector/test/mongo/roles.mongo.repository.js +3 -1
  30. package/dist/TypeOrmConnector/test/mongo/user.mongo.repository.d.ts +2 -2
  31. package/dist/TypeOrmConnector/test/mongo/user.mongo.repository.js +2 -1
  32. package/dist/TypeOrmConnector/test/mysql/car.mysql.repository.d.ts +6 -2
  33. package/dist/TypeOrmConnector/test/mysql/car.mysql.repository.js +10 -1
  34. package/dist/TypeOrmConnector/test/mysql/mysqlDataSource.js +1 -1
  35. package/dist/TypeOrmConnector/test/mysql/roles.mysql.repository.d.ts +3 -2
  36. package/dist/TypeOrmConnector/test/mysql/roles.mysql.repository.js +3 -1
  37. package/dist/TypeOrmConnector/test/mysql/user.mysql.repository.d.ts +2 -2
  38. package/dist/TypeOrmConnector/test/mysql/user.mysql.repository.js +2 -1
  39. package/dist/TypeOrmConnector/test/relations/car/car.entity.d.ts +0 -1
  40. package/dist/TypeOrmConnector/test/relations/car/car.entity.js +0 -8
  41. package/dist/TypeOrmConnector/test/relations/car/car.output.schema.d.ts +511 -0
  42. package/dist/TypeOrmConnector/test/relations/car/car.output.schema.js +8 -0
  43. package/dist/TypeOrmConnector/test/relations/car/car.repositoryTypeOrm.d.ts +4 -2
  44. package/dist/TypeOrmConnector/test/relations/car/car.repositoryTypeOrm.js +6 -1
  45. package/dist/TypeOrmConnector/test/relations/car/car.schema.d.ts +2 -25
  46. package/dist/TypeOrmConnector/test/relations/car/car.schema.js +3 -8
  47. package/dist/TypeOrmConnector/test/relations/relationsTestsSuite.d.ts +1 -1
  48. package/dist/TypeOrmConnector/test/relations/relationsTestsSuite.js +435 -35
  49. package/dist/TypeOrmConnector/test/relations/roles/role.output.schema.d.ts +152 -0
  50. package/dist/TypeOrmConnector/test/relations/roles/role.output.schema.js +14 -0
  51. package/dist/TypeOrmConnector/test/relations/roles/role.schema.d.ts +2 -25
  52. package/dist/TypeOrmConnector/test/relations/roles/role.schema.js +2 -10
  53. package/dist/TypeOrmConnector/test/relations/roles/roles.repositoryTypeOrm.d.ts +3 -2
  54. package/dist/TypeOrmConnector/test/relations/roles/roles.repositoryTypeOrm.js +3 -1
  55. package/dist/TypeOrmConnector/test/relations/user/user.repositoryTypeOrm.d.ts +2 -2
  56. package/dist/TypeOrmConnector/test/relations/user/user.repositoryTypeOrm.js +2 -1
  57. package/dist/TypeOrmConnector/test/relations/user/user.schema.d.ts +465 -69
  58. package/dist/TypeOrmConnector/test/relations/user/user.schema.js +54 -5
  59. package/dist/TypeOrmConnector/util/clearEmpties.d.ts +1 -0
  60. package/dist/TypeOrmConnector/util/clearEmpties.js +25 -0
  61. package/dist/TypeOrmConnector/util/extractConditions.d.ts +6 -0
  62. package/dist/TypeOrmConnector/util/extractConditions.js +80 -0
  63. package/dist/TypeOrmConnector/util/extractInclude.d.ts +2 -0
  64. package/dist/TypeOrmConnector/util/extractInclude.js +25 -0
  65. package/dist/TypeOrmConnector/util/extractMetadataFromKeys.d.ts +12 -0
  66. package/dist/TypeOrmConnector/util/extractMetadataFromKeys.js +42 -0
  67. package/dist/TypeOrmConnector/util/extractOrderBy.d.ts +4 -0
  68. package/dist/TypeOrmConnector/util/extractOrderBy.js +18 -0
  69. package/dist/TypeOrmConnector/util/getRelationsFromModelGenerator.d.ts +19 -0
  70. package/dist/TypeOrmConnector/util/getRelationsFromModelGenerator.js +26 -0
  71. package/dist/TypeOrmConnector/util/getSelectedKeysFromRawSql.d.ts +1 -0
  72. package/dist/TypeOrmConnector/util/getSelectedKeysFromRawSql.js +20 -0
  73. package/dist/TypeOrmConnector/util/isAnyObject.d.ts +1 -0
  74. package/dist/TypeOrmConnector/util/isAnyObject.js +7 -0
  75. package/dist/TypeOrmConnector/util/nestQueryResults.d.ts +2 -0
  76. package/dist/TypeOrmConnector/util/nestQueryResults.js +31 -0
  77. package/dist/index.d.ts +5 -4
  78. package/dist/index.js +2 -1
  79. package/dist/loadRelations.js +8 -10
  80. package/dist/tsconfig.tsbuildinfo +1 -1
  81. package/dist/types.d.ts +37 -20
  82. package/package.json +4 -3
  83. package/CHANGELOG.md +0 -1072
  84. package/dist/TypeOrmConnector/test/mongo/mongo.memory.d.ts +0 -4
  85. package/dist/TypeOrmConnector/test/mongo/mongo.memory.js +0 -43
@@ -1,35 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TypeOrmConnector = exports.getRelationsFromModelGenerator = void 0;
4
- const types_1 = require("./../types");
5
- const typeorm_1 = require("typeorm");
3
+ exports.TypeOrmConnector = void 0;
6
4
  const js_utils_1 = require("@goatlab/js-utils");
7
5
  const BaseConnector_1 = require("../BaseConnector");
8
6
  const outputKeys_1 = require("../outputKeys");
9
7
  const generatorDatasource_1 = require("../generatorDatasource");
10
- const getRelationsFromModelGenerator = (typeOrmRepo) => {
11
- const relations = {};
12
- for (const relation of typeOrmRepo.metadata.relations) {
13
- const pPath = relation.inverseRelation?.joinColumns[0];
14
- relations[relation.propertyName] = {
15
- isOneToMany: relation.isOneToMany,
16
- isManyToOne: relation.isManyToOne,
17
- isManyToMany: relation.isManyToMany,
18
- inverseSidePropertyRelationPath: relation.inverseSidePropertyPath,
19
- inverseSidePropertyPath: pPath?.propertyPath,
20
- propertyName: relation.propertyName,
21
- entityName: relation.inverseEntityMetadata.name,
22
- tableName: relation.inverseEntityMetadata.tableName,
23
- targetClass: relation.inverseEntityMetadata.target,
24
- joinColumns: relation.joinColumns,
25
- inverseJoinColumns: relation.inverseJoinColumns
26
- };
27
- }
28
- return {
29
- relations
30
- };
31
- };
32
- exports.getRelationsFromModelGenerator = getRelationsFromModelGenerator;
8
+ const getMongoWhere_1 = require("./queryBuilder/mongodb/getMongoWhere");
9
+ const getRelationsFromModelGenerator_1 = require("./util/getRelationsFromModelGenerator");
10
+ const getMongoFindAggregatedQuery_1 = require("./queryBuilder/mongodb/getMongoFindAggregatedQuery");
11
+ const extractInclude_1 = require("./util/extractInclude");
12
+ const extractOrderBy_1 = require("./util/extractOrderBy");
13
+ const getTypeOrmWhere_1 = require("./queryBuilder/sql/getTypeOrmWhere");
14
+ const getQueryBuilderWhere_1 = require("./queryBuilder/sql/getQueryBuilderWhere");
15
+ const clearEmpties_1 = require("./util/clearEmpties");
33
16
  class TypeOrmConnector extends BaseConnector_1.BaseConnector {
34
17
  constructor({ entity, dataSource, inputSchema, outputSchema }) {
35
18
  super();
@@ -45,7 +28,7 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
45
28
  this.repository = this.dataSource.getMongoRepository(entity);
46
29
  }
47
30
  const relationShipBuilder = generatorDatasource_1.modelGeneratorDataSource.getRepository(entity);
48
- const { relations } = (0, exports.getRelationsFromModelGenerator)(relationShipBuilder);
31
+ const { relations } = (0, getRelationsFromModelGenerator_1.getRelationsFromModelGenerator)(relationShipBuilder);
49
32
  this.modelRelations = relations;
50
33
  this.outputKeys = (0, outputKeys_1.getOutputKeys)(relationShipBuilder) || [];
51
34
  }
@@ -55,7 +38,7 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
55
38
  if (this.isMongoDB) {
56
39
  datum['id'] = datum['id'].toString();
57
40
  }
58
- return this.outputSchema.parse(this.clearEmpties(js_utils_1.Objects.deleteNulls(datum)));
41
+ return this.outputSchema.parse((0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(datum)));
59
42
  }
60
43
  async insertMany(data) {
61
44
  const validatedData = this.inputSchema.array().parse(data);
@@ -66,13 +49,22 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
66
49
  if (this.isMongoDB) {
67
50
  d['id'] = d['id'].toString();
68
51
  }
69
- return this.clearEmpties(js_utils_1.Objects.deleteNulls(d));
52
+ return (0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(d));
70
53
  }));
71
54
  }
72
55
  async findMany(query) {
73
- if (this.isMongoDB && query?.include) {
74
- const mongoRelationResult = this.customMongoRelatedSearch(query);
75
- return mongoRelationResult;
56
+ const requiresCustomQuery = query?.include && Object.keys(query.include).length;
57
+ if (this.isMongoDB && requiresCustomQuery) {
58
+ const results = await this.customMongoRelatedFind(query);
59
+ return results;
60
+ }
61
+ if (requiresCustomQuery) {
62
+ const { queryBuilder: customQuery, selectedKeys } = this.customTypeOrmRelatedFind({
63
+ fluentQuery: query
64
+ });
65
+ customQuery.select(selectedKeys);
66
+ let [result, count] = await customQuery.getManyAndCount();
67
+ return result;
76
68
  }
77
69
  const generatedQuery = this.generateTypeOrmQuery(query);
78
70
  let [found, count] = await this.repository.findAndCount(generatedQuery);
@@ -80,7 +72,7 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
80
72
  if (this.isMongoDB) {
81
73
  d['id'] = d['id'].toString();
82
74
  }
83
- this.clearEmpties(js_utils_1.Objects.deleteNulls(d));
75
+ (0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(d));
84
76
  });
85
77
  if (query?.paginated) {
86
78
  const paginationInfo = {
@@ -126,7 +118,7 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
126
118
  if (this.isMongoDB) {
127
119
  dbResult['id'] = dbResult['id'].toString();
128
120
  }
129
- return this.outputSchema?.parse(this.clearEmpties(js_utils_1.Objects.deleteNulls(dbResult)));
121
+ return this.outputSchema?.parse((0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(dbResult)));
130
122
  }
131
123
  async replaceById(id, data) {
132
124
  const parsedId = this.isMongoDB
@@ -167,7 +159,7 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
167
159
  if (this.isMongoDB) {
168
160
  val['id'] = val['id'].toString();
169
161
  }
170
- return this.outputSchema.parse(this.clearEmpties(js_utils_1.Objects.deleteNulls(val)));
162
+ return this.outputSchema.parse((0, clearEmpties_1.clearEmpties)(js_utils_1.Objects.deleteNulls(val)));
171
163
  }
172
164
  async deleteById(id) {
173
165
  const parsedId = this.isMongoDB
@@ -214,173 +206,15 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
214
206
  clone() {
215
207
  return new this.constructor();
216
208
  }
217
- getOrderBy(orderBy) {
218
- if (!orderBy || orderBy.length === 0) {
219
- return {};
220
- }
221
- const order = {};
222
- for (const orderElement of orderBy) {
223
- const flattenOrder = js_utils_1.Objects.flatten(orderElement);
224
- for (const k of Object.keys(flattenOrder)) {
225
- order[k] = flattenOrder[k];
226
- }
227
- }
228
- return js_utils_1.Objects.nest(order);
229
- }
230
- getMongoSelect(select) {
231
- const selected = js_utils_1.Objects.flatten(select || {});
232
- for (const k of Object.keys(selected)) {
233
- if (k === 'id') {
234
- delete selected[k];
235
- selected['_id'] = 1;
236
- continue;
237
- }
238
- const containsId = k.lastIndexOf('.id');
239
- if (containsId >= 0 && containsId + 3 === k.length) {
240
- selected[`${k.replace('.id', '')}._id`] = 1;
241
- delete selected[k];
242
- continue;
243
- }
244
- selected[k] = 1;
245
- }
246
- return selected;
247
- }
248
- getMongoLookup(include) {
249
- if (!include) {
250
- return [];
251
- }
252
- const lookUps = [];
253
- for (const relation of Object.keys(include)) {
254
- if (this.modelRelations[relation]) {
255
- const dbRelation = this.modelRelations[relation];
256
- if (dbRelation.isManyToOne) {
257
- const localField = dbRelation.joinColumns[0].propertyPath;
258
- lookUps.push({
259
- $addFields: {
260
- [`${localField}_object`]: { $toObjectId: `$${localField}` }
261
- }
262
- });
263
- lookUps.push({ $addFields: { id: { $toString: '$_id' } } });
264
- lookUps.push({
265
- $lookup: {
266
- from: dbRelation.tableName,
267
- localField: `${localField}_object`,
268
- foreignField: '_id',
269
- as: dbRelation.propertyName,
270
- pipeline: [
271
- { $addFields: { id: { $toString: '$_id' } } }
272
- ]
273
- }
274
- });
275
- lookUps.push({ $unwind: `$${dbRelation.propertyName}` });
276
- }
277
- if (dbRelation.isOneToMany) {
278
- lookUps.push({ $addFields: { string_id: { $toString: '$_id' } } });
279
- lookUps.push({ $addFields: { id: { $toString: '$_id' } } });
280
- lookUps.push({
281
- $lookup: {
282
- from: dbRelation.tableName,
283
- localField: 'string_id',
284
- foreignField: dbRelation.inverseSidePropertyPath,
285
- as: dbRelation.propertyName,
286
- pipeline: [
287
- { $addFields: { id: { $toString: '$_id' } } }
288
- ]
289
- }
290
- });
291
- }
292
- if (dbRelation.isManyToMany) {
293
- const relatedTableName = dbRelation.tableName;
294
- const pivotTableName = dbRelation.joinColumns[0].relationMetadata.joinTableName;
295
- const pivotForeignField = dbRelation.joinColumns[0].propertyPath;
296
- const inverseForeignField = dbRelation.inverseJoinColumns[0].propertyPath;
297
- if (!relatedTableName ||
298
- !pivotTableName ||
299
- !pivotForeignField ||
300
- !inverseForeignField) {
301
- throw new Error(`Your many to many relation is not properly set up. Please check both your models and schema for relation: ${relation}`);
302
- }
303
- lookUps.push({ $addFields: { id: { $toString: '$_id' } } });
304
- lookUps.push({
305
- $addFields: { parent_string_id: { $toString: '$_id' } }
306
- });
307
- lookUps.push({
308
- $lookup: {
309
- from: pivotTableName,
310
- localField: 'parent_string_id',
311
- foreignField: pivotForeignField,
312
- as: dbRelation.propertyName,
313
- pipeline: [
314
- { $addFields: { id: { $toString: '$_id' } } },
315
- {
316
- $addFields: {
317
- [`${inverseForeignField}_object`]: {
318
- $toObjectId: `$${inverseForeignField}`
319
- }
320
- }
321
- },
322
- {
323
- $lookup: {
324
- from: relatedTableName,
325
- localField: `${inverseForeignField}_object`,
326
- foreignField: '_id',
327
- pipeline: [
328
- { $addFields: { id: { $toString: '$_id' } } }
329
- ],
330
- as: dbRelation.propertyName
331
- }
332
- },
333
- { $unwind: `$${dbRelation.propertyName}` },
334
- {
335
- $project: {
336
- [dbRelation.propertyName]: `$${dbRelation.propertyName}`,
337
- pivot: '$$ROOT'
338
- }
339
- },
340
- {
341
- $replaceRoot: {
342
- newRoot: {
343
- $mergeObjects: ['$$ROOT', `$${dbRelation.propertyName}`]
344
- }
345
- }
346
- },
347
- { $project: { [dbRelation.propertyName]: 0 } }
348
- ]
349
- }
350
- });
351
- }
352
- }
353
- }
354
- return lookUps;
355
- }
356
- async customMongoRelatedSearch(query) {
357
- const where = this.getTypeOrmMongoWhere(query?.where);
358
- const selected = this.getMongoSelect(query?.select);
359
- const lookups = this.getMongoLookup(query?.include);
360
- const aggregate = [
361
- {
362
- $match: where
363
- }
364
- ];
365
- if (query?.limit) {
366
- aggregate.push({ $limit: query.limit });
367
- }
368
- for (const lookup of lookups) {
369
- aggregate.push(lookup);
370
- }
371
- if (selected && Object.keys(selected).length) {
372
- aggregate.push({
373
- $project: selected
374
- });
375
- }
376
- let raw = await this.mongoRaw().aggregate(aggregate).toArray();
377
- return this.outputSchema?.array().parse(raw);
378
- }
379
209
  generateTypeOrmQuery(query) {
380
210
  let filter = {};
381
211
  filter.where = this.isMongoDB
382
- ? this.getTypeOrmMongoWhere(query?.where)
383
- : this.getTypeOrmWhere(query?.where);
212
+ ? (0, getMongoWhere_1.getMongoWhere)({
213
+ where: query?.where
214
+ })
215
+ : (0, getTypeOrmWhere_1.getTypeOrmWhere)({
216
+ where: query?.where
217
+ });
384
218
  filter.take = query?.limit;
385
219
  filter.skip = query?.offset;
386
220
  if (query?.paginated) {
@@ -389,372 +223,175 @@ class TypeOrmConnector extends BaseConnector_1.BaseConnector {
389
223
  }
390
224
  if (query?.select) {
391
225
  const selectQuery = js_utils_1.Objects.flatten(query?.select || {});
226
+ filter.select = selectQuery;
392
227
  if (this.isMongoDB) {
393
228
  filter.select = Object.keys(selectQuery);
394
229
  }
395
- else {
396
- filter.select = selectQuery;
397
- }
398
230
  }
399
- filter.order = this.getOrderBy(query?.orderBy);
400
- filter.relations = query?.include;
401
- return filter;
402
- }
403
- getTypeOrmWhere(where) {
404
- if (!where || Object.keys(where).length === 0) {
405
- return {};
231
+ if (query?.orderBy) {
232
+ filter.order = (0, extractOrderBy_1.extractOrderBy)(query.orderBy);
406
233
  }
407
- const Filters = { where: [{}] };
408
- const orConditions = this.extractConditions(where['OR']);
409
- const andConditions = this.extractConditions(where['AND']);
410
- const copy = js_utils_1.Objects.clone(where);
411
- if (!!copy['AND']) {
412
- delete copy['AND'];
234
+ if (query?.include) {
235
+ filter.relations = (0, extractInclude_1.extractInclude)(query.include);
413
236
  }
414
- if (!!copy['OR']) {
415
- delete copy['OR'];
237
+ return filter;
238
+ }
239
+ customTypeOrmRelatedFind({ fluentQuery: query, queryBuilder, targetFluentRepository, alias, isLeftJoin }) {
240
+ const queryAlias = alias || queryBuilder?.alias || `${this.repository.metadata.tableName}`;
241
+ let customQuery = queryBuilder || this.raw().createQueryBuilder(queryAlias);
242
+ const self = targetFluentRepository || this;
243
+ if (!isLeftJoin) {
244
+ customQuery = (0, getQueryBuilderWhere_1.getQueryBuilderWhere)({
245
+ queryBuilder: customQuery,
246
+ queryAlias,
247
+ where: query?.where
248
+ });
416
249
  }
417
- const rootLevelConditions = this.extractConditions([copy]);
418
- for (const condition of andConditions) {
419
- const { element, operator, value } = condition;
420
- switch (operator) {
421
- case types_1.LogicOperator.equals:
422
- Filters.where[0] = js_utils_1.Objects.nest({
423
- ...Filters.where[0],
424
- ...{ [element]: (0, typeorm_1.Equal)(value) }
425
- });
426
- break;
427
- case types_1.LogicOperator.isNot:
428
- Filters.where[0] = js_utils_1.Objects.nest({
429
- ...Filters.where[0],
430
- ...{ [element]: (0, typeorm_1.Not)((0, typeorm_1.Equal)(value)) }
431
- });
432
- break;
433
- case types_1.LogicOperator.greaterThan:
434
- Filters.where[0] = js_utils_1.Objects.nest({
435
- ...Filters.where[0],
436
- ...{ [element]: (0, typeorm_1.MoreThan)(value) }
437
- });
438
- break;
439
- case types_1.LogicOperator.greaterOrEqualThan:
440
- Filters.where[0] = js_utils_1.Objects.nest({
441
- ...Filters.where[0],
442
- ...{ [element]: (0, typeorm_1.MoreThanOrEqual)(value) }
443
- });
444
- break;
445
- case types_1.LogicOperator.lessThan:
446
- Filters.where[0] = js_utils_1.Objects.nest({
447
- ...Filters.where[0],
448
- ...{ [element]: (0, typeorm_1.LessThan)(value) }
449
- });
450
- break;
451
- case types_1.LogicOperator.lessOrEqualThan:
452
- Filters.where[0] = js_utils_1.Objects.nest({
453
- ...Filters.where[0],
454
- ...{ [element]: (0, typeorm_1.LessThanOrEqual)(value) }
455
- });
456
- break;
457
- case types_1.LogicOperator.in:
458
- Filters.where[0] = js_utils_1.Objects.nest({
459
- ...Filters.where[0],
460
- ...{ [element]: (0, typeorm_1.In)(value) }
461
- });
462
- break;
463
- case types_1.LogicOperator.notIn:
464
- Filters.where[0] = js_utils_1.Objects.nest({
465
- ...Filters.where[0],
466
- ...{ [element]: (0, typeorm_1.Not)((0, typeorm_1.In)(value)) }
467
- });
468
- break;
469
- case types_1.LogicOperator.exists:
470
- Filters.where[0] = js_utils_1.Objects.nest({
471
- ...Filters.where[0],
472
- ...{ [element]: (0, typeorm_1.Not)((0, typeorm_1.IsNull)()) }
473
- });
474
- break;
475
- case types_1.LogicOperator.notExists:
476
- Filters.where[0] = js_utils_1.Objects.nest({
477
- ...Filters.where[0],
478
- ...{ [element]: (0, typeorm_1.IsNull)() }
479
- });
480
- break;
481
- case types_1.LogicOperator.regexp:
482
- Filters.where[0] = js_utils_1.Objects.nest({
483
- ...Filters.where[0],
484
- ...{ [element]: (0, typeorm_1.Like)(value) }
485
- });
486
- break;
250
+ const { queryBuilder: qb, selectedKeys } = this.getTypeOrmQueryBuilderSubqueries({
251
+ queryBuilder: customQuery,
252
+ selfReference: targetFluentRepository,
253
+ include: query?.include,
254
+ leftTableAlias: alias
255
+ });
256
+ customQuery = qb;
257
+ const extraKeys = this.getTypeOrmQueryBuilderSelect(queryAlias, self, query?.select);
258
+ const keySet = new Set([...selectedKeys, ...extraKeys]);
259
+ return {
260
+ queryBuilder: customQuery,
261
+ selectedKeys: Array.from(keySet)
262
+ };
263
+ }
264
+ getTypeOrmQueryBuilderSelect(queryAlias, self, select) {
265
+ const selected = js_utils_1.Objects.flatten(select || {});
266
+ const selectedKeys = [];
267
+ const iterableKeys = Object.keys(selected).length
268
+ ? Object.keys(selected)
269
+ : self.outputKeys || [];
270
+ const baseNestedKeys = new Set();
271
+ for (const key of iterableKeys) {
272
+ const keyArray = key.split('.');
273
+ if (keyArray.length <= 1) {
274
+ continue;
487
275
  }
488
- }
489
- for (const condition of rootLevelConditions) {
490
- const { element, operator, value } = condition;
491
- switch (operator) {
492
- case types_1.LogicOperator.equals:
493
- Filters.where[0] = js_utils_1.Objects.nest({
494
- ...Filters.where[0],
495
- ...{ [element]: (0, typeorm_1.Equal)(value) }
496
- });
497
- break;
498
- case types_1.LogicOperator.isNot:
499
- Filters.where[0] = js_utils_1.Objects.nest({
500
- ...Filters.where[0],
501
- ...{ [element]: (0, typeorm_1.Not)((0, typeorm_1.Equal)(value)) }
502
- });
503
- break;
504
- case types_1.LogicOperator.greaterThan:
505
- Filters.where[0] = js_utils_1.Objects.nest({
506
- ...Filters.where[0],
507
- ...{ [element]: (0, typeorm_1.MoreThan)(value) }
508
- });
509
- break;
510
- case types_1.LogicOperator.greaterOrEqualThan:
511
- Filters.where[0] = js_utils_1.Objects.nest({
512
- ...Filters.where[0],
513
- ...{ [element]: (0, typeorm_1.MoreThanOrEqual)(value) }
514
- });
515
- break;
516
- case types_1.LogicOperator.lessThan:
517
- Filters.where[0] = js_utils_1.Objects.nest({
518
- ...Filters.where[0],
519
- ...{ [element]: (0, typeorm_1.LessThan)(value) }
520
- });
521
- break;
522
- case types_1.LogicOperator.lessOrEqualThan:
523
- Filters.where[0] = js_utils_1.Objects.nest({
524
- ...Filters.where[0],
525
- ...{ [element]: (0, typeorm_1.LessThanOrEqual)(value) }
526
- });
527
- break;
528
- case types_1.LogicOperator.in:
529
- Filters.where[0] = js_utils_1.Objects.nest({
530
- ...Filters.where[0],
531
- ...{ [element]: (0, typeorm_1.In)(value) }
532
- });
533
- break;
534
- case types_1.LogicOperator.notIn:
535
- Filters.where[0] = js_utils_1.Objects.nest({
536
- ...Filters.where[0],
537
- ...{ [element]: (0, typeorm_1.Not)((0, typeorm_1.In)(value)) }
538
- });
539
- break;
540
- case types_1.LogicOperator.exists:
541
- Filters.where[0] = js_utils_1.Objects.nest({
542
- ...Filters.where[0],
543
- ...{ [element]: (0, typeorm_1.Not)((0, typeorm_1.IsNull)()) }
544
- });
545
- break;
546
- case types_1.LogicOperator.notExists:
547
- Filters.where[0] = js_utils_1.Objects.nest({
548
- ...Filters.where[0],
549
- ...{ [element]: (0, typeorm_1.IsNull)() }
550
- });
551
- break;
552
- case types_1.LogicOperator.regexp:
553
- Filters.where[0] = js_utils_1.Objects.nest({
554
- ...Filters.where[0],
555
- ...{ [element]: (0, typeorm_1.Like)(value) }
556
- });
557
- break;
276
+ const total = keyArray.length;
277
+ for (const [index, val] of keyArray.entries()) {
278
+ if (total === index + 1) {
279
+ continue;
280
+ }
281
+ let excludedField = '';
282
+ if (excludedField) {
283
+ excludedField = `${excludedField}.${excludedField}${val}`;
284
+ }
285
+ excludedField = `${excludedField}${val}`;
286
+ baseNestedKeys.add(excludedField);
558
287
  }
559
288
  }
560
- for (const condition of orConditions) {
561
- const { element, operator, value } = condition;
562
- switch (operator) {
563
- case types_1.LogicOperator.equals:
564
- Filters.where.push({ [element]: (0, typeorm_1.Equal)(value) });
565
- break;
566
- case types_1.LogicOperator.isNot:
567
- Filters.where.push({ [element]: (0, typeorm_1.Not)((0, typeorm_1.Equal)(value)) });
568
- break;
569
- case types_1.LogicOperator.greaterThan:
570
- Filters.where.push({ [element]: (0, typeorm_1.MoreThan)(value) });
571
- break;
572
- case types_1.LogicOperator.greaterOrEqualThan:
573
- Filters.where.push({ [element]: (0, typeorm_1.MoreThanOrEqual)(value) });
574
- break;
575
- case types_1.LogicOperator.lessThan:
576
- Filters.where.push({ [element]: (0, typeorm_1.LessThan)(value) });
577
- break;
578
- case types_1.LogicOperator.lessOrEqualThan:
579
- Filters.where.push({ [element]: (0, typeorm_1.LessThanOrEqual)(value) });
580
- break;
581
- case types_1.LogicOperator.in:
582
- Filters.where.push({ [element]: (0, typeorm_1.In)(value) });
583
- break;
584
- case types_1.LogicOperator.notIn:
585
- Filters.where.push({ [element]: (0, typeorm_1.Not)((0, typeorm_1.In)(value)) });
586
- break;
587
- case types_1.LogicOperator.exists:
588
- Filters.where.push({ [element]: (0, typeorm_1.Not)((0, typeorm_1.IsNull)()) });
589
- break;
590
- case types_1.LogicOperator.notExists:
591
- Filters.where.push({ [element]: (0, typeorm_1.IsNull)() });
592
- break;
593
- case types_1.LogicOperator.regexp:
594
- Filters.where.push({ [element]: (0, typeorm_1.Like)(value) });
289
+ for (const k of iterableKeys) {
290
+ const field = k.includes('.') ? js_utils_1.Strings.camel(`${k}`) : k;
291
+ const search = `${queryAlias}.${field}`;
292
+ let isNestedRelation = false;
293
+ for (const item of k.split('.')) {
294
+ if (!!self[item]) {
295
+ isNestedRelation = true;
595
296
  break;
297
+ }
596
298
  }
597
- }
598
- const filtered = this.clearEmpties(Filters.where);
599
- return filtered;
600
- }
601
- getTypeOrmMongoWhere(where) {
602
- if (!where || Object.keys(where).length === 0) {
603
- return {};
604
- }
605
- const Filters = {
606
- where: { $or: [{ $and: [] }] }
607
- };
608
- const orConditions = this.extractConditions(where['OR']);
609
- const andConditions = this.extractConditions(where['AND']);
610
- const copy = js_utils_1.Objects.clone(where);
611
- if (!!copy['AND']) {
612
- delete copy['AND'];
613
- }
614
- if (!!copy['OR']) {
615
- delete copy['OR'];
616
- }
617
- const rootLevelConditions = this.extractConditions([copy]);
618
- for (const condition of andConditions) {
619
- let { element, operator, value } = condition;
620
- if (element === 'id') {
621
- element = '_id';
622
- value = (Array.isArray(value)
623
- ? value.map(v => js_utils_1.Ids.objectID(v))
624
- : js_utils_1.Ids.objectID(value));
299
+ if (!!self[field] || !!self[queryAlias] || isNestedRelation) {
300
+ continue;
625
301
  }
626
- switch (operator) {
627
- case types_1.LogicOperator.equals:
628
- Filters.where.$or[0].$and.push({ [element]: { $eq: value } });
629
- break;
630
- case types_1.LogicOperator.isNot:
631
- Filters.where.$or[0].$and.push({ [element]: { $neq: value } });
632
- break;
633
- case types_1.LogicOperator.greaterThan:
634
- Filters.where.$or[0].$and.push({ [element]: { $gt: value } });
635
- break;
636
- case types_1.LogicOperator.greaterOrEqualThan:
637
- Filters.where.$or[0].$and.push({ [element]: { $gte: value } });
638
- break;
639
- case types_1.LogicOperator.lessThan:
640
- Filters.where.$or[0].$and.push({ [element]: { $lt: value } });
641
- break;
642
- case types_1.LogicOperator.lessOrEqualThan:
643
- Filters.where.$or[0].$and.push({ [element]: { $lte: value } });
644
- break;
645
- case types_1.LogicOperator.in:
646
- Filters.where.$or[0].$and.push({ [element]: { $in: value } });
647
- break;
648
- case types_1.LogicOperator.notIn:
649
- Filters.where.$or[0].$and.push({
650
- [element]: { $not: { $in: value } }
651
- });
652
- break;
653
- case types_1.LogicOperator.exists:
654
- Filters.where.$or[0].$and.push({ [element]: { $exists: true } });
655
- break;
656
- case types_1.LogicOperator.notExists:
657
- Filters.where.$or[0].$and.push({ [element]: { $exists: false } });
658
- break;
659
- case types_1.LogicOperator.regexp:
660
- Filters.where.$or[0].$and.push({ [element]: { $regex: value } });
661
- break;
302
+ if (baseNestedKeys.has(field)) {
303
+ continue;
662
304
  }
305
+ selectedKeys.push(search);
663
306
  }
664
- for (const condition of rootLevelConditions) {
665
- let { element, operator, value } = condition;
666
- if (element === 'id') {
667
- element = '_id';
668
- value = (Array.isArray(value)
669
- ? value.map(v => js_utils_1.Ids.objectID(v))
670
- : js_utils_1.Ids.objectID(value));
671
- }
672
- switch (operator) {
673
- case types_1.LogicOperator.equals:
674
- Filters.where.$or[0].$and.push({ [element]: { $eq: value } });
675
- break;
676
- case types_1.LogicOperator.isNot:
677
- Filters.where.$or[0].$and.push({ [element]: { $neq: value } });
678
- break;
679
- case types_1.LogicOperator.greaterThan:
680
- Filters.where.$or[0].$and.push({ [element]: { $gt: value } });
681
- break;
682
- case types_1.LogicOperator.greaterOrEqualThan:
683
- Filters.where.$or[0].$and.push({ [element]: { $gte: value } });
684
- break;
685
- case types_1.LogicOperator.lessThan:
686
- Filters.where.$or[0].$and.push({ [element]: { $lt: value } });
687
- break;
688
- case types_1.LogicOperator.lessOrEqualThan:
689
- Filters.where.$or[0].$and.push({ [element]: { $lte: value } });
690
- break;
691
- case types_1.LogicOperator.in:
692
- Filters.where.$or[0].$and.push({ [element]: { $in: value } });
693
- break;
694
- case types_1.LogicOperator.notIn:
695
- Filters.where.$or[0].$and.push({
696
- [element]: { $not: { $in: value } }
697
- });
698
- break;
699
- case types_1.LogicOperator.exists:
700
- Filters.where.$or[0].$and.push({ [element]: { $exists: true } });
701
- break;
702
- case types_1.LogicOperator.notExists:
703
- Filters.where.$or[0].$and.push({ [element]: { $exists: false } });
704
- break;
705
- case types_1.LogicOperator.regexp:
706
- Filters.where.$or[0].$and.push({ [element]: { $regex: value } });
707
- break;
708
- }
307
+ return selectedKeys;
308
+ }
309
+ getTypeOrmQueryBuilderSubqueries({ queryBuilder, selfReference, include, leftTableAlias }) {
310
+ const selectedKeys = [];
311
+ if (!include) {
312
+ return { queryBuilder, selectedKeys };
709
313
  }
710
- for (const condition of orConditions) {
711
- let { element, operator, value } = condition;
712
- if (element === 'id') {
713
- element = '_id';
714
- value = (Array.isArray(value)
715
- ? value.map(v => js_utils_1.Ids.objectID(v))
716
- : js_utils_1.Ids.objectID(value));
314
+ for (const relation of Object.keys(include)) {
315
+ const self = selfReference || this;
316
+ const dbRelation = self.modelRelations[relation];
317
+ const newSelf = self[relation]();
318
+ const fluentRelatedQuery = include[relation] === true ? {} : include[relation];
319
+ if (!dbRelation) {
320
+ throw new Error(`The relation ${relation} is not properly defined. Check your entity and repository`);
717
321
  }
718
- switch (operator) {
719
- case types_1.LogicOperator.equals:
720
- Filters.where.$or.push({ [element]: { $eq: value } });
721
- break;
722
- case types_1.LogicOperator.isNot:
723
- Filters.where.$or.push({ [element]: { $neq: value } });
724
- break;
725
- case types_1.LogicOperator.greaterThan:
726
- Filters.where.$or.push({ [element]: { $gt: value } });
727
- break;
728
- case types_1.LogicOperator.greaterOrEqualThan:
729
- Filters.where.$or.push({ [element]: { $gte: value } });
730
- break;
731
- case types_1.LogicOperator.lessThan:
732
- Filters.where.$or.push({ [element]: { $lt: value } });
733
- break;
734
- case types_1.LogicOperator.lessOrEqualThan:
735
- Filters.where.$or.push({ [element]: { $lte: value } });
736
- break;
737
- case types_1.LogicOperator.in:
738
- Filters.where.$or.push({ [element]: { $in: value } });
739
- break;
740
- case types_1.LogicOperator.notIn:
741
- Filters.where.$or.push({
742
- [element]: { $not: { $in: value } }
743
- });
744
- break;
745
- case types_1.LogicOperator.exists:
746
- Filters.where.$or.push({ [element]: { $exists: true } });
747
- break;
748
- case types_1.LogicOperator.notExists:
749
- Filters.where.$or.push({ [element]: { $exists: false } });
750
- break;
751
- case types_1.LogicOperator.regexp:
752
- Filters.where.$or.push({ [element]: { $regex: value } });
753
- break;
322
+ const selectedKeysArray = fluentRelatedQuery.select
323
+ ? Object.keys(js_utils_1.Objects.flatten(fluentRelatedQuery.select))
324
+ : [];
325
+ if (dbRelation.isManyToOne) {
326
+ const leftSideTableName = leftTableAlias || queryBuilder.alias;
327
+ const leftSideForeignKey = `${leftSideTableName}.${dbRelation.joinColumns[0].propertyPath}`;
328
+ const rightSideTableName = `${leftSideTableName}_${relation}`;
329
+ const rightSidePrimaryKey = `${rightSideTableName}.id`;
330
+ const keys = new Set(selectedKeysArray.map(k => `${rightSideTableName}.${k}`));
331
+ selectedKeys.push(...Array.from(keys));
332
+ const shallowQuery = { ...fluentRelatedQuery };
333
+ delete shallowQuery['include'];
334
+ const { queryBuilder: leftJoinBuilder, selectedKeys: deepkeys } = this.customTypeOrmRelatedFind({
335
+ queryBuilder: this.raw().createQueryBuilder(rightSideTableName),
336
+ fluentQuery: shallowQuery,
337
+ targetFluentRepository: newSelf,
338
+ alias: rightSideTableName
339
+ });
340
+ selectedKeys.push(...deepkeys);
341
+ const joinQuery = leftJoinBuilder.getQuery().split('WHERE');
342
+ const customLeftJoin = joinQuery && joinQuery[1] ? joinQuery[1].trim() : '1=1';
343
+ const leftJoinParams = leftJoinBuilder.getParameters();
344
+ queryBuilder.leftJoinAndMapOne(`${leftSideTableName}.${relation}`, dbRelation.targetClass, rightSideTableName, `(${leftSideForeignKey} = ${rightSidePrimaryKey} AND ${customLeftJoin} )`, leftJoinParams);
345
+ const { queryBuilder: qb, selectedKeys: k } = this.customTypeOrmRelatedFind({
346
+ queryBuilder,
347
+ fluentQuery: fluentRelatedQuery,
348
+ targetFluentRepository: newSelf,
349
+ alias: rightSideTableName,
350
+ isLeftJoin: true
351
+ });
352
+ selectedKeys.push(...k);
353
+ queryBuilder = qb;
354
+ }
355
+ if (dbRelation.isOneToMany) {
356
+ const leftSideTableName = leftTableAlias || queryBuilder.alias;
357
+ const leftSidePrimaryKey = `${leftSideTableName}.id`;
358
+ const rightSideTableName = `${leftSideTableName}_${relation}`;
359
+ const rightSideForeignKey = `${rightSideTableName}.${dbRelation.inverseSidePropertyPath}`;
360
+ const keys = new Set(selectedKeysArray.map(k => `${rightSideTableName}.${k}`));
361
+ selectedKeys.push(...Array.from(keys));
362
+ const shallowQuery = { ...fluentRelatedQuery };
363
+ delete shallowQuery['include'];
364
+ const { queryBuilder: leftJoinBuilder, selectedKeys: deepKeys } = this.customTypeOrmRelatedFind({
365
+ queryBuilder: this.raw().createQueryBuilder(rightSideTableName),
366
+ fluentQuery: shallowQuery,
367
+ targetFluentRepository: newSelf,
368
+ alias: rightSideTableName
369
+ });
370
+ selectedKeys.push(...deepKeys);
371
+ const joinQuery = leftJoinBuilder.getQuery().split('WHERE');
372
+ const customLeftJoin = joinQuery && joinQuery[1] ? joinQuery[1].trim() : '1=1';
373
+ const leftJoinParams = leftJoinBuilder.getParameters();
374
+ queryBuilder.leftJoinAndMapMany(`${leftSideTableName}.${relation}`, dbRelation.targetClass, rightSideTableName, `(${leftSidePrimaryKey} = ${rightSideForeignKey} AND ${customLeftJoin} )`, leftJoinParams);
375
+ const { queryBuilder: q, selectedKeys: k } = this.customTypeOrmRelatedFind({
376
+ queryBuilder,
377
+ fluentQuery: fluentRelatedQuery,
378
+ targetFluentRepository: newSelf,
379
+ alias: rightSideTableName,
380
+ isLeftJoin: true
381
+ });
382
+ selectedKeys.push(...k);
383
+ queryBuilder = q;
754
384
  }
755
385
  }
756
- const filtered = this.clearEmpties(Filters.where);
757
- return filtered;
386
+ return { queryBuilder, selectedKeys };
387
+ }
388
+ async customMongoRelatedFind(query) {
389
+ const aggregate = (0, getMongoFindAggregatedQuery_1.getMongoFindAggregatedQuery)({
390
+ query,
391
+ self: this
392
+ });
393
+ const raw = await this.mongoRaw().aggregate(aggregate).toArray();
394
+ return this.outputSchema?.array().parse(raw);
758
395
  }
759
396
  }
760
397
  exports.TypeOrmConnector = TypeOrmConnector;