@spinajs/orm-sql 2.0.28 → 2.0.39
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/compilers.d.ts +25 -6
- package/lib/compilers.js +223 -16
- package/lib/compilers.js.map +1 -1
- package/lib/converters.js +4 -7
- package/lib/converters.js.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/orm/src/builders.d.ts +636 -0
- package/lib/orm/src/builders.js +1509 -0
- package/lib/orm/src/builders.js.map +1 -0
- package/lib/orm/src/converters.d.ts +14 -0
- package/lib/orm/src/converters.js +57 -0
- package/lib/orm/src/converters.js.map +1 -0
- package/lib/orm/src/decorators.d.ts +152 -0
- package/lib/orm/src/decorators.js +454 -0
- package/lib/orm/src/decorators.js.map +1 -0
- package/lib/orm/src/dehydrators.d.ts +7 -0
- package/lib/orm/src/dehydrators.js +41 -0
- package/lib/orm/src/dehydrators.js.map +1 -0
- package/lib/orm/src/driver.d.ts +80 -0
- package/lib/orm/src/driver.js +104 -0
- package/lib/orm/src/driver.js.map +1 -0
- package/lib/orm/src/enums.d.ts +115 -0
- package/lib/orm/src/enums.js +125 -0
- package/lib/orm/src/enums.js.map +1 -0
- package/lib/orm/src/exceptions.d.ts +6 -0
- package/lib/orm/src/exceptions.js +11 -0
- package/lib/orm/src/exceptions.js.map +1 -0
- package/lib/orm/src/hydrators.d.ts +19 -0
- package/lib/orm/src/hydrators.js +110 -0
- package/lib/orm/src/hydrators.js.map +1 -0
- package/lib/orm/src/interfaces.d.ts +794 -0
- package/lib/orm/src/interfaces.js +293 -0
- package/lib/orm/src/interfaces.js.map +1 -0
- package/lib/orm/src/model.d.ts +310 -0
- package/lib/orm/src/model.js +779 -0
- package/lib/orm/src/model.js.map +1 -0
- package/lib/orm/src/orm.d.ts +61 -0
- package/lib/orm/src/orm.js +341 -0
- package/lib/orm/src/orm.js.map +1 -0
- package/lib/orm/src/relations.d.ts +150 -0
- package/lib/orm/src/relations.js +681 -0
- package/lib/orm/src/relations.js.map +1 -0
- package/lib/orm/src/statements.d.ts +140 -0
- package/lib/orm/src/statements.js +314 -0
- package/lib/orm/src/statements.js.map +1 -0
- package/lib/orm/src/types.d.ts +11 -0
- package/lib/orm/src/types.js +3 -0
- package/lib/orm/src/types.js.map +1 -0
- package/lib/orm-sql/src/builders.d.ts +11 -0
- package/lib/orm-sql/src/builders.js +42 -0
- package/lib/orm-sql/src/builders.js.map +1 -0
- package/lib/orm-sql/src/compilers.d.ts +226 -0
- package/lib/orm-sql/src/compilers.js +1016 -0
- package/lib/orm-sql/src/compilers.js.map +1 -0
- package/lib/orm-sql/src/converters.d.ts +10 -0
- package/lib/orm-sql/src/converters.js +39 -0
- package/lib/orm-sql/src/converters.js.map +1 -0
- package/lib/orm-sql/src/index.d.ts +6 -0
- package/lib/orm-sql/src/index.js +70 -0
- package/lib/orm-sql/src/index.js.map +1 -0
- package/lib/orm-sql/src/statements.d.ts +46 -0
- package/lib/orm-sql/src/statements.js +268 -0
- package/lib/orm-sql/src/statements.js.map +1 -0
- package/lib/statements.js +22 -4
- package/lib/statements.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
25
|
+
if (mod && mod.__esModule) return mod;
|
|
26
|
+
var result = {};
|
|
27
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
28
|
+
__setModuleDefault(result, mod);
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
32
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
33
|
+
};
|
|
34
|
+
var OneToManyRelation_1;
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.OneToManyRelationList = exports.ManyToManyRelationList = exports.Relation = exports.SingleRelation = exports.ManyToManyRelation = exports.OneToManyRelation = exports.BelongsToRecursiveRelation = exports.BelongsToRelation = exports.DiscriminationMapMiddleware = exports.OrmRelation = void 0;
|
|
37
|
+
/* eslint-disable prettier/prettier */
|
|
38
|
+
const exceptions_1 = require("@spinajs/exceptions");
|
|
39
|
+
const interfaces_1 = require("./interfaces");
|
|
40
|
+
const di_1 = require("@spinajs/di");
|
|
41
|
+
const builders_1 = require("./builders");
|
|
42
|
+
const model_1 = require("./model");
|
|
43
|
+
const orm_1 = require("./orm");
|
|
44
|
+
const _ = __importStar(require("lodash"));
|
|
45
|
+
class OrmRelation {
|
|
46
|
+
constructor(_orm, _query, _description, parentRelation) {
|
|
47
|
+
var _a;
|
|
48
|
+
this._orm = _orm;
|
|
49
|
+
this._query = _query;
|
|
50
|
+
this._description = _description;
|
|
51
|
+
this.parentRelation = parentRelation;
|
|
52
|
+
if (this._description) {
|
|
53
|
+
this._targetModel = (_a = this._description.TargetModel) !== null && _a !== void 0 ? _a : undefined;
|
|
54
|
+
}
|
|
55
|
+
this._targetModelDescriptor = (0, model_1.extractModelDescriptor)(this._targetModel);
|
|
56
|
+
const driver = this._orm.Connections.get(this._targetModelDescriptor.Connection);
|
|
57
|
+
const cnt = driver.Container;
|
|
58
|
+
this._relationQuery = cnt.resolve(builders_1.SelectQueryBuilder, [driver, this._targetModel, this]);
|
|
59
|
+
this._separator = driver.Options.AliasSeparator;
|
|
60
|
+
if (driver.Options.Database) {
|
|
61
|
+
this._relationQuery.database(driver.Options.Database);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
get Alias() {
|
|
65
|
+
return this.parentRelation ? `${this.parentRelation.Alias}.${this._separator}${this._description.Name}${this._separator}` : `${this._separator}${this._description.Name}${this._separator}`;
|
|
66
|
+
}
|
|
67
|
+
executeOnQuery(callback) {
|
|
68
|
+
callback.call(this._relationQuery, [this]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.OrmRelation = OrmRelation;
|
|
72
|
+
class HasManyRelationMiddleware {
|
|
73
|
+
constructor(_relationQuery, _description, _path) {
|
|
74
|
+
this._relationQuery = _relationQuery;
|
|
75
|
+
this._description = _description;
|
|
76
|
+
this._path = _path;
|
|
77
|
+
}
|
|
78
|
+
afterQuery(data) {
|
|
79
|
+
return data;
|
|
80
|
+
}
|
|
81
|
+
modelCreation(_) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
async afterHydration(data) {
|
|
85
|
+
const self = this;
|
|
86
|
+
const pks = data.map((d) => {
|
|
87
|
+
if (this._path) {
|
|
88
|
+
return _.get(d, this._path)[this._description.PrimaryKey];
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return d[this._description.PrimaryKey];
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const hydrateMiddleware = {
|
|
95
|
+
afterQuery(data) {
|
|
96
|
+
return data;
|
|
97
|
+
},
|
|
98
|
+
modelCreation() {
|
|
99
|
+
return null;
|
|
100
|
+
},
|
|
101
|
+
async afterHydration(relationData) {
|
|
102
|
+
relationData.forEach((d) => (d.__relationKey__ = self._description.Name));
|
|
103
|
+
data.forEach((d) => {
|
|
104
|
+
const relData = relationData.filter((rd) => {
|
|
105
|
+
if (self._path) {
|
|
106
|
+
return _.get(d, self._path)[self._description.PrimaryKey] === rd[self._description.ForeignKey];
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
return rd[self._description.ForeignKey] === d[self._description.PrimaryKey];
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
if (self._path) {
|
|
113
|
+
_.get(d, self._path)[self._description.Name] = new OneToManyRelationList(d, self._description.TargetModel, self._description, relData);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
d[self._description.Name] = new OneToManyRelationList(d, self._description.TargetModel, self._description, relData);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
if (pks.length !== 0) {
|
|
122
|
+
this._relationQuery.whereIn(this._description.ForeignKey, pks);
|
|
123
|
+
this._relationQuery.middleware(hydrateMiddleware);
|
|
124
|
+
return await this._relationQuery;
|
|
125
|
+
}
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
class BelongsToRelationRecursiveMiddleware {
|
|
130
|
+
constructor(_relationQuery, _description, _targetModelDescriptor) {
|
|
131
|
+
this._relationQuery = _relationQuery;
|
|
132
|
+
this._description = _description;
|
|
133
|
+
this._targetModelDescriptor = _targetModelDescriptor;
|
|
134
|
+
}
|
|
135
|
+
afterQuery(data) {
|
|
136
|
+
return data;
|
|
137
|
+
}
|
|
138
|
+
modelCreation(_) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
async afterHydration(data) {
|
|
142
|
+
const self = this;
|
|
143
|
+
const pks = data.map((d) => d[this._description.PrimaryKey]);
|
|
144
|
+
const hydrateMiddleware = {
|
|
145
|
+
afterQuery(data) {
|
|
146
|
+
return data;
|
|
147
|
+
},
|
|
148
|
+
modelCreation(_) {
|
|
149
|
+
return null;
|
|
150
|
+
},
|
|
151
|
+
async afterHydration(relationData) {
|
|
152
|
+
relationData.forEach((d) => (d.__relationKey__ = self._description.Name));
|
|
153
|
+
const roots = relationData.filter((rd) => rd[self._description.ForeignKey] === 0 || rd[self._description.ForeignKey] === null);
|
|
154
|
+
const leafs = roots.map((r) => {
|
|
155
|
+
return fillRecursive(r);
|
|
156
|
+
function fillRecursive(parent) {
|
|
157
|
+
const child = relationData.find((rd) => rd[self._description.ForeignKey] === parent[self._description.PrimaryKey]);
|
|
158
|
+
if (!child) {
|
|
159
|
+
return parent;
|
|
160
|
+
}
|
|
161
|
+
child[self._description.Name] = new SingleRelation(child, self._description.TargetModel, self._description, parent);
|
|
162
|
+
return fillRecursive(child);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
data.forEach((d) => {
|
|
166
|
+
const val = leafs.find((l) => l[self._description.PrimaryKey] === d[self._description.PrimaryKey])[self._description.Name];
|
|
167
|
+
const rel = val;
|
|
168
|
+
d[self._description.Name] = rel;
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
this._relationQuery.whereIn(this._description.PrimaryKey, pks);
|
|
173
|
+
this._relationQuery.middleware(new DiscriminationMapMiddleware(this._targetModelDescriptor));
|
|
174
|
+
this._relationQuery.middleware(hydrateMiddleware);
|
|
175
|
+
return await this._relationQuery;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
class HasManyToManyRelationMiddleware {
|
|
179
|
+
constructor(_relationQuery, _description, _targetModelDescriptor) {
|
|
180
|
+
this._relationQuery = _relationQuery;
|
|
181
|
+
this._description = _description;
|
|
182
|
+
this._targetModelDescriptor = _targetModelDescriptor;
|
|
183
|
+
}
|
|
184
|
+
afterQuery(data) {
|
|
185
|
+
return data;
|
|
186
|
+
}
|
|
187
|
+
modelCreation(_) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
async afterHydration(data) {
|
|
191
|
+
const self = this;
|
|
192
|
+
const pks = data.map((d) => d[this._description.PrimaryKey]);
|
|
193
|
+
const hydrateMiddleware = {
|
|
194
|
+
afterQuery(data) {
|
|
195
|
+
return data.map((d) => Object.assign({}, d[self._description.Name], { JunctionModel: self.pickProps(d, [self._description.Name]) }));
|
|
196
|
+
},
|
|
197
|
+
modelCreation(_) {
|
|
198
|
+
return null;
|
|
199
|
+
},
|
|
200
|
+
async afterHydration(relationData) {
|
|
201
|
+
relationData.forEach((d) => (d.__relationKey__ = self._description.Name));
|
|
202
|
+
data.forEach((d) => {
|
|
203
|
+
const relData = relationData.filter((rd) => rd.JunctionModel[self._description.ForeignKey] === d[self._description.PrimaryKey]);
|
|
204
|
+
d[self._description.Name] = new ManyToManyRelationList(d, self._description.TargetModel, self._description, relData);
|
|
205
|
+
});
|
|
206
|
+
relationData.forEach((d) => delete d.JunctionModel);
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
if (pks.length !== 0) {
|
|
210
|
+
this._relationQuery.whereIn(this._description.ForeignKey, pks);
|
|
211
|
+
this._relationQuery.middleware(new BelongsToRelationResultTransformMiddleware(this._description));
|
|
212
|
+
this._relationQuery.middleware(new DiscriminationMapMiddleware(this._targetModelDescriptor));
|
|
213
|
+
this._relationQuery.middleware(hydrateMiddleware);
|
|
214
|
+
return await this._relationQuery;
|
|
215
|
+
}
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
pickProps(source, except) {
|
|
219
|
+
const obj = {};
|
|
220
|
+
for (const p in source) {
|
|
221
|
+
if (except.indexOf(p) === -1) {
|
|
222
|
+
obj[p] = source[p];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return obj;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
class BelongsToRelationResultTransformMiddleware {
|
|
229
|
+
constructor(_description) {
|
|
230
|
+
this._description = _description;
|
|
231
|
+
}
|
|
232
|
+
afterQuery(data) {
|
|
233
|
+
return data.map((d) => {
|
|
234
|
+
const transformedData = Object.assign(d);
|
|
235
|
+
for (const key in transformedData) {
|
|
236
|
+
if (key.startsWith('$')) {
|
|
237
|
+
this.setDeep(transformedData, this.keyTransform(key), d[key]);
|
|
238
|
+
delete transformedData[key];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return transformedData;
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
modelCreation(_) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
// tslint:disable-next-line: no-empty
|
|
248
|
+
async afterHydration(_data) { }
|
|
249
|
+
/**
|
|
250
|
+
* Dynamically sets a deeply nested value in an object.
|
|
251
|
+
* Optionally "bores" a path to it if its undefined.
|
|
252
|
+
*
|
|
253
|
+
* @param obj - The object which contains the value you want to change/set.
|
|
254
|
+
* @param path - The array representation of path to the value you want to change/set.
|
|
255
|
+
* @param value - The value you want to set it to.
|
|
256
|
+
* @param setrecursively - If true, will set value of non-existing path as well.
|
|
257
|
+
*/
|
|
258
|
+
setDeep(obj, path, value, setrecursively = true) {
|
|
259
|
+
path.reduce((a, b, level) => {
|
|
260
|
+
if (setrecursively && typeof a[b] === 'undefined' && level !== path.length - 1) {
|
|
261
|
+
a[b] = {};
|
|
262
|
+
return a[b];
|
|
263
|
+
}
|
|
264
|
+
if (level === path.length - 1) {
|
|
265
|
+
a[b] = value;
|
|
266
|
+
return value;
|
|
267
|
+
}
|
|
268
|
+
return a[b];
|
|
269
|
+
}, obj);
|
|
270
|
+
}
|
|
271
|
+
keyTransform(key) {
|
|
272
|
+
return key.replace(/\$+/g, '').split('.');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
class BelongsToRelationResultTransformOneToManyMiddleware extends BelongsToRelationResultTransformMiddleware {
|
|
276
|
+
keyTransform(key) {
|
|
277
|
+
return key.replace(/\$+/g, '').split('.');
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
class DiscriminationMapMiddleware {
|
|
281
|
+
constructor(_description) {
|
|
282
|
+
this._description = _description;
|
|
283
|
+
}
|
|
284
|
+
afterQuery(data) {
|
|
285
|
+
return data;
|
|
286
|
+
}
|
|
287
|
+
modelCreation(data) {
|
|
288
|
+
if (this._description.DiscriminationMap && this._description.DiscriminationMap.Field) {
|
|
289
|
+
const distValue = data[this._description.DiscriminationMap.Field];
|
|
290
|
+
if (distValue && this._description.DiscriminationMap.Models.has(distValue)) {
|
|
291
|
+
const result = new (this._description.DiscriminationMap.Models.get(distValue))();
|
|
292
|
+
result.hydrate(data);
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
// tslint:disable-next-line: no-empty
|
|
299
|
+
async afterHydration(_data) { }
|
|
300
|
+
}
|
|
301
|
+
exports.DiscriminationMapMiddleware = DiscriminationMapMiddleware;
|
|
302
|
+
let BelongsToRelation = class BelongsToRelation extends OrmRelation {
|
|
303
|
+
constructor(_orm, _query, _description, _parentRelation) {
|
|
304
|
+
super(_orm, _query, _description, _parentRelation);
|
|
305
|
+
this._relationQuery.from(this._targetModelDescriptor.TableName, this.Alias);
|
|
306
|
+
this._targetModelDescriptor.Columns.forEach((c) => {
|
|
307
|
+
this._relationQuery.select(c.Name, `${this.Alias}.${c.Name}`);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
execute(callback) {
|
|
311
|
+
if (!this.parentRelation && !this._query.TableAlias) {
|
|
312
|
+
this._query.setAlias(`${this._separator}${this._description.SourceModel.name}${this._separator}`);
|
|
313
|
+
}
|
|
314
|
+
this._query.leftJoin(this._targetModelDescriptor.TableName, this.Alias, this._description.ForeignKey, `${this._description.PrimaryKey}`);
|
|
315
|
+
if (callback) {
|
|
316
|
+
callback.call(this._relationQuery, [this]);
|
|
317
|
+
}
|
|
318
|
+
this._query.mergeStatements(this._relationQuery);
|
|
319
|
+
if (!this.parentRelation) {
|
|
320
|
+
// if we are on top of the belongsTo relation stack
|
|
321
|
+
// add transform middleware
|
|
322
|
+
// we do this becouse belongsTo modifies query (not creating new like oneToMany and manyToMany)
|
|
323
|
+
// and we only need to run transform once
|
|
324
|
+
this._query.middleware(new BelongsToRelationResultTransformMiddleware(this._description));
|
|
325
|
+
}
|
|
326
|
+
else if (!this.parentRelation.parentRelation && this.parentRelation instanceof OneToManyRelation) {
|
|
327
|
+
// if we called populate from OneToMany relation
|
|
328
|
+
// we must use different path transform ( couse onetomany is separate query)
|
|
329
|
+
// otherwise we would fill invalid property on entity
|
|
330
|
+
this._query.middleware(new BelongsToRelationResultTransformOneToManyMiddleware(this._description));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
BelongsToRelation = __decorate([
|
|
335
|
+
(0, di_1.NewInstance)(),
|
|
336
|
+
__metadata("design:paramtypes", [orm_1.Orm, builders_1.SelectQueryBuilder, Object, OrmRelation])
|
|
337
|
+
], BelongsToRelation);
|
|
338
|
+
exports.BelongsToRelation = BelongsToRelation;
|
|
339
|
+
let BelongsToRecursiveRelation = class BelongsToRecursiveRelation extends OrmRelation {
|
|
340
|
+
constructor(_orm, _query, _description, _parentRelation) {
|
|
341
|
+
super(_orm, _query, _description, _parentRelation);
|
|
342
|
+
this._relationQuery.withRecursive(this._description.ForeignKey, this._description.PrimaryKey).from(this._targetModelDescriptor.TableName, this.Alias);
|
|
343
|
+
this._targetModelDescriptor.Columns.forEach((c) => {
|
|
344
|
+
this._relationQuery.select(c.Name, `${this.Alias}.${c.Name}`);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
execute(callback) {
|
|
348
|
+
if (callback) {
|
|
349
|
+
callback.call(this._relationQuery, [this]);
|
|
350
|
+
}
|
|
351
|
+
this._query.middleware(new BelongsToRelationRecursiveMiddleware(this._relationQuery, this._description, this._targetModelDescriptor));
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
BelongsToRecursiveRelation = __decorate([
|
|
355
|
+
(0, di_1.NewInstance)(),
|
|
356
|
+
__metadata("design:paramtypes", [orm_1.Orm, builders_1.SelectQueryBuilder, Object, OrmRelation])
|
|
357
|
+
], BelongsToRecursiveRelation);
|
|
358
|
+
exports.BelongsToRecursiveRelation = BelongsToRecursiveRelation;
|
|
359
|
+
let OneToManyRelation = OneToManyRelation_1 = class OneToManyRelation extends OrmRelation {
|
|
360
|
+
constructor(_orm, _query, _description, _parentRelation) {
|
|
361
|
+
super(_orm, _query, _description, _parentRelation);
|
|
362
|
+
this._relationQuery.from(this._targetModelDescriptor.TableName, this.Alias);
|
|
363
|
+
this._relationQuery.columns(this._targetModelDescriptor.Columns.map((c) => {
|
|
364
|
+
return c.Name;
|
|
365
|
+
}));
|
|
366
|
+
}
|
|
367
|
+
execute(callback) {
|
|
368
|
+
if (!this.parentRelation && !this._query.TableAlias) {
|
|
369
|
+
this._query.setAlias(`${this._separator}${this._description.SourceModel.name}${this._separator}`);
|
|
370
|
+
}
|
|
371
|
+
const path = [];
|
|
372
|
+
let cur = this.parentRelation;
|
|
373
|
+
while (cur && !(cur instanceof OneToManyRelation_1)) {
|
|
374
|
+
path.push(cur._description.Name);
|
|
375
|
+
cur = cur.parentRelation;
|
|
376
|
+
}
|
|
377
|
+
if (callback) {
|
|
378
|
+
callback.call(this._relationQuery, [this]);
|
|
379
|
+
}
|
|
380
|
+
this._query.middleware(new DiscriminationMapMiddleware(this._targetModelDescriptor));
|
|
381
|
+
this._query.middleware(new HasManyRelationMiddleware(this._relationQuery, this._description, path.join('.')));
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
OneToManyRelation = OneToManyRelation_1 = __decorate([
|
|
385
|
+
(0, di_1.NewInstance)(),
|
|
386
|
+
__metadata("design:paramtypes", [orm_1.Orm, builders_1.SelectQueryBuilder, Object, OrmRelation])
|
|
387
|
+
], OneToManyRelation);
|
|
388
|
+
exports.OneToManyRelation = OneToManyRelation;
|
|
389
|
+
let ManyToManyRelation = class ManyToManyRelation extends OrmRelation {
|
|
390
|
+
constructor(_orm, _query, _description, _parentRelation) {
|
|
391
|
+
var _a, _b;
|
|
392
|
+
super(_orm, _query, _description, _parentRelation);
|
|
393
|
+
this._joinModel = (_b = (_a = this._orm.Models.find((m) => { var _a; return m.name === ((_a = this._description.JunctionModel) === null || _a === void 0 ? void 0 : _a.name); })) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : undefined;
|
|
394
|
+
if (this._joinModel === undefined) {
|
|
395
|
+
throw new exceptions_1.InvalidOperation(`model ${this._description.JunctionModel} not exists in orm module`);
|
|
396
|
+
}
|
|
397
|
+
this._joinModelDescriptor = (0, model_1.extractModelDescriptor)(this._joinModel);
|
|
398
|
+
const orm = di_1.DI.get(orm_1.Orm);
|
|
399
|
+
const driver = orm.Connections.get(this._targetModelDescriptor.Connection);
|
|
400
|
+
const cnt = driver.Container;
|
|
401
|
+
this._joinQuery = cnt.resolve(builders_1.SelectQueryBuilder, [driver, this._targetModel, this]);
|
|
402
|
+
if (driver.Options.Database) {
|
|
403
|
+
this._joinQuery.database(driver.Options.Database);
|
|
404
|
+
}
|
|
405
|
+
this._joinQuery.from(this._joinModelDescriptor.TableName, `${this._separator}${this._joinModelDescriptor.TableName}${this._separator}`);
|
|
406
|
+
this._joinQuery.columns(this._joinModelDescriptor.Columns.map((c) => {
|
|
407
|
+
return c.Name;
|
|
408
|
+
}));
|
|
409
|
+
this._relationQuery.from(this._targetModelDescriptor.TableName, this.Alias);
|
|
410
|
+
this._targetModelDescriptor.Columns.forEach((c) => {
|
|
411
|
+
this._relationQuery.select(c.Name, `${this.Alias}.${c.Name}`);
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
get TableJoinQuery() {
|
|
415
|
+
return this._joinQuery;
|
|
416
|
+
}
|
|
417
|
+
get RelationQuery() {
|
|
418
|
+
return this._relationQuery;
|
|
419
|
+
}
|
|
420
|
+
execute(callback) {
|
|
421
|
+
this._joinQuery.leftJoin(this._targetModelDescriptor.TableName, this.Alias, this._description.JunctionModelTargetModelFKey_Name, this._description.ForeignKey);
|
|
422
|
+
if (callback) {
|
|
423
|
+
callback.call(this._relationQuery, [this]);
|
|
424
|
+
}
|
|
425
|
+
const joinRelationDescriptor = {
|
|
426
|
+
Name: this._description.Name,
|
|
427
|
+
Type: interfaces_1.RelationType.Many,
|
|
428
|
+
TargetModelType: this._description.JunctionModel,
|
|
429
|
+
TargetModel: this._description.JunctionModel,
|
|
430
|
+
SourceModel: this._description.SourceModel,
|
|
431
|
+
ForeignKey: this._description.JunctionModelSourceModelFKey_Name,
|
|
432
|
+
PrimaryKey: this._description.PrimaryKey,
|
|
433
|
+
Recursive: false,
|
|
434
|
+
};
|
|
435
|
+
this._joinQuery.mergeStatements(this._relationQuery);
|
|
436
|
+
this._query.middleware(new HasManyToManyRelationMiddleware(this._joinQuery, joinRelationDescriptor, this._targetModelDescriptor));
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
ManyToManyRelation = __decorate([
|
|
440
|
+
(0, di_1.NewInstance)(),
|
|
441
|
+
__metadata("design:paramtypes", [orm_1.Orm, builders_1.SelectQueryBuilder, Object, OrmRelation])
|
|
442
|
+
], ManyToManyRelation);
|
|
443
|
+
exports.ManyToManyRelation = ManyToManyRelation;
|
|
444
|
+
class SingleRelation {
|
|
445
|
+
constructor(_owner, model, Relation, object) {
|
|
446
|
+
this._owner = _owner;
|
|
447
|
+
this.model = model;
|
|
448
|
+
this.Relation = Relation;
|
|
449
|
+
this.Populated = false;
|
|
450
|
+
this.TargetModelDescriptor = (0, model_1.extractModelDescriptor)(model);
|
|
451
|
+
this.Orm = di_1.DI.get(orm_1.Orm);
|
|
452
|
+
this.Value = object;
|
|
453
|
+
}
|
|
454
|
+
async set(obj) {
|
|
455
|
+
this.Value = obj;
|
|
456
|
+
await this._owner.update();
|
|
457
|
+
}
|
|
458
|
+
attach(obj) {
|
|
459
|
+
this.Value = obj;
|
|
460
|
+
}
|
|
461
|
+
detach() {
|
|
462
|
+
this.Value = null;
|
|
463
|
+
}
|
|
464
|
+
async remove() {
|
|
465
|
+
this.Value = null;
|
|
466
|
+
await this.Value.destroy();
|
|
467
|
+
await this._owner.update();
|
|
468
|
+
}
|
|
469
|
+
async populate(callback) {
|
|
470
|
+
/**
|
|
471
|
+
* Do little cheat - we construct query that loads initial model with given relation.
|
|
472
|
+
* Then we only assign relation property.
|
|
473
|
+
*
|
|
474
|
+
* TODO: create only relation query without loading its owner.
|
|
475
|
+
*/
|
|
476
|
+
const query = (0, model_1.createQuery)(this.Relation.TargetModel, (builders_1.SelectQueryBuilder)).query;
|
|
477
|
+
const desc = (0, model_1.extractModelDescriptor)(this.Relation.TargetModel);
|
|
478
|
+
query.where({ [desc.PrimaryKey]: this._owner[this.Relation.ForeignKey] });
|
|
479
|
+
if (callback) {
|
|
480
|
+
callback.apply(query);
|
|
481
|
+
}
|
|
482
|
+
const result = await query.firstOrFail();
|
|
483
|
+
if (result) {
|
|
484
|
+
this.Value = result;
|
|
485
|
+
}
|
|
486
|
+
this.Populated = true;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
exports.SingleRelation = SingleRelation;
|
|
490
|
+
/**
|
|
491
|
+
* Iterable list of populated relation entities
|
|
492
|
+
*
|
|
493
|
+
* It allows to add / remove objects to relation
|
|
494
|
+
*/
|
|
495
|
+
class Relation extends Array {
|
|
496
|
+
constructor(owner, model, Relation, objects) {
|
|
497
|
+
super();
|
|
498
|
+
this.owner = owner;
|
|
499
|
+
this.model = model;
|
|
500
|
+
this.Relation = Relation;
|
|
501
|
+
this.Populated = false;
|
|
502
|
+
if (objects) {
|
|
503
|
+
this.push(...objects);
|
|
504
|
+
}
|
|
505
|
+
this.TargetModelDescriptor = (0, model_1.extractModelDescriptor)(model);
|
|
506
|
+
this.Orm = di_1.DI.get(orm_1.Orm);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Delete all objects from relation
|
|
510
|
+
*/
|
|
511
|
+
async clear() {
|
|
512
|
+
await this.remove(this);
|
|
513
|
+
}
|
|
514
|
+
empty() {
|
|
515
|
+
this.length = 0;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Populates this relation
|
|
519
|
+
*/
|
|
520
|
+
async populate(callback) {
|
|
521
|
+
const query = this.Relation.TargetModel.where(this.Relation.ForeignKey, this.owner.PrimaryKeyValue);
|
|
522
|
+
if (callback) {
|
|
523
|
+
callback.apply(query);
|
|
524
|
+
}
|
|
525
|
+
const result = await query;
|
|
526
|
+
if (result) {
|
|
527
|
+
this.length = 0;
|
|
528
|
+
this.push(...result);
|
|
529
|
+
}
|
|
530
|
+
this.Populated = true;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
exports.Relation = Relation;
|
|
534
|
+
class ManyToManyRelationList extends Relation {
|
|
535
|
+
intersection(_obj, _callback) {
|
|
536
|
+
throw new Error('Method not implemented.');
|
|
537
|
+
}
|
|
538
|
+
union(_obj, _mode) {
|
|
539
|
+
throw new Error('Method not implemented.');
|
|
540
|
+
}
|
|
541
|
+
diff(_obj, _callback) {
|
|
542
|
+
throw new Error('Method not implemented.');
|
|
543
|
+
}
|
|
544
|
+
set(_obj, _callback) {
|
|
545
|
+
throw new Error('Method not implemented.');
|
|
546
|
+
}
|
|
547
|
+
async remove(obj) {
|
|
548
|
+
const self = this;
|
|
549
|
+
const data = (Array.isArray(obj) ? obj : [obj]).map((d) => d.PrimaryKeyValue);
|
|
550
|
+
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection);
|
|
551
|
+
const jmodelDescriptor = (0, model_1.extractModelDescriptor)(this.Relation.JunctionModel);
|
|
552
|
+
if (!driver) {
|
|
553
|
+
throw new exceptions_1.InvalidArgument(`connection ${this.TargetModelDescriptor.Connection} not exists`);
|
|
554
|
+
}
|
|
555
|
+
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.JunctionModel])
|
|
556
|
+
.from(jmodelDescriptor.TableName)
|
|
557
|
+
.where(function () {
|
|
558
|
+
this.whereIn(self.Relation.JunctionModelTargetModelFKey_Name, data);
|
|
559
|
+
this.andWhere(self.Relation.JunctionModelSourceModelFKey_Name, self.owner.PrimaryKeyValue);
|
|
560
|
+
});
|
|
561
|
+
await query;
|
|
562
|
+
_.remove(this, (o) => data.indexOf(o.PrimaryKeyValue) !== -1);
|
|
563
|
+
}
|
|
564
|
+
async add(obj, mode) {
|
|
565
|
+
const data = Array.isArray(obj) ? obj : [obj];
|
|
566
|
+
const relEntities = data.map((d) => {
|
|
567
|
+
const relEntity = new this.Relation.JunctionModel();
|
|
568
|
+
relEntity[this.Relation.JunctionModelSourceModelFKey_Name] = this.owner.PrimaryKeyValue;
|
|
569
|
+
relEntity[this.Relation.JunctionModelTargetModelFKey_Name] = d.PrimaryKeyValue;
|
|
570
|
+
return relEntity;
|
|
571
|
+
});
|
|
572
|
+
for (const m of relEntities) {
|
|
573
|
+
await m.insert(mode);
|
|
574
|
+
}
|
|
575
|
+
this.push(...data);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
exports.ManyToManyRelationList = ManyToManyRelationList;
|
|
579
|
+
class OneToManyRelationList extends Relation {
|
|
580
|
+
async diff(obj, callback) {
|
|
581
|
+
const result = callback ? _.differenceWith(obj, [...this], callback) : _.differenceBy(obj, [...this], this.TargetModelDescriptor.PrimaryKey);
|
|
582
|
+
const result2 = callback ? _.differenceWith([...this], obj, callback) : _.differenceBy([...this], obj, this.TargetModelDescriptor.PrimaryKey);
|
|
583
|
+
const finalDiff = [...result, ...result2];
|
|
584
|
+
const self = this;
|
|
585
|
+
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection);
|
|
586
|
+
const relData = finalDiff.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue);
|
|
587
|
+
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).andWhere(function () {
|
|
588
|
+
if (relData.length !== 0) {
|
|
589
|
+
this.whereNotIn(self.Relation.PrimaryKey, relData);
|
|
590
|
+
}
|
|
591
|
+
this.where(self.Relation.ForeignKey, self.owner.PrimaryKeyValue);
|
|
592
|
+
});
|
|
593
|
+
query.setTable(this.TargetModelDescriptor.TableName);
|
|
594
|
+
if (driver.Options.Database) {
|
|
595
|
+
query.database(driver.Options.Database);
|
|
596
|
+
}
|
|
597
|
+
await query;
|
|
598
|
+
this.empty();
|
|
599
|
+
await this.add(finalDiff), interfaces_1.InsertBehaviour.InsertOrUpdate;
|
|
600
|
+
}
|
|
601
|
+
async set(obj) {
|
|
602
|
+
const self = this;
|
|
603
|
+
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection);
|
|
604
|
+
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).andWhere(function () {
|
|
605
|
+
const relData = obj.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue);
|
|
606
|
+
if (relData.length !== 0) {
|
|
607
|
+
this.whereNotIn(self.Relation.PrimaryKey, relData);
|
|
608
|
+
}
|
|
609
|
+
this.where(self.Relation.ForeignKey, self.owner.PrimaryKeyValue);
|
|
610
|
+
});
|
|
611
|
+
query.setTable(this.TargetModelDescriptor.TableName);
|
|
612
|
+
if (driver.Options.Database) {
|
|
613
|
+
query.database(driver.Options.Database);
|
|
614
|
+
}
|
|
615
|
+
await query;
|
|
616
|
+
this.empty();
|
|
617
|
+
await this.add(obj, interfaces_1.InsertBehaviour.InsertOrUpdate);
|
|
618
|
+
}
|
|
619
|
+
async intersection(obj, callback) {
|
|
620
|
+
const self = this;
|
|
621
|
+
const result = callback ? _.intersectionWith(obj, [...this], callback) : _.intersectionBy(obj, [...this], this.TargetModelDescriptor.PrimaryKey);
|
|
622
|
+
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection);
|
|
623
|
+
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).andWhere(function () {
|
|
624
|
+
const relData = result.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue);
|
|
625
|
+
if (relData.length !== 0) {
|
|
626
|
+
this.whereNotIn(self.Relation.PrimaryKey, relData);
|
|
627
|
+
}
|
|
628
|
+
this.where(self.Relation.ForeignKey, self.owner.PrimaryKeyValue);
|
|
629
|
+
});
|
|
630
|
+
query.setTable(this.TargetModelDescriptor.TableName);
|
|
631
|
+
if (driver.Options.Database) {
|
|
632
|
+
query.database(driver.Options.Database);
|
|
633
|
+
}
|
|
634
|
+
await query;
|
|
635
|
+
this.empty();
|
|
636
|
+
await this.add(result, interfaces_1.InsertBehaviour.InsertOrUpdate);
|
|
637
|
+
}
|
|
638
|
+
async union(obj, mode) {
|
|
639
|
+
await this.add(obj, mode);
|
|
640
|
+
}
|
|
641
|
+
async remove(obj) {
|
|
642
|
+
const data = (Array.isArray(obj) ? obj : [obj]).map((d) => d.PrimaryKeyValue);
|
|
643
|
+
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection);
|
|
644
|
+
if (!driver) {
|
|
645
|
+
throw new exceptions_1.InvalidArgument(`connection ${this.TargetModelDescriptor.Connection} not exists`);
|
|
646
|
+
}
|
|
647
|
+
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).whereIn(this.Relation.ForeignKey, data);
|
|
648
|
+
query.setTable(this.TargetModelDescriptor.TableName);
|
|
649
|
+
if (driver.Options.Database) {
|
|
650
|
+
query.database(driver.Options.Database);
|
|
651
|
+
}
|
|
652
|
+
await query;
|
|
653
|
+
_.remove(this, (o) => data.indexOf(o.PrimaryKeyValue) !== -1);
|
|
654
|
+
}
|
|
655
|
+
async add(obj, mode) {
|
|
656
|
+
const data = Array.isArray(obj) ? obj : [obj];
|
|
657
|
+
const tInsert = data.map((x) => {
|
|
658
|
+
if (x instanceof model_1.ModelBase) {
|
|
659
|
+
return x;
|
|
660
|
+
}
|
|
661
|
+
if (_.isFunction(this.model)) {
|
|
662
|
+
return new (this.model())(x);
|
|
663
|
+
}
|
|
664
|
+
return new this.model(x);
|
|
665
|
+
});
|
|
666
|
+
data.forEach((d) => {
|
|
667
|
+
d[this.Relation.ForeignKey] = this.owner.PrimaryKeyValue;
|
|
668
|
+
});
|
|
669
|
+
for (const m of data) {
|
|
670
|
+
if (m.PrimaryKeyValue) {
|
|
671
|
+
await m.update();
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
await m.insert(mode);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
this.push(...tInsert);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
exports.OneToManyRelationList = OneToManyRelationList;
|
|
681
|
+
//# sourceMappingURL=relations.js.map
|