@rws-framework/db 2.2.1 → 2.2.3
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/dist/models/_model.js +0 -458
- package/package.json +1 -1
- package/src/models/_model.ts +0 -654
package/dist/models/_model.js
CHANGED
|
@@ -3,465 +3,7 @@
|
|
|
3
3
|
* @deprecated This file is deprecated. Import from 'models' directory instead.
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
<<<<<<< HEAD
|
|
7
|
-
exports.RWSModel = exports.TrackType = void 0;
|
|
8
|
-
const decorators_1 = require("../decorators");
|
|
9
|
-
Object.defineProperty(exports, "TrackType", { enumerable: true, get: function () { return decorators_1.TrackType; } });
|
|
10
|
-
const FieldsHelper_1 = require("../helper/FieldsHelper");
|
|
11
|
-
class RWSModel {
|
|
12
|
-
constructor(data) {
|
|
13
|
-
if (!this.getCollection()) {
|
|
14
|
-
throw new Error('Model must have a collection defined');
|
|
15
|
-
}
|
|
16
|
-
this.dbService = RWSModel.services.dbService;
|
|
17
|
-
this.configService = RWSModel.services.configService;
|
|
18
|
-
if (!data) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
if (!this.hasTimeSeries()) {
|
|
22
|
-
this._fill(data);
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
throw new Error('Time Series not supported in synchronous constructor. Use `await Model.create(data)` static method to instantiate this model.');
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
checkForInclusionWithThrow() {
|
|
29
|
-
this.checkForInclusionWithThrow();
|
|
30
|
-
}
|
|
31
|
-
static checkForInclusionWithThrow(checkModelType) {
|
|
32
|
-
if (!this.checkForInclusion(this.name)) {
|
|
33
|
-
throw new Error('Model undefined: ' + this.name);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
checkForInclusion() {
|
|
37
|
-
return this.checkForInclusion();
|
|
38
|
-
}
|
|
39
|
-
static checkForInclusion(checkModelType) {
|
|
40
|
-
return this.loadModels().find((definedModel) => {
|
|
41
|
-
return definedModel.name === checkModelType;
|
|
42
|
-
}) !== undefined;
|
|
43
|
-
}
|
|
44
|
-
_fill(data) {
|
|
45
|
-
for (const key in data) {
|
|
46
|
-
if (data.hasOwnProperty(key)) {
|
|
47
|
-
const meta = Reflect.getMetadata(`InverseTimeSeries:${key}`, this.constructor.prototype);
|
|
48
|
-
if (meta) {
|
|
49
|
-
data[key] = {
|
|
50
|
-
create: data[key]
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
this[key] = data[key];
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return this;
|
|
59
|
-
}
|
|
60
|
-
hasRelation(key) {
|
|
61
|
-
return !!this[key] && this[key] instanceof RWSModel;
|
|
62
|
-
}
|
|
63
|
-
bindRelation(key, relatedModel) {
|
|
64
|
-
return {
|
|
65
|
-
connect: {
|
|
66
|
-
id: relatedModel.id
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
async _asyncFill(data, fullDataMode = false, allowRelations = true) {
|
|
71
|
-
const collections_to_models = {};
|
|
72
|
-
const timeSeriesIds = this.getTimeSeriesModelFields();
|
|
73
|
-
const classFields = FieldsHelper_1.FieldsHelper.getAllClassFields(this.constructor);
|
|
74
|
-
// Get both relation metadata types asynchronously
|
|
75
|
-
const [relOneData, relManyData] = await Promise.all([
|
|
76
|
-
this.getRelationOneMeta(classFields),
|
|
77
|
-
this.getRelationManyMeta(classFields)
|
|
78
|
-
]);
|
|
79
|
-
this.loadModels().forEach((model) => {
|
|
80
|
-
collections_to_models[model.getCollection()] = model;
|
|
81
|
-
});
|
|
82
|
-
const seriesHydrationfields = [];
|
|
83
|
-
if (allowRelations) {
|
|
84
|
-
for (const key in relManyData) {
|
|
85
|
-
if (!fullDataMode && this.constructor._CUT_KEYS.includes(key)) {
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
const relMeta = relManyData[key];
|
|
89
|
-
const relationEnabled = this.checkRelEnabled(relMeta.key);
|
|
90
|
-
if (relationEnabled) {
|
|
91
|
-
this[relMeta.key] = await relMeta.inversionModel.findBy({
|
|
92
|
-
conditions: {
|
|
93
|
-
[relMeta.foreignKey]: data.id
|
|
94
|
-
},
|
|
95
|
-
allowRelations: false
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
for (const key in relOneData) {
|
|
100
|
-
if (!fullDataMode && this.constructor._CUT_KEYS.includes(key)) {
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
const relMeta = relOneData[key];
|
|
104
|
-
const relationEnabled = this.checkRelEnabled(relMeta.key);
|
|
105
|
-
if (!data[relMeta.hydrationField] && relMeta.required) {
|
|
106
|
-
throw new Error(`Relation field "${relMeta.hydrationField}" is required in model ${this.constructor.name}.`);
|
|
107
|
-
}
|
|
108
|
-
if (relationEnabled && data[relMeta.hydrationField]) {
|
|
109
|
-
this[relMeta.key] = await relMeta.model.find(data[relMeta.hydrationField], { allowRelations: false });
|
|
110
|
-
}
|
|
111
|
-
else if (relationEnabled && !data[relMeta.hydrationField] && data[relMeta.key]) {
|
|
112
|
-
const newRelModel = await relMeta.model.create(data[relMeta.key]);
|
|
113
|
-
this[relMeta.key] = await newRelModel.save();
|
|
114
|
-
}
|
|
115
|
-
const cutKeys = this.constructor._CUT_KEYS;
|
|
116
|
-
if (!cutKeys.includes(relMeta.hydrationField)) {
|
|
117
|
-
cutKeys.push(relMeta.hydrationField);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// Process regular fields and time series
|
|
122
|
-
for (const key in data) {
|
|
123
|
-
if (data.hasOwnProperty(key)) {
|
|
124
|
-
if (!fullDataMode && this.constructor._CUT_KEYS.includes(key)) {
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
if (Object.keys(relOneData).includes(key)) {
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
if (seriesHydrationfields.includes(key)) {
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
const timeSeriesMetaData = timeSeriesIds[key];
|
|
134
|
-
if (timeSeriesMetaData) {
|
|
135
|
-
this[key] = data[key];
|
|
136
|
-
const seriesModel = collections_to_models[timeSeriesMetaData.collection];
|
|
137
|
-
const dataModels = await seriesModel.findBy({
|
|
138
|
-
id: { in: data[key] }
|
|
139
|
-
});
|
|
140
|
-
seriesHydrationfields.push(timeSeriesMetaData.hydrationField);
|
|
141
|
-
this[timeSeriesMetaData.hydrationField] = dataModels;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
this[key] = data[key];
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return this;
|
|
149
|
-
}
|
|
150
|
-
getModelScalarFields(model) {
|
|
151
|
-
return FieldsHelper_1.FieldsHelper.getAllClassFields(model)
|
|
152
|
-
.filter(item => item.indexOf('TrackType') === 0)
|
|
153
|
-
.map(item => item.split(':').at(-1));
|
|
154
|
-
}
|
|
155
|
-
getTimeSeriesModelFields() {
|
|
156
|
-
const timeSeriesIds = {};
|
|
157
|
-
for (const key in this) {
|
|
158
|
-
if (this.hasOwnProperty(key)) {
|
|
159
|
-
const meta = Reflect.getMetadata(`InverseTimeSeries:${key}`, this);
|
|
160
|
-
if (meta) {
|
|
161
|
-
if (!timeSeriesIds[key]) {
|
|
162
|
-
timeSeriesIds[key] = {
|
|
163
|
-
collection: meta.timeSeriesModel,
|
|
164
|
-
hydrationField: meta.hydrationField,
|
|
165
|
-
ids: this[key]
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return timeSeriesIds;
|
|
172
|
-
}
|
|
173
|
-
async getRelationOneMeta(classFields) {
|
|
174
|
-
return RWSModel.getRelationOneMeta(this, classFields);
|
|
175
|
-
}
|
|
176
|
-
static async getRelationOneMeta(model, classFields) {
|
|
177
|
-
const relIds = {};
|
|
178
|
-
const relationFields = classFields
|
|
179
|
-
.filter((item) => item.indexOf('Relation') === 0 && !item.includes('Inverse'))
|
|
180
|
-
.map((item) => item.split(':').at(-1));
|
|
181
|
-
for (const key of relationFields) {
|
|
182
|
-
const metadataKey = `Relation:${key}`;
|
|
183
|
-
const metadata = Reflect.getMetadata(metadataKey, model);
|
|
184
|
-
if (metadata && metadata.promise) {
|
|
185
|
-
const resolvedMetadata = await metadata.promise;
|
|
186
|
-
if (!relIds[key]) {
|
|
187
|
-
relIds[key] = {
|
|
188
|
-
key: resolvedMetadata.key,
|
|
189
|
-
required: resolvedMetadata.required,
|
|
190
|
-
model: resolvedMetadata.relatedTo,
|
|
191
|
-
hydrationField: resolvedMetadata.relationField,
|
|
192
|
-
foreignKey: resolvedMetadata.relatedToField
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return relIds;
|
|
198
|
-
}
|
|
199
|
-
async getRelationManyMeta(classFields) {
|
|
200
|
-
return RWSModel.getRelationManyMeta(this, classFields);
|
|
201
|
-
}
|
|
202
|
-
static async getRelationManyMeta(model, classFields) {
|
|
203
|
-
const relIds = {};
|
|
204
|
-
const inverseFields = classFields
|
|
205
|
-
.filter((item) => item.indexOf('InverseRelation') === 0)
|
|
206
|
-
.map((item) => item.split(':').at(-1));
|
|
207
|
-
for (const key of inverseFields) {
|
|
208
|
-
const metadataKey = `InverseRelation:${key}`;
|
|
209
|
-
const metadata = Reflect.getMetadata(metadataKey, model);
|
|
210
|
-
if (metadata && metadata.promise) {
|
|
211
|
-
const resolvedMetadata = await metadata.promise;
|
|
212
|
-
if (!relIds[key]) {
|
|
213
|
-
relIds[key] = {
|
|
214
|
-
key: resolvedMetadata.key,
|
|
215
|
-
inversionModel: resolvedMetadata.inversionModel,
|
|
216
|
-
foreignKey: resolvedMetadata.foreignKey
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return relIds;
|
|
222
|
-
}
|
|
223
|
-
async toMongo() {
|
|
224
|
-
const data = {};
|
|
225
|
-
const timeSeriesIds = this.getTimeSeriesModelFields();
|
|
226
|
-
const timeSeriesHydrationFields = [];
|
|
227
|
-
for (const key in this) {
|
|
228
|
-
if (this.hasRelation(key)) {
|
|
229
|
-
data[key] = this.bindRelation(key, this[key]);
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
if (!(await this.isDbVariable(key))) {
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
const passedFieldCondition = this.hasOwnProperty(key) &&
|
|
236
|
-
!(this.constructor._BANNED_KEYS
|
|
237
|
-
|| RWSModel._BANNED_KEYS).includes(key) &&
|
|
238
|
-
!timeSeriesHydrationFields.includes(key);
|
|
239
|
-
if (passedFieldCondition) {
|
|
240
|
-
data[key] = this[key];
|
|
241
|
-
}
|
|
242
|
-
if (timeSeriesIds[key]) {
|
|
243
|
-
data[key] = this[key];
|
|
244
|
-
timeSeriesHydrationFields.push(timeSeriesIds[key].hydrationField);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return data;
|
|
248
|
-
}
|
|
249
|
-
getCollection() {
|
|
250
|
-
return this.constructor._collection || this._collection;
|
|
251
|
-
}
|
|
252
|
-
static getCollection() {
|
|
253
|
-
return this.constructor._collection || this._collection;
|
|
254
|
-
}
|
|
255
|
-
async save() {
|
|
256
|
-
const data = await this.toMongo();
|
|
257
|
-
let updatedModelData = data;
|
|
258
|
-
if (this.id) {
|
|
259
|
-
this.preUpdate();
|
|
260
|
-
updatedModelData = await this.dbService.update(data, this.getCollection());
|
|
261
|
-
await this._asyncFill(updatedModelData);
|
|
262
|
-
this.postUpdate();
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
this.preCreate();
|
|
266
|
-
const timeSeriesModel = await Promise.resolve().then(() => __importStar(require('./TimeSeriesModel')));
|
|
267
|
-
const isTimeSeries = this instanceof timeSeriesModel.default;
|
|
268
|
-
updatedModelData = await this.dbService.insert(data, this.getCollection(), isTimeSeries);
|
|
269
|
-
await this._asyncFill(updatedModelData);
|
|
270
|
-
this.postCreate();
|
|
271
|
-
}
|
|
272
|
-
return this;
|
|
273
|
-
}
|
|
274
|
-
static async getModelAnnotations(constructor) {
|
|
275
|
-
const annotationsData = {};
|
|
276
|
-
const metadataKeys = Reflect.getMetadataKeys(constructor.prototype);
|
|
277
|
-
// Process all metadata keys and collect promises
|
|
278
|
-
const metadataPromises = metadataKeys.map(async (fullKey) => {
|
|
279
|
-
const [annotationType, propertyKey] = fullKey.split(':');
|
|
280
|
-
const metadata = Reflect.getMetadata(fullKey, constructor.prototype);
|
|
281
|
-
if (metadata) {
|
|
282
|
-
// If this is a relation metadata with a promise
|
|
283
|
-
if (metadata.promise && (annotationType === 'Relation' || annotationType === 'InverseRelation')) {
|
|
284
|
-
const resolvedMetadata = await metadata.promise;
|
|
285
|
-
annotationsData[propertyKey] = {
|
|
286
|
-
annotationType,
|
|
287
|
-
metadata: resolvedMetadata
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
// Handle non-relation metadata as before
|
|
292
|
-
const key = metadata.key || propertyKey;
|
|
293
|
-
annotationsData[key] = {
|
|
294
|
-
annotationType,
|
|
295
|
-
metadata
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
// Wait for all metadata to be processed
|
|
301
|
-
await Promise.all(metadataPromises);
|
|
302
|
-
return annotationsData;
|
|
303
|
-
}
|
|
304
|
-
preUpdate() {
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
postUpdate() {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
preCreate() {
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
postCreate() {
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
static isSubclass(constructor, baseClass) {
|
|
317
|
-
return baseClass.prototype.isPrototypeOf(constructor.prototype);
|
|
318
|
-
}
|
|
319
|
-
hasTimeSeries() {
|
|
320
|
-
return RWSModel.checkTimeSeries(this.constructor);
|
|
321
|
-
}
|
|
322
|
-
static checkTimeSeries(constructor) {
|
|
323
|
-
const data = constructor.prototype;
|
|
324
|
-
for (const key in data) {
|
|
325
|
-
if (data.hasOwnProperty(key)) {
|
|
326
|
-
if (Reflect.getMetadata(`InverseTimeSeries:${key}`, constructor.prototype)) {
|
|
327
|
-
return true;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
|
-
async isDbVariable(variable) {
|
|
334
|
-
return RWSModel.checkDbVariable(this.constructor, variable);
|
|
335
|
-
}
|
|
336
|
-
static async checkDbVariable(constructor, variable) {
|
|
337
|
-
if (variable === 'id') {
|
|
338
|
-
return true;
|
|
339
|
-
}
|
|
340
|
-
const dbAnnotations = await RWSModel.getModelAnnotations(constructor);
|
|
341
|
-
const dbProperties = Object.keys(dbAnnotations)
|
|
342
|
-
.map((key) => { return { ...dbAnnotations[key], key }; })
|
|
343
|
-
.filter((element) => element.annotationType === 'TrackType')
|
|
344
|
-
.map((element) => element.key);
|
|
345
|
-
return dbProperties.includes(variable);
|
|
346
|
-
}
|
|
347
|
-
sanitizeDBData(data) {
|
|
348
|
-
const dataKeys = Object.keys(data);
|
|
349
|
-
const sanitizedData = {};
|
|
350
|
-
for (const key of dataKeys) {
|
|
351
|
-
if (this.isDbVariable(key)) {
|
|
352
|
-
sanitizedData[key] = data[key];
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
return sanitizedData;
|
|
356
|
-
}
|
|
357
|
-
static async watchCollection(preRun) {
|
|
358
|
-
const collection = Reflect.get(this, '_collection');
|
|
359
|
-
this.checkForInclusionWithThrow(this.name);
|
|
360
|
-
return await this.services.dbService.watchCollection(collection, preRun);
|
|
361
|
-
}
|
|
362
|
-
static async findOneBy(findParams) {
|
|
363
|
-
var _a, _b, _c, _d, _e;
|
|
364
|
-
const conditions = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.conditions) !== null && _a !== void 0 ? _a : {};
|
|
365
|
-
const ordering = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _b !== void 0 ? _b : null;
|
|
366
|
-
const fields = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _c !== void 0 ? _c : null;
|
|
367
|
-
const allowRelations = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _d !== void 0 ? _d : true;
|
|
368
|
-
const fullData = (_e = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _e !== void 0 ? _e : false;
|
|
369
|
-
this.checkForInclusionWithThrow('');
|
|
370
|
-
const collection = Reflect.get(this, '_collection');
|
|
371
|
-
const dbData = await this.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
|
|
372
|
-
if (dbData) {
|
|
373
|
-
const inst = new this();
|
|
374
|
-
return await inst._asyncFill(dbData, fullData, allowRelations);
|
|
375
|
-
}
|
|
376
|
-
return null;
|
|
377
|
-
}
|
|
378
|
-
static async find(id, findParams = null) {
|
|
379
|
-
var _a, _b, _c, _d;
|
|
380
|
-
const ordering = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _a !== void 0 ? _a : null;
|
|
381
|
-
const fields = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _b !== void 0 ? _b : null;
|
|
382
|
-
const allowRelations = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _c !== void 0 ? _c : true;
|
|
383
|
-
const fullData = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _d !== void 0 ? _d : false;
|
|
384
|
-
const collection = Reflect.get(this, '_collection');
|
|
385
|
-
this.checkForInclusionWithThrow(this.name);
|
|
386
|
-
const dbData = await this.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
|
|
387
|
-
if (dbData) {
|
|
388
|
-
const inst = new this();
|
|
389
|
-
return await inst._asyncFill(dbData, fullData, allowRelations);
|
|
390
|
-
}
|
|
391
|
-
return null;
|
|
392
|
-
}
|
|
393
|
-
static async findBy(findParams) {
|
|
394
|
-
var _a, _b, _c, _d, _e;
|
|
395
|
-
const conditions = (_a = findParams === null || findParams === void 0 ? void 0 : findParams.conditions) !== null && _a !== void 0 ? _a : {};
|
|
396
|
-
const ordering = (_b = findParams === null || findParams === void 0 ? void 0 : findParams.ordering) !== null && _b !== void 0 ? _b : null;
|
|
397
|
-
const fields = (_c = findParams === null || findParams === void 0 ? void 0 : findParams.fields) !== null && _c !== void 0 ? _c : null;
|
|
398
|
-
const allowRelations = (_d = findParams === null || findParams === void 0 ? void 0 : findParams.allowRelations) !== null && _d !== void 0 ? _d : true;
|
|
399
|
-
const fullData = (_e = findParams === null || findParams === void 0 ? void 0 : findParams.fullData) !== null && _e !== void 0 ? _e : false;
|
|
400
|
-
const collection = Reflect.get(this, '_collection');
|
|
401
|
-
this.checkForInclusionWithThrow(this.name);
|
|
402
|
-
try {
|
|
403
|
-
const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, allowRelations);
|
|
404
|
-
if (dbData.length) {
|
|
405
|
-
const instanced = [];
|
|
406
|
-
for (const data of dbData) {
|
|
407
|
-
const inst = new this();
|
|
408
|
-
instanced.push((await inst._asyncFill(data, fullData, allowRelations)));
|
|
409
|
-
}
|
|
410
|
-
return instanced;
|
|
411
|
-
}
|
|
412
|
-
return [];
|
|
413
|
-
}
|
|
414
|
-
catch (rwsError) {
|
|
415
|
-
console.error(rwsError);
|
|
416
|
-
throw rwsError;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
static async delete(conditions) {
|
|
420
|
-
const collection = Reflect.get(this, '_collection');
|
|
421
|
-
this.checkForInclusionWithThrow(this.name);
|
|
422
|
-
return await this.services.dbService.delete(collection, conditions);
|
|
423
|
-
}
|
|
424
|
-
async delete() {
|
|
425
|
-
const collection = Reflect.get(this, '_collection');
|
|
426
|
-
this.checkForInclusionWithThrow();
|
|
427
|
-
return await this.dbService.delete(collection, {
|
|
428
|
-
id: this.id
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
static async create(data) {
|
|
432
|
-
const newModel = new this();
|
|
433
|
-
const sanitizedData = newModel.sanitizeDBData(data);
|
|
434
|
-
await newModel._asyncFill(sanitizedData);
|
|
435
|
-
return newModel;
|
|
436
|
-
}
|
|
437
|
-
static loadModels() {
|
|
438
|
-
return this.allModels || [];
|
|
439
|
-
}
|
|
440
|
-
loadModels() {
|
|
441
|
-
return RWSModel.loadModels();
|
|
442
|
-
}
|
|
443
|
-
checkRelEnabled(key) {
|
|
444
|
-
return Object.keys(this.constructor._RELATIONS).includes(key) && this.constructor._RELATIONS[key] === true;
|
|
445
|
-
}
|
|
446
|
-
static setServices(services) {
|
|
447
|
-
this.allModels = services.configService.get('db_models');
|
|
448
|
-
this.services = services;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
exports.RWSModel = RWSModel;
|
|
452
|
-
RWSModel.services = {};
|
|
453
|
-
RWSModel._collection = null;
|
|
454
|
-
RWSModel._RELATIONS = {};
|
|
455
|
-
RWSModel._BANNED_KEYS = ['_collection'];
|
|
456
|
-
RWSModel.allModels = [];
|
|
457
|
-
RWSModel._CUT_KEYS = [];
|
|
458
|
-
__decorate([
|
|
459
|
-
(0, decorators_1.TrackType)(String),
|
|
460
|
-
__metadata("design:type", String)
|
|
461
|
-
], RWSModel.prototype, "id", void 0);
|
|
462
|
-
=======
|
|
463
6
|
exports.TrackType = exports.RWSModel = void 0;
|
|
464
7
|
const index_1 = require("./index");
|
|
465
8
|
Object.defineProperty(exports, "RWSModel", { enumerable: true, get: function () { return index_1.RWSModel; } });
|
|
466
9
|
Object.defineProperty(exports, "TrackType", { enumerable: true, get: function () { return index_1.TrackType; } });
|
|
467
|
-
>>>>>>> 7c50786 (v2.2.0)
|
package/package.json
CHANGED
package/src/models/_model.ts
CHANGED
|
@@ -25,657 +25,3 @@ export {
|
|
|
25
25
|
TrackType,
|
|
26
26
|
IMetaOpts
|
|
27
27
|
};
|
|
28
|
-
<<<<<<< HEAD
|
|
29
|
-
|
|
30
|
-
type RelOneMetaType<T extends IRWSModel> = {[key: string]: {required: boolean, key?: string, model: OpModelType<T>, hydrationField: string, foreignKey: string}};
|
|
31
|
-
type RelManyMetaType<T extends IRWSModel> = {[key: string]: {key: string, inversionModel: OpModelType<T>, foreignKey: string}};
|
|
32
|
-
|
|
33
|
-
export interface OpModelType<ChildClass> {
|
|
34
|
-
new(data?: any | null): ChildClass;
|
|
35
|
-
services: IRWSModelServices;
|
|
36
|
-
name: string
|
|
37
|
-
_collection: string;
|
|
38
|
-
_RELATIONS: {[key: string]: boolean}
|
|
39
|
-
_CUT_KEYS: string[]
|
|
40
|
-
allModels: OpModelType<any>[];
|
|
41
|
-
loadModels: () => OpModelType<any>[];
|
|
42
|
-
checkForInclusionWithThrow: (className: string) => void;
|
|
43
|
-
checkForInclusion: (className: string) => boolean;
|
|
44
|
-
findOneBy<T extends RWSModel<T>>(
|
|
45
|
-
this: OpModelType<T>,
|
|
46
|
-
findParams: FindByType
|
|
47
|
-
): Promise<T | null>;
|
|
48
|
-
find<T extends RWSModel<T>>(
|
|
49
|
-
this: OpModelType<T>,
|
|
50
|
-
id: string,
|
|
51
|
-
findParams?: Omit<FindByType, 'conditions'>
|
|
52
|
-
): Promise<T | null>;
|
|
53
|
-
findBy<T extends RWSModel<T>>(
|
|
54
|
-
this: OpModelType<T>,
|
|
55
|
-
findParams: FindByType
|
|
56
|
-
): Promise<T[]>;
|
|
57
|
-
delete<ChildClass extends RWSModel<ChildClass>>(
|
|
58
|
-
this: OpModelType<ChildClass>,
|
|
59
|
-
conditions: any
|
|
60
|
-
): Promise<void>
|
|
61
|
-
create<T extends RWSModel<T>>(this: OpModelType<T>, data: T): Promise<T>;
|
|
62
|
-
getRelationOneMeta(model: any, classFields: string[]): Promise<RelOneMetaType<IRWSModel>>;
|
|
63
|
-
getRelationManyMeta(model: any, classFields: string[]): Promise<RelManyMetaType<IRWSModel>>;
|
|
64
|
-
getCollection(): string;
|
|
65
|
-
setServices(services: IRWSModelServices): void;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
class RWSModel<ChildClass> implements IModel{
|
|
69
|
-
static services: IRWSModelServices = {};
|
|
70
|
-
|
|
71
|
-
[key: string]: any;
|
|
72
|
-
@TrackType(String)
|
|
73
|
-
id: string;
|
|
74
|
-
static _collection: string = null;
|
|
75
|
-
static _RELATIONS = {};
|
|
76
|
-
static _BANNED_KEYS = ['_collection'];
|
|
77
|
-
static allModels: OpModelType<any>[] = [];
|
|
78
|
-
static _CUT_KEYS: string[] = [];
|
|
79
|
-
|
|
80
|
-
constructor(data: any) {
|
|
81
|
-
if(!this.getCollection()){
|
|
82
|
-
throw new Error('Model must have a collection defined');
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
this.dbService = RWSModel.services.dbService;
|
|
87
|
-
this.configService = RWSModel.services.configService;
|
|
88
|
-
|
|
89
|
-
if(!data){
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if(!this.hasTimeSeries()){
|
|
94
|
-
this._fill(data);
|
|
95
|
-
}else{
|
|
96
|
-
throw new Error('Time Series not supported in synchronous constructor. Use `await Model.create(data)` static method to instantiate this model.');
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
checkForInclusionWithThrow(): void
|
|
101
|
-
{
|
|
102
|
-
this.checkForInclusionWithThrow();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
static checkForInclusionWithThrow(this: OpModelType<any>, checkModelType: string): void
|
|
106
|
-
{
|
|
107
|
-
if(!this.checkForInclusion(this.name)){
|
|
108
|
-
throw new Error('Model undefined: ' + this.name);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
checkForInclusion(): boolean
|
|
113
|
-
{
|
|
114
|
-
return this.checkForInclusion();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
static checkForInclusion(this: OpModelType<any>, checkModelType: string): boolean
|
|
118
|
-
{
|
|
119
|
-
return this.loadModels().find((definedModel: OpModelType<any>) => {
|
|
120
|
-
return definedModel.name === checkModelType;
|
|
121
|
-
}) !== undefined;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
_fill(data: any): RWSModel<ChildClass>{
|
|
125
|
-
for (const key in data) {
|
|
126
|
-
if (data.hasOwnProperty(key)) {
|
|
127
|
-
|
|
128
|
-
const meta = Reflect.getMetadata(`InverseTimeSeries:${key}`, (this as any).constructor.prototype);
|
|
129
|
-
|
|
130
|
-
if(meta){
|
|
131
|
-
data[key] = {
|
|
132
|
-
create: data[key]
|
|
133
|
-
};
|
|
134
|
-
}else{
|
|
135
|
-
this[key] = data[key];
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return this;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
protected hasRelation(key: string): boolean
|
|
144
|
-
{
|
|
145
|
-
return !!this[key] && this[key] instanceof RWSModel;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
protected bindRelation(key: string, relatedModel: RWSModel<any>): RelationBindType
|
|
149
|
-
{
|
|
150
|
-
return {
|
|
151
|
-
connect: {
|
|
152
|
-
id: relatedModel.id
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
public async _asyncFill(data: any, fullDataMode = false, allowRelations = true): Promise<ChildClass> {
|
|
158
|
-
const collections_to_models: {[key: string]: any} = {};
|
|
159
|
-
const timeSeriesIds = this.getTimeSeriesModelFields();
|
|
160
|
-
|
|
161
|
-
const classFields = FieldsHelper.getAllClassFields(this.constructor);
|
|
162
|
-
|
|
163
|
-
// Get both relation metadata types asynchronously
|
|
164
|
-
const [relOneData, relManyData] = await Promise.all([
|
|
165
|
-
this.getRelationOneMeta(classFields),
|
|
166
|
-
this.getRelationManyMeta(classFields)
|
|
167
|
-
]);
|
|
168
|
-
|
|
169
|
-
this.loadModels().forEach((model) => {
|
|
170
|
-
collections_to_models[model.getCollection()] = model;
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
const seriesHydrationfields: string[] = [];
|
|
174
|
-
|
|
175
|
-
if (allowRelations) {
|
|
176
|
-
for (const key in relManyData) {
|
|
177
|
-
if(!fullDataMode && (this as any).constructor._CUT_KEYS.includes(key)){
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const relMeta = relManyData[key];
|
|
182
|
-
|
|
183
|
-
const relationEnabled = this.checkRelEnabled(relMeta.key);
|
|
184
|
-
if (relationEnabled) {
|
|
185
|
-
this[relMeta.key] = await relMeta.inversionModel.findBy({
|
|
186
|
-
conditions: {
|
|
187
|
-
[relMeta.foreignKey]: data.id
|
|
188
|
-
},
|
|
189
|
-
allowRelations: false
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
for (const key in relOneData) {
|
|
195
|
-
if(!fullDataMode && (this as any).constructor._CUT_KEYS.includes(key)){
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const relMeta = relOneData[key];
|
|
200
|
-
const relationEnabled = this.checkRelEnabled(relMeta.key);
|
|
201
|
-
|
|
202
|
-
if(!data[relMeta.hydrationField] && relMeta.required){
|
|
203
|
-
throw new Error(`Relation field "${relMeta.hydrationField}" is required in model ${this.constructor.name}.`)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (relationEnabled && data[relMeta.hydrationField]) {
|
|
207
|
-
this[relMeta.key] = await relMeta.model.find(data[relMeta.hydrationField], { allowRelations: false });
|
|
208
|
-
}
|
|
209
|
-
else if(relationEnabled && !data[relMeta.hydrationField] && data[relMeta.key]){
|
|
210
|
-
const newRelModel: RWSModel<any> = await relMeta.model.create(data[relMeta.key]);
|
|
211
|
-
this[relMeta.key] = await newRelModel.save();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const cutKeys = ((this.constructor as any)._CUT_KEYS as string[]);
|
|
215
|
-
|
|
216
|
-
if(!cutKeys.includes(relMeta.hydrationField)){
|
|
217
|
-
cutKeys.push(relMeta.hydrationField)
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Process regular fields and time series
|
|
223
|
-
for (const key in data) {
|
|
224
|
-
if (data.hasOwnProperty(key)) {
|
|
225
|
-
if(!fullDataMode && (this as any).constructor._CUT_KEYS.includes(key)){
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (Object.keys(relOneData).includes(key)) {
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (seriesHydrationfields.includes(key)) {
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const timeSeriesMetaData = timeSeriesIds[key];
|
|
238
|
-
|
|
239
|
-
if (timeSeriesMetaData) {
|
|
240
|
-
this[key] = data[key];
|
|
241
|
-
const seriesModel = collections_to_models[timeSeriesMetaData.collection];
|
|
242
|
-
|
|
243
|
-
const dataModels = await seriesModel.findBy({
|
|
244
|
-
id: { in: data[key] }
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
seriesHydrationfields.push(timeSeriesMetaData.hydrationField);
|
|
248
|
-
|
|
249
|
-
this[timeSeriesMetaData.hydrationField] = dataModels;
|
|
250
|
-
} else {
|
|
251
|
-
this[key] = data[key];
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return this as any as ChildClass;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
private getModelScalarFields(model: OpModelType<any>): string[]
|
|
260
|
-
{
|
|
261
|
-
return FieldsHelper.getAllClassFields(model)
|
|
262
|
-
.filter(item => item.indexOf('TrackType') === 0)
|
|
263
|
-
.map(item => item.split(':').at(-1))
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
private getTimeSeriesModelFields()
|
|
267
|
-
{
|
|
268
|
-
const timeSeriesIds: {[key: string]: {collection: string, hydrationField: string, ids: string[]}} = {};
|
|
269
|
-
|
|
270
|
-
for (const key in this as any) {
|
|
271
|
-
if (this.hasOwnProperty(key)) {
|
|
272
|
-
|
|
273
|
-
const meta = Reflect.getMetadata(`InverseTimeSeries:${key}`, (this as any));
|
|
274
|
-
if(meta){
|
|
275
|
-
if(!timeSeriesIds[key]){
|
|
276
|
-
timeSeriesIds[key] = {
|
|
277
|
-
collection: meta.timeSeriesModel,
|
|
278
|
-
hydrationField: meta.hydrationField,
|
|
279
|
-
ids: this[key]
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
return timeSeriesIds;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
private async getRelationOneMeta(classFields: string[]): Promise<RelOneMetaType<RWSModel<any>>> {
|
|
290
|
-
return RWSModel.getRelationOneMeta(this, classFields);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
static async getRelationOneMeta(model: any, classFields: string[]): Promise<RelOneMetaType<RWSModel<any>>>
|
|
294
|
-
{
|
|
295
|
-
const relIds: RelOneMetaType<RWSModel<any>> = {};
|
|
296
|
-
const relationFields = classFields
|
|
297
|
-
.filter((item: string) => item.indexOf('Relation') === 0 && !item.includes('Inverse'))
|
|
298
|
-
.map((item: string) => item.split(':').at(-1));
|
|
299
|
-
|
|
300
|
-
for (const key of relationFields) {
|
|
301
|
-
const metadataKey = `Relation:${key}`;
|
|
302
|
-
const metadata = Reflect.getMetadata(metadataKey, model);
|
|
303
|
-
|
|
304
|
-
if (metadata && metadata.promise) {
|
|
305
|
-
const resolvedMetadata = await metadata.promise;
|
|
306
|
-
if (!relIds[key]) {
|
|
307
|
-
relIds[key] = {
|
|
308
|
-
key: resolvedMetadata.key,
|
|
309
|
-
required: resolvedMetadata.required,
|
|
310
|
-
model: resolvedMetadata.relatedTo,
|
|
311
|
-
hydrationField: resolvedMetadata.relationField,
|
|
312
|
-
foreignKey: resolvedMetadata.relatedToField
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return relIds;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
private async getRelationManyMeta(classFields: string[]): Promise<RelManyMetaType<RWSModel<any>>> {
|
|
322
|
-
return RWSModel.getRelationManyMeta(this, classFields);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
static async getRelationManyMeta(model: any, classFields: string[]): Promise<RelManyMetaType<RWSModel<any>>>
|
|
326
|
-
{
|
|
327
|
-
const relIds: RelManyMetaType<RWSModel<any>> = {};
|
|
328
|
-
|
|
329
|
-
const inverseFields = classFields
|
|
330
|
-
.filter((item: string) => item.indexOf('InverseRelation') === 0)
|
|
331
|
-
.map((item: string) => item.split(':').at(-1));
|
|
332
|
-
|
|
333
|
-
for (const key of inverseFields) {
|
|
334
|
-
const metadataKey = `InverseRelation:${key}`;
|
|
335
|
-
const metadata = Reflect.getMetadata(metadataKey, model);
|
|
336
|
-
|
|
337
|
-
if (metadata && metadata.promise) {
|
|
338
|
-
const resolvedMetadata = await metadata.promise;
|
|
339
|
-
if (!relIds[key]) {
|
|
340
|
-
relIds[key] = {
|
|
341
|
-
key: resolvedMetadata.key,
|
|
342
|
-
inversionModel: resolvedMetadata.inversionModel,
|
|
343
|
-
foreignKey: resolvedMetadata.foreignKey
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return relIds;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
public async toMongo(): Promise<any> {
|
|
353
|
-
const data: any = {};
|
|
354
|
-
const timeSeriesIds = this.getTimeSeriesModelFields();
|
|
355
|
-
const timeSeriesHydrationFields: string[] = [];
|
|
356
|
-
|
|
357
|
-
for (const key in (this as any)) {
|
|
358
|
-
if (this.hasRelation(key)) {
|
|
359
|
-
data[key] = this.bindRelation(key, this[key]);
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (!(await this.isDbVariable(key))) {
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const passedFieldCondition: boolean = this.hasOwnProperty(key) &&
|
|
368
|
-
!((this as any).constructor._BANNED_KEYS
|
|
369
|
-
|| RWSModel._BANNED_KEYS
|
|
370
|
-
).includes(key) &&
|
|
371
|
-
!timeSeriesHydrationFields.includes(key)
|
|
372
|
-
;
|
|
373
|
-
|
|
374
|
-
if (passedFieldCondition) {
|
|
375
|
-
data[key] = this[key];
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
if (timeSeriesIds[key]) {
|
|
379
|
-
data[key] = this[key];
|
|
380
|
-
timeSeriesHydrationFields.push(timeSeriesIds[key].hydrationField);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
return data;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
getCollection(): string | null {
|
|
388
|
-
return (this as any).constructor._collection || this._collection;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
static getCollection(): string | null {
|
|
392
|
-
return (this as any).constructor._collection || this._collection;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
async save(): Promise<this> {
|
|
397
|
-
const data = await this.toMongo();
|
|
398
|
-
let updatedModelData = data;
|
|
399
|
-
if (this.id) {
|
|
400
|
-
this.preUpdate();
|
|
401
|
-
|
|
402
|
-
updatedModelData = await this.dbService.update(data, this.getCollection());
|
|
403
|
-
|
|
404
|
-
await this._asyncFill(updatedModelData);
|
|
405
|
-
this.postUpdate();
|
|
406
|
-
} else {
|
|
407
|
-
this.preCreate();
|
|
408
|
-
|
|
409
|
-
const timeSeriesModel = await import('./TimeSeriesModel');
|
|
410
|
-
const isTimeSeries = this instanceof timeSeriesModel.default;
|
|
411
|
-
|
|
412
|
-
updatedModelData = await this.dbService.insert(data, this.getCollection(), isTimeSeries);
|
|
413
|
-
|
|
414
|
-
await this._asyncFill(updatedModelData);
|
|
415
|
-
|
|
416
|
-
this.postCreate();
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
return this;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
static async getModelAnnotations<T extends unknown>(constructor: new () => T): Promise<Record<string, {annotationType: string, metadata: any}>> {
|
|
423
|
-
const annotationsData: Record<string, {annotationType: string, metadata: any}> = {};
|
|
424
|
-
|
|
425
|
-
const metadataKeys = Reflect.getMetadataKeys(constructor.prototype);
|
|
426
|
-
|
|
427
|
-
// Process all metadata keys and collect promises
|
|
428
|
-
const metadataPromises = metadataKeys.map(async (fullKey: string) => {
|
|
429
|
-
const [annotationType, propertyKey] = fullKey.split(':');
|
|
430
|
-
const metadata = Reflect.getMetadata(fullKey, constructor.prototype);
|
|
431
|
-
|
|
432
|
-
if (metadata) {
|
|
433
|
-
// If this is a relation metadata with a promise
|
|
434
|
-
if (metadata.promise && (annotationType === 'Relation' || annotationType === 'InverseRelation')) {
|
|
435
|
-
const resolvedMetadata = await metadata.promise;
|
|
436
|
-
annotationsData[propertyKey] = {
|
|
437
|
-
annotationType,
|
|
438
|
-
metadata: resolvedMetadata
|
|
439
|
-
};
|
|
440
|
-
} else {
|
|
441
|
-
// Handle non-relation metadata as before
|
|
442
|
-
const key = metadata.key || propertyKey;
|
|
443
|
-
annotationsData[key] = {
|
|
444
|
-
annotationType,
|
|
445
|
-
metadata
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
// Wait for all metadata to be processed
|
|
452
|
-
await Promise.all(metadataPromises);
|
|
453
|
-
|
|
454
|
-
return annotationsData;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
public preUpdate(): void
|
|
458
|
-
{
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
public postUpdate(): void
|
|
463
|
-
{
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
public preCreate(): void
|
|
468
|
-
{
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
public postCreate(): void
|
|
473
|
-
{
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
public static isSubclass<T extends RWSModel<T>, C extends new () => T>(constructor: C, baseClass: new () => T): boolean {
|
|
478
|
-
return baseClass.prototype.isPrototypeOf(constructor.prototype);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
hasTimeSeries(): boolean
|
|
482
|
-
{
|
|
483
|
-
return RWSModel.checkTimeSeries((this as any).constructor);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
static checkTimeSeries(constructor: any): boolean
|
|
487
|
-
{
|
|
488
|
-
const data = constructor.prototype as any;
|
|
489
|
-
|
|
490
|
-
for (const key in data) {
|
|
491
|
-
|
|
492
|
-
if (data.hasOwnProperty(key)) {
|
|
493
|
-
|
|
494
|
-
if(Reflect.getMetadata(`InverseTimeSeries:${key}`, constructor.prototype)){
|
|
495
|
-
return true;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
return false;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
async isDbVariable(variable: string): Promise<boolean>
|
|
504
|
-
{
|
|
505
|
-
return RWSModel.checkDbVariable((this as any).constructor, variable);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
static async checkDbVariable(constructor: any, variable: string): Promise<boolean> {
|
|
509
|
-
if(variable === 'id'){
|
|
510
|
-
return true;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
const dbAnnotations = await RWSModel.getModelAnnotations(constructor);
|
|
514
|
-
type AnnotationType = { annotationType: string, key: string };
|
|
515
|
-
|
|
516
|
-
const dbProperties: string[] = Object.keys(dbAnnotations)
|
|
517
|
-
.map((key: string): AnnotationType => {return {...dbAnnotations[key], key};})
|
|
518
|
-
.filter((element: AnnotationType) => element.annotationType === 'TrackType' )
|
|
519
|
-
.map((element: AnnotationType) => element.key);
|
|
520
|
-
|
|
521
|
-
return dbProperties.includes(variable);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
sanitizeDBData(data: any): any
|
|
525
|
-
{
|
|
526
|
-
const dataKeys = Object.keys(data);
|
|
527
|
-
const sanitizedData: {[key: string]: any} = {};
|
|
528
|
-
|
|
529
|
-
for (const key of dataKeys){
|
|
530
|
-
if(this.isDbVariable(key)){
|
|
531
|
-
sanitizedData[key] = data[key];
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return sanitizedData;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
public static async watchCollection<ChildClass extends RWSModel<ChildClass>>(
|
|
539
|
-
this: OpModelType<ChildClass>,
|
|
540
|
-
preRun: () => void
|
|
541
|
-
){
|
|
542
|
-
const collection = Reflect.get(this, '_collection');
|
|
543
|
-
this.checkForInclusionWithThrow(this.name);
|
|
544
|
-
return await this.services.dbService.watchCollection(collection, preRun);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
public static async findOneBy<ChildClass extends RWSModel<ChildClass>>(
|
|
548
|
-
this: OpModelType<ChildClass>,
|
|
549
|
-
findParams?: FindByType
|
|
550
|
-
): Promise<ChildClass | null> {
|
|
551
|
-
const conditions = findParams?.conditions ?? {};
|
|
552
|
-
const ordering = findParams?.ordering ?? null;
|
|
553
|
-
const fields = findParams?.fields ?? null;
|
|
554
|
-
const allowRelations = findParams?.allowRelations ?? true;
|
|
555
|
-
const fullData = findParams?.fullData ?? false;
|
|
556
|
-
|
|
557
|
-
this.checkForInclusionWithThrow('');
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const collection = Reflect.get(this, '_collection');
|
|
561
|
-
const dbData = await this.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
if (dbData) {
|
|
565
|
-
const inst: ChildClass = new (this as { new(): ChildClass })();
|
|
566
|
-
return await inst._asyncFill(dbData, fullData, allowRelations);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
return null;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
public static async find<ChildClass extends RWSModel<ChildClass>>(
|
|
573
|
-
this: OpModelType<ChildClass>,
|
|
574
|
-
id: string,
|
|
575
|
-
findParams: Omit<FindByType, 'conditions'> = null
|
|
576
|
-
): Promise<ChildClass | null> {
|
|
577
|
-
const ordering = findParams?.ordering ?? null;
|
|
578
|
-
const fields = findParams?.fields ?? null;
|
|
579
|
-
const allowRelations = findParams?.allowRelations ?? true;
|
|
580
|
-
const fullData = findParams?.fullData ?? false;
|
|
581
|
-
|
|
582
|
-
const collection = Reflect.get(this, '_collection');
|
|
583
|
-
this.checkForInclusionWithThrow(this.name);
|
|
584
|
-
|
|
585
|
-
const dbData = await this.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
|
|
586
|
-
|
|
587
|
-
if (dbData) {
|
|
588
|
-
const inst: ChildClass = new (this as { new(): ChildClass })();
|
|
589
|
-
return await inst._asyncFill(dbData, fullData, allowRelations);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
return null;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
public static async findBy<ChildClass extends RWSModel<ChildClass>>(
|
|
596
|
-
this: OpModelType<ChildClass>,
|
|
597
|
-
findParams?: FindByType
|
|
598
|
-
): Promise<ChildClass[]> {
|
|
599
|
-
const conditions = findParams?.conditions ?? {};
|
|
600
|
-
const ordering = findParams?.ordering ?? null;
|
|
601
|
-
const fields = findParams?.fields ?? null;
|
|
602
|
-
const allowRelations = findParams?.allowRelations ?? true;
|
|
603
|
-
const fullData = findParams?.fullData ?? false;
|
|
604
|
-
|
|
605
|
-
const collection = Reflect.get(this, '_collection');
|
|
606
|
-
this.checkForInclusionWithThrow(this.name);
|
|
607
|
-
try {
|
|
608
|
-
const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, allowRelations);
|
|
609
|
-
if (dbData.length) {
|
|
610
|
-
const instanced: ChildClass[] = [];
|
|
611
|
-
|
|
612
|
-
for (const data of dbData) {
|
|
613
|
-
const inst: ChildClass = new (this as { new(): ChildClass })();
|
|
614
|
-
instanced.push((await inst._asyncFill(data, fullData,allowRelations)) as ChildClass);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
return instanced;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
return [];
|
|
621
|
-
} catch (rwsError: Error | any) {
|
|
622
|
-
console.error(rwsError);
|
|
623
|
-
|
|
624
|
-
throw rwsError;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
public static async delete<ChildClass extends RWSModel<ChildClass>>(
|
|
629
|
-
this: OpModelType<ChildClass>,
|
|
630
|
-
conditions: any
|
|
631
|
-
): Promise<void> {
|
|
632
|
-
const collection = Reflect.get(this, '_collection');
|
|
633
|
-
this.checkForInclusionWithThrow(this.name);
|
|
634
|
-
return await this.services.dbService.delete(collection, conditions);
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
public async delete<ChildClass extends RWSModel<ChildClass>>(): Promise<void> {
|
|
638
|
-
const collection = Reflect.get(this, '_collection');
|
|
639
|
-
this.checkForInclusionWithThrow();
|
|
640
|
-
return await this.dbService.delete(collection, {
|
|
641
|
-
id: this.id
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
static async create<T extends RWSModel<T>>(this: new () => T, data: any): Promise<T> {
|
|
647
|
-
const newModel = new this();
|
|
648
|
-
|
|
649
|
-
const sanitizedData = newModel.sanitizeDBData(data);
|
|
650
|
-
|
|
651
|
-
await newModel._asyncFill(sanitizedData);
|
|
652
|
-
|
|
653
|
-
return newModel;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
static loadModels(): OpModelType<any>[]
|
|
657
|
-
{
|
|
658
|
-
return this.allModels || [];
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
loadModels(): OpModelType<any>[]
|
|
662
|
-
{
|
|
663
|
-
return RWSModel.loadModels();
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
private checkRelEnabled(key: string): boolean
|
|
667
|
-
{
|
|
668
|
-
return Object.keys((this as any).constructor._RELATIONS).includes(key) && (this as any).constructor._RELATIONS[key] === true
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
public static setServices(services: IRWSModelServices){
|
|
672
|
-
this.allModels = services.configService.get('db_models');
|
|
673
|
-
this.services = services;
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
export { IModel, TrackType, IMetaOpts, RWSModel };
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
=======
|
|
681
|
-
>>>>>>> 7c50786 (v2.2.0)
|