@spinajs/orm 2.0.45 → 2.0.48
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/README.md +11 -11
- package/lib/builders.d.ts +9 -8
- package/lib/builders.d.ts.map +1 -0
- package/lib/builders.js +277 -310
- package/lib/builders.js.map +1 -1
- package/lib/converters.d.ts +10 -3
- package/lib/converters.d.ts.map +1 -0
- package/lib/converters.js +32 -10
- package/lib/converters.js.map +1 -1
- package/lib/decorators.d.ts +4 -3
- package/lib/decorators.d.ts.map +1 -0
- package/lib/decorators.js +71 -99
- package/lib/decorators.js.map +1 -1
- package/lib/dehydrators.d.ts +2 -1
- package/lib/dehydrators.d.ts.map +1 -0
- package/lib/dehydrators.js +9 -16
- package/lib/dehydrators.js.map +1 -1
- package/lib/driver.d.ts +6 -5
- package/lib/driver.d.ts.map +1 -0
- package/lib/driver.js +21 -20
- package/lib/driver.js.map +1 -1
- package/lib/enums.d.ts +2 -1
- package/lib/enums.d.ts.map +1 -0
- package/lib/enums.js +14 -17
- package/lib/enums.js.map +1 -1
- package/lib/exceptions.d.ts +2 -1
- package/lib/exceptions.d.ts.map +1 -0
- package/lib/exceptions.js +2 -6
- package/lib/exceptions.js.map +1 -1
- package/lib/hydrators.d.ts +2 -1
- package/lib/hydrators.d.ts.map +1 -0
- package/lib/hydrators.js +23 -28
- package/lib/hydrators.js.map +1 -1
- package/lib/index.d.ts +16 -15
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +15 -31
- package/lib/index.js.map +1 -1
- package/lib/interfaces.d.ts +16 -9
- package/lib/interfaces.d.ts.map +1 -0
- package/lib/interfaces.js +78 -85
- package/lib/interfaces.js.map +1 -1
- package/lib/model.d.ts +12 -7
- package/lib/model.d.ts.map +1 -0
- package/lib/model.js +119 -172
- package/lib/model.js.map +1 -1
- package/lib/orm.d.ts +5 -3
- package/lib/orm.d.ts.map +1 -0
- package/lib/orm.js +51 -75
- package/lib/orm.js.map +1 -1
- package/lib/relations.d.ts +6 -11
- package/lib/relations.d.ts.map +1 -0
- package/lib/relations.js +56 -90
- package/lib/relations.js.map +1 -1
- package/lib/statements.d.ts +6 -7
- package/lib/statements.d.ts.map +1 -0
- package/lib/statements.js +55 -86
- package/lib/statements.js.map +1 -1
- package/lib/types.d.ts +15 -14
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +1 -2
- package/lib/wrappers.d.ts +2 -1
- package/lib/wrappers.d.ts.map +1 -0
- package/lib/wrappers.js +4 -7
- package/lib/wrappers.js.map +1 -1
- package/package.json +63 -61
package/lib/model.js
CHANGED
|
@@ -1,45 +1,19 @@
|
|
|
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 __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.MODEL_STATIC_MIXINS = exports.createQuery = exports.HistoricalModel = exports.ModelBase = exports.extractModelDescriptor = void 0;
|
|
27
1
|
/* eslint-disable prettier/prettier */
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
function extractModelDescriptor(targetOrForward) {
|
|
42
|
-
const target = !
|
|
2
|
+
import { DiscriminationMapMiddleware, OneToManyRelationList, ManyToManyRelationList, SingleRelation } from './relations.js';
|
|
3
|
+
import { SordOrder } from './enums.js';
|
|
4
|
+
import { MODEL_DESCTRIPTION_SYMBOL } from './decorators.js';
|
|
5
|
+
import { RelationType, InsertBehaviour, ModelToSqlConverter, ObjectToSqlConverter } from './interfaces.js';
|
|
6
|
+
import { UpdateQueryBuilder, TruncateTableQueryBuilder, SelectQueryBuilder, DeleteQueryBuilder, InsertQueryBuilder } from './builders.js';
|
|
7
|
+
import { DI, isConstructor } from '@spinajs/di';
|
|
8
|
+
import { Orm } from './orm.js';
|
|
9
|
+
import { ModelHydrator } from './hydrators.js';
|
|
10
|
+
import _ from 'lodash';
|
|
11
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
12
|
+
import { OrmException } from './exceptions.js';
|
|
13
|
+
import { StandardModelDehydrator, StandardModelWithRelationsDehydrator } from './dehydrators.js';
|
|
14
|
+
import { DateTime } from 'luxon';
|
|
15
|
+
export function extractModelDescriptor(targetOrForward) {
|
|
16
|
+
const target = !isConstructor(targetOrForward) && targetOrForward ? targetOrForward() : targetOrForward;
|
|
43
17
|
if (!target) {
|
|
44
18
|
return null;
|
|
45
19
|
}
|
|
@@ -50,9 +24,9 @@ function extractModelDescriptor(targetOrForward) {
|
|
|
50
24
|
if (!t) {
|
|
51
25
|
return;
|
|
52
26
|
}
|
|
53
|
-
if (t[
|
|
54
|
-
descriptor = descriptor
|
|
55
|
-
_.mergeWith(descriptor, t[
|
|
27
|
+
if (t[MODEL_DESCTRIPTION_SYMBOL]) {
|
|
28
|
+
descriptor = descriptor ?? {};
|
|
29
|
+
_.mergeWith(descriptor, t[MODEL_DESCTRIPTION_SYMBOL], (a, b) => {
|
|
56
30
|
if (!a) {
|
|
57
31
|
return b;
|
|
58
32
|
}
|
|
@@ -66,19 +40,7 @@ function extractModelDescriptor(targetOrForward) {
|
|
|
66
40
|
_reduce(t.__proto__);
|
|
67
41
|
}
|
|
68
42
|
}
|
|
69
|
-
|
|
70
|
-
class ModelBase {
|
|
71
|
-
constructor(data) {
|
|
72
|
-
/**
|
|
73
|
-
* List of hidden properties from JSON / dehydrations
|
|
74
|
-
* eg. password field of user
|
|
75
|
-
*/
|
|
76
|
-
this._hidden = [];
|
|
77
|
-
this.setDefaults();
|
|
78
|
-
if (data) {
|
|
79
|
-
this.hydrate(data);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
43
|
+
export class ModelBase {
|
|
82
44
|
/**
|
|
83
45
|
* Gets descriptor for this model. It contains information about relations, orm driver, connection properties,
|
|
84
46
|
* db table attached, column information and others.
|
|
@@ -91,7 +53,7 @@ class ModelBase {
|
|
|
91
53
|
*/
|
|
92
54
|
get Container() {
|
|
93
55
|
if (!this._container) {
|
|
94
|
-
const orm =
|
|
56
|
+
const orm = DI.get(Orm);
|
|
95
57
|
const driver = orm.Connections.get(this.ModelDescriptor.Connection);
|
|
96
58
|
if (!driver) {
|
|
97
59
|
throw new Error(`model ${this.constructor.name} have invalid connection ${this.ModelDescriptor.Connection}, please check your db config file or model connection name`);
|
|
@@ -113,20 +75,20 @@ class ModelBase {
|
|
|
113
75
|
if (!rel)
|
|
114
76
|
return;
|
|
115
77
|
switch (r.Type) {
|
|
116
|
-
case
|
|
78
|
+
case RelationType.One:
|
|
117
79
|
rel[r.ForeignKey] = newVal;
|
|
118
80
|
break;
|
|
119
|
-
case
|
|
81
|
+
case RelationType.Many:
|
|
120
82
|
rel.forEach((rVal) => (rVal[r.ForeignKey] = newVal));
|
|
121
83
|
break;
|
|
122
|
-
case
|
|
84
|
+
case RelationType.ManyToMany:
|
|
123
85
|
// TODO: rethink this
|
|
124
86
|
break;
|
|
125
87
|
}
|
|
126
88
|
});
|
|
127
89
|
}
|
|
128
90
|
driver() {
|
|
129
|
-
const orm =
|
|
91
|
+
const orm = DI.get(Orm);
|
|
130
92
|
const driver = orm.Connections.get(this.ModelDescriptor.Connection);
|
|
131
93
|
return driver;
|
|
132
94
|
}
|
|
@@ -137,7 +99,7 @@ class ModelBase {
|
|
|
137
99
|
const reduceRelations = function (m) {
|
|
138
100
|
const relations = [...m.ModelDescriptor.Relations.values()];
|
|
139
101
|
const models = _.flatMap(relations, (r) => {
|
|
140
|
-
if (r.Type ===
|
|
102
|
+
if (r.Type === RelationType.Many || r.Type === RelationType.ManyToMany) {
|
|
141
103
|
return m[r.Name];
|
|
142
104
|
}
|
|
143
105
|
if (m[r.Name].Value) {
|
|
@@ -168,7 +130,7 @@ class ModelBase {
|
|
|
168
130
|
*
|
|
169
131
|
* @param _data - data to insert
|
|
170
132
|
*/
|
|
171
|
-
static insert(_data, _insertBehaviour =
|
|
133
|
+
static insert(_data, _insertBehaviour = InsertBehaviour.None) {
|
|
172
134
|
throw new Error('Not implemented');
|
|
173
135
|
}
|
|
174
136
|
static where(_column, _operator, _value) {
|
|
@@ -264,13 +226,24 @@ class ModelBase {
|
|
|
264
226
|
static destroy(_pk) {
|
|
265
227
|
throw new Error('Not implemented');
|
|
266
228
|
}
|
|
229
|
+
constructor(data) {
|
|
230
|
+
/**
|
|
231
|
+
* List of hidden properties from JSON / dehydrations
|
|
232
|
+
* eg. password field of user
|
|
233
|
+
*/
|
|
234
|
+
this._hidden = [];
|
|
235
|
+
this.setDefaults();
|
|
236
|
+
if (data) {
|
|
237
|
+
this.hydrate(data);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
267
240
|
/**
|
|
268
241
|
* Fills model with data. It only fills properties that exists in database
|
|
269
242
|
*
|
|
270
243
|
* @param data - data to fill
|
|
271
244
|
*/
|
|
272
245
|
hydrate(data) {
|
|
273
|
-
this.Container.resolve(Array.ofType(
|
|
246
|
+
this.Container.resolve(Array.ofType(ModelHydrator)).forEach((h) => h.hydrate(this, data));
|
|
274
247
|
}
|
|
275
248
|
/**
|
|
276
249
|
*
|
|
@@ -285,11 +258,11 @@ class ModelBase {
|
|
|
285
258
|
if (v.TargetModel.name === data.constructor.name) {
|
|
286
259
|
data[v.ForeignKey] = this.PrimaryKeyValue;
|
|
287
260
|
switch (v.Type) {
|
|
288
|
-
case
|
|
261
|
+
case RelationType.One:
|
|
289
262
|
this[v.Name].attach(data);
|
|
290
263
|
break;
|
|
291
|
-
case
|
|
292
|
-
case
|
|
264
|
+
case RelationType.Many:
|
|
265
|
+
case RelationType.ManyToMany:
|
|
293
266
|
this[v.Name].push(data);
|
|
294
267
|
break;
|
|
295
268
|
}
|
|
@@ -300,7 +273,7 @@ class ModelBase {
|
|
|
300
273
|
* Extracts all data from model. It takes only properties that exists in DB
|
|
301
274
|
*/
|
|
302
275
|
dehydrate(omit) {
|
|
303
|
-
return this.Container.resolve(
|
|
276
|
+
return this.Container.resolve(StandardModelDehydrator).dehydrate(this, [...(omit ?? []), ...this._hidden]);
|
|
304
277
|
}
|
|
305
278
|
/**
|
|
306
279
|
*
|
|
@@ -309,27 +282,10 @@ class ModelBase {
|
|
|
309
282
|
* @param omit - fields to omit
|
|
310
283
|
*/
|
|
311
284
|
dehydrateWithRelations(omit) {
|
|
312
|
-
return this.Container.resolve(
|
|
285
|
+
return this.Container.resolve(StandardModelWithRelationsDehydrator).dehydrate(this, [...(omit ?? []), ...this._hidden]);
|
|
313
286
|
}
|
|
314
287
|
toSql() {
|
|
315
|
-
|
|
316
|
-
const obj = {};
|
|
317
|
-
const relArr = [...this.ModelDescriptor.Relations.values()];
|
|
318
|
-
(_a = this.ModelDescriptor.Columns) === null || _a === void 0 ? void 0 : _a.forEach((c) => {
|
|
319
|
-
const val = this[c.Name];
|
|
320
|
-
if (!c.PrimaryKey && !c.Nullable && (val === null || val === undefined || val === '')) {
|
|
321
|
-
throw new exceptions_1.OrmException(`Field ${c.Name} cannot be null`);
|
|
322
|
-
}
|
|
323
|
-
obj[c.Name] = c.Converter ? c.Converter.toDB(val, this, this.ModelDescriptor.Converters.get(c.Name).Options) : val;
|
|
324
|
-
});
|
|
325
|
-
for (const val of relArr) {
|
|
326
|
-
if (val.Type === interfaces_1.RelationType.One) {
|
|
327
|
-
if (this[val.Name].Value) {
|
|
328
|
-
obj[val.ForeignKey] = this[val.Name].Value.PrimaryKeyValue;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
return obj;
|
|
288
|
+
return this.Container.resolve(ModelToSqlConverter).toSql(this);
|
|
333
289
|
}
|
|
334
290
|
/**
|
|
335
291
|
* deletes enitt from db. If model have SoftDelete decorator, model is marked as deleted
|
|
@@ -345,10 +301,10 @@ class ModelBase {
|
|
|
345
301
|
*/
|
|
346
302
|
async archive() {
|
|
347
303
|
if (this.ModelDescriptor.Archived) {
|
|
348
|
-
this[this.ModelDescriptor.Archived.ArchivedAt] =
|
|
304
|
+
this[this.ModelDescriptor.Archived.ArchivedAt] = DateTime.now();
|
|
349
305
|
}
|
|
350
306
|
else {
|
|
351
|
-
throw new
|
|
307
|
+
throw new OrmException('archived at column not exists in model');
|
|
352
308
|
}
|
|
353
309
|
const { query } = this.createUpdateQuery();
|
|
354
310
|
await query.update(this.toSql()).where(this.PrimaryKeyName, this.PrimaryKeyValue);
|
|
@@ -356,7 +312,7 @@ class ModelBase {
|
|
|
356
312
|
async update() {
|
|
357
313
|
const { query } = this.createUpdateQuery();
|
|
358
314
|
if (this.ModelDescriptor.Timestamps.UpdatedAt) {
|
|
359
|
-
this[this.ModelDescriptor.Timestamps.UpdatedAt] =
|
|
315
|
+
this[this.ModelDescriptor.Timestamps.UpdatedAt] = DateTime.now();
|
|
360
316
|
}
|
|
361
317
|
await query.update(this.toSql()).where(this.PrimaryKeyName, this.PrimaryKeyValue);
|
|
362
318
|
}
|
|
@@ -364,23 +320,22 @@ class ModelBase {
|
|
|
364
320
|
* Save all changes to db. It creates new entry id db or updates existing one if
|
|
365
321
|
* primary key exists
|
|
366
322
|
*/
|
|
367
|
-
async insert(insertBehaviour =
|
|
323
|
+
async insert(insertBehaviour = InsertBehaviour.None) {
|
|
368
324
|
const { query, description } = this.createInsertQuery();
|
|
369
325
|
switch (insertBehaviour) {
|
|
370
|
-
case
|
|
326
|
+
case InsertBehaviour.InsertOrIgnore:
|
|
371
327
|
query.orIgnore();
|
|
372
328
|
break;
|
|
373
|
-
case
|
|
329
|
+
case InsertBehaviour.InsertOrUpdate:
|
|
374
330
|
query.onDuplicate().update(description.Columns.filter((c) => !c.PrimaryKey).map((c) => c.Name));
|
|
375
331
|
break;
|
|
376
|
-
case
|
|
332
|
+
case InsertBehaviour.InsertOrReplace:
|
|
377
333
|
query.orReplace();
|
|
378
334
|
break;
|
|
379
335
|
}
|
|
380
336
|
const iMidleware = {
|
|
381
337
|
afterQuery: (data) => {
|
|
382
|
-
|
|
383
|
-
this.PrimaryKeyValue = (_a = this.PrimaryKeyValue) !== null && _a !== void 0 ? _a : data.LastInsertId;
|
|
338
|
+
this.PrimaryKeyValue = this.PrimaryKeyValue ?? data.LastInsertId;
|
|
384
339
|
return data;
|
|
385
340
|
},
|
|
386
341
|
modelCreation: () => null,
|
|
@@ -396,7 +351,7 @@ class ModelBase {
|
|
|
396
351
|
*
|
|
397
352
|
* @param insertBehaviour - insert mode
|
|
398
353
|
*/
|
|
399
|
-
async insertOrUpdate(insertBehaviour =
|
|
354
|
+
async insertOrUpdate(insertBehaviour = InsertBehaviour.None) {
|
|
400
355
|
if (this.PrimaryKeyValue) {
|
|
401
356
|
await this.update();
|
|
402
357
|
}
|
|
@@ -438,17 +393,16 @@ class ModelBase {
|
|
|
438
393
|
* sets default values for model. values are taken from DB default column prop
|
|
439
394
|
*/
|
|
440
395
|
setDefaults() {
|
|
441
|
-
|
|
442
|
-
(_a = this.ModelDescriptor.Columns) === null || _a === void 0 ? void 0 : _a.forEach((c) => {
|
|
396
|
+
this.ModelDescriptor.Columns?.forEach((c) => {
|
|
443
397
|
if (c.Uuid) {
|
|
444
|
-
this[c.Name] = (
|
|
398
|
+
this[c.Name] = uuidv4();
|
|
445
399
|
}
|
|
446
400
|
else {
|
|
447
401
|
this[c.Name] = c.DefaultValue;
|
|
448
402
|
}
|
|
449
403
|
});
|
|
450
404
|
if (this.ModelDescriptor.Timestamps.CreatedAt) {
|
|
451
|
-
this[this.ModelDescriptor.Timestamps.CreatedAt] =
|
|
405
|
+
this[this.ModelDescriptor.Timestamps.CreatedAt] = DateTime.now();
|
|
452
406
|
}
|
|
453
407
|
for (const [, rel] of this.ModelDescriptor.Relations) {
|
|
454
408
|
if (rel.Factory) {
|
|
@@ -457,30 +411,29 @@ class ModelBase {
|
|
|
457
411
|
else if (rel.RelationClass) {
|
|
458
412
|
this[rel.Name] = this.Container.resolve(rel.RelationClass, [this, rel.TargetModel, rel, []]);
|
|
459
413
|
}
|
|
460
|
-
else if (rel.Type ===
|
|
461
|
-
this[rel.Name] = new
|
|
414
|
+
else if (rel.Type === RelationType.Many) {
|
|
415
|
+
this[rel.Name] = new OneToManyRelationList(this, rel.TargetModel, rel, []);
|
|
462
416
|
}
|
|
463
|
-
else if (rel.Type ===
|
|
464
|
-
this[rel.Name] = new
|
|
417
|
+
else if (rel.Type === RelationType.ManyToMany) {
|
|
418
|
+
this[rel.Name] = new ManyToManyRelationList(this, rel.TargetModel, rel, []);
|
|
465
419
|
}
|
|
466
420
|
else {
|
|
467
|
-
this[rel.Name] = new
|
|
421
|
+
this[rel.Name] = new SingleRelation(this, rel.TargetModel, rel, null);
|
|
468
422
|
}
|
|
469
423
|
}
|
|
470
424
|
}
|
|
471
425
|
createSelectQuery() {
|
|
472
|
-
return createQuery(this.constructor,
|
|
426
|
+
return createQuery(this.constructor, SelectQueryBuilder);
|
|
473
427
|
}
|
|
474
428
|
createUpdateQuery() {
|
|
475
|
-
return createQuery(this.constructor,
|
|
429
|
+
return createQuery(this.constructor, UpdateQueryBuilder);
|
|
476
430
|
}
|
|
477
431
|
createInsertQuery() {
|
|
478
|
-
return createQuery(this.constructor,
|
|
432
|
+
return createQuery(this.constructor, InsertQueryBuilder);
|
|
479
433
|
}
|
|
480
434
|
}
|
|
481
|
-
exports.ModelBase = ModelBase;
|
|
482
435
|
function _descriptor(model) {
|
|
483
|
-
return model[
|
|
436
|
+
return model[MODEL_DESCTRIPTION_SYMBOL];
|
|
484
437
|
}
|
|
485
438
|
function _preparePkWhere(description, query, model) {
|
|
486
439
|
if (description.PrimaryKey) {
|
|
@@ -494,31 +447,29 @@ function _preparePkWhere(description, query, model) {
|
|
|
494
447
|
}
|
|
495
448
|
}
|
|
496
449
|
else {
|
|
497
|
-
throw new
|
|
450
|
+
throw new OrmException('Model dont have primary key set or columns with unique constraint, cannot fetch model from database');
|
|
498
451
|
}
|
|
499
452
|
}
|
|
500
453
|
}
|
|
501
454
|
function _prepareOrderBy(description, query, order) {
|
|
502
|
-
var _a, _b;
|
|
503
455
|
if (description.PrimaryKey) {
|
|
504
|
-
query.order(description.PrimaryKey, order
|
|
456
|
+
query.order(description.PrimaryKey, order ?? SordOrder.DESC);
|
|
505
457
|
}
|
|
506
458
|
else {
|
|
507
459
|
const unique = description.Columns.filter((c) => c.Unique);
|
|
508
460
|
if (unique.length !== 0) {
|
|
509
|
-
unique.forEach((c) => query.order(c.Name, order
|
|
461
|
+
unique.forEach((c) => query.order(c.Name, order ?? SordOrder.DESC));
|
|
510
462
|
}
|
|
511
|
-
else if (
|
|
512
|
-
query.order(description.Timestamps.CreatedAt, order
|
|
463
|
+
else if (description.Timestamps?.CreatedAt) {
|
|
464
|
+
query.order(description.Timestamps.CreatedAt, order ?? SordOrder.DESC);
|
|
513
465
|
}
|
|
514
|
-
else if (
|
|
515
|
-
query.order(description.Timestamps.UpdatedAt, order
|
|
466
|
+
else if (description.Timestamps?.UpdatedAt) {
|
|
467
|
+
query.order(description.Timestamps.UpdatedAt, order ?? SordOrder.DESC);
|
|
516
468
|
}
|
|
517
469
|
}
|
|
518
470
|
}
|
|
519
|
-
class HistoricalModel {
|
|
471
|
+
export class HistoricalModel {
|
|
520
472
|
}
|
|
521
|
-
exports.HistoricalModel = HistoricalModel;
|
|
522
473
|
/**
|
|
523
474
|
* Helper function to create query based on model
|
|
524
475
|
*
|
|
@@ -528,19 +479,19 @@ exports.HistoricalModel = HistoricalModel;
|
|
|
528
479
|
*
|
|
529
480
|
* @returns
|
|
530
481
|
*/
|
|
531
|
-
function createQuery(model, query, injectModel = true) {
|
|
482
|
+
export function createQuery(model, query, injectModel = true) {
|
|
532
483
|
const dsc = _descriptor(model);
|
|
533
484
|
if (!dsc) {
|
|
534
485
|
throw new Error(`model ${model.name} does not have model descriptor. Use @model decorator on class`);
|
|
535
486
|
}
|
|
536
|
-
const orm =
|
|
487
|
+
const orm = DI.get(Orm);
|
|
537
488
|
const driver = orm.Connections.get(dsc.Connection);
|
|
538
489
|
if (!driver) {
|
|
539
490
|
throw new Error(`model ${model.name} have invalid connection ${dsc.Connection}, please check your db config file or model connection name`);
|
|
540
491
|
}
|
|
541
492
|
const cnt = driver.Container;
|
|
542
493
|
const qr = cnt.resolve(query, [driver, injectModel ? orm.Models.find((x) => x.name === model.name).type : null]);
|
|
543
|
-
if (qr instanceof
|
|
494
|
+
if (qr instanceof SelectQueryBuilder) {
|
|
544
495
|
const scope = model._queryScopes;
|
|
545
496
|
if (scope) {
|
|
546
497
|
Object.getOwnPropertyNames(scope.__proto__)
|
|
@@ -552,7 +503,7 @@ function createQuery(model, query, injectModel = true) {
|
|
|
552
503
|
});
|
|
553
504
|
}
|
|
554
505
|
}
|
|
555
|
-
qr.middleware(new
|
|
506
|
+
qr.middleware(new DiscriminationMapMiddleware(dsc));
|
|
556
507
|
qr.setTable(dsc.TableName);
|
|
557
508
|
if (driver.Options.Database) {
|
|
558
509
|
qr.database(driver.Options.Database);
|
|
@@ -561,17 +512,17 @@ function createQuery(model, query, injectModel = true) {
|
|
|
561
512
|
query: qr,
|
|
562
513
|
description: dsc,
|
|
563
514
|
model,
|
|
515
|
+
container: driver.Container,
|
|
564
516
|
};
|
|
565
517
|
}
|
|
566
|
-
|
|
567
|
-
exports.MODEL_STATIC_MIXINS = {
|
|
518
|
+
export const MODEL_STATIC_MIXINS = {
|
|
568
519
|
truncate() {
|
|
569
|
-
const { query } = createQuery(this,
|
|
520
|
+
const { query } = createQuery(this, TruncateTableQueryBuilder, false);
|
|
570
521
|
return query;
|
|
571
522
|
},
|
|
572
523
|
driver() {
|
|
573
524
|
const dsc = _descriptor(this);
|
|
574
|
-
const orm =
|
|
525
|
+
const orm = DI.get(Orm);
|
|
575
526
|
const driver = orm.Connections.get(dsc.Connection);
|
|
576
527
|
if (!driver) {
|
|
577
528
|
throw new Error(`model ${this.name} have invalid connection ${dsc.Connection}, please check your db config file or model connection name`);
|
|
@@ -579,20 +530,20 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
579
530
|
return driver;
|
|
580
531
|
},
|
|
581
532
|
query() {
|
|
582
|
-
const { query } = createQuery(this,
|
|
533
|
+
const { query } = createQuery(this, SelectQueryBuilder);
|
|
583
534
|
return query;
|
|
584
535
|
},
|
|
585
536
|
where(column, operator, value) {
|
|
586
|
-
const { query } = createQuery(this,
|
|
537
|
+
const { query } = createQuery(this, SelectQueryBuilder);
|
|
587
538
|
query.select('*');
|
|
588
539
|
return query.where(column, operator, value);
|
|
589
540
|
},
|
|
590
541
|
update(data) {
|
|
591
|
-
const { query } = createQuery(this,
|
|
542
|
+
const { query } = createQuery(this, UpdateQueryBuilder);
|
|
592
543
|
return query.update(data);
|
|
593
544
|
},
|
|
594
545
|
all(page, perPage) {
|
|
595
|
-
const { query } = createQuery(this,
|
|
546
|
+
const { query } = createQuery(this, SelectQueryBuilder);
|
|
596
547
|
query.select('*');
|
|
597
548
|
if (page >= 0 && perPage > 0) {
|
|
598
549
|
query.take(perPage).skip(page * perPage);
|
|
@@ -602,28 +553,29 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
602
553
|
/**
|
|
603
554
|
* Try to insert new value
|
|
604
555
|
*/
|
|
605
|
-
async insert(data, insertBehaviour =
|
|
606
|
-
const { query, description } = createQuery(this,
|
|
556
|
+
async insert(data, insertBehaviour = InsertBehaviour.None) {
|
|
557
|
+
const { query, description, container } = createQuery(this, InsertQueryBuilder);
|
|
558
|
+
const converter = container.resolve(ObjectToSqlConverter);
|
|
607
559
|
if (Array.isArray(data)) {
|
|
608
|
-
if (insertBehaviour !==
|
|
609
|
-
throw new
|
|
560
|
+
if (insertBehaviour !== InsertBehaviour.None) {
|
|
561
|
+
throw new OrmException(`insert behaviour is not supported with arrays`);
|
|
610
562
|
}
|
|
611
563
|
query.values(data.map((d) => {
|
|
612
564
|
if (d instanceof ModelBase) {
|
|
613
565
|
return d.toSql();
|
|
614
566
|
}
|
|
615
|
-
return d;
|
|
567
|
+
return converter.toSql(d);
|
|
616
568
|
}));
|
|
617
569
|
}
|
|
618
570
|
else {
|
|
619
571
|
switch (insertBehaviour) {
|
|
620
|
-
case
|
|
572
|
+
case InsertBehaviour.InsertOrIgnore:
|
|
621
573
|
query.orIgnore();
|
|
622
574
|
break;
|
|
623
|
-
case
|
|
575
|
+
case InsertBehaviour.InsertOrUpdate:
|
|
624
576
|
query.onDuplicate().update(description.Columns.filter((c) => !c.PrimaryKey).map((c) => c.Name));
|
|
625
577
|
break;
|
|
626
|
-
case
|
|
578
|
+
case InsertBehaviour.InsertOrReplace:
|
|
627
579
|
query.orReplace();
|
|
628
580
|
break;
|
|
629
581
|
}
|
|
@@ -631,22 +583,20 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
631
583
|
query.values(data.toSql());
|
|
632
584
|
}
|
|
633
585
|
else {
|
|
634
|
-
query.values(data);
|
|
586
|
+
query.values(converter.toSql(data));
|
|
635
587
|
}
|
|
636
588
|
}
|
|
637
589
|
const iMidleware = {
|
|
638
590
|
afterQuery: (result) => {
|
|
639
|
-
var _a;
|
|
640
591
|
if (Array.isArray(data)) {
|
|
641
592
|
data.forEach((v, idx) => {
|
|
642
|
-
var _a;
|
|
643
593
|
if (v instanceof ModelBase) {
|
|
644
|
-
v.PrimaryKeyValue =
|
|
594
|
+
v.PrimaryKeyValue = v.PrimaryKeyValue ?? result.LastInsertId - data.length + idx;
|
|
645
595
|
}
|
|
646
596
|
});
|
|
647
597
|
}
|
|
648
598
|
else if (data instanceof ModelBase) {
|
|
649
|
-
data.PrimaryKeyValue =
|
|
599
|
+
data.PrimaryKeyValue = data.PrimaryKeyValue ?? result.LastInsertId;
|
|
650
600
|
}
|
|
651
601
|
return result;
|
|
652
602
|
},
|
|
@@ -657,14 +607,14 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
657
607
|
return query;
|
|
658
608
|
},
|
|
659
609
|
async find(pks) {
|
|
660
|
-
const { query, description } = createQuery(this,
|
|
610
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
661
611
|
const pkey = description.PrimaryKey;
|
|
662
612
|
query.select('*');
|
|
663
613
|
query.whereIn(pkey, pks);
|
|
664
614
|
return await query;
|
|
665
615
|
},
|
|
666
616
|
async findOrFail(pks) {
|
|
667
|
-
const { query, description, model } = createQuery(this,
|
|
617
|
+
const { query, description, model } = createQuery(this, SelectQueryBuilder);
|
|
668
618
|
const pkey = description.PrimaryKey;
|
|
669
619
|
query.select('*');
|
|
670
620
|
query.whereIn(pkey, pks);
|
|
@@ -675,7 +625,7 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
675
625
|
return result;
|
|
676
626
|
},
|
|
677
627
|
async get(pk) {
|
|
678
|
-
const { query, description } = createQuery(this,
|
|
628
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
679
629
|
const pkey = description.PrimaryKey;
|
|
680
630
|
query.select('*');
|
|
681
631
|
query.where(pkey, pk);
|
|
@@ -683,7 +633,7 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
683
633
|
return (await query.first());
|
|
684
634
|
},
|
|
685
635
|
async getOrFail(pk) {
|
|
686
|
-
const { query, description } = createQuery(this,
|
|
636
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
687
637
|
const pkey = description.PrimaryKey;
|
|
688
638
|
query.select('*');
|
|
689
639
|
query.where(pkey, pk);
|
|
@@ -691,13 +641,12 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
691
641
|
return (await query.firstOrFail());
|
|
692
642
|
},
|
|
693
643
|
destroy(pks) {
|
|
694
|
-
var _a, _b;
|
|
695
644
|
const description = _descriptor(this);
|
|
696
645
|
const data = Array.isArray(pks) ? pks : [pks];
|
|
697
|
-
const { query } =
|
|
698
|
-
if (
|
|
646
|
+
const { query } = description.SoftDelete?.DeletedAt ? createQuery(this, UpdateQueryBuilder) : createQuery(this, DeleteQueryBuilder);
|
|
647
|
+
if (description.SoftDelete?.DeletedAt) {
|
|
699
648
|
query.update({
|
|
700
|
-
[description.SoftDelete.DeletedAt]:
|
|
649
|
+
[description.SoftDelete.DeletedAt]: DateTime.now(),
|
|
701
650
|
});
|
|
702
651
|
}
|
|
703
652
|
if (pks) {
|
|
@@ -711,7 +660,7 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
711
660
|
return entity;
|
|
712
661
|
},
|
|
713
662
|
async getOrCreate(pk, data) {
|
|
714
|
-
const { query, description } = createQuery(this,
|
|
663
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
715
664
|
// pk constrain
|
|
716
665
|
if (description.PrimaryKey && pk !== null) {
|
|
717
666
|
query.where(description.PrimaryKey, pk);
|
|
@@ -730,7 +679,7 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
730
679
|
return entity;
|
|
731
680
|
},
|
|
732
681
|
async getOrNew(pk, data) {
|
|
733
|
-
const { query, description } = createQuery(this,
|
|
682
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
734
683
|
// pk constrain
|
|
735
684
|
if (description.PrimaryKey) {
|
|
736
685
|
query.where(description.PrimaryKey, pk);
|
|
@@ -748,29 +697,28 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
748
697
|
return entity;
|
|
749
698
|
},
|
|
750
699
|
async first(callback) {
|
|
751
|
-
const { query, description } = createQuery(this,
|
|
752
|
-
_prepareOrderBy(description, query,
|
|
700
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
701
|
+
_prepareOrderBy(description, query, SordOrder.ASC);
|
|
753
702
|
if (callback) {
|
|
754
703
|
callback(query);
|
|
755
704
|
}
|
|
756
705
|
return (await query.first());
|
|
757
706
|
},
|
|
758
707
|
async last(callback) {
|
|
759
|
-
const { query, description } = createQuery(this,
|
|
760
|
-
_prepareOrderBy(description, query,
|
|
708
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
709
|
+
_prepareOrderBy(description, query, SordOrder.DESC);
|
|
761
710
|
if (callback) {
|
|
762
711
|
callback(query);
|
|
763
712
|
}
|
|
764
713
|
return (await query.first());
|
|
765
714
|
},
|
|
766
715
|
async newest(callback) {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
query.order(description.Timestamps.CreatedAt, enums_1.SordOrder.DESC);
|
|
716
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
717
|
+
if (description.Timestamps?.CreatedAt) {
|
|
718
|
+
query.order(description.Timestamps.CreatedAt, SordOrder.DESC);
|
|
771
719
|
}
|
|
772
720
|
else {
|
|
773
|
-
throw new
|
|
721
|
+
throw new OrmException('cannot fetch newest entity - CreateAt column not exists in model/db');
|
|
774
722
|
}
|
|
775
723
|
if (callback) {
|
|
776
724
|
callback(query);
|
|
@@ -778,13 +726,12 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
778
726
|
return (await query.first());
|
|
779
727
|
},
|
|
780
728
|
async oldest(callback) {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
query.order(description.Timestamps.CreatedAt, enums_1.SordOrder.ASC);
|
|
729
|
+
const { query, description } = createQuery(this, SelectQueryBuilder);
|
|
730
|
+
if (description.Timestamps?.CreatedAt) {
|
|
731
|
+
query.order(description.Timestamps.CreatedAt, SordOrder.ASC);
|
|
785
732
|
}
|
|
786
733
|
else {
|
|
787
|
-
throw new
|
|
734
|
+
throw new OrmException('cannot fetch oldest entity - CreateAt column not exists in model/db');
|
|
788
735
|
}
|
|
789
736
|
if (callback) {
|
|
790
737
|
callback(query);
|
|
@@ -792,7 +739,7 @@ exports.MODEL_STATIC_MIXINS = {
|
|
|
792
739
|
return (await query.first());
|
|
793
740
|
},
|
|
794
741
|
async count(callback) {
|
|
795
|
-
const { query } = createQuery(this,
|
|
742
|
+
const { query } = createQuery(this, SelectQueryBuilder);
|
|
796
743
|
query.count('*', 'count');
|
|
797
744
|
if (callback) {
|
|
798
745
|
callback(query);
|