@spinajs/orm 2.0.175 → 2.0.176

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 (75) hide show
  1. package/lib/cjs/builders.d.ts.map +1 -1
  2. package/lib/cjs/builders.js +9 -14
  3. package/lib/cjs/builders.js.map +1 -1
  4. package/lib/cjs/decorators.d.ts +1 -1
  5. package/lib/cjs/decorators.d.ts.map +1 -1
  6. package/lib/cjs/decorators.js.map +1 -1
  7. package/lib/cjs/hydrators.d.ts.map +1 -1
  8. package/lib/cjs/hydrators.js +3 -3
  9. package/lib/cjs/hydrators.js.map +1 -1
  10. package/lib/cjs/index.d.ts +2 -0
  11. package/lib/cjs/index.d.ts.map +1 -1
  12. package/lib/cjs/index.js +2 -0
  13. package/lib/cjs/index.js.map +1 -1
  14. package/lib/cjs/interfaces.d.ts +10 -2
  15. package/lib/cjs/interfaces.d.ts.map +1 -1
  16. package/lib/cjs/interfaces.js.map +1 -1
  17. package/lib/cjs/middlewares.d.ts +63 -0
  18. package/lib/cjs/middlewares.d.ts.map +1 -0
  19. package/lib/cjs/middlewares.js +259 -0
  20. package/lib/cjs/middlewares.js.map +1 -0
  21. package/lib/cjs/model.d.ts.map +1 -1
  22. package/lib/cjs/model.js +6 -5
  23. package/lib/cjs/model.js.map +1 -1
  24. package/lib/cjs/orm.d.ts.map +1 -1
  25. package/lib/cjs/orm.js +14 -8
  26. package/lib/cjs/orm.js.map +1 -1
  27. package/lib/cjs/relation-objects.d.ts +109 -0
  28. package/lib/cjs/relation-objects.d.ts.map +1 -0
  29. package/lib/cjs/relation-objects.js +222 -0
  30. package/lib/cjs/relation-objects.js.map +1 -0
  31. package/lib/cjs/relations.d.ts +24 -158
  32. package/lib/cjs/relations.d.ts.map +1 -1
  33. package/lib/cjs/relations.js +50 -500
  34. package/lib/cjs/relations.js.map +1 -1
  35. package/lib/cjs/types.d.ts +1 -1
  36. package/lib/cjs/types.d.ts.map +1 -1
  37. package/lib/mjs/builders.d.ts.map +1 -1
  38. package/lib/mjs/builders.js +10 -15
  39. package/lib/mjs/builders.js.map +1 -1
  40. package/lib/mjs/decorators.d.ts +1 -1
  41. package/lib/mjs/decorators.d.ts.map +1 -1
  42. package/lib/mjs/decorators.js.map +1 -1
  43. package/lib/mjs/hydrators.d.ts.map +1 -1
  44. package/lib/mjs/hydrators.js +1 -1
  45. package/lib/mjs/hydrators.js.map +1 -1
  46. package/lib/mjs/index.d.ts +2 -0
  47. package/lib/mjs/index.d.ts.map +1 -1
  48. package/lib/mjs/index.js +2 -0
  49. package/lib/mjs/index.js.map +1 -1
  50. package/lib/mjs/interfaces.d.ts +10 -2
  51. package/lib/mjs/interfaces.d.ts.map +1 -1
  52. package/lib/mjs/interfaces.js.map +1 -1
  53. package/lib/mjs/middlewares.d.ts +63 -0
  54. package/lib/mjs/middlewares.d.ts.map +1 -0
  55. package/lib/mjs/middlewares.js +250 -0
  56. package/lib/mjs/middlewares.js.map +1 -0
  57. package/lib/mjs/model.d.ts.map +1 -1
  58. package/lib/mjs/model.js +2 -1
  59. package/lib/mjs/model.js.map +1 -1
  60. package/lib/mjs/orm.d.ts.map +1 -1
  61. package/lib/mjs/orm.js +14 -8
  62. package/lib/mjs/orm.js.map +1 -1
  63. package/lib/mjs/relation-objects.d.ts +109 -0
  64. package/lib/mjs/relation-objects.d.ts.map +1 -0
  65. package/lib/mjs/relation-objects.js +212 -0
  66. package/lib/mjs/relation-objects.js.map +1 -0
  67. package/lib/mjs/relations.d.ts +24 -158
  68. package/lib/mjs/relations.d.ts.map +1 -1
  69. package/lib/mjs/relations.js +48 -487
  70. package/lib/mjs/relations.js.map +1 -1
  71. package/lib/mjs/types.d.ts +1 -1
  72. package/lib/mjs/types.d.ts.map +1 -1
  73. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  74. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  75. package/package.json +5 -5
