@spinajs/orm 2.0.86 → 2.0.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/lib/{builders.d.ts → cjs/builders.d.ts} +0 -0
  2. package/lib/cjs/builders.d.ts.map +1 -0
  3. package/lib/cjs/builders.js +1554 -0
  4. package/lib/cjs/builders.js.map +1 -0
  5. package/lib/cjs/converters.d.ts +21 -0
  6. package/lib/cjs/converters.d.ts.map +1 -0
  7. package/lib/cjs/converters.js +86 -0
  8. package/lib/cjs/converters.js.map +1 -0
  9. package/lib/{decorators.d.ts → cjs/decorators.d.ts} +0 -0
  10. package/lib/cjs/decorators.d.ts.map +1 -0
  11. package/lib/cjs/decorators.js +453 -0
  12. package/lib/cjs/decorators.js.map +1 -0
  13. package/lib/{dehydrators.d.ts → cjs/dehydrators.d.ts} +0 -0
  14. package/lib/cjs/dehydrators.d.ts.map +1 -0
  15. package/lib/cjs/dehydrators.js +48 -0
  16. package/lib/cjs/dehydrators.js.map +1 -0
  17. package/lib/{driver.d.ts → cjs/driver.d.ts} +0 -0
  18. package/lib/cjs/driver.d.ts.map +1 -0
  19. package/lib/cjs/driver.js +100 -0
  20. package/lib/cjs/driver.js.map +1 -0
  21. package/lib/{enums.d.ts → cjs/enums.d.ts} +0 -0
  22. package/lib/cjs/enums.d.ts.map +1 -0
  23. package/lib/cjs/enums.js +125 -0
  24. package/lib/cjs/enums.js.map +1 -0
  25. package/lib/{exceptions.d.ts → cjs/exceptions.d.ts} +0 -0
  26. package/lib/cjs/exceptions.d.ts.map +1 -0
  27. package/lib/cjs/exceptions.js +11 -0
  28. package/lib/cjs/exceptions.js.map +1 -0
  29. package/lib/{hydrators.d.ts → cjs/hydrators.d.ts} +0 -0
  30. package/lib/cjs/hydrators.d.ts.map +1 -0
  31. package/lib/cjs/hydrators.js +130 -0
  32. package/lib/cjs/hydrators.js.map +1 -0
  33. package/lib/{index.d.ts → cjs/index.d.ts} +0 -0
  34. package/lib/cjs/index.d.ts.map +1 -0
  35. package/lib/cjs/index.js +32 -0
  36. package/lib/cjs/index.js.map +1 -0
  37. package/lib/{interfaces.d.ts → cjs/interfaces.d.ts} +0 -0
  38. package/lib/cjs/interfaces.d.ts.map +1 -0
  39. package/lib/cjs/interfaces.js +299 -0
  40. package/lib/cjs/interfaces.js.map +1 -0
  41. package/lib/{model.d.ts → cjs/model.d.ts} +0 -0
  42. package/lib/cjs/model.d.ts.map +1 -0
  43. package/lib/cjs/model.js +760 -0
  44. package/lib/cjs/model.js.map +1 -0
  45. package/lib/{orm.d.ts → cjs/orm.d.ts} +0 -0
  46. package/lib/cjs/orm.d.ts.map +1 -0
  47. package/lib/cjs/orm.js +329 -0
  48. package/lib/cjs/orm.js.map +1 -0
  49. package/lib/{relations.d.ts → cjs/relations.d.ts} +0 -0
  50. package/lib/cjs/relations.d.ts.map +1 -0
  51. package/lib/cjs/relations.js +630 -0
  52. package/lib/cjs/relations.js.map +1 -0
  53. package/lib/{statements.d.ts → cjs/statements.d.ts} +0 -0
  54. package/lib/cjs/statements.d.ts.map +1 -0
  55. package/lib/cjs/statements.js +296 -0
  56. package/lib/cjs/statements.js.map +1 -0
  57. package/lib/{types.d.ts → cjs/types.d.ts} +0 -0
  58. package/lib/cjs/types.d.ts.map +1 -0
  59. package/lib/cjs/types.js +3 -0
  60. package/lib/cjs/types.js.map +1 -0
  61. package/lib/{wrappers.d.ts → cjs/wrappers.d.ts} +0 -0
  62. package/lib/cjs/wrappers.d.ts.map +1 -0
  63. package/lib/cjs/wrappers.js +13 -0
  64. package/lib/cjs/wrappers.js.map +1 -0
  65. package/lib/mjs/builders.d.ts +639 -0
  66. package/lib/mjs/builders.d.ts.map +1 -0
  67. package/lib/{builders.js → mjs/builders.js} +0 -0
  68. package/lib/mjs/builders.js.map +1 -0
  69. package/lib/{converters.d.ts → mjs/converters.d.ts} +0 -0
  70. package/lib/mjs/converters.d.ts.map +1 -0
  71. package/lib/{converters.js → mjs/converters.js} +0 -0
  72. package/lib/mjs/converters.js.map +1 -0
  73. package/lib/mjs/decorators.d.ts +153 -0
  74. package/lib/mjs/decorators.d.ts.map +1 -0
  75. package/lib/{decorators.js → mjs/decorators.js} +0 -0
  76. package/lib/mjs/decorators.js.map +1 -0
  77. package/lib/mjs/dehydrators.d.ts +11 -0
  78. package/lib/mjs/dehydrators.d.ts.map +1 -0
  79. package/lib/{dehydrators.js → mjs/dehydrators.js} +0 -0
  80. package/lib/mjs/dehydrators.js.map +1 -0
  81. package/lib/mjs/driver.d.ts +83 -0
  82. package/lib/mjs/driver.d.ts.map +1 -0
  83. package/lib/{driver.js → mjs/driver.js} +0 -0
  84. package/lib/mjs/driver.js.map +1 -0
  85. package/lib/mjs/enums.d.ts +116 -0
  86. package/lib/mjs/enums.d.ts.map +1 -0
  87. package/lib/{enums.js → mjs/enums.js} +7 -7
  88. package/lib/mjs/enums.js.map +1 -0
  89. package/lib/mjs/exceptions.d.ts +7 -0
  90. package/lib/mjs/exceptions.d.ts.map +1 -0
  91. package/lib/{exceptions.js → mjs/exceptions.js} +0 -0
  92. package/lib/mjs/exceptions.js.map +1 -0
  93. package/lib/mjs/hydrators.d.ts +20 -0
  94. package/lib/mjs/hydrators.d.ts.map +1 -0
  95. package/lib/{hydrators.js → mjs/hydrators.js} +0 -0
  96. package/lib/mjs/hydrators.js.map +1 -0
  97. package/lib/mjs/index.d.ts +16 -0
  98. package/lib/mjs/index.d.ts.map +1 -0
  99. package/lib/{index.js → mjs/index.js} +0 -0
  100. package/lib/mjs/index.js.map +1 -0
  101. package/lib/mjs/interfaces.d.ts +801 -0
  102. package/lib/mjs/interfaces.d.ts.map +1 -0
  103. package/lib/{interfaces.js → mjs/interfaces.js} +6 -6
  104. package/lib/mjs/interfaces.js.map +1 -0
  105. package/lib/mjs/model.d.ts +344 -0
  106. package/lib/mjs/model.d.ts.map +1 -0
  107. package/lib/{model.js → mjs/model.js} +0 -0
  108. package/lib/mjs/model.js.map +1 -0
  109. package/lib/mjs/orm.d.ts +63 -0
  110. package/lib/mjs/orm.d.ts.map +1 -0
  111. package/lib/{orm.js → mjs/orm.js} +0 -0
  112. package/lib/mjs/orm.js.map +1 -0
  113. package/lib/mjs/relations.d.ts +176 -0
  114. package/lib/mjs/relations.d.ts.map +1 -0
  115. package/lib/{relations.js → mjs/relations.js} +0 -0
  116. package/lib/mjs/relations.js.map +1 -0
  117. package/lib/mjs/statements.d.ts +139 -0
  118. package/lib/mjs/statements.d.ts.map +1 -0
  119. package/lib/{statements.js → mjs/statements.js} +0 -0
  120. package/lib/mjs/statements.js.map +1 -0
  121. package/lib/mjs/types.d.ts +25 -0
  122. package/lib/mjs/types.d.ts.map +1 -0
  123. package/lib/{types.js → mjs/types.js} +0 -0
  124. package/lib/mjs/types.js.map +1 -0
  125. package/lib/mjs/wrappers.d.ts +6 -0
  126. package/lib/mjs/wrappers.d.ts.map +1 -0
  127. package/lib/{wrappers.js → mjs/wrappers.js} +0 -0
  128. package/lib/mjs/wrappers.js.map +1 -0
  129. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  130. package/lib/tsconfig.tsbuildinfo +1 -0
  131. package/package.json +16 -8
  132. package/lib/builders.d.ts.map +0 -1
  133. package/lib/builders.js.map +0 -1
  134. package/lib/converters.d.ts.map +0 -1
  135. package/lib/converters.js.map +0 -1
  136. package/lib/decorators.d.ts.map +0 -1
  137. package/lib/decorators.js.map +0 -1
  138. package/lib/dehydrators.d.ts.map +0 -1
  139. package/lib/dehydrators.js.map +0 -1
  140. package/lib/driver.d.ts.map +0 -1
  141. package/lib/driver.js.map +0 -1
  142. package/lib/enums.d.ts.map +0 -1
  143. package/lib/enums.js.map +0 -1
  144. package/lib/exceptions.d.ts.map +0 -1
  145. package/lib/exceptions.js.map +0 -1
  146. package/lib/hydrators.d.ts.map +0 -1
  147. package/lib/hydrators.js.map +0 -1
  148. package/lib/index.d.ts.map +0 -1
  149. package/lib/index.js.map +0 -1
  150. package/lib/interfaces.d.ts.map +0 -1
  151. package/lib/interfaces.js.map +0 -1
  152. package/lib/model.d.ts.map +0 -1
  153. package/lib/model.js.map +0 -1
  154. package/lib/orm.d.ts.map +0 -1
  155. package/lib/orm.js.map +0 -1
  156. package/lib/relations.d.ts.map +0 -1
  157. package/lib/relations.js.map +0 -1
  158. package/lib/statements.d.ts.map +0 -1
  159. package/lib/statements.js.map +0 -1
  160. package/lib/types.d.ts.map +0 -1
  161. package/lib/types.js.map +0 -1
  162. package/lib/wrappers.d.ts.map +0 -1
  163. package/lib/wrappers.js.map +0 -1
