@goatlab/fluent 0.6.24 → 0.7.1

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 (126) hide show
  1. package/README.md +17 -136
  2. package/dist/BaseConnector.d.ts +45 -75
  3. package/dist/BaseConnector.js +218 -317
  4. package/dist/Fluent.d.ts +2 -21
  5. package/dist/Fluent.js +0 -33
  6. package/dist/FluentEntity.d.ts +7 -0
  7. package/dist/FluentEntity.js +28 -0
  8. package/dist/TypeOrmConnector/TypeOrmConnector.d.ts +31 -24
  9. package/dist/TypeOrmConnector/TypeOrmConnector.js +599 -343
  10. package/dist/TypeOrmConnector/test/advanced/advancedTestSuite.js +182 -48
  11. package/dist/TypeOrmConnector/test/advanced/typeOrm.entity.d.ts +103 -3
  12. package/dist/TypeOrmConnector/test/advanced/typeOrm.entity.js +30 -13
  13. package/dist/TypeOrmConnector/test/advanced/typeOrm.mongo.repository.d.ts +5 -0
  14. package/dist/TypeOrmConnector/test/advanced/typeOrm.mongo.repository.js +17 -0
  15. package/dist/TypeOrmConnector/test/advanced/typeOrm.mysql.repository.d.ts +5 -0
  16. package/dist/TypeOrmConnector/test/advanced/typeOrm.mysql.repository.js +17 -0
  17. package/dist/TypeOrmConnector/test/advanced/typeOrm.repository.d.ts +3 -3
  18. package/dist/TypeOrmConnector/test/advanced/typeOrm.repository.js +8 -3
  19. package/dist/TypeOrmConnector/test/basic/basicTestSuite.d.ts +1 -1
  20. package/dist/TypeOrmConnector/test/basic/basicTestSuite.js +42 -16
  21. package/dist/TypeOrmConnector/test/basic/goat.entity.d.ts +43 -0
  22. package/dist/TypeOrmConnector/test/basic/goat.entity.js +19 -8
  23. package/dist/TypeOrmConnector/test/basic/goat.mongo.repository.d.ts +5 -0
  24. package/dist/TypeOrmConnector/test/basic/goat.mongo.repository.js +16 -0
  25. package/dist/TypeOrmConnector/test/basic/goat.mysql.repository.d.ts +5 -0
  26. package/dist/TypeOrmConnector/test/basic/goat.mysql.repository.js +16 -0
  27. package/dist/TypeOrmConnector/test/basic/goat.repository.d.ts +3 -4
  28. package/dist/TypeOrmConnector/test/basic/goat.repository.js +7 -3
  29. package/dist/TypeOrmConnector/test/dbEntities.d.ts +6 -6
  30. package/dist/TypeOrmConnector/test/docker/docker.d.ts +35 -0
  31. package/dist/TypeOrmConnector/test/docker/docker.js +149 -0
  32. package/dist/TypeOrmConnector/test/docker/mysql.d.ts +17 -0
  33. package/dist/TypeOrmConnector/test/docker/mysql.js +132 -0
  34. package/dist/TypeOrmConnector/test/mongo/car.mongo.repository.d.ts +8 -0
  35. package/dist/TypeOrmConnector/test/mongo/car.mongo.repository.js +23 -0
  36. package/dist/TypeOrmConnector/test/mongo/mongo.memory.d.ts +4 -0
  37. package/dist/TypeOrmConnector/test/mongo/mongo.memory.js +43 -0
  38. package/dist/TypeOrmConnector/test/mongo/mongoDatasource.d.ts +2 -0
  39. package/dist/TypeOrmConnector/test/mongo/mongoDatasource.js +12 -0
  40. package/dist/TypeOrmConnector/test/mongo/roles.mongo.repository.d.ts +8 -0
  41. package/dist/TypeOrmConnector/test/mongo/roles.mongo.repository.js +23 -0
  42. package/dist/TypeOrmConnector/test/mongo/roles_user.mongo.repository.d.ts +6 -0
  43. package/dist/TypeOrmConnector/test/mongo/roles_user.mongo.repository.js +17 -0
  44. package/dist/TypeOrmConnector/test/mongo/user.mongo.repository.d.ts +10 -0
  45. package/dist/TypeOrmConnector/test/mongo/user.mongo.repository.js +31 -0
  46. package/dist/TypeOrmConnector/test/mysql/car.mysql.repository.d.ts +6 -0
  47. package/dist/TypeOrmConnector/test/mysql/car.mysql.repository.js +17 -0
  48. package/dist/TypeOrmConnector/test/mysql/mysqlDataSource.d.ts +2 -0
  49. package/dist/TypeOrmConnector/test/mysql/mysqlDataSource.js +16 -0
  50. package/dist/TypeOrmConnector/test/mysql/roles.mysql.repository.d.ts +8 -0
  51. package/dist/TypeOrmConnector/test/mysql/roles.mysql.repository.js +23 -0
  52. package/dist/TypeOrmConnector/test/mysql/roles_user.mysql.repository.d.ts +6 -0
  53. package/dist/TypeOrmConnector/test/mysql/roles_user.mysql.repository.js +17 -0
  54. package/dist/TypeOrmConnector/test/mysql/user.mysql.repository.d.ts +10 -0
  55. package/dist/TypeOrmConnector/test/mysql/user.mysql.repository.js +32 -0
  56. package/dist/TypeOrmConnector/test/relations/car/car.entity.d.ts +1 -0
  57. package/dist/TypeOrmConnector/test/relations/car/car.entity.js +13 -5
  58. package/dist/TypeOrmConnector/test/relations/car/car.repositoryTypeOrm.d.ts +3 -3
  59. package/dist/TypeOrmConnector/test/relations/car/car.repositoryTypeOrm.js +11 -4
  60. package/dist/TypeOrmConnector/test/relations/car/car.schema.d.ts +38 -0
  61. package/dist/TypeOrmConnector/test/relations/car/car.schema.js +14 -0
  62. package/dist/TypeOrmConnector/test/relations/relationsTestsSuite.js +85 -32
  63. package/dist/TypeOrmConnector/test/relations/roles/role.schema.d.ts +35 -0
  64. package/dist/TypeOrmConnector/test/relations/roles/role.schema.js +16 -0
  65. package/dist/TypeOrmConnector/test/relations/roles/roles.entity.js +4 -4
  66. package/dist/TypeOrmConnector/test/relations/roles/roles.repositoryTypeOrm.d.ts +3 -3
  67. package/dist/TypeOrmConnector/test/relations/roles/roles.repositoryTypeOrm.js +12 -4
  68. package/dist/TypeOrmConnector/test/relations/roles/roles_user.entity.d.ts +2 -2
  69. package/dist/TypeOrmConnector/test/relations/roles/roles_user.entity.js +4 -4
  70. package/dist/TypeOrmConnector/test/relations/roles/roles_user.schema.d.ts +15 -0
  71. package/dist/TypeOrmConnector/test/relations/roles/roles_user.schema.js +9 -0
  72. package/dist/TypeOrmConnector/test/relations/roles/roles_users.repositoryTypeOrm.d.ts +3 -3
  73. package/dist/TypeOrmConnector/test/relations/roles/roles_users.repositoryTypeOrm.js +8 -3
  74. package/dist/TypeOrmConnector/test/relations/user/user.entity.js +10 -10
  75. package/dist/TypeOrmConnector/test/relations/user/user.repositoryTypeOrm.d.ts +3 -3
  76. package/dist/TypeOrmConnector/test/relations/user/user.repositoryTypeOrm.js +17 -5
  77. package/dist/TypeOrmConnector/test/relations/user/user.schema.d.ts +150 -0
  78. package/dist/TypeOrmConnector/test/relations/user/user.schema.js +18 -0
  79. package/dist/TypeOrmConnector/test/{memoryDataSource.d.ts → sqlite/memoryDataSource.d.ts} +0 -0
  80. package/dist/TypeOrmConnector/test/{memoryDataSource.js → sqlite/memoryDataSource.js} +1 -1
  81. package/dist/core/Loopback/build-schema.js +1 -3
  82. package/dist/core/Loopback/json-to-schema.js +6 -6
  83. package/dist/core/Loopback/mapValues.d.ts +2 -0
  84. package/dist/core/Loopback/mapValues.js +835 -0
  85. package/dist/core/Loopback/query.js +6 -4
  86. package/dist/core/Loopback/type-resolver.d.ts +1 -1
  87. package/dist/core/Nestjs/applyDecorators.d.ts +1 -1
  88. package/dist/core/Nestjs/types/common.js +3 -1
  89. package/dist/core/Nestjs/types/decorators/apply-is-optional.decorator.d.ts +1 -1
  90. package/dist/core/Nestjs/types/decorators/create-property.decorator.js +9 -4
  91. package/dist/core/Nestjs/types/decorators/field.decorator.d.ts +1 -1
  92. package/dist/core/Nestjs/types/decorators/field.decorator.js +6 -6
  93. package/dist/core/Nestjs/types/lazy-metadata.storage.js +3 -3
  94. package/dist/core/Nestjs/types/omit-type.js +6 -2
  95. package/dist/core/Nestjs/types/reflection.utils.d.ts +1 -1
  96. package/dist/core/Nestjs/types/reflection.utils.js +9 -2
  97. package/dist/core/Nestjs/types/type-metadata.storage.js +4 -4
  98. package/dist/core/Nestjs/types/utils/get-fields-and-decorator.util.d.ts +1 -11
  99. package/dist/core/Nestjs/types/utils/mapped-types.utils.js +2 -2
  100. package/dist/decorators.d.ts +25 -21
  101. package/dist/decorators.js +76 -70
  102. package/dist/index.d.ts +6 -7
  103. package/dist/index.js +5 -7
  104. package/dist/loadRelations.js +108 -68
  105. package/dist/tsconfig.tsbuildinfo +1 -1
  106. package/dist/types.d.ts +104 -55
  107. package/dist/types.js +20 -0
  108. package/package.json +11 -102
  109. package/dist/TypeOrmConnector/TypeOrmMongoConnector._bypass.d.ts +0 -1
  110. package/dist/TypeOrmConnector/TypeOrmMongoConnector._bypass.js +0 -52
  111. package/dist/TypeOrmConnector/TypeOrmMysqlConnector._bypass.d.ts +0 -1
  112. package/dist/TypeOrmConnector/TypeOrmMysqlConnector._bypass.js +0 -55
  113. package/dist/TypeOrmConnector/test/basic/goat.dto.d.ts +0 -8
  114. package/dist/TypeOrmConnector/test/basic/goat.dto.js +0 -18
  115. package/dist/TypeOrmConnector/test/relations/car/car.dto.d.ts +0 -5
  116. package/dist/TypeOrmConnector/test/relations/car/car.dto.js +0 -12
  117. package/dist/TypeOrmConnector/test/relations/roles/role.dto.d.ts +0 -5
  118. package/dist/TypeOrmConnector/test/relations/roles/role.dto.js +0 -12
  119. package/dist/TypeOrmConnector/test/relations/roles/roles_user.dto.d.ts +0 -5
  120. package/dist/TypeOrmConnector/test/relations/roles/roles_user.dto.js +0 -12
  121. package/dist/TypeOrmConnector/test/relations/user/user.dto.d.ts +0 -5
  122. package/dist/TypeOrmConnector/test/relations/user/user.dto.js +0 -12
  123. package/dist/core/dtos/access.dto.d.ts +0 -4
  124. package/dist/core/dtos/access.dto.js +0 -21
  125. package/dist/core/dtos/pagination.dto.d.ts +0 -13
  126. package/dist/core/dtos/pagination.dto.js +0 -62