@@ -10,290 +10,48 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  var BelongsToRelation_1;
11
11
  /* eslint-disable prettier/prettier */
12
12
  import { InvalidOperation } from '@spinajs/exceptions';
13
- import { RelationType, InsertBehaviour } from './interfaces.js';
14
- import { NewInstance, DI, isConstructor } from '@spinajs/di';
15
- import { SelectQueryBuilder } from './builders.js';
16
- import { createQuery, extractModelDescriptor, ModelBase } from './model.js';
13
+ import { RelationType } from './interfaces.js';
14
+ import { NewInstance, DI, Inject, Container } from '@spinajs/di';
15
+ import { BelongsToPopulateDataMiddleware, BelongsToRelationRecursiveMiddleware, BelongsToRelationResultTransformMiddleware, DiscriminationMapMiddleware, HasManyRelationMiddleware, HasManyToManyRelationMiddleware } from './middlewares.js';
16
+ import { extractModelDescriptor } from './model.js';
17
17
  import { Orm } from './orm.js';
18
- import _ from 'lodash';
19
- export class OrmRelation {
18
+ function _paramCheck(callback, err) {
19
+ const val = callback();
20
+ if (!callback()) {
21
+ throw new Error(err);
22
+ }
23
+ return val;
24
+ }
25
+ let OrmRelation = class OrmRelation {
20
26
  get Alias() {
21
27
  return this.parentRelation ? `${this.parentRelation.Alias}.${this._separator}${this._description.Name}${this._separator}` : `${this._separator}${this._description.Name}${this._separator}`;
22
28
  }
23
- constructor(_orm, _query, _description, parentRelation) {
24
- this._orm = _orm;
29
+ constructor(_container, _query, _description, parentRelation) {
30
+ this._container = _container;
25
31
  this._query = _query;
26
32
  this._description = _description;
27
33
  this.parentRelation = parentRelation;
28
- if (this._description) {
29
- this._targetModel = this._description.TargetModel ?? undefined;
30
- }
31
- this._targetModelDescriptor = extractModelDescriptor(this._targetModel);
32
- const driver = this._orm.Connections.get(this._targetModelDescriptor.Connection);
33
- const cnt = driver.Container;
34
- this._relationQuery = cnt.resolve(SelectQueryBuilder, [driver, this._targetModel, this]);
35
- this._separator = driver.Options.AliasSeparator;
36
- if (driver.Options.Database) {
37
- this._relationQuery.database(driver.Options.Database);
34
+ this._targetModel = this._description.TargetModel;
35
+ this._targetModelDescriptor = _paramCheck(() => extractModelDescriptor(this._targetModel), `Model ${this._targetModel?.name} does not have model descriptor set`);
36
+ this._driver = _paramCheck(() => DI.resolve("OrmConnection", [this._targetModelDescriptor.Connection]), `Connection ${this._targetModelDescriptor.Connection} is not set in configuration file`);
37
+ this._relationQuery = this._container.resolve("SelectQueryBuilder", [this._driver, this._targetModel, this]);
38
+ this._separator = this._driver.Options.AliasSeparator;
39
+ if (this._driver.Options.Database) {
40
+ this._relationQuery.database(this._driver.Options.Database);
38
41
  }
39
42
  }
40
43
  executeOnQuery(callback) {
41
44
  callback.call(this._relationQuery, [this]);
42
45
  }
43
- }
44
- export class HasManyRelationMiddleware {
45
- constructor(_relationQuery, _description, _path) {
46
- this._relationQuery = _relationQuery;
47
- this._description = _description;
48
- this._path = _path;
49
- }
50
- afterQuery(data) {
51
- return data;
52
- }
53
- modelCreation(_) {
54
- return null;
55
- }
56
- async afterHydration(data) {
57
- const self = this;
58
- const pks = data.map((d) => {
59
- return d[this._description.PrimaryKey];
60
- });
61
- const hydrateMiddleware = {
62
- afterQuery(data) {
63
- return data;
64
- },
65
- modelCreation() {
66
- return null;
67
- },
68
- async afterHydration(relationData) {
69
- relationData.forEach((d) => (d.__relationKey__ = self._description.Name));
70
- data.forEach((d) => {
71
- const relData = relationData.filter((rd) => {
72
- return d[self._description.PrimaryKey] === rd[self._description.ForeignKey];
73
- });
74
- d[self._description.Name] = new OneToManyRelationList(d, self._description.TargetModel, self._description, relData);
75
- });
76
- },
77
- };
78
- if (pks.length !== 0) {
79
- this._relationQuery.whereIn(this._description.ForeignKey, pks);
80
- this._relationQuery.middleware(hydrateMiddleware);
81
- return await this._relationQuery;
82
- }
83
- return [];
84
- }
85
- }
86
- class BelongsToRelationRecursiveMiddleware {
87
- constructor(_relationQuery, _description, _targetModelDescriptor) {
88
- this._relationQuery = _relationQuery;
89
- this._description = _description;
90
- this._targetModelDescriptor = _targetModelDescriptor;
91
- }
92
- afterQuery(data) {
93
- return data;
94
- }
95
- modelCreation(_) {
96
- return null;
97
- }
98
- async afterHydration(data) {
99
- const self = this;
100
- const pks = data.map((d) => d[this._description.PrimaryKey]);
101
- const fKey = this._description.ForeignKey;
102
- const key = this._description.PrimaryKey;
103
- const name = this._description.Name;
104
- const hydrateMiddleware = {
105
- afterQuery(data) {
106
- return data;
107
- },
108
- modelCreation(_) {
109
- return null;
110
- },
111
- async afterHydration(relationData) {
112
- relationData.forEach((d) => (d.__relationKey__ = self._description.Name));
113
- function buildRelationTree(_d, parent) {
114
- const branch = [];
115
- _d.forEach((d) => {
116
- if (d[fKey] === parent) {
117
- const children = buildRelationTree(_d, d[key]);
118
- if (children) {
119
- // TODO:
120
- // implement RecursiveRelation list to allow for
121
- // manipulation of the recursive data
122
- d[name] = new OneToManyRelationList(d, d.Model, {
123
- Name: name,
124
- Type: RelationType.Many,
125
- TargetModelType: d.Model,
126
- TargetModel: d.Model,
127
- SourceModel: d.Model,
128
- ForeignKey: fKey,
129
- PrimaryKey: key,
130
- Recursive: false,
131
- }, children);
132
- }
133
- branch.push(d);
134
- }
135
- });
136
- return branch;
137
- }
138
- const result = buildRelationTree(relationData, null);
139
- data.forEach((d) => {
140
- d[name] = result.find((r) => r[key] === d[key])[name];
141
- });
142
- },
143
- };
144
- this._relationQuery.whereIn(this._description.PrimaryKey, pks);
145
- this._relationQuery.middleware(new DiscriminationMapMiddleware(this._targetModelDescriptor));
146
- this._relationQuery.middleware(hydrateMiddleware);
147
- return await this._relationQuery;
148
- }
149
- }
150
- export class HasManyToManyRelationMiddleware {
151
- constructor(_relationQuery, _description, _targetModelDescriptor) {
152
- this._relationQuery = _relationQuery;
153
- this._description = _description;
154
- this._targetModelDescriptor = _targetModelDescriptor;
155
- }
156
- afterQuery(data) {
157
- return data;
158
- }
159
- modelCreation(_) {
160
- return null;
161
- }
162
- async afterHydration(data) {
163
- const self = this;
164
- const pks = data.map((d) => d[this._description.PrimaryKey]);
165
- const hydrateMiddleware = {
166
- afterQuery(data) {
167
- return data.map((d) => Object.assign({}, d[self._description.Name], { JunctionModel: self.pickProps(d, [self._description.Name]) }));
168
- },
169
- modelCreation(_) {
170
- return null;
171
- },
172
- async afterHydration(relationData) {
173
- relationData.forEach((d) => (d.__relationKey__ = self._description.Name));
174
- data.forEach((d) => {
175
- const relData = relationData.filter((rd) => rd.JunctionModel[self._description.ForeignKey] === d[self._description.PrimaryKey]);
176
- d[self._description.Name] = new ManyToManyRelationList(d, self._description.TargetModel, self._description, relData);
177
- });
178
- relationData.forEach((d) => delete d.JunctionModel);
179
- },
180
- };
181
- if (pks.length !== 0) {
182
- this._relationQuery.whereIn(this._description.ForeignKey, pks);
183
- this._relationQuery.middleware(new BelongsToRelationResultTransformMiddleware(this._description, null));
184
- this._relationQuery.middleware(new DiscriminationMapMiddleware(this._targetModelDescriptor));
185
- this._relationQuery.middleware(hydrateMiddleware);
186
- return await this._relationQuery;
187
- }
188
- return [];
189
- }
190
- pickProps(source, except) {
191
- const obj = {};
192
- for (const p in source) {
193
- if (except.indexOf(p) === -1) {
194
- obj[p] = source[p];
195
- }
196
- }
197
- return obj;
198
- }
199
- }
200
- class BelongsToPopulateDataMiddleware {
201
- constructor(_description, relation) {
202
- this._description = _description;
203
- this.relation = relation;
204
- }
205
- afterQuery(data) {
206
- return data;
207
- }
208
- modelCreation(_) {
209
- return null;
210
- }
211
- afterHydration(data) {
212
- const relData = data.map((d) => d[this._description.Name].Value).filter((x) => x !== null && x !== undefined);
213
- const middlewares = this.relation._relationQuery.Relations
214
- .map((x) => {
215
- return x._query._middlewares;
216
- })
217
- .reduce((prev, current) => {
218
- return prev.concat(current);
219
- }, []);
220
- return Promise.all(middlewares.map((x) => {
221
- return x.afterHydration(relData);
222
- }));
223
- }
224
- }
225
- class BelongsToRelationResultTransformMiddleware {
226
- constructor(_description, relation) {
227
- this._description = _description;
228
- this.relation = relation;
229
- }
230
- afterQuery(data) {
231
- return data.map((d) => {
232
- const transformedData = Object.assign(d);
233
- for (const key in transformedData) {
234
- if (key.startsWith('$')) {
235
- this.setDeep(transformedData, this.keyTransform(key), d[key]);
236
- delete transformedData[key];
237
- }
238
- }
239
- return transformedData;
240
- });
241
- }
242
- modelCreation(_) {
243
- return null;
244
- }
245
- // tslint:disable-next-line: no-empty
246
- async afterHydration(_data) { }
247
- /**
248
- * Dynamically sets a deeply nested value in an object.
249
- * Optionally "bores" a path to it if its undefined.
250
- *
251
- * @param obj - The object which contains the value you want to change/set.
252
- * @param path - The array representation of path to the value you want to change/set.
253
- * @param value - The value you want to set it to.
254
- * @param setrecursively - If true, will set value of non-existing path as well.
255
- */
256
- setDeep(obj, path, value, setrecursively = true) {
257
- path.reduce((a, b, level) => {
258
- if (setrecursively && typeof a[b] === 'undefined' && level !== path.length - 1) {
259
- a[b] = {};
260
- return a[b];
261
- }
262
- if (level === path.length - 1) {
263
- a[b] = value;
264
- return value;
265
- }
266
- return a[b];
267
- }, obj);
268
- }
269
- keyTransform(key) {
270
- return key.replace(/\$+/g, '').split('.');
271
- }
272
- }
273
- export class DiscriminationMapMiddleware {
274
- constructor(_description) {
275
- this._description = _description;
276
- }
277
- afterQuery(data) {
278
- return data;
279
- }
280
- modelCreation(data) {
281
- if (this._description.DiscriminationMap && this._description.DiscriminationMap.Field) {
282
- const distValue = data[this._description.DiscriminationMap.Field];
283
- if (distValue && this._description.DiscriminationMap.Models.has(distValue)) {
284
- const result = new (this._description.DiscriminationMap.Models.get(distValue))();
285
- result.hydrate(data);
286
- return result;
287
- }
288
- }
289
- return null;
290
- }
291
- // tslint:disable-next-line: no-empty
292
- async afterHydration(_data) { }
293
- }
46
+ };
47
+ OrmRelation = __decorate([
48
+ Inject(Container),
49
+ __metadata("design:paramtypes", [Container, Object, Object, OrmRelation])
50
+ ], OrmRelation);
51
+ export { OrmRelation };
294
52
  let BelongsToRelation = BelongsToRelation_1 = class BelongsToRelation extends OrmRelation {
295
- constructor(_orm, _query, _description, _parentRelation) {
296
- super(_orm, _query, _description, _parentRelation);
53
+ constructor(_container, _query, _description, _parentRelation) {
54
+ super(_container, _query, _description, _parentRelation);
297
55
  this._relationQuery.from(this._targetModelDescriptor.TableName, this.Alias);
298
56
  this._targetModelDescriptor.Columns.forEach((c) => {
299
57
  this._relationQuery.select(c.Name, `${this.Alias}.${c.Name}`);
@@ -307,6 +65,7 @@ let BelongsToRelation = BelongsToRelation_1 = class BelongsToRelation extends Or
307
65
  if (callback) {
308
66
  callback.call(this._relationQuery, [this]);
309
67
  }
68
+ // todo: fix this cast
310
69
  this._query.mergeBuilder(this._relationQuery);
311
70
  this._query.middleware(new BelongsToPopulateDataMiddleware(this._description, this));
312
71
  if (!this.parentRelation || !(this.parentRelation instanceof BelongsToRelation_1)) {
@@ -314,18 +73,19 @@ let BelongsToRelation = BelongsToRelation_1 = class BelongsToRelation extends Or
314
73
  // add transform middleware
315
74
  // we do this becouse belongsTo modifies query (not creating new like oneToMany and manyToMany)
316
75
  // and we only need to run transform once
317
- this._query.middleware(new BelongsToRelationResultTransformMiddleware(this._description, this));
76
+ this._query.middleware(new BelongsToRelationResultTransformMiddleware());
318
77
  }
319
78
  }
320
79
  };
321
80
  BelongsToRelation = BelongsToRelation_1 = __decorate([
322
81
  NewInstance(),
323
- __metadata("design:paramtypes", [Orm, SelectQueryBuilder, Object, OrmRelation])
82
+ Inject(Container),
83
+ __metadata("design:paramtypes", [Container, Object, Object, OrmRelation])
324
84
  ], BelongsToRelation);
325
85
  export { BelongsToRelation };
326
86
  let BelongsToRecursiveRelation = class BelongsToRecursiveRelation extends OrmRelation {
327
- constructor(_orm, _query, _description, _parentRelation) {
328
- super(_orm, _query, _description, _parentRelation);
87
+ constructor(_container, _query, _description, _parentRelation) {
88
+ super(_container, _query, _description, _parentRelation);
329
89
  this._relationQuery.withRecursive(this._description.ForeignKey, this._description.PrimaryKey).from(this._targetModelDescriptor.TableName, this.Alias);
330
90
  this._targetModelDescriptor.Columns.forEach((c) => {
331
91
  this._relationQuery.select(c.Name, `${this.Alias}.${c.Name}`);
@@ -340,12 +100,13 @@ let BelongsToRecursiveRelation = class BelongsToRecursiveRelation extends OrmRel
340
100
  };
341
101
  BelongsToRecursiveRelation = __decorate([
342
102
  NewInstance(),
343
- __metadata("design:paramtypes", [Orm, SelectQueryBuilder, Object, OrmRelation])
103
+ Inject(Container),
104
+ __metadata("design:paramtypes", [Container, Object, Object, OrmRelation])
344
105
  ], BelongsToRecursiveRelation);
345
106
  export { BelongsToRecursiveRelation };
346
107
  let OneToManyRelation = class OneToManyRelation extends OrmRelation {
347
- constructor(_orm, _query, _description, _parentRelation) {
348
- super(_orm, _query, _description, _parentRelation);
108
+ constructor(_container, _query, _description, _parentRelation) {
109
+ super(_container, _query, _description, _parentRelation);
349
110
  this._relationQuery.from(this._targetModelDescriptor.TableName, this.Alias);
350
111
  this._relationQuery.columns(this._targetModelDescriptor.Columns.map((c) => {
351
112
  return c.Name;
@@ -364,7 +125,8 @@ let OneToManyRelation = class OneToManyRelation extends OrmRelation {
364
125
  };
365
126
  OneToManyRelation = __decorate([
366
127
  NewInstance(),
367
- __metadata("design:paramtypes", [Orm, SelectQueryBuilder, Object, OrmRelation])
128
+ Inject(Container),
129
+ __metadata("design:paramtypes", [Container, Object, Object, OrmRelation])
368
130
  ], OneToManyRelation);
369
131
  export { OneToManyRelation };
370
132
  let ManyToManyRelation = class ManyToManyRelation extends OrmRelation {
@@ -374,8 +136,9 @@ let ManyToManyRelation = class ManyToManyRelation extends OrmRelation {
374
136
  get RelationQuery() {
375
137
  return this._relationQuery;
376
138
  }
377
- constructor(_orm, _query, _description, _parentRelation) {
378
- super(_orm, _query, _description, _parentRelation);
139
+ constructor(_container, _orm, _query, _description, _parentRelation) {
140
+ super(_container, _query, _description, _parentRelation);
141
+ this._orm = _orm;
379
142
  this._joinModel = this._orm.Models.find((m) => m.name === this._description.JunctionModel?.name)?.type ?? undefined;
380
143
  if (this._joinModel === undefined) {
381
144
  throw new InvalidOperation(`model ${this._description.JunctionModel} not exists in orm module`);
@@ -384,7 +147,7 @@ let ManyToManyRelation = class ManyToManyRelation extends OrmRelation {
384
147
  const orm = DI.get(Orm);
385
148
  const driver = orm.Connections.get(this._joinModelDescriptor.Connection);
386
149
  const cnt = driver.Container;
387
- this._joinQuery = cnt.resolve(SelectQueryBuilder, [driver, this._targetModel, this]);
150
+ this._joinQuery = cnt.resolve("SelectQueryBuilder", [driver, this._targetModel, this]);
388
151
  if (driver.Options.Database) {
389
152
  this._joinQuery.database(driver.Options.Database);
390
153
  }
@@ -414,6 +177,7 @@ let ManyToManyRelation = class ManyToManyRelation extends OrmRelation {
414
177
  PrimaryKey: this._description.PrimaryKey,
415
178
  Recursive: false,
416
179
  };
180
+ // todo fix this cast
417
181
  this._joinQuery.mergeBuilder(this._relationQuery);
418
182
  this._joinQuery.mergeRelations(this._relationQuery);
419
183
  this._query.middleware(new HasManyToManyRelationMiddleware(this._joinQuery, joinRelationDescriptor, this._targetModelDescriptor));
@@ -421,211 +185,8 @@ let ManyToManyRelation = class ManyToManyRelation extends OrmRelation {
421
185
  };
422
186
  ManyToManyRelation = __decorate([
423
187
  NewInstance(),
424
- __metadata("design:paramtypes", [Orm, SelectQueryBuilder, Object, OrmRelation])
188
+ Inject(Container, Orm),
189
+ __metadata("design:paramtypes", [Container, Orm, Object, Object, OrmRelation])
425
190
  ], ManyToManyRelation);
426
191
  export { ManyToManyRelation };
427
- export class SingleRelation {
428
- constructor(_owner, model, Relation, object) {
429
- this._owner = _owner;
430
- this.model = model;
431
- this.Relation = Relation;
432
- this.Populated = false;
433
- this.TargetModelDescriptor = extractModelDescriptor(model);
434
- this.Orm = DI.get(Orm);
435
- this.Value = object;
436
- }
437
- async set(obj) {
438
- this.Value = obj;
439
- await this._owner.update();
440
- }
441
- attach(obj) {
442
- this.Value = obj;
443
- }
444
- detach() {
445
- this.Value = null;
446
- }
447
- async remove() {
448
- this.Value = null;
449
- await this.Value.destroy();
450
- await this._owner.update();
451
- }
452
- async populate(callback) {
453
- /**
454
- * Do little cheat - we construct query that loads initial model with given relation.
455
- * Then we only assign relation property.
456
- *
457
- * TODO: create only relation query without loading its owner.
458
- */
459
- const query = createQuery(this.Relation.TargetModel, (SelectQueryBuilder)).query;
460
- const desc = extractModelDescriptor(this.Relation.TargetModel);
461
- query.where({ [desc.PrimaryKey]: this._owner[this.Relation.ForeignKey] });
462
- if (callback) {
463
- callback.apply(query);
464
- }
465
- const result = await query.firstOrFail();
466
- if (result) {
467
- this.Value = result;
468
- }
469
- this.Populated = true;
470
- }
471
- }
472
- /**
473
- * Iterable list of populated relation entities
474
- *
475
- * It allows to add / remove objects to relation
476
- */
477
- export class Relation extends Array {
478
- constructor(owner, Model, Relation, objects) {
479
- super();
480
- this.owner = owner;
481
- this.Model = Model;
482
- this.Relation = Relation;
483
- this.Populated = false;
484
- if (objects) {
485
- this.push(...objects);
486
- }
487
- this.TargetModelDescriptor = extractModelDescriptor(Model);
488
- this.Orm = DI.get(Orm);
489
- if (this.TargetModelDescriptor) {
490
- this.Driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection);
491
- }
492
- this.IsModelAForwardRef = !isConstructor(this.Model);
493
- }
494
- /**
495
- * Delete all objects from relation
496
- */
497
- async clear() {
498
- await this.remove(this);
499
- }
500
- empty() {
501
- this.length = 0;
502
- }
503
- /**
504
- * Populates this relation ( loads all data related to owner of this relation)
505
- */
506
- async populate(callback) {
507
- const query = this.Relation.TargetModel.where(this.Relation.ForeignKey, this.owner.PrimaryKeyValue);
508
- if (callback) {
509
- callback.apply(query);
510
- }
511
- const result = await query;
512
- if (result) {
513
- this.length = 0;
514
- this.push(...result);
515
- }
516
- this.Populated = true;
517
- }
518
- }
519
- export class ManyToManyRelationList extends Relation {
520
- intersection(_obj, _callback) {
521
- throw new Error('Method not implemented.');
522
- }
523
- union(_obj, _mode) {
524
- throw new Error('Method not implemented.');
525
- }
526
- diff(_obj, _callback) {
527
- throw new Error('Method not implemented.');
528
- }
529
- set(_obj, _callback) {
530
- throw new Error('Method not implemented.');
531
- }
532
- async remove(obj) {
533
- const self = this;
534
- const data = (Array.isArray(obj) ? obj : [obj]).map((d) => d.PrimaryKeyValue);
535
- const jmodelDescriptor = extractModelDescriptor(this.Relation.JunctionModel);
536
- const query = this.Driver.del()
537
- .from(jmodelDescriptor.TableName)
538
- .where(function () {
539
- this.whereIn(self.Relation.JunctionModelTargetModelFKey_Name, data);
540
- this.andWhere(self.Relation.JunctionModelSourceModelFKey_Name, self.owner.PrimaryKeyValue);
541
- });
542
- if (this.Driver.Options.Database) {
543
- query.database(this.Driver.Options.Database);
544
- }
545
- await query;
546
- _.remove(this, (o) => data.indexOf(o.PrimaryKeyValue) !== -1);
547
- }
548
- async add(obj, mode) {
549
- const data = Array.isArray(obj) ? obj : [obj];
550
- const relEntities = data.map((d) => {
551
- const relEntity = new this.Relation.JunctionModel();
552
- relEntity[this.Relation.JunctionModelSourceModelFKey_Name] = this.owner.PrimaryKeyValue;
553
- relEntity[this.Relation.JunctionModelTargetModelFKey_Name] = d.PrimaryKeyValue;
554
- return relEntity;
555
- });
556
- for (const m of relEntities) {
557
- await m.insert(mode);
558
- }
559
- this.push(...data);
560
- }
561
- }
562
- export class OneToManyRelationList extends Relation {
563
- async deleteRelationData(data) {
564
- if (data.length === 0) {
565
- return;
566
- }
567
- const self = this;
568
- const query = this.Driver.del()
569
- .from(this.TargetModelDescriptor.TableName)
570
- .andWhere(function () {
571
- this.whereNotIn(self.Relation.PrimaryKey, data.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue));
572
- this.where(self.Relation.ForeignKey, self.owner.PrimaryKeyValue);
573
- });
574
- if (this.Driver.Options.Database) {
575
- query.database(this.Driver.Options.Database);
576
- }
577
- await query;
578
- this.empty();
579
- }
580
- async diff(dataset, callback) {
581
- // calculate difference between this data in relation and dataset ( objects from this relation)
582
- const result = callback ? _.differenceWith(dataset, [...this], callback) : _.differenceBy(dataset, [...this], this.TargetModelDescriptor.PrimaryKey);
583
- // calculate difference between dataset and data in this relation ( objects from dataset )
584
- const result2 = callback ? _.differenceWith([...this], dataset, callback) : _.differenceBy([...this], dataset, this.TargetModelDescriptor.PrimaryKey);
585
- // combine difference from two sets
586
- const finalDiff = [...result, ...result2];
587
- await this.deleteRelationData(finalDiff);
588
- await this.add(finalDiff, InsertBehaviour.InsertOrUpdate);
589
- }
590
- async set(obj) {
591
- await this.deleteRelationData(obj);
592
- await this.add(obj, InsertBehaviour.InsertOrUpdate);
593
- }
594
- async intersection(obj, callback) {
595
- const result = callback ? _.intersectionWith(obj, [...this], callback) : _.intersectionBy(obj, [...this], this.TargetModelDescriptor.PrimaryKey);
596
- await this.deleteRelationData(result);
597
- await this.add(result, InsertBehaviour.InsertOrUpdate);
598
- }
599
- async union(obj, mode) {
600
- await this.add(obj, mode ?? InsertBehaviour.InsertOrIgnore);
601
- }
602
- async remove(obj) {
603
- const data = (Array.isArray(obj) ? obj : [obj]).map((d) => d.PrimaryKeyValue);
604
- const query = this.Driver.del().whereIn(this.Relation.ForeignKey, data).setTable(this.TargetModelDescriptor.TableName);
605
- if (this.Driver.Options.Database) {
606
- query.database(this.Driver.Options.Database);
607
- }
608
- await query;
609
- _.remove(this, (o) => data.indexOf(o.PrimaryKeyValue) !== -1);
610
- }
611
- async add(obj, mode) {
612
- const data = Array.isArray(obj) ? obj : [obj];
613
- const tInsert = data.map((x) => {
614
- if (x instanceof ModelBase) {
615
- return x;
616
- }
617
- if (this.IsModelAForwardRef) {
618
- new (this.Model())(x);
619
- }
620
- return new this.Model(x);
621
- });
622
- data.forEach((d) => {
623
- d[this.Relation.ForeignKey] = this.owner.PrimaryKeyValue;
624
- });
625
- for (const m of tInsert) {
626
- await m.insertOrUpdate(mode);
627
- }
628
- this.push(...tInsert);
629
- }
630
- }
631
192
  //# sourceMappingURL=relations.js.map