@@ -0,0 +1,760 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MODEL_STATIC_MIXINS = exports.createQuery = exports.HistoricalModel = exports.ModelBase = exports.extractModelDescriptor = void 0;
7
+ /* eslint-disable prettier/prettier */
8
+ const relations_js_1 = require("./relations.js");
9
+ const enums_js_1 = require("./enums.js");
10
+ const decorators_js_1 = require("./decorators.js");
11
+ const interfaces_js_1 = require("./interfaces.js");
12
+ const builders_js_1 = require("./builders.js");
13
+ const di_1 = require("@spinajs/di");
14
+ const orm_js_1 = require("./orm.js");
15
+ const hydrators_js_1 = require("./hydrators.js");
16
+ const lodash_1 = __importDefault(require("lodash"));
17
+ const uuid_1 = require("uuid");
18
+ const exceptions_js_1 = require("./exceptions.js");
19
+ const dehydrators_js_1 = require("./dehydrators.js");
20
+ const luxon_1 = require("luxon");
21
+ function extractModelDescriptor(targetOrForward) {
22
+ const target = !(0, di_1.isConstructor)(targetOrForward) && targetOrForward ? targetOrForward() : targetOrForward;
23
+ if (!target) {
24
+ return null;
25
+ }
26
+ let descriptor = null;
27
+ _reduce(target);
28
+ return descriptor;
29
+ function _reduce(t) {
30
+ if (!t) {
31
+ return;
32
+ }
33
+ if (t[decorators_js_1.MODEL_DESCTRIPTION_SYMBOL]) {
34
+ descriptor = descriptor ?? {};
35
+ lodash_1.default.mergeWith(descriptor, t[decorators_js_1.MODEL_DESCTRIPTION_SYMBOL], (a, b) => {
36
+ if (!a) {
37
+ return b;
38
+ }
39
+ if (Array.isArray(a)) {
40
+ return a.concat(b);
41
+ }
42
+ return a;
43
+ });
44
+ }
45
+ _reduce(t.prototype);
46
+ _reduce(t.__proto__);
47
+ }
48
+ }
49
+ exports.extractModelDescriptor = extractModelDescriptor;
50
+ class ModelBase {
51
+ /**
52
+ * Gets descriptor for this model. It contains information about relations, orm driver, connection properties,
53
+ * db table attached, column information and others.
54
+ */
55
+ get ModelDescriptor() {
56
+ return extractModelDescriptor(this.constructor);
57
+ }
58
+ /**
59
+ * Gets di container associated with this model ( via connection object eg. different drivers have their own implementation of things)
60
+ */
61
+ get Container() {
62
+ if (!this._container) {
63
+ const orm = di_1.DI.get(orm_js_1.Orm);
64
+ const driver = orm.Connections.get(this.ModelDescriptor.Connection);
65
+ if (!driver) {
66
+ throw new Error(`model ${this.constructor.name} have invalid connection ${this.ModelDescriptor.Connection}, please check your db config file or model connection name`);
67
+ }
68
+ this._container = driver.Container;
69
+ }
70
+ return this._container;
71
+ }
72
+ get PrimaryKeyName() {
73
+ return this.ModelDescriptor.PrimaryKey;
74
+ }
75
+ get PrimaryKeyValue() {
76
+ return this[this.PrimaryKeyName];
77
+ }
78
+ set PrimaryKeyValue(newVal) {
79
+ this[this.PrimaryKeyName] = newVal;
80
+ this.ModelDescriptor.Relations.forEach((r) => {
81
+ const rel = this[r.Name];
82
+ if (!rel)
83
+ return;
84
+ switch (r.Type) {
85
+ case interfaces_js_1.RelationType.One:
86
+ rel[r.ForeignKey] = newVal;
87
+ break;
88
+ case interfaces_js_1.RelationType.Many:
89
+ rel.forEach((rVal) => (rVal[r.ForeignKey] = newVal));
90
+ break;
91
+ case interfaces_js_1.RelationType.ManyToMany:
92
+ // TODO: rethink this
93
+ break;
94
+ }
95
+ });
96
+ }
97
+ driver() {
98
+ const orm = di_1.DI.get(orm_js_1.Orm);
99
+ const driver = orm.Connections.get(this.ModelDescriptor.Connection);
100
+ return driver;
101
+ }
102
+ /**
103
+ * Recursivelly takes all relation data and returns as single array
104
+ */
105
+ getFlattenRelationModels(recursive) {
106
+ const reduceRelations = function (m) {
107
+ const relations = [...m.ModelDescriptor.Relations.values()];
108
+ const models = lodash_1.default.flatMap(relations, (r) => {
109
+ if (r.Type === interfaces_js_1.RelationType.Many || r.Type === interfaces_js_1.RelationType.ManyToMany) {
110
+ return m[r.Name];
111
+ }
112
+ if (m[r.Name].Value) {
113
+ return [m[r.Name].Value];
114
+ }
115
+ }).filter((x) => x !== undefined);
116
+ if (recursive) {
117
+ return [...models, ...lodash_1.default.flatMap(models, reduceRelations)];
118
+ }
119
+ return models;
120
+ };
121
+ return reduceRelations(this);
122
+ }
123
+ /**
124
+ * Clears all data in table
125
+ */
126
+ static truncate() {
127
+ throw new Error('Not implemented');
128
+ }
129
+ /**
130
+ * Get all data from db
131
+ */
132
+ static all(_page, _perPage) {
133
+ throw new Error('Not implemented');
134
+ }
135
+ /**
136
+ * Inserts data to DB.
137
+ *
138
+ * @param _data - data to insert
139
+ */
140
+ static insert(_data, _insertBehaviour = interfaces_js_1.InsertBehaviour.None) {
141
+ throw new Error('Not implemented');
142
+ }
143
+ static where(_column, _operator, _value) {
144
+ throw new Error('Not implemented');
145
+ }
146
+ /**
147
+ * Updates single or multiple records at once with provided value based on condition
148
+ *
149
+ * @param _data - data to set
150
+ */
151
+ static update(_data) {
152
+ throw new Error('Not implemented');
153
+ }
154
+ /**
155
+ * Tries to find all models with given primary keys
156
+ */
157
+ static find(_pks) {
158
+ throw new Error('Not implemented');
159
+ }
160
+ static first() {
161
+ throw new Error('Not implemented');
162
+ }
163
+ static last() {
164
+ throw new Error('Not implemented');
165
+ }
166
+ static newest() {
167
+ throw new Error('Not implemented');
168
+ }
169
+ static oldest() {
170
+ throw new Error('Not implemented');
171
+ }
172
+ static count() {
173
+ throw new Error('Not implemented');
174
+ }
175
+ /**
176
+ * Tries to find all models in db. If not all exists, throws exception
177
+ */
178
+ static findOrFail(_pks) {
179
+ throw new Error('Not implemented');
180
+ }
181
+ /**
182
+ * gets model by specified pk, if not exists, returns null
183
+ *
184
+ */
185
+ static get(_pk) {
186
+ throw new Error('Not implemented');
187
+ }
188
+ /**
189
+ * Finds model by specified pk. If model not exists in db throws exception
190
+ *
191
+ */
192
+ static getOrFail(_pk) {
193
+ throw new Error('Not implemented');
194
+ }
195
+ /**
196
+ *
197
+ * Checks if model with pk key or unique fields exists and if not creates one AND NOT save in db
198
+ * NOTE: it checks for unique fields constraint
199
+ */
200
+ static getOrNew(_pk, _data) {
201
+ throw new Error('Not implemented');
202
+ }
203
+ /**
204
+ * Creates query on this model. used for quering db for partial data, to perform some kind of operations
205
+ * that dont need full ORM model to involve, or other non standard operations eg. joins or raw data queries based on this model
206
+ */
207
+ static query() {
208
+ throw new Error('Not implemented');
209
+ }
210
+ /**
211
+ *
212
+ * Checks if model with pk key / unique fields exists and if not creates one and saves to db
213
+ * NOTE: it checks for unique fields too.
214
+ *
215
+ * @param data - model width data to check
216
+ */
217
+ static getOrCreate(_pk, _data) {
218
+ throw new Error('Not implemented');
219
+ }
220
+ /**
221
+ * Creates new model & saves is to db
222
+ *
223
+ * @param data - initial model data
224
+ */
225
+ static create(_data) {
226
+ throw new Error('Not implemented');
227
+ }
228
+ /**
229
+ * Deletes model from db
230
+ *
231
+ * @param pk - primary key
232
+ */
233
+ static destroy(_pk) {
234
+ throw new Error('Not implemented');
235
+ }
236
+ constructor(data) {
237
+ /**
238
+ * List of hidden properties from JSON / dehydrations
239
+ * eg. password field of user
240
+ */
241
+ this._hidden = [];
242
+ this.setDefaults();
243
+ if (data) {
244
+ this.hydrate(data);
245
+ }
246
+ }
247
+ /**
248
+ * Fills model with data. It only fills properties that exists in database
249
+ *
250
+ * @param data - data to fill
251
+ */
252
+ hydrate(data) {
253
+ this.Container.resolve(Array.ofType(hydrators_js_1.ModelHydrator)).forEach((h) => h.hydrate(this, data));
254
+ }
255
+ /**
256
+ *
257
+ * Attachess model to proper relation an sets foreign key
258
+ *
259
+ * @param data - model to attach
260
+ */
261
+ attach(data) {
262
+ // TODO: refactor this, to not check every time for relation
263
+ // do this as map or smth
264
+ for (const [_, v] of this.ModelDescriptor.Relations.entries()) {
265
+ if (v.TargetModel.name === data.constructor.name) {
266
+ data[v.ForeignKey] = this.PrimaryKeyValue;
267
+ switch (v.Type) {
268
+ case interfaces_js_1.RelationType.One:
269
+ this[v.Name].attach(data);
270
+ break;
271
+ case interfaces_js_1.RelationType.Many:
272
+ case interfaces_js_1.RelationType.ManyToMany:
273
+ this[v.Name].push(data);
274
+ break;
275
+ }
276
+ }
277
+ }
278
+ }
279
+ /**
280
+ * Extracts all data from model. It takes only properties that exists in DB
281
+ */
282
+ dehydrate(omit) {
283
+ return this.Container.resolve(dehydrators_js_1.StandardModelDehydrator).dehydrate(this, [...(omit ?? []), ...this._hidden]);
284
+ }
285
+ /**
286
+ *
287
+ * Extracts all data from model with relation data. Relation data are dehydrated recursively.
288
+ *
289
+ * @param omit - fields to omit
290
+ */
291
+ dehydrateWithRelations(omit) {
292
+ return this.Container.resolve(dehydrators_js_1.StandardModelWithRelationsDehydrator).dehydrate(this, [...(omit ?? []), ...this._hidden]);
293
+ }
294
+ toSql() {
295
+ return this.Container.resolve(interfaces_js_1.ModelToSqlConverter).toSql(this);
296
+ }
297
+ /**
298
+ * deletes enitt from db. If model have SoftDelete decorator, model is marked as deleted
299
+ */
300
+ async destroy() {
301
+ if (!this.PrimaryKeyValue) {
302
+ return;
303
+ }
304
+ await this.constructor.destroy(this.PrimaryKeyValue);
305
+ }
306
+ /**
307
+ * If model can be in achived state - sets archived at date and saves it to db
308
+ */
309
+ async archive() {
310
+ if (this.ModelDescriptor.Archived) {
311
+ this[this.ModelDescriptor.Archived.ArchivedAt] = luxon_1.DateTime.now();
312
+ }
313
+ else {
314
+ throw new exceptions_js_1.OrmException('archived at column not exists in model');
315
+ }
316
+ const { query } = this.createUpdateQuery();
317
+ await query.update(this.toSql()).where(this.PrimaryKeyName, this.PrimaryKeyValue);
318
+ }
319
+ async update() {
320
+ const { query } = this.createUpdateQuery();
321
+ if (this.ModelDescriptor.Timestamps.UpdatedAt) {
322
+ this[this.ModelDescriptor.Timestamps.UpdatedAt] = luxon_1.DateTime.now();
323
+ }
324
+ await query.update(this.toSql()).where(this.PrimaryKeyName, this.PrimaryKeyValue);
325
+ }
326
+ /**
327
+ * Save all changes to db. It creates new entry id db or updates existing one if
328
+ * primary key exists
329
+ */
330
+ async insert(insertBehaviour = interfaces_js_1.InsertBehaviour.None) {
331
+ const { query, description } = this.createInsertQuery();
332
+ switch (insertBehaviour) {
333
+ case interfaces_js_1.InsertBehaviour.InsertOrIgnore:
334
+ query.orIgnore();
335
+ break;
336
+ case interfaces_js_1.InsertBehaviour.InsertOrUpdate:
337
+ query.onDuplicate().update(description.Columns.filter((c) => !c.PrimaryKey).map((c) => c.Name));
338
+ break;
339
+ case interfaces_js_1.InsertBehaviour.InsertOrReplace:
340
+ query.orReplace();
341
+ break;
342
+ }
343
+ const iMidleware = {
344
+ afterQuery: (data) => {
345
+ this.PrimaryKeyValue = this.PrimaryKeyValue ?? data.LastInsertId;
346
+ return data;
347
+ },
348
+ modelCreation: () => null,
349
+ afterHydration: () => null,
350
+ };
351
+ query.middleware(iMidleware);
352
+ return query.values(this.toSql());
353
+ }
354
+ /**
355
+ *
356
+ * Shorthand for inserting model when no primary key exists, or update
357
+ * its value in db if primary key is set
358
+ *
359
+ * @param insertBehaviour - insert mode
360
+ */
361
+ async insertOrUpdate(insertBehaviour = interfaces_js_1.InsertBehaviour.None) {
362
+ if (this.PrimaryKeyValue) {
363
+ await this.update();
364
+ }
365
+ else {
366
+ await this.insert(insertBehaviour);
367
+ }
368
+ }
369
+ /**
370
+ * Gets model data from database and returns as fresh instance.
371
+ *
372
+ * If primary key is not fetched, tries to load by columns with unique constraint.
373
+ * If there is no unique columns or primary key, throws error
374
+ */
375
+ async fresh() {
376
+ const { query, description } = this.createSelectQuery();
377
+ query.select('*');
378
+ _preparePkWhere(description, query, this);
379
+ _prepareOrderBy(description, query);
380
+ // TODO: rethink all cast of this type?
381
+ return (await query.firstOrFail());
382
+ }
383
+ /**
384
+ * Refresh model from database.
385
+ *
386
+ * If no primary key is set, tries to fetch data base on columns
387
+ * with unique constraints. If none exists, throws exception
388
+ */
389
+ async refresh() {
390
+ let model = null;
391
+ model = await this.fresh();
392
+ for (const c of this.ModelDescriptor.Columns) {
393
+ this[c.Name] = model[c.Name];
394
+ }
395
+ }
396
+ toJSON() {
397
+ return this.dehydrate();
398
+ }
399
+ /**
400
+ * sets default values for model. values are taken from DB default column prop
401
+ */
402
+ setDefaults() {
403
+ this.ModelDescriptor.Columns?.forEach((c) => {
404
+ if (c.Uuid) {
405
+ this[c.Name] = (0, uuid_1.v4)();
406
+ }
407
+ else {
408
+ this[c.Name] = c.DefaultValue;
409
+ }
410
+ });
411
+ if (this.ModelDescriptor.Timestamps.CreatedAt) {
412
+ this[this.ModelDescriptor.Timestamps.CreatedAt] = luxon_1.DateTime.now();
413
+ }
414
+ for (const [, rel] of this.ModelDescriptor.Relations) {
415
+ if (rel.Factory) {
416
+ this[rel.Name] = rel.Factory(this, rel, this.Container);
417
+ }
418
+ else if (rel.RelationClass) {
419
+ this[rel.Name] = this.Container.resolve(rel.RelationClass, [this, rel.TargetModel, rel, []]);
420
+ }
421
+ else if (rel.Type === interfaces_js_1.RelationType.Many) {
422
+ this[rel.Name] = new relations_js_1.OneToManyRelationList(this, rel.TargetModel, rel, []);
423
+ }
424
+ else if (rel.Type === interfaces_js_1.RelationType.ManyToMany) {
425
+ this[rel.Name] = new relations_js_1.ManyToManyRelationList(this, rel.TargetModel, rel, []);
426
+ }
427
+ else {
428
+ this[rel.Name] = new relations_js_1.SingleRelation(this, rel.TargetModel, rel, null);
429
+ }
430
+ }
431
+ }
432
+ createSelectQuery() {
433
+ return createQuery(this.constructor, builders_js_1.SelectQueryBuilder);
434
+ }
435
+ createUpdateQuery() {
436
+ return createQuery(this.constructor, builders_js_1.UpdateQueryBuilder);
437
+ }
438
+ createInsertQuery() {
439
+ return createQuery(this.constructor, builders_js_1.InsertQueryBuilder);
440
+ }
441
+ }
442
+ exports.ModelBase = ModelBase;
443
+ function _descriptor(model) {
444
+ return model[decorators_js_1.MODEL_DESCTRIPTION_SYMBOL];
445
+ }
446
+ function _preparePkWhere(description, query, model) {
447
+ if (description.PrimaryKey) {
448
+ query.where(description.PrimaryKey, model.PrimaryKeyValue);
449
+ }
450
+ else {
451
+ const unique = description.Columns.filter((x) => x.Unique);
452
+ if (unique.length !== 0) {
453
+ for (const c of unique) {
454
+ query.where(c.Name, '=', model[c.Name]);
455
+ }
456
+ }
457
+ else {
458
+ throw new exceptions_js_1.OrmException('Model dont have primary key set or columns with unique constraint, cannot fetch model from database');
459
+ }
460
+ }
461
+ }
462
+ function _prepareOrderBy(description, query, order) {
463
+ if (description.PrimaryKey) {
464
+ query.order(description.PrimaryKey, order ?? enums_js_1.SordOrder.DESC);
465
+ }
466
+ else {
467
+ const unique = description.Columns.filter((c) => c.Unique);
468
+ if (unique.length !== 0) {
469
+ unique.forEach((c) => query.order(c.Name, order ?? enums_js_1.SordOrder.DESC));
470
+ }
471
+ else if (description.Timestamps?.CreatedAt) {
472
+ query.order(description.Timestamps.CreatedAt, order ?? enums_js_1.SordOrder.DESC);
473
+ }
474
+ else if (description.Timestamps?.UpdatedAt) {
475
+ query.order(description.Timestamps.UpdatedAt, order ?? enums_js_1.SordOrder.DESC);
476
+ }
477
+ }
478
+ }
479
+ class HistoricalModel {
480
+ }
481
+ exports.HistoricalModel = HistoricalModel;
482
+ /**
483
+ * Helper function to create query based on model
484
+ *
485
+ * @param model - source model for query
486
+ * @param query - query class
487
+ * @param injectModel - should inject model information into query, if not, query will return raw data
488
+ *
489
+ * @returns
490
+ */
491
+ function createQuery(model, query, injectModel = true) {
492
+ const dsc = _descriptor(model);
493
+ if (!dsc) {
494
+ throw new Error(`model ${model.name} does not have model descriptor. Use @model decorator on class`);
495
+ }
496
+ const orm = di_1.DI.get(orm_js_1.Orm);
497
+ const driver = orm.Connections.get(dsc.Connection);
498
+ if (!driver) {
499
+ throw new Error(`model ${model.name} have invalid connection ${dsc.Connection}, please check your db config file or model connection name`);
500
+ }
501
+ const cnt = driver.Container;
502
+ const qr = cnt.resolve(query, [driver, injectModel ? orm.Models.find((x) => x.name === model.name).type : null]);
503
+ if (qr instanceof builders_js_1.SelectQueryBuilder) {
504
+ const scope = model._queryScopes;
505
+ if (scope) {
506
+ Object.getOwnPropertyNames(scope.__proto__)
507
+ .filter((x) => x !== 'constructor')
508
+ .forEach(function (property) {
509
+ if (typeof scope[property] === 'function') {
510
+ qr[property] = scope[property].bind(qr);
511
+ }
512
+ });
513
+ }
514
+ }
515
+ qr.middleware(new relations_js_1.DiscriminationMapMiddleware(dsc));
516
+ qr.setTable(dsc.TableName);
517
+ if (driver.Options.Database) {
518
+ qr.database(driver.Options.Database);
519
+ }
520
+ return {
521
+ query: qr,
522
+ description: dsc,
523
+ model,
524
+ container: driver.Container,
525
+ };
526
+ }
527
+ exports.createQuery = createQuery;
528
+ exports.MODEL_STATIC_MIXINS = {
529
+ truncate() {
530
+ const { query } = createQuery(this, builders_js_1.TruncateTableQueryBuilder, false);
531
+ return query;
532
+ },
533
+ driver() {
534
+ const dsc = _descriptor(this);
535
+ const orm = di_1.DI.get(orm_js_1.Orm);
536
+ const driver = orm.Connections.get(dsc.Connection);
537
+ if (!driver) {
538
+ throw new Error(`model ${this.name} have invalid connection ${dsc.Connection}, please check your db config file or model connection name`);
539
+ }
540
+ return driver;
541
+ },
542
+ query() {
543
+ const { query } = createQuery(this, builders_js_1.SelectQueryBuilder);
544
+ return query;
545
+ },
546
+ where(column, operator, value) {
547
+ const { query } = createQuery(this, builders_js_1.SelectQueryBuilder);
548
+ query.select('*');
549
+ return query.where(column, operator, value);
550
+ },
551
+ update(data) {
552
+ const { query } = createQuery(this, builders_js_1.UpdateQueryBuilder);
553
+ return query.update(data);
554
+ },
555
+ all(page, perPage) {
556
+ const { query } = createQuery(this, builders_js_1.SelectQueryBuilder);
557
+ query.select('*');
558
+ if (page >= 0 && perPage > 0) {
559
+ query.take(perPage).skip(page * perPage);
560
+ }
561
+ return query;
562
+ },
563
+ /**
564
+ * Try to insert new value
565
+ */
566
+ async insert(data, insertBehaviour = interfaces_js_1.InsertBehaviour.None) {
567
+ const { query, description, container } = createQuery(this, builders_js_1.InsertQueryBuilder);
568
+ const converter = container.resolve(interfaces_js_1.ObjectToSqlConverter);
569
+ if (Array.isArray(data)) {
570
+ if (insertBehaviour !== interfaces_js_1.InsertBehaviour.None) {
571
+ throw new exceptions_js_1.OrmException(`insert behaviour is not supported with arrays`);
572
+ }
573
+ query.values(data.map((d) => {
574
+ if (d instanceof ModelBase) {
575
+ return d.toSql();
576
+ }
577
+ return converter.toSql(d);
578
+ }));
579
+ }
580
+ else {
581
+ switch (insertBehaviour) {
582
+ case interfaces_js_1.InsertBehaviour.InsertOrIgnore:
583
+ query.orIgnore();
584
+ break;
585
+ case interfaces_js_1.InsertBehaviour.InsertOrUpdate:
586
+ query.onDuplicate().update(description.Columns.filter((c) => !c.PrimaryKey).map((c) => c.Name));
587
+ break;
588
+ case interfaces_js_1.InsertBehaviour.InsertOrReplace:
589
+ query.orReplace();
590
+ break;
591
+ }
592
+ if (data instanceof ModelBase) {
593
+ query.values(data.toSql());
594
+ }
595
+ else {
596
+ query.values(converter.toSql(data));
597
+ }
598
+ }
599
+ const iMidleware = {
600
+ afterQuery: (result) => {
601
+ if (Array.isArray(data)) {
602
+ data.forEach((v, idx) => {
603
+ if (v instanceof ModelBase) {
604
+ v.PrimaryKeyValue = v.PrimaryKeyValue ?? result.LastInsertId - data.length + idx;
605
+ }
606
+ });
607
+ }
608
+ else if (data instanceof ModelBase) {
609
+ data.PrimaryKeyValue = data.PrimaryKeyValue ?? result.LastInsertId;
610
+ }
611
+ return result;
612
+ },
613
+ modelCreation: () => null,
614
+ afterHydration: () => null,
615
+ };
616
+ query.middleware(iMidleware);
617
+ return query;
618
+ },
619
+ async find(pks) {
620
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
621
+ const pkey = description.PrimaryKey;
622
+ query.select('*');
623
+ query.whereIn(pkey, pks);
624
+ return await query;
625
+ },
626
+ async findOrFail(pks) {
627
+ const { query, description, model } = createQuery(this, builders_js_1.SelectQueryBuilder);
628
+ const pkey = description.PrimaryKey;
629
+ query.select('*');
630
+ query.whereIn(pkey, pks);
631
+ const result = await query;
632
+ if (result.length !== pks.length) {
633
+ throw new Error(`could not find all results for model ${model.name}`);
634
+ }
635
+ return result;
636
+ },
637
+ async get(pk) {
638
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
639
+ const pkey = description.PrimaryKey;
640
+ query.select('*');
641
+ query.where(pkey, pk);
642
+ _prepareOrderBy(description, query);
643
+ return (await query.first());
644
+ },
645
+ async getOrFail(pk) {
646
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
647
+ const pkey = description.PrimaryKey;
648
+ query.select('*');
649
+ query.where(pkey, pk);
650
+ _prepareOrderBy(description, query);
651
+ return (await query.firstOrFail());
652
+ },
653
+ destroy(pks) {
654
+ const description = _descriptor(this);
655
+ const data = Array.isArray(pks) ? pks : [pks];
656
+ const { query } = description.SoftDelete?.DeletedAt ? createQuery(this, builders_js_1.UpdateQueryBuilder) : createQuery(this, builders_js_1.DeleteQueryBuilder);
657
+ if (description.SoftDelete?.DeletedAt) {
658
+ query.update({
659
+ [description.SoftDelete.DeletedAt]: luxon_1.DateTime.now(),
660
+ });
661
+ }
662
+ if (pks) {
663
+ query.whereIn(description.PrimaryKey, data);
664
+ }
665
+ return query;
666
+ },
667
+ async create(data) {
668
+ const entity = new (Function.prototype.bind.apply(this))(data);
669
+ await entity.insert();
670
+ return entity;
671
+ },
672
+ async getOrCreate(pk, data) {
673
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
674
+ // pk constrain
675
+ if (description.PrimaryKey && pk !== null) {
676
+ query.where(description.PrimaryKey, pk);
677
+ }
678
+ // check for all unique columns ( unique constrain )
679
+ description.Columns.filter((c) => c.Unique).forEach((c) => {
680
+ query.andWhere(c, data[c.Name]);
681
+ });
682
+ _prepareOrderBy(description, query);
683
+ let entity = (await query.first());
684
+ if (!entity) {
685
+ entity = new (Function.prototype.bind.apply(this))(data);
686
+ await entity.insert();
687
+ return entity;
688
+ }
689
+ return entity;
690
+ },
691
+ async getOrNew(pk, data) {
692
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
693
+ // pk constrain
694
+ if (description.PrimaryKey) {
695
+ query.where(description.PrimaryKey, pk);
696
+ }
697
+ // check for all unique columns ( unique constrain )
698
+ description.Columns.filter((c) => c.Unique).forEach((c) => {
699
+ query.andWhere(c, data[c.Name]);
700
+ });
701
+ _prepareOrderBy(description, query);
702
+ let entity = (await query.first());
703
+ if (!entity) {
704
+ entity = new (Function.prototype.bind.apply(this))(data);
705
+ return entity;
706
+ }
707
+ return entity;
708
+ },
709
+ async first(callback) {
710
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
711
+ _prepareOrderBy(description, query, enums_js_1.SordOrder.ASC);
712
+ if (callback) {
713
+ callback(query);
714
+ }
715
+ return (await query.first());
716
+ },
717
+ async last(callback) {
718
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
719
+ _prepareOrderBy(description, query, enums_js_1.SordOrder.DESC);
720
+ if (callback) {
721
+ callback(query);
722
+ }
723
+ return (await query.first());
724
+ },
725
+ async newest(callback) {
726
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
727
+ if (description.Timestamps?.CreatedAt) {
728
+ query.order(description.Timestamps.CreatedAt, enums_js_1.SordOrder.DESC);
729
+ }
730
+ else {
731
+ throw new exceptions_js_1.OrmException('cannot fetch newest entity - CreateAt column not exists in model/db');
732
+ }
733
+ if (callback) {
734
+ callback(query);
735
+ }
736
+ return (await query.first());
737
+ },
738
+ async oldest(callback) {
739
+ const { query, description } = createQuery(this, builders_js_1.SelectQueryBuilder);
740
+ if (description.Timestamps?.CreatedAt) {
741
+ query.order(description.Timestamps.CreatedAt, enums_js_1.SordOrder.ASC);
742
+ }
743
+ else {
744
+ throw new exceptions_js_1.OrmException('cannot fetch oldest entity - CreateAt column not exists in model/db');
745
+ }
746
+ if (callback) {
747
+ callback(query);
748
+ }
749
+ return (await query.first());
750
+ },
751
+ async count(callback) {
752
+ const { query } = createQuery(this, builders_js_1.SelectQueryBuilder);
753
+ query.count('*', 'count');
754
+ if (callback) {
755
+ callback(query);
756
+ }
757
+ return await (await query.asRaw()).count;
758
+ },
759
+ };
760
+ //# sourceMappingURL=model.js.map