@@ -1,302 +1,82 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseConnector = void 0;
4
- const typed_path_1 = require("typed-path");
5
4
  const js_utils_1 = require("@goatlab/js-utils");
6
- const class_transformer_1 = require("class-transformer");
7
- const class_validator_1 = require("class-validator");
5
+ const types_1 = require("./types");
6
+ const bson_1 = require("bson");
8
7
  class BaseConnector {
9
8
  constructor() {
10
- this.generatedKeyPath = (0, typed_path_1.typedPath)();
11
- this.chainReference = [];
12
- this.whereArray = [];
13
- this.orWhereArray = [];
14
- this.selectArray = [];
15
- this.forceSelectArray = [];
16
- this.orderByArray = [];
17
- this.limitNumber = 0;
18
- this.offsetNumber = 0;
19
- this.populateArray = [];
20
9
  this.chunk = null;
21
10
  this.pullSize = null;
22
- this.ownerId = undefined;
23
11
  this.paginator = undefined;
24
12
  this.rawQuery = undefined;
25
- this.getFirst = false;
26
- this.relations = undefined;
27
- this.loadModels = false;
28
- this.chainReference = [];
29
- this.whereArray = [];
30
- this.orWhereArray = [];
31
- this.selectArray = [];
32
- this.forceSelectArray = [];
33
- this.orderByArray = [];
34
- this.limitNumber = undefined;
35
- this.offsetNumber = undefined;
36
- this.populateArray = [];
37
13
  this.chunk = null;
38
14
  this.pullSize = null;
39
- this.ownerId = undefined;
40
15
  this.paginator = undefined;
41
16
  this.rawQuery = undefined;
42
17
  this.outputKeys = [];
43
- this.getFirst = false;
44
18
  }
45
- async findByIds(ids) {
19
+ async findByIds(ids, q) {
46
20
  throw new Error('findByIds() method not implemented');
47
21
  }
48
- async get() {
49
- throw new Error('get() method not implemented');
50
- }
51
22
  async insertMany(data) {
52
23
  throw new Error('get() method not implemented');
53
24
  }
54
25
  async updateById(id, data) {
55
26
  throw new Error('get() method not implemented');
56
27
  }
57
- owner(user) {
58
- this.chainReference.push({ method: 'owner', args: user });
59
- this.ownerId = user;
60
- return this;
28
+ async findMany(query) {
29
+ throw new Error('findMany() method not implemented');
61
30
  }
62
- own(user) {
63
- return this.owner(user);
64
- }
65
- async first() {
66
- this.limit(1);
67
- const data = await this.get();
31
+ async findFirst(query) {
32
+ const data = await this.findMany({ ...query, limit: 1 });
68
33
  if (!data[0]) {
69
34
  return null;
70
35
  }
71
36
  return data[0];
72
37
  }
73
- async collect() {
74
- const data = await this.get();
38
+ async collect(query) {
39
+ const data = await this.findMany(query);
75
40
  if (!Array.isArray(data)) {
76
- throw new Error('Collect method only accepts arrays of data');
41
+ return new js_utils_1.Collection([data]);
77
42
  }
78
43
  return new js_utils_1.Collection(data);
79
44
  }
80
- select(paths) {
81
- const arrCols = paths(this.generatedKeyPath);
82
- const cols = arrCols.map(c => c.toString());
83
- const columns = this.prepareInput(cols);
84
- this.chainReference.push({ method: 'select', args: columns });
85
- this.selectArray = this.selectArray
86
- .concat(columns)
87
- .filter((elem, pos, arr) => arr.indexOf(elem) === pos);
88
- return this;
89
- }
90
- forceSelect(paths) {
91
- if (typeof module === 'undefined' || !module.exports) {
92
- throw new Error('forceSelect cant be used in frontend');
93
- }
94
- const arrCols = paths(this.generatedKeyPath);
95
- const cols = arrCols.map(c => c.toString());
96
- const columns = this.prepareInput(cols);
97
- this.chainReference.push({ method: 'forceSelect', args: columns });
98
- this.forceSelectArray = this.forceSelectArray
99
- .concat(columns)
100
- .filter((elem, pos, arr) => arr.indexOf(elem) === pos);
101
- return this;
102
- }
103
- offset(offset) {
104
- this.chainReference.push({ method: 'offset', args: offset });
105
- this.offsetNumber = offset;
106
- return this;
107
- }
108
- populate(...relations) {
109
- this.chainReference.push({ method: 'relations', args: relations });
110
- this.populateArray = relations;
111
- return this;
112
- }
113
- skip(offset) {
114
- return this.offset(offset);
115
- }
116
- where(path, operator, value) {
117
- const stringP = path(this.generatedKeyPath);
118
- const stringPath = stringP.toString();
119
- const chainedWhere = [stringPath, operator, value];
120
- this.chainReference.push({ method: 'where', chainedWhere });
121
- this.whereArray = [];
122
- this.whereArray.push(chainedWhere);
123
- return this;
124
- }
125
- andWhere(path, operator, value) {
126
- const stringP = path(this.generatedKeyPath);
127
- const stringPath = stringP.toString();
128
- const chainedWhere = [stringPath, operator, value];
129
- this.chainReference.push({ method: 'andWhere', chainedWhere });
130
- this.whereArray.push(chainedWhere);
131
- return this;
132
- }
133
- orWhere(path, operator, value) {
134
- const stringP = path(this.generatedKeyPath);
135
- const stringPath = stringP.toString();
136
- const chainedWhere = [stringPath, operator, value];
137
- this.chainReference.push({ method: 'orWhere', chainedWhere });
138
- this.orWhereArray.push(chainedWhere);
139
- return this;
140
- }
141
- limit(limit) {
142
- this.chainReference.push({ method: 'limit', args: limit });
143
- this.limitNumber = limit;
144
- return this;
145
- }
146
- take(limit) {
147
- return this.limit(limit);
148
- }
149
- async pluck(path) {
150
- const stringP = path(this.generatedKeyPath);
151
- const stringPath = stringP.toString();
152
- this.chainReference.push({ method: 'pluck', args: stringPath });
153
- const data = await this.get();
45
+ async pluck(path, query) {
46
+ const data = await this.findMany(query);
47
+ const paths = Object.keys(js_utils_1.Objects.flatten(path));
154
48
  const result = data.map(e => {
155
- const extracted = js_utils_1.Objects.getFromPath(e, String(stringPath), undefined);
49
+ const extracted = js_utils_1.Objects.getFromPath(e, String(paths[0]), undefined);
156
50
  if (typeof extracted.value !== 'undefined') {
157
51
  return extracted.value;
158
52
  }
159
53
  });
160
54
  return result;
161
55
  }
162
- orderBy(path, order = 'desc', orderType = 'string') {
163
- const stringP = path(this.generatedKeyPath);
164
- const stringPath = stringP.toString();
165
- const orderB = [stringPath, order, orderType];
166
- this.chainReference.push({ method: 'orderBy', orderB });
167
- this.orderByArray = orderB;
168
- return this;
169
- }
170
- jsApplySelect(data) {
171
- const _data = Array.isArray(data) ? [...data] : [data];
172
- if (this.selectArray.length <= 0 && this.outputKeys.length <= 0) {
173
- return _data;
174
- }
175
- const iterationArray = this.outputKeys.length === 0 && this.selectArray.length > 0
176
- ? this.selectArray
177
- : [...this.outputKeys, ...this.forceSelectArray];
178
- const compareArray = this.outputKeys.length === 0 && this.selectArray.length > 0
179
- ? [...this.outputKeys, ...this.forceSelectArray]
180
- : this.selectArray;
181
- return _data.map(element => {
182
- const newElement = {};
183
- iterationArray.forEach(attribute => {
184
- if (compareArray.length > 0 && !compareArray.includes(attribute)) {
185
- return undefined;
186
- }
187
- const extract = js_utils_1.Objects.getFromPath(element, attribute, undefined);
188
- let value = js_utils_1.Objects.get(() => extract.value, undefined);
189
- if (typeof value !== 'undefined' && value !== null) {
190
- if (typeof value === 'object' &&
191
- value.hasOwnProperty('data') &&
192
- value.data.hasOwnProperty('name')) {
193
- newElement[extract.label] = value.data.name;
194
- }
195
- else {
196
- if (typeof value === 'object' && js_utils_1.Ids.isValidObjectID(value)) {
197
- value = js_utils_1.Ids.objectIdString(value);
198
- }
199
- newElement[extract.label] = value;
200
- }
201
- }
202
- });
203
- return js_utils_1.Objects.nest(newElement);
204
- });
56
+ setRelatedQuery(r) {
57
+ this.relatedQuery = r;
205
58
  }
206
- jsApplyOrderBy(data) {
207
- let _data = [...data];
208
- if (this.orderByArray.length === 0) {
209
- return _data;
210
- }
211
- const field = this.orderByArray[0];
212
- if (this.selectArray.length > 0 &&
213
- (field.includes('.') || field.includes('['))) {
214
- throw new Error(`Cannot orderBy nested attribute "${field}" when using Select. You must rename the attribute`);
215
- }
216
- const order = this.orderByArray[1];
217
- let type = this.orderByArray[2];
218
- if (!type) {
219
- type = 'string';
59
+ async associate(data) {
60
+ if (!this.relatedQuery?.entity || !this.relatedQuery.key) {
61
+ throw new Error('Associate can only be called as a related model');
220
62
  }
221
- _data = _data.sort((a, b) => {
222
- const A = js_utils_1.Objects.getFromPath(a, field, undefined).value;
223
- const B = js_utils_1.Objects.getFromPath(b, field, undefined).value;
224
- if (typeof A === 'undefined' || typeof B === 'undefined') {
225
- throw new Error(`Cannot order by property "${field}" not all values have this property`);
226
- }
227
- if (type.includes('string') || type.includes('number')) {
228
- if (order === 'asc') {
229
- return A > B ? 1 : A < B ? -1 : 0;
230
- }
231
- return A > B ? -1 : A < B ? 1 : 0;
232
- }
233
- if (type.includes('date')) {
234
- if (order === 'asc') {
235
- return new Date(A).getTime() - new Date(B).getTime();
236
- }
237
- return new Date(B).getTime() - new Date(A).getTime();
238
- }
63
+ const parentData = await this.relatedQuery.repository.findMany({
64
+ ...this.relatedQuery.query,
65
+ select: { id: true }
239
66
  });
240
- return _data;
241
- }
242
- reset() {
243
- this.chainReference = [];
244
- this.whereArray = [];
245
- this.orWhereArray = [];
246
- this.selectArray = [];
247
- this.forceSelectArray = [];
248
- this.orderByArray = [];
249
- this.limitNumber = undefined;
250
- this.offsetNumber = undefined;
251
- this.populateArray = [];
252
- this.chunk = null;
253
- this.pullSize = null;
254
- this.ownerId = undefined;
255
- this.paginator = undefined;
256
- this.rawQuery = undefined;
257
- this.getFirst = false;
258
- this.relations = undefined;
259
- this.loadModels = false;
260
- this.relationQuery = undefined;
261
- }
262
- async load() {
263
- const result = await this.get();
264
- this.relationQuery = {
265
- data: result,
266
- relations: this.modelRelations
267
- };
268
- return this;
269
- }
270
- async loadFirst() {
271
- const result = await this.first();
272
- this.relationQuery = {
273
- data: result,
274
- relations: this.modelRelations
275
- };
276
- return this;
277
- }
278
- getLoadedData() {
279
- return this.relationQuery.data;
280
- }
281
- with(entities) {
282
- this.relations = entities;
283
- return this;
284
- }
285
- async attach(data) {
286
- if (!this.relationQuery.relation || !this.relationQuery.data) {
287
- throw new Error('Attached can only be called as a related model');
67
+ const foreignKeyName = this.relatedQuery['repository']['modelRelations'][this.relatedQuery.key]
68
+ .inverseSidePropertyPath;
69
+ if (!foreignKeyName) {
70
+ throw new Error('The relationship was not properly defined. Please check that your Repository and Model relations have the same keys');
288
71
  }
289
- const foreignKeyName = this.relationQuery.relation.inverseSidePropertyPath;
290
- const D = Array.isArray(this.relationQuery.data)
291
- ? this.relationQuery.data
292
- : [this.relationQuery.data];
293
- const relatedData = D.map(d => ({
294
- [foreignKeyName]: this.isMongoDB
295
- ? js_utils_1.Ids.objectID(d.id)
296
- : d.id,
72
+ const relatedData = parentData.map(r => ({
73
+ [foreignKeyName]: r.id,
297
74
  ...data
298
75
  }));
299
- const existingData = await this.findByIds(relatedData.map(r => r.id));
76
+ const existingIds = this.clearEmpties(relatedData.map(r => r.id));
77
+ const existingData = existingIds.length
78
+ ? await this.findByIds(relatedData.map(r => r.id))
79
+ : [];
300
80
  const updateQueries = [];
301
81
  const insertQueries = [];
302
82
  for (const related of relatedData) {
@@ -315,87 +95,208 @@ class BaseConnector {
315
95
  const insertedResult = await this.insertMany(insertQueries);
316
96
  return [...updateResult, ...insertedResult];
317
97
  }
318
- associate(id) {
319
- if (!this.relationQuery?.relation || !this.relationQuery.data) {
98
+ async attach(id) {
99
+ if (!this.relatedQuery?.entity || !this.relatedQuery.key) {
320
100
  throw new Error('Associate can only be called as a related model');
321
101
  }
322
- const D = Array.isArray(this.relationQuery.data)
323
- ? this.relationQuery.data
324
- : [this.relationQuery.data];
325
- const relatedData = D.map(d => ({
326
- [this.relationQuery.relation.joinColumns[0].propertyName]: this.isMongoDB
327
- ? js_utils_1.Ids.objectID(d.id)
328
- : d.id,
329
- [this.relationQuery.relation.inverseJoinColumns[0].propertyName]: this
330
- .isMongoDB
331
- ? js_utils_1.Ids.objectID(id)
332
- : id
102
+ const parentData = await this.relatedQuery.repository.findMany({
103
+ ...this.relatedQuery.query,
104
+ select: { id: true }
105
+ });
106
+ const foreignKeyName = this.relatedQuery['repository']['modelRelations'][this.relatedQuery.key]
107
+ .joinColumns[0].propertyPath;
108
+ const inverseKeyName = this.relatedQuery['repository']['modelRelations'][this.relatedQuery.key]
109
+ .inverseJoinColumns[0].propertyPath;
110
+ if (!foreignKeyName || !inverseKeyName) {
111
+ throw new Error(`The relationship was not properly defined. Please check that your Repository and Model relations have the same keys: Searching for: ${this.relatedQuery.key}`);
112
+ }
113
+ const relatedData = parentData.map(d => ({
114
+ [foreignKeyName]: d.id,
115
+ [inverseKeyName]: id
333
116
  }));
334
- return this.relationQuery.pivot.insertMany(relatedData);
335
- }
336
- hasMany(Repository, relationName) {
337
- if (this.relationQuery) {
338
- this.relationQuery.relation = this.relationQuery.relations[relationName];
117
+ return this.relatedQuery.pivot.insertMany(relatedData);
118
+ }
119
+ hasMany(r) {
120
+ const newRepo = new r.repository();
121
+ const calleeName = new Error('dummy')
122
+ .stack.split('\n')[2]
123
+ .replace(/^\s+at\s+(.+?)\s.+/g, '$1')
124
+ .split('.')[1];
125
+ if (this.relatedQuery) {
126
+ newRepo.setRelatedQuery({
127
+ ...this.relatedQuery,
128
+ key: calleeName
129
+ });
339
130
  }
340
- const newClass = new Repository(this.relationQuery);
341
- this.reset();
342
- return newClass;
131
+ return newRepo;
132
+ }
133
+ belongsTo(r) {
134
+ return this.hasMany(r);
343
135
  }
344
136
  hasOne() {
345
137
  throw new Error('Method not implemented');
346
138
  }
347
- belongsTo(Repository, relationName) {
348
- if (this.relationQuery) {
349
- this.relationQuery.relation = this.relationQuery.relations[relationName];
139
+ belongsToMany(r) {
140
+ const newRepo = new r.repository();
141
+ const relationName = new Error('dummy')
142
+ .stack.split('\n')[2]
143
+ .replace(/^\s+at\s+(.+?)\s.+/g, '$1')
144
+ .split('.')[1];
145
+ const pivot = new r.pivot();
146
+ pivot.setRelatedQuery({
147
+ ...this.relatedQuery,
148
+ key: relationName
149
+ });
150
+ if (this.relatedQuery) {
151
+ newRepo.setRelatedQuery({
152
+ ...this.relatedQuery,
153
+ key: relationName,
154
+ pivot
155
+ });
350
156
  }
351
- const newClass = new Repository(this.relationQuery);
352
- this.reset();
353
- return newClass;
354
- }
355
- belongsToMany(Repository, Pivot, relationName) {
356
- this.relationQuery = !this.relationQuery
357
- ? { pivot: new Pivot(this.relationQuery) }
358
- : {
359
- ...this.relationQuery,
360
- ...{
361
- pivot: new Pivot(this.relationQuery),
362
- relation: this.relationQuery.relations[relationName]
363
- }
364
- };
365
- const newClass = new Repository(this.relationQuery);
366
- this.reset();
367
- return newClass;
368
- }
369
- withPivot() {
370
- if (this.relationQuery?.pivot) {
371
- this.relationQuery.returnPivot = true;
157
+ else {
158
+ newRepo.setRelatedQuery({
159
+ key: relationName,
160
+ pivot
161
+ });
372
162
  }
373
- return this;
163
+ return newRepo;
374
164
  }
375
165
  hasManyThrough() {
376
166
  throw new Error('Method not implemented');
377
167
  }
378
- prepareInput(columns) {
379
- let cols = [];
380
- columns.forEach(col => {
381
- cols = cols.concat(col.toString().trim());
168
+ clearEmpties(object) {
169
+ Object.entries(object).forEach(([k, v]) => {
170
+ if (v && typeof v === 'object')
171
+ this.clearEmpties(v);
172
+ if ((v && typeof v === 'object' && !Object.keys(v).length) ||
173
+ v === null ||
174
+ v === undefined ||
175
+ v.length === 0) {
176
+ if (Array.isArray(object)) {
177
+ if (!(object[k] instanceof bson_1.ObjectId)) {
178
+ object.splice(k, 1);
179
+ }
180
+ }
181
+ else if (!(v instanceof Date) && !(v instanceof bson_1.ObjectId)) {
182
+ delete object[k];
183
+ }
184
+ }
382
185
  });
383
- cols.filter((elem, pos, arr) => arr.indexOf(elem) === pos);
384
- return cols;
186
+ return object;
187
+ }
188
+ isAnyObject(val) {
189
+ return typeof val === 'object' && !Array.isArray(val) && val !== null;
190
+ }
191
+ extractConditions(conditions) {
192
+ const accumulatedClauses = [];
193
+ if (!conditions) {
194
+ return accumulatedClauses;
195
+ }
196
+ for (const clause of conditions) {
197
+ if (!clause) {
198
+ continue;
199
+ }
200
+ for (const el of Object.keys(clause)) {
201
+ const value = clause[el];
202
+ if (this.isAnyObject(value)) {
203
+ const initialKey = el;
204
+ const flatten = js_utils_1.Objects.flatten(value);
205
+ for (const key of Object.keys(flatten)) {
206
+ const transformedKey = key.replace(new RegExp('.[0-9]', 'g'), '');
207
+ if (types_1.LogicOperator[transformedKey]) {
208
+ if (types_1.LogicOperator[transformedKey] === types_1.LogicOperator.in ||
209
+ types_1.LogicOperator[transformedKey] === types_1.LogicOperator.notIn) {
210
+ accumulatedClauses.push({
211
+ operator: types_1.LogicOperator[transformedKey],
212
+ element: `${initialKey}`,
213
+ value: value[transformedKey]
214
+ });
215
+ }
216
+ else {
217
+ accumulatedClauses.push({
218
+ operator: types_1.LogicOperator[transformedKey],
219
+ element: `${initialKey}`,
220
+ value: flatten[key]
221
+ });
222
+ }
223
+ }
224
+ else if (transformedKey.includes('.')) {
225
+ const op = key.split('.').slice(-1).pop();
226
+ if (!op) {
227
+ continue;
228
+ }
229
+ if (types_1.LogicOperator[op]) {
230
+ accumulatedClauses.push({
231
+ operator: types_1.LogicOperator[op],
232
+ element: `${initialKey}.${key.replace(`.${op}`, '')}`,
233
+ value: flatten[key]
234
+ });
235
+ }
236
+ else {
237
+ accumulatedClauses.push({
238
+ operator: types_1.LogicOperator.equals,
239
+ element: `${initialKey}.${key}`,
240
+ value: flatten[key]
241
+ });
242
+ }
243
+ }
244
+ else {
245
+ accumulatedClauses.push({
246
+ operator: types_1.LogicOperator.equals,
247
+ element: `${initialKey}.${transformedKey}`,
248
+ value: flatten[key]
249
+ });
250
+ }
251
+ }
252
+ }
253
+ else {
254
+ accumulatedClauses.push({
255
+ operator: types_1.LogicOperator.equals,
256
+ element: el,
257
+ value
258
+ });
259
+ }
260
+ }
261
+ }
262
+ return accumulatedClauses;
385
263
  }
386
- async validateInput(validationClass, input) {
387
- const validationOptions = {
388
- whitelist: true,
389
- skipMissingProperties: false,
390
- forbidUnknownValues: true,
391
- stopAtFirstError: false
392
- };
393
- const instance = (0, class_transformer_1.plainToInstance)(validationClass, { ...input });
394
- const errors = await (0, class_validator_1.validate)(instance, validationOptions);
395
- return {
396
- errors: errors && errors.length ? errors : null,
397
- result: errors && errors.length ? undefined : instance
398
- };
264
+ jsApplySelect(select, data) {
265
+ const _data = Array.isArray(data) ? [...data] : [data];
266
+ if (!select) {
267
+ return data;
268
+ }
269
+ const selectedAttributes = Object.keys(js_utils_1.Objects.flatten(select));
270
+ const iterationArray = this.outputKeys.length === 0 && selectedAttributes.length > 0
271
+ ? selectedAttributes
272
+ : [...this.outputKeys];
273
+ const compareArray = this.outputKeys.length === 0 && selectedAttributes.length > 0
274
+ ? [...this.outputKeys]
275
+ : selectedAttributes;
276
+ return _data.map(element => {
277
+ const newElement = {};
278
+ iterationArray.forEach(attribute => {
279
+ if (compareArray.length > 0 && !compareArray.includes(attribute)) {
280
+ return undefined;
281
+ }
282
+ const extract = js_utils_1.Objects.getFromPath(element, attribute, undefined);
283
+ let value = js_utils_1.Objects.get(() => extract.value, undefined);
284
+ if (typeof value !== 'undefined' && value !== null) {
285
+ if (typeof value === 'object' &&
286
+ value.hasOwnProperty('data') &&
287
+ value.data.hasOwnProperty('name')) {
288
+ newElement[extract.label] = value.data.name;
289
+ }
290
+ else {
291
+ if (typeof value === 'object' && js_utils_1.Ids.isValidObjectID(value)) {
292
+ value = js_utils_1.Ids.objectIdString(value);
293
+ }
294
+ newElement[extract.label] = value;
295
+ }
296
+ }
297
+ });
298
+ return js_utils_1.Objects.nest(newElement);
299
+ });
399
300
  }
400
301
  }
401
302
  exports.BaseConnector = BaseConnector;
package/dist/Fluent.d.ts CHANGED
@@ -1,26 +1,7 @@
1
1
  import { DataSource } from 'typeorm';
2
- import { BaseDataElement, Primitives } from './types';
2
+ import { AnyObject, Primitives } from './types';
3
3
  import { Collection } from '@goatlab/js-utils';
4
- interface _FLUENT_ {
5
- models?: {
6
- [key: string]: boolean;
7
- };
8
- }
9
- declare global {
10
- interface Window {
11
- _FLUENT_: _FLUENT_;
12
- }
13
- namespace NodeJS {
14
- interface Global {
15
- _FLUENT_: _FLUENT_;
16
- }
17
- }
18
- }
19
4
  export declare class Fluent {
20
- private static registerModel;
21
- static model<T = BaseDataElement>(name: string): any;
22
- static collect<T = BaseDataElement | Primitives>(data: T[]): Collection<T>;
23
- static getConfig(): _FLUENT_;
5
+ static collect<T = AnyObject | Primitives>(data: T[]): Collection<T>;
24
6
  static initialize(dataSources: DataSource[], Entities: any[]): Promise<void>;
25
7
  }
26
- export {};
package/dist/Fluent.js CHANGED
@@ -1,45 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Fluent = void 0;
4
- const typed_path_1 = require("typed-path");
5
4
  const js_utils_1 = require("@goatlab/js-utils");
6
5
  const generatorDatasource_1 = require("./generatorDatasource");
7
- if (typeof window !== 'undefined' && window && !window._FLUENT_) {
8
- window._FLUENT_ = {
9
- models: {}
10
- };
11
- }
12
- if (global && !global._FLUENT_) {
13
- global._FLUENT_ = {
14
- models: {}
15
- };
16
- }
17
6
  class Fluent {
18
- static registerModel(name) {
19
- if (!name || name === 'baseModel') {
20
- return;
21
- }
22
- if (typeof window !== 'undefined') {
23
- window._FLUENT_.models[name] = true;
24
- return;
25
- }
26
- global._FLUENT_.models[name] = true;
27
- }
28
- static model(name) {
29
- this.registerModel(name);
30
- return (0, typed_path_1.typedPath)();
31
- }
32
7
  static collect(data) {
33
8
  return new js_utils_1.Collection(data);
34
9
  }
35
- static getConfig() {
36
- if (typeof window !== 'undefined' && window) {
37
- return window._FLUENT_;
38
- }
39
- if (typeof global !== 'undefined' && global) {
40
- return global._FLUENT_;
41
- }
42
- }
43
10
  static async initialize(dataSources, Entities) {
44
11
  generatorDatasource_1.modelGeneratorDataSource.setOptions({ entities: Entities });
45
12
  if (!generatorDatasource_1.modelGeneratorDataSource.isInitialized) {