@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.
- package/lib/cjs/builders.d.ts.map +1 -1
- package/lib/cjs/builders.js +9 -14
- package/lib/cjs/builders.js.map +1 -1
- package/lib/cjs/decorators.d.ts +1 -1
- package/lib/cjs/decorators.d.ts.map +1 -1
- package/lib/cjs/decorators.js.map +1 -1
- package/lib/cjs/hydrators.d.ts.map +1 -1
- package/lib/cjs/hydrators.js +3 -3
- package/lib/cjs/hydrators.js.map +1 -1
- package/lib/cjs/index.d.ts +2 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +2 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces.d.ts +10 -2
- package/lib/cjs/interfaces.d.ts.map +1 -1
- package/lib/cjs/interfaces.js.map +1 -1
- package/lib/cjs/middlewares.d.ts +63 -0
- package/lib/cjs/middlewares.d.ts.map +1 -0
- package/lib/cjs/middlewares.js +259 -0
- package/lib/cjs/middlewares.js.map +1 -0
- package/lib/cjs/model.d.ts.map +1 -1
- package/lib/cjs/model.js +6 -5
- package/lib/cjs/model.js.map +1 -1
- package/lib/cjs/orm.d.ts.map +1 -1
- package/lib/cjs/orm.js +14 -8
- package/lib/cjs/orm.js.map +1 -1
- package/lib/cjs/relation-objects.d.ts +109 -0
- package/lib/cjs/relation-objects.d.ts.map +1 -0
- package/lib/cjs/relation-objects.js +222 -0
- package/lib/cjs/relation-objects.js.map +1 -0
- package/lib/cjs/relations.d.ts +24 -158
- package/lib/cjs/relations.d.ts.map +1 -1
- package/lib/cjs/relations.js +50 -500
- package/lib/cjs/relations.js.map +1 -1
- package/lib/cjs/types.d.ts +1 -1
- package/lib/cjs/types.d.ts.map +1 -1
- package/lib/mjs/builders.d.ts.map +1 -1
- package/lib/mjs/builders.js +10 -15
- package/lib/mjs/builders.js.map +1 -1
- package/lib/mjs/decorators.d.ts +1 -1
- package/lib/mjs/decorators.d.ts.map +1 -1
- package/lib/mjs/decorators.js.map +1 -1
- package/lib/mjs/hydrators.d.ts.map +1 -1
- package/lib/mjs/hydrators.js +1 -1
- package/lib/mjs/hydrators.js.map +1 -1
- package/lib/mjs/index.d.ts +2 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +2 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/interfaces.d.ts +10 -2
- package/lib/mjs/interfaces.d.ts.map +1 -1
- package/lib/mjs/interfaces.js.map +1 -1
- package/lib/mjs/middlewares.d.ts +63 -0
- package/lib/mjs/middlewares.d.ts.map +1 -0
- package/lib/mjs/middlewares.js +250 -0
- package/lib/mjs/middlewares.js.map +1 -0
- package/lib/mjs/model.d.ts.map +1 -1
- package/lib/mjs/model.js +2 -1
- package/lib/mjs/model.js.map +1 -1
- package/lib/mjs/orm.d.ts.map +1 -1
- package/lib/mjs/orm.js +14 -8
- package/lib/mjs/orm.js.map +1 -1
- package/lib/mjs/relation-objects.d.ts +109 -0
- package/lib/mjs/relation-objects.d.ts.map +1 -0
- package/lib/mjs/relation-objects.js +212 -0
- package/lib/mjs/relation-objects.js.map +1 -0
- package/lib/mjs/relations.d.ts +24 -158
- package/lib/mjs/relations.d.ts.map +1 -1
- package/lib/mjs/relations.js +48 -487
- package/lib/mjs/relations.js.map +1 -1
- package/lib/mjs/types.d.ts +1 -1
- package/lib/mjs/types.d.ts.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +5 -5
package/lib/mjs/relations.js
CHANGED
|
@@ -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
|
|
14
|
-
import { NewInstance, DI,
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
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
|
-
|
|
19
|
-
|
|
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(
|
|
24
|
-
this.
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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(
|
|
296
|
-
super(
|
|
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(
|
|
76
|
+
this._query.middleware(new BelongsToRelationResultTransformMiddleware());
|
|
318
77
|
}
|
|
319
78
|
}
|
|
320
79
|
};
|
|
321
80
|
BelongsToRelation = BelongsToRelation_1 = __decorate([
|
|
322
81
|
NewInstance(),
|
|
323
|
-
|
|
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(
|
|
328
|
-
super(
|
|
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
|
-
|
|
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(
|
|
348
|
-
super(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|