@abedmurrar/objection 4.0.0-alpha.0 → 4.0.0-beta.0

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 (192) hide show
  1. package/README.md +103 -67
  2. package/lib/index.mjs +6 -0
  3. package/lib/initialize.js +6 -9
  4. package/lib/model/AjvValidator.js +235 -282
  5. package/lib/model/Model.js +653 -823
  6. package/lib/model/ModifierNotFoundError.js +5 -7
  7. package/lib/model/NotFoundError.js +14 -18
  8. package/lib/model/RelationDoesNotExistError.js +6 -9
  9. package/lib/model/ValidationError.js +33 -41
  10. package/lib/model/Validator.js +15 -21
  11. package/lib/model/getModel.js +1 -3
  12. package/lib/model/graph/ModelGraph.js +44 -64
  13. package/lib/model/graph/ModelGraphBuilder.js +164 -217
  14. package/lib/model/graph/ModelGraphEdge.js +31 -43
  15. package/lib/model/graph/ModelGraphNode.js +192 -231
  16. package/lib/model/inheritModel.js +9 -18
  17. package/lib/model/modelBindKnex.js +48 -62
  18. package/lib/model/modelClone.js +79 -98
  19. package/lib/model/modelColPropMap.js +16 -26
  20. package/lib/model/modelConcurrency.js +24 -0
  21. package/lib/model/modelId.js +44 -49
  22. package/lib/model/modelJsonAttributes.js +56 -76
  23. package/lib/model/modelParseRelations.js +68 -67
  24. package/lib/model/modelQueryProps.js +76 -107
  25. package/lib/model/modelSet.js +92 -112
  26. package/lib/model/modelTableMetadata.js +60 -72
  27. package/lib/model/modelToJson.js +120 -150
  28. package/lib/model/modelUtils.js +30 -37
  29. package/lib/model/modelValidate.js +34 -42
  30. package/lib/model/modelValues.js +78 -91
  31. package/lib/model/modelVisitor.js +22 -29
  32. package/lib/objection.js +42 -67
  33. package/lib/queryBuilder/FunctionBuilder.js +231 -279
  34. package/lib/queryBuilder/InternalOptions.js +19 -24
  35. package/lib/queryBuilder/JoinBuilder.js +116 -149
  36. package/lib/queryBuilder/QueryBuilder.js +1009 -1271
  37. package/lib/queryBuilder/QueryBuilderBase.js +647 -865
  38. package/lib/queryBuilder/QueryBuilderContext.js +14 -21
  39. package/lib/queryBuilder/QueryBuilderContextBase.js +20 -29
  40. package/lib/queryBuilder/QueryBuilderOperationSupport.js +462 -536
  41. package/lib/queryBuilder/QueryBuilderUserContext.js +19 -25
  42. package/lib/queryBuilder/RawBuilder.js +58 -73
  43. package/lib/queryBuilder/ReferenceBuilder.js +232 -270
  44. package/lib/queryBuilder/RelationExpression.js +322 -380
  45. package/lib/queryBuilder/StaticHookArguments.js +94 -106
  46. package/lib/queryBuilder/ValueBuilder.js +100 -112
  47. package/lib/queryBuilder/expressions.js +86 -116
  48. package/lib/queryBuilder/functions/mysql.js +642 -697
  49. package/lib/queryBuilder/graph/GraphAction.js +44 -59
  50. package/lib/queryBuilder/graph/GraphData.js +7 -9
  51. package/lib/queryBuilder/graph/GraphFetcher.js +115 -151
  52. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +114 -152
  53. package/lib/queryBuilder/graph/GraphOperation.js +16 -22
  54. package/lib/queryBuilder/graph/GraphOptions.js +143 -185
  55. package/lib/queryBuilder/graph/GraphUpsert.js +167 -241
  56. package/lib/queryBuilder/graph/delete/GraphDelete.js +8 -13
  57. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +44 -62
  58. package/lib/queryBuilder/graph/insert/GraphInsert.js +99 -128
  59. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +151 -193
  60. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +57 -79
  61. package/lib/queryBuilder/graph/patch/GraphPatch.js +8 -13
  62. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +181 -234
  63. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +16 -21
  64. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +80 -110
  65. package/lib/queryBuilder/join/JoinResultColumn.js +14 -18
  66. package/lib/queryBuilder/join/JoinResultParser.js +88 -101
  67. package/lib/queryBuilder/join/RelationJoiner.js +205 -288
  68. package/lib/queryBuilder/join/TableNode.js +117 -144
  69. package/lib/queryBuilder/join/TableTree.js +60 -76
  70. package/lib/queryBuilder/join/utils.js +10 -16
  71. package/lib/queryBuilder/operations/DelegateOperation.js +93 -133
  72. package/lib/queryBuilder/operations/DeleteOperation.js +33 -37
  73. package/lib/queryBuilder/operations/FindByIdOperation.js +20 -28
  74. package/lib/queryBuilder/operations/FindByIdsOperation.js +17 -23
  75. package/lib/queryBuilder/operations/FindOperation.js +114 -131
  76. package/lib/queryBuilder/operations/FirstOperation.js +14 -19
  77. package/lib/queryBuilder/operations/FromOperation.js +69 -88
  78. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +28 -39
  79. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +25 -35
  80. package/lib/queryBuilder/operations/InsertGraphOperation.js +77 -98
  81. package/lib/queryBuilder/operations/InsertOperation.js +132 -165
  82. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +27 -36
  83. package/lib/queryBuilder/operations/InstanceFindOperation.js +9 -13
  84. package/lib/queryBuilder/operations/InstanceInsertOperation.js +13 -17
  85. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +32 -46
  86. package/lib/queryBuilder/operations/JoinRelatedOperation.js +66 -86
  87. package/lib/queryBuilder/operations/KnexOperation.js +4 -7
  88. package/lib/queryBuilder/operations/MergeOperation.js +32 -45
  89. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +131 -150
  90. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +17 -23
  91. package/lib/queryBuilder/operations/OnBuildOperation.js +17 -23
  92. package/lib/queryBuilder/operations/OnErrorOperation.js +17 -23
  93. package/lib/queryBuilder/operations/QueryBuilderOperation.js +231 -270
  94. package/lib/queryBuilder/operations/RangeOperation.js +30 -40
  95. package/lib/queryBuilder/operations/RelateOperation.js +14 -21
  96. package/lib/queryBuilder/operations/ReturningOperation.js +12 -18
  97. package/lib/queryBuilder/operations/RunAfterOperation.js +17 -23
  98. package/lib/queryBuilder/operations/RunBeforeOperation.js +17 -23
  99. package/lib/queryBuilder/operations/UnrelateOperation.js +12 -17
  100. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +48 -65
  101. package/lib/queryBuilder/operations/UpdateOperation.js +104 -129
  102. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +25 -35
  103. package/lib/queryBuilder/operations/UpsertGraphOperation.js +36 -55
  104. package/lib/queryBuilder/operations/WhereCompositeOperation.js +30 -39
  105. package/lib/queryBuilder/operations/WhereInOperation.js +34 -36
  106. package/lib/queryBuilder/operations/eager/EagerOperation.js +37 -52
  107. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +34 -44
  108. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +4 -7
  109. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +193 -251
  110. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +18 -25
  111. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +25 -41
  112. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +19 -20
  113. package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +23 -21
  114. package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +106 -118
  115. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +79 -108
  116. package/lib/queryBuilder/operations/select/SelectOperation.js +37 -53
  117. package/lib/queryBuilder/operations/select/Selection.js +94 -105
  118. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +68 -101
  119. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +65 -75
  120. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +75 -84
  121. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +760 -859
  122. package/lib/queryBuilder/parsers/relationExpressionParser.js +840 -952
  123. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +10 -15
  124. package/lib/queryBuilder/transformations/QueryTransformation.js +4 -6
  125. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +35 -49
  126. package/lib/queryBuilder/transformations/index.js +3 -9
  127. package/lib/queryBuilder/whereScopes.js +158 -186
  128. package/lib/relations/Relation.js +279 -363
  129. package/lib/relations/RelationDeleteOperation.js +16 -22
  130. package/lib/relations/RelationFindOperation.js +100 -133
  131. package/lib/relations/RelationInsertOperation.js +19 -27
  132. package/lib/relations/RelationOwner.js +167 -204
  133. package/lib/relations/RelationProperty.js +177 -217
  134. package/lib/relations/RelationUpdateOperation.js +16 -23
  135. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +11 -16
  136. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +24 -35
  137. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +30 -41
  138. package/lib/relations/belongsToOne/BelongsToOneRelation.js +33 -41
  139. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +38 -53
  140. package/lib/relations/hasMany/HasManyInsertOperation.js +35 -51
  141. package/lib/relations/hasMany/HasManyRelateOperation.js +38 -54
  142. package/lib/relations/hasMany/HasManyRelation.js +30 -38
  143. package/lib/relations/hasMany/HasManyUnrelateOperation.js +19 -26
  144. package/lib/relations/hasOne/HasOneRelation.js +4 -7
  145. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +4 -7
  146. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +67 -90
  147. package/lib/relations/manyToMany/ManyToManyRelation.js +349 -451
  148. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +19 -26
  149. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +3 -5
  150. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +14 -20
  151. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +3 -7
  152. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +71 -94
  153. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +31 -43
  154. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +50 -67
  155. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +4 -7
  156. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +20 -27
  157. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +5 -10
  158. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +3 -5
  159. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +55 -72
  160. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +3 -7
  161. package/lib/transaction.js +53 -83
  162. package/lib/utils/assert.js +15 -21
  163. package/lib/utils/buildUtils.js +17 -19
  164. package/lib/utils/classUtils.js +7 -11
  165. package/lib/utils/cloneDeep.js +365 -0
  166. package/lib/utils/createModifier.js +36 -41
  167. package/lib/utils/deprecate.js +8 -12
  168. package/lib/utils/identifierMapping.js +153 -192
  169. package/lib/utils/internalPropUtils.js +4 -8
  170. package/lib/utils/knexUtils.js +61 -56
  171. package/lib/utils/mixin.js +16 -23
  172. package/lib/utils/mysqlJsonPath.js +55 -40
  173. package/lib/utils/normalizeIds.js +110 -127
  174. package/lib/utils/objectUtils.js +236 -338
  175. package/lib/utils/parseFieldExpression.js +66 -44
  176. package/lib/utils/postgresJsonPath.js +48 -62
  177. package/lib/utils/promiseUtils/after.js +10 -13
  178. package/lib/utils/promiseUtils/afterReturn.js +10 -13
  179. package/lib/utils/promiseUtils/index.js +15 -17
  180. package/lib/utils/promiseUtils/isPromise.js +6 -9
  181. package/lib/utils/promiseUtils/map.js +75 -89
  182. package/lib/utils/promiseUtils/mapAfterAllReturn.js +17 -23
  183. package/lib/utils/promiseUtils/try.js +15 -18
  184. package/lib/utils/resolveModel.js +91 -94
  185. package/lib/utils/tmpColumnUtils.js +4 -13
  186. package/package.json +50 -23
  187. package/typings/objection/index.d.mts +362 -0
  188. package/typings/objection/index.d.ts +36 -9
  189. package/lib/.eslintrc.json +0 -8
  190. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +0 -97
  191. package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +0 -141
  192. package/lib/utils/clone.js +0 -2329
@@ -1,5 +1,4 @@
1
1
  'use strict';
2
-
3
2
  const { clone } = require('./modelClone');
4
3
  const { bindKnex } = require('./modelBindKnex');
5
4
  const { validate } = require('./modelValidate');
@@ -14,716 +13,583 @@ const { parseRelationsIntoModelInstances } = require('./modelParseRelations');
14
13
  const { fetchTableMetadata, tableMetadata } = require('./modelTableMetadata');
15
14
  const { asArray, isFunction, isString, asSingle } = require('../utils/objectUtils');
16
15
  const { setJson, setFast, setRelated, appendRelated, setDatabaseJson } = require('./modelSet');
17
- const {
18
- getJsonAttributes,
19
- parseJsonAttributes,
20
- formatJsonAttributes,
21
- } = require('./modelJsonAttributes');
16
+ const { getJsonAttributes, parseJsonAttributes, formatJsonAttributes, } = require('./modelJsonAttributes');
22
17
  const { columnNameToPropertyName, propertyNameToColumnName } = require('./modelColPropMap');
23
-
24
18
  const { raw } = require('../queryBuilder/RawBuilder');
25
19
  const { ref } = require('../queryBuilder/ReferenceBuilder');
26
20
  const { fn } = require('../queryBuilder/FunctionBuilder');
27
-
28
21
  const { AjvValidator } = require('./AjvValidator');
29
22
  const { QueryBuilder } = require('../queryBuilder/QueryBuilder');
23
+ const { markDefaultStaticHook } = require('../queryBuilder/StaticHookArguments');
24
+ const { setDefaultGetConcurrency } = require('./modelConcurrency');
30
25
  const { NotFoundError } = require('./NotFoundError');
31
26
  const { ValidationError } = require('./ValidationError');
32
27
  const { ModifierNotFoundError } = require('./ModifierNotFoundError');
33
28
  const { RelationProperty } = require('../relations/RelationProperty');
34
29
  const { RelationOwner } = require('../relations/RelationOwner');
35
-
36
30
  const { HasOneRelation } = require('../relations/hasOne/HasOneRelation');
37
31
  const { HasManyRelation } = require('../relations/hasMany/HasManyRelation');
38
32
  const { ManyToManyRelation } = require('../relations/manyToMany/ManyToManyRelation');
39
33
  const { BelongsToOneRelation } = require('../relations/belongsToOne/BelongsToOneRelation');
40
34
  const { HasOneThroughRelation } = require('../relations/hasOneThrough/HasOneThroughRelation');
41
-
42
35
  const { InstanceFindOperation } = require('../queryBuilder/operations/InstanceFindOperation');
43
36
  const { InstanceInsertOperation } = require('../queryBuilder/operations/InstanceInsertOperation');
44
37
  const { InstanceUpdateOperation } = require('../queryBuilder/operations/InstanceUpdateOperation');
45
38
  const { InstanceDeleteOperation } = require('../queryBuilder/operations/InstanceDeleteOperation');
46
-
47
39
  class Model {
48
- get $modelClass() {
49
- return this.constructor;
50
- }
51
-
52
- $id(maybeId) {
53
- return getSetId(this, maybeId);
54
- }
55
-
56
- $hasId() {
57
- return hasId(this);
58
- }
59
-
60
- $hasProps(props) {
61
- return hasProps(this, props);
62
- }
63
-
64
- $query(trx) {
65
- return instanceQuery({
66
- instance: this,
67
- transaction: trx,
68
- });
69
- }
70
-
71
- $relatedQuery(relationName, trx) {
72
- return relatedQuery({
73
- modelClass: this.constructor,
74
- relationName,
75
- transaction: trx,
76
- alwaysReturnArray: false,
77
- }).for(this);
78
- }
79
-
80
- $fetchGraph(relationExpression, options) {
81
- return this.constructor.fetchGraph(this, relationExpression, options);
82
- }
83
-
84
- $beforeValidate(jsonSchema, json, options) {
85
- /* istanbul ignore next */
86
- return jsonSchema;
87
- }
88
-
89
- $validate(json, options) {
90
- return validate(this, json, options);
91
- }
92
-
93
- $afterValidate(json, options) {
94
- // Do nothing by default.
95
- }
96
-
97
- $parseDatabaseJson(json) {
98
- const columnNameMappers = this.constructor.getColumnNameMappers();
99
-
100
- if (columnNameMappers) {
101
- json = columnNameMappers.parse(json);
102
- }
103
-
104
- return parseJsonAttributes(json, this.constructor);
105
- }
106
-
107
- $formatDatabaseJson(json) {
108
- const columnNameMappers = this.constructor.getColumnNameMappers();
109
-
110
- json = formatJsonAttributes(json, this.constructor);
111
-
112
- if (columnNameMappers) {
113
- json = columnNameMappers.format(json);
114
- }
115
-
116
- return json;
117
- }
118
-
119
- $parseJson(json, options) {
120
- return json;
121
- }
122
-
123
- $formatJson(json) {
124
- return json;
125
- }
126
-
127
- $setJson(json, options) {
128
- return setJson(this, json, options);
129
- }
130
-
131
- $setDatabaseJson(json) {
132
- return setDatabaseJson(this, json);
133
- }
134
-
135
- $set(obj) {
136
- return setFast(this, obj);
137
- }
138
-
139
- $setRelated(relation, models) {
140
- return setRelated(this, relation, models);
141
- }
142
-
143
- $appendRelated(relation, models) {
144
- return appendRelated(this, relation, models);
145
- }
146
-
147
- $toJson(opt) {
148
- return toJson(this, opt);
149
- }
150
-
151
- toJSON(opt) {
152
- return this.$toJson(opt);
153
- }
154
-
155
- $toDatabaseJson(builder) {
156
- return toDatabaseJson(this, builder);
157
- }
158
-
159
- $beforeInsert(queryContext) {
160
- // Do nothing by default.
161
- }
162
-
163
- $afterInsert(queryContext) {
164
- // Do nothing by default.
165
- }
166
-
167
- $beforeUpdate(opt, queryContext) {
168
- // Do nothing by default.
169
- }
170
-
171
- $afterUpdate(opt, queryContext) {
172
- // Do nothing by default.
173
- }
174
-
175
- $afterFind(queryContext) {
176
- // Do nothing by default.
177
- }
178
-
179
- $beforeDelete(queryContext) {
180
- // Do nothing by default.
181
- }
182
-
183
- $afterDelete(queryContext) {
184
- // Do nothing by default.
185
- }
186
-
187
- $values(props) {
188
- return values(this, props);
189
- }
190
-
191
- $propKey(props) {
192
- return propKey(this, props);
193
- }
194
-
195
- $idKey() {
196
- return this.$propKey(this.constructor.getIdPropertyArray());
197
- }
198
-
199
- $clone(opt) {
200
- return clone(this, !!(opt && opt.shallow), false);
201
- }
202
-
203
- $traverse(filterConstructor, callback) {
204
- if (callback === undefined) {
205
- callback = filterConstructor;
206
- filterConstructor = null;
207
- }
208
-
209
- this.constructor.traverse(filterConstructor, this, callback);
210
- return this;
211
- }
212
-
213
- $traverseAsync(filterConstructor, callback) {
214
- if (callback === undefined) {
215
- callback = filterConstructor;
216
- filterConstructor = null;
217
- }
218
-
219
- return this.constructor.traverseAsync(filterConstructor, this, callback);
220
- }
221
-
222
- $omitFromJson(...props) {
223
- if (arguments.length === 0) {
224
- return this.$$omitFromJson;
225
- } else {
226
- if (!this.hasOwnProperty('$$omitFromJson')) {
227
- defineNonEnumerableProperty(this, '$$omitFromJson', []);
228
- }
229
- this.$$omitFromJson = this.$$omitFromJson.concat(asPropsArray(props));
230
- return this;
231
- }
232
- }
233
-
234
- $omitFromDatabaseJson(...props) {
235
- if (arguments.length === 0) {
236
- return this.$$omitFromDatabaseJson;
237
- } else {
238
- if (!this.hasOwnProperty('$$omitFromDatabaseJson')) {
239
- defineNonEnumerableProperty(this, '$$omitFromDatabaseJson', []);
240
- }
241
- this.$$omitFromDatabaseJson = this.$$omitFromDatabaseJson.concat(asPropsArray(props));
242
- return this;
243
- }
244
- }
245
-
246
- $knex() {
247
- return this.constructor.knex();
248
- }
249
-
250
- $transaction(...args) {
251
- return this.constructor.transaction(...args);
252
- }
253
-
254
- get $ref() {
255
- return this.constructor.ref;
256
- }
257
-
258
- static get objectionModelClass() {
259
- return Model;
260
- }
261
-
262
- static fromJson(json, options) {
263
- const model = new this();
264
- model.$setJson(json || {}, options);
265
- return model;
266
- }
267
-
268
- static fromDatabaseJson(json) {
269
- const model = new this();
270
- model.$setDatabaseJson(json || {});
271
- return model;
272
- }
273
-
274
- static onCreateQuery(builder) {
275
- // Do nothing by default.
276
- }
277
-
278
- static beforeFind(args) {
279
- // Do nothing by default.
280
- }
281
-
282
- static afterFind(args) {
283
- // Do nothing by default.
284
- }
285
-
286
- static beforeInsert(args) {
287
- // Do nothing by default.
288
- }
289
-
290
- static afterInsert(args) {
291
- // Do nothing by default.
292
- }
293
-
294
- static beforeUpdate(args) {
295
- // Do nothing by default.
296
- }
297
-
298
- static afterUpdate(args) {
299
- // Do nothing by default.
300
- }
301
-
302
- static beforeDelete(args) {
303
- // Do nothing by default.
304
- }
305
-
306
- static afterDelete(args) {
307
- // Do nothing by default.
308
- }
309
-
310
- static omitImpl(obj, prop) {
311
- delete obj[prop];
312
- }
313
-
314
- static joinTableAlias(relationPath) {
315
- return `${relationPath}_join`;
316
- }
317
-
318
- static createValidator() {
319
- return new AjvValidator({
320
- options: {
321
- allErrors: true,
322
- validateSchema: false,
323
- ownProperties: true,
324
- v5: true,
325
- },
326
- });
327
- }
328
-
329
- static modifierNotFound(builder, modifier) {
330
- throw new this.ModifierNotFoundError(modifier);
331
- }
332
-
333
- static createNotFoundError(queryContext, props) {
334
- return new this.NotFoundError({ ...props, modelClass: this });
335
- }
336
-
337
- static createValidationError(props) {
338
- return new this.ValidationError({ ...props, modelClass: this });
339
- }
340
-
341
- static getTableName() {
342
- let tableName = this.tableName;
343
-
344
- if (isFunction(tableName)) {
345
- tableName = this.tableName();
346
- }
347
-
348
- if (!isString(tableName)) {
349
- throw new Error(`Model ${this.name} must have a static property tableName`);
350
- }
351
-
352
- return tableName;
353
- }
354
-
355
- static getIdColumn() {
356
- let idColumn = this.idColumn;
357
-
358
- if (isFunction(idColumn)) {
359
- idColumn = this.idColumn();
360
- }
361
-
362
- return idColumn;
363
- }
364
-
365
- static getValidator() {
366
- return cachedGet(this, '$$validator', getValidator);
367
- }
368
-
369
- static getJsonSchema() {
370
- return cachedGet(this, '$$jsonSchema', getJsonSchema);
371
- }
372
-
373
- static getJsonAttributes() {
374
- return cachedGet(this, '$$jsonAttributes', getJsonAttributes);
375
- }
376
-
377
- static getColumnNameMappers() {
378
- return cachedGet(this, '$$columnNameMappers', getColumnNameMappers);
379
- }
380
-
381
- static getConcurrency(knex) {
382
- const DEFAULT_CONCURRENCY = 4;
383
-
384
- if (this.concurrency === null) {
385
- if (!knex) {
386
- return DEFAULT_CONCURRENCY;
387
- }
388
-
389
- // The mssql driver is shit, and we cannot have concurrent queries.
390
- // On MySQL, concurrent graph updates and deletes deadlock: MySQL needs
391
- // them wrapped in a subquery, which locks the rows of the join tables
392
- // it reads.
393
- if (isMsSql(knex) || isMySql(knex)) {
394
- return 1;
395
- } else {
396
- return DEFAULT_CONCURRENCY;
397
- }
398
- } else {
399
- if (isFunction(this.concurrency)) {
400
- return this.concurrency();
401
- } else {
402
- return this.concurrency;
403
- }
404
- }
405
- }
406
-
407
- static getModifiers() {
408
- return this.modifiers || {};
409
- }
410
-
411
- static columnNameToPropertyName(columnName) {
412
- let colToProp = cachedGet(this, '$$colToProp', () => new Map());
413
- let propertyName = colToProp.get(columnName);
414
-
415
- if (!propertyName) {
416
- propertyName = columnNameToPropertyName(this, columnName);
417
- colToProp.set(columnName, propertyName);
418
- }
419
-
420
- return propertyName;
421
- }
422
-
423
- static propertyNameToColumnName(propertyName) {
424
- let propToCol = cachedGet(this, '$$propToCol', () => new Map());
425
- let columnName = propToCol.get(propertyName);
426
-
427
- if (!columnName) {
428
- columnName = propertyNameToColumnName(this, propertyName);
429
- propToCol.set(propertyName, columnName);
430
- }
431
-
432
- return columnName;
433
- }
434
-
435
- static getReadOnlyAttributes() {
436
- return cachedGet(this, '$$readOnlyAttributes', getReadOnlyAttributes);
437
- }
438
-
439
- static getIdRelationProperty() {
440
- return cachedGet(this, '$$idRelationProperty', getIdRelationProperty);
441
- }
442
-
443
- static getIdColumnArray() {
444
- return this.getIdRelationProperty().cols;
445
- }
446
-
447
- static getIdPropertyArray() {
448
- return this.getIdRelationProperty().props;
449
- }
450
-
451
- static getIdProperty() {
452
- const idProps = this.getIdPropertyArray();
453
-
454
- if (idProps.length === 1) {
455
- return idProps[0];
456
- } else {
457
- return idProps;
458
- }
459
- }
460
-
461
- static getRelationMappings() {
462
- return cachedGet(this, '$$relationMappings', getRelationMappings);
463
- }
464
-
465
- static getRelations() {
466
- const relations = Object.create(null);
467
-
468
- for (const relationName of this.getRelationNames()) {
469
- relations[relationName] = this.getRelation(relationName);
470
- }
471
-
472
- return relations;
473
- }
474
-
475
- static getRelationNames() {
476
- return cachedGet(this, '$$relationNames', getRelationNames);
477
- }
478
-
479
- static getVirtualAttributes() {
480
- return cachedGet(this, '$$virtualAttributes', getVirtualAttributes);
481
- }
482
-
483
- static getDefaultGraphOptions() {
484
- return this.defaultGraphOptions;
485
- }
486
-
487
- static getRelatedFindQueryMutates() {
488
- return this.relatedFindQueryMutates;
489
- }
490
-
491
- static getRelatedInsertQueryMutates() {
492
- return this.relatedInsertQueryMutates;
493
- }
494
-
495
- static query(trx) {
496
- const query = this.QueryBuilder.forClass(this).transacting(trx);
497
- this.onCreateQuery(query);
498
- return query;
499
- }
500
-
501
- static relatedQuery(relationName, trx) {
502
- return relatedQuery({
503
- modelClass: this,
504
- relationName,
505
- transaction: trx,
506
- alwaysReturnArray: true,
507
- });
508
- }
509
-
510
- static fetchTableMetadata(opt) {
511
- return fetchTableMetadata(this, opt);
512
- }
513
-
514
- static tableMetadata(opt) {
515
- return tableMetadata(this, opt);
516
- }
517
-
518
- static knex(...args) {
519
- if (args.length) {
520
- defineNonEnumerableProperty(this, '$$knex', args[0]);
521
- } else {
522
- return this.$$knex;
523
- }
524
- }
525
-
526
- static transaction(knexOrTrx, cb) {
527
- if (!cb) {
528
- cb = knexOrTrx;
529
- knexOrTrx = null;
530
- }
531
-
532
- return (knexOrTrx || this.knex()).transaction(cb);
533
- }
534
-
535
- static startTransaction(knexOrTrx) {
536
- const { transaction } = require('../transaction');
537
- return transaction.start(knexOrTrx || this.knex());
538
- }
539
-
540
- static get raw() {
541
- return raw;
542
- }
543
-
544
- static get ref() {
545
- return (...args) => {
546
- return ref(...args).model(this);
547
- };
548
- }
549
-
550
- static get fn() {
551
- return fn;
552
- }
553
-
554
- static knexQuery() {
555
- return this.knex().table(this.getTableName());
556
- }
557
-
558
- static uniqueTag() {
559
- if (this.name) {
560
- return `${this.getTableName()}_${this.name}`;
561
- } else {
562
- return this.getTableName();
563
- }
564
- }
565
-
566
- static bindKnex(knex) {
567
- return bindKnex(this, knex);
568
- }
569
-
570
- static bindTransaction(trx) {
571
- return bindKnex(this, trx);
572
- }
573
-
574
- static ensureModel(model, options) {
575
- const modelClass = this;
576
-
577
- if (!model) {
578
- return null;
579
- }
580
-
581
- if (model instanceof modelClass) {
582
- return parseRelationsIntoModelInstances(model, model, options);
583
- } else {
584
- return modelClass.fromJson(model, options);
585
- }
586
- }
587
-
588
- static ensureModelArray(input, options) {
589
- if (!input) {
590
- return [];
591
- }
592
-
593
- if (Array.isArray(input)) {
594
- const models = new Array(input.length);
595
-
596
- for (let i = 0, l = input.length; i < l; ++i) {
597
- models[i] = this.ensureModel(input[i], options);
598
- }
599
-
600
- return models;
601
- } else {
602
- return [this.ensureModel(input, options)];
603
- }
604
- }
605
-
606
- static getRelationUnsafe(name) {
607
- const mapping = this.getRelationMappings()[name];
608
-
609
- if (!mapping) {
610
- return null;
611
- }
612
-
613
- if (!this.hasOwnProperty('$$relations')) {
614
- defineNonEnumerableProperty(this, '$$relations', Object.create(null));
615
- }
616
-
617
- if (!this.$$relations[name]) {
618
- this.$$relations[name] = new mapping.relation(name, this);
619
- this.$$relations[name].setMapping(mapping);
620
- }
621
-
622
- return this.$$relations[name];
623
- }
624
-
625
- static getRelation(name) {
626
- const relation = this.getRelationUnsafe(name);
627
-
628
- if (!relation) {
629
- throw new Error(`A model class ${this.name} doesn't have relation ${name}`);
630
- }
631
-
632
- return relation;
633
- }
634
-
635
- static fetchGraph($models, expression, options = {}) {
636
- return this.query(options.transaction)
637
- .resolve(this.ensureModelArray($models))
638
- .findOptions({ dontCallFindHooks: true })
639
- .withGraphFetched(expression, options)
640
- .runAfter((models) => (Array.isArray($models) ? models : models[0]));
641
- }
642
-
643
- static traverse(...args) {
644
- const { traverser, models, filterConstructor } = getTraverseArgs(...args);
645
-
646
- if (!asSingle(models)) {
647
- return;
648
- }
649
-
650
- const modelClass = asSingle(models).constructor;
651
-
652
- visitModels(models, modelClass, (model, _, parent, relation) => {
653
- if (!filterConstructor || model instanceof filterConstructor) {
654
- traverser(model, parent, relation && relation.name);
655
- }
656
- });
657
-
658
- return this;
659
- }
660
-
661
- static traverseAsync(...args) {
662
- const { traverser, models, filterConstructor } = getTraverseArgs(...args);
663
-
664
- if (!asSingle(models)) {
665
- return Promise.resolve();
666
- }
667
-
668
- const modelClass = asSingle(models).constructor;
669
- const promises = [];
670
-
671
- visitModels(models, modelClass, (model, _, parent, relation) => {
672
- if (!filterConstructor || model instanceof filterConstructor) {
673
- const maybePromise = traverser(model, parent, relation && relation.name);
674
- promises.push(maybePromise);
675
- }
676
- });
677
-
678
- return promiseMap(promises, (it) => it, { concurrency: this.getConcurrency(this.knex()) });
679
- }
40
+ get $modelClass() {
41
+ return this.constructor;
42
+ }
43
+ $id(maybeId) {
44
+ return getSetId(this, maybeId);
45
+ }
46
+ $hasId() {
47
+ return hasId(this);
48
+ }
49
+ $hasProps(props) {
50
+ return hasProps(this, props);
51
+ }
52
+ $query(trx) {
53
+ return instanceQuery({
54
+ instance: this,
55
+ transaction: trx,
56
+ });
57
+ }
58
+ $relatedQuery(relationName, trx) {
59
+ return relatedQuery({
60
+ modelClass: this.constructor,
61
+ relationName,
62
+ transaction: trx,
63
+ alwaysReturnArray: false,
64
+ }).for(this);
65
+ }
66
+ $fetchGraph(relationExpression, options) {
67
+ return this.constructor.fetchGraph(this, relationExpression, options);
68
+ }
69
+ $beforeValidate(jsonSchema, json, options) {
70
+ /* istanbul ignore next */
71
+ return jsonSchema;
72
+ }
73
+ $validate(json, options) {
74
+ return validate(this, json, options);
75
+ }
76
+ $afterValidate(json, options) {
77
+ // Do nothing by default.
78
+ }
79
+ $parseDatabaseJson(json) {
80
+ const columnNameMappers = this.constructor.getColumnNameMappers();
81
+ if (columnNameMappers) {
82
+ json = columnNameMappers.parse(json);
83
+ }
84
+ return parseJsonAttributes(json, this.constructor);
85
+ }
86
+ $formatDatabaseJson(json) {
87
+ const columnNameMappers = this.constructor.getColumnNameMappers();
88
+ json = formatJsonAttributes(json, this.constructor);
89
+ if (columnNameMappers) {
90
+ json = columnNameMappers.format(json);
91
+ }
92
+ return json;
93
+ }
94
+ $parseJson(json, options) {
95
+ return json;
96
+ }
97
+ $formatJson(json) {
98
+ return json;
99
+ }
100
+ $setJson(json, options) {
101
+ return setJson(this, json, options);
102
+ }
103
+ $setDatabaseJson(json) {
104
+ return setDatabaseJson(this, json);
105
+ }
106
+ $set(obj) {
107
+ return setFast(this, obj);
108
+ }
109
+ $setRelated(relation, models) {
110
+ return setRelated(this, relation, models);
111
+ }
112
+ $appendRelated(relation, models) {
113
+ return appendRelated(this, relation, models);
114
+ }
115
+ $toJson(opt) {
116
+ return toJson(this, opt);
117
+ }
118
+ toJSON(opt) {
119
+ return this.$toJson(opt);
120
+ }
121
+ $toDatabaseJson(builder) {
122
+ return toDatabaseJson(this, builder);
123
+ }
124
+ $beforeInsert(queryContext) {
125
+ // Do nothing by default.
126
+ }
127
+ $afterInsert(queryContext) {
128
+ // Do nothing by default.
129
+ }
130
+ $beforeUpdate(opt, queryContext) {
131
+ // Do nothing by default.
132
+ }
133
+ $afterUpdate(opt, queryContext) {
134
+ // Do nothing by default.
135
+ }
136
+ $afterFind(queryContext) {
137
+ // Do nothing by default.
138
+ }
139
+ $beforeDelete(queryContext) {
140
+ // Do nothing by default.
141
+ }
142
+ $afterDelete(queryContext) {
143
+ // Do nothing by default.
144
+ }
145
+ $values(props) {
146
+ return values(this, props);
147
+ }
148
+ $propKey(props) {
149
+ return propKey(this, props);
150
+ }
151
+ $idKey() {
152
+ return this.$propKey(this.constructor.getIdPropertyArray());
153
+ }
154
+ $clone(opt) {
155
+ return clone(this, !!(opt && opt.shallow), false);
156
+ }
157
+ $traverse(filterConstructor, callback) {
158
+ if (callback === undefined) {
159
+ callback = filterConstructor;
160
+ filterConstructor = null;
161
+ }
162
+ this.constructor.traverse(filterConstructor, this, callback);
163
+ return this;
164
+ }
165
+ $traverseAsync(filterConstructor, callback) {
166
+ if (callback === undefined) {
167
+ callback = filterConstructor;
168
+ filterConstructor = null;
169
+ }
170
+ return this.constructor.traverseAsync(filterConstructor, this, callback);
171
+ }
172
+ $omitFromJson(...props) {
173
+ if (arguments.length === 0) {
174
+ return this.$$omitFromJson;
175
+ }
176
+ else {
177
+ if (!Object.hasOwn(this, '$$omitFromJson')) {
178
+ defineNonEnumerableProperty(this, '$$omitFromJson', []);
179
+ }
180
+ this.$$omitFromJson = this.$$omitFromJson.concat(asPropsArray(props));
181
+ return this;
182
+ }
183
+ }
184
+ $omitFromDatabaseJson(...props) {
185
+ if (arguments.length === 0) {
186
+ return this.$$omitFromDatabaseJson;
187
+ }
188
+ else {
189
+ if (!Object.hasOwn(this, '$$omitFromDatabaseJson')) {
190
+ defineNonEnumerableProperty(this, '$$omitFromDatabaseJson', []);
191
+ }
192
+ this.$$omitFromDatabaseJson = this.$$omitFromDatabaseJson.concat(asPropsArray(props));
193
+ return this;
194
+ }
195
+ }
196
+ $knex() {
197
+ return this.constructor.knex();
198
+ }
199
+ $transaction(...args) {
200
+ return this.constructor.transaction(...args);
201
+ }
202
+ get $ref() {
203
+ return this.constructor.ref;
204
+ }
205
+ static get objectionModelClass() {
206
+ return Model;
207
+ }
208
+ static fromJson(json, options) {
209
+ const model = new this();
210
+ model.$setJson(json || {}, options);
211
+ return model;
212
+ }
213
+ static fromDatabaseJson(json) {
214
+ const model = new this();
215
+ model.$setDatabaseJson(json || {});
216
+ return model;
217
+ }
218
+ static onCreateQuery(builder) {
219
+ // Do nothing by default.
220
+ }
221
+ static beforeFind(args) {
222
+ // Do nothing by default.
223
+ }
224
+ static afterFind(args) {
225
+ // Do nothing by default.
226
+ }
227
+ static beforeInsert(args) {
228
+ // Do nothing by default.
229
+ }
230
+ static afterInsert(args) {
231
+ // Do nothing by default.
232
+ }
233
+ static beforeUpdate(args) {
234
+ // Do nothing by default.
235
+ }
236
+ static afterUpdate(args) {
237
+ // Do nothing by default.
238
+ }
239
+ static beforeDelete(args) {
240
+ // Do nothing by default.
241
+ }
242
+ static afterDelete(args) {
243
+ // Do nothing by default.
244
+ }
245
+ static omitImpl(obj, prop) {
246
+ delete obj[prop];
247
+ }
248
+ static joinTableAlias(relationPath) {
249
+ return `${relationPath}_join`;
250
+ }
251
+ static createValidator() {
252
+ return new AjvValidator({
253
+ options: {
254
+ allErrors: true,
255
+ validateSchema: false,
256
+ ownProperties: true,
257
+ v5: true,
258
+ },
259
+ });
260
+ }
261
+ static modifierNotFound(builder, modifier) {
262
+ throw new this.ModifierNotFoundError(modifier);
263
+ }
264
+ static createNotFoundError(queryContext, props) {
265
+ return new this.NotFoundError({ ...props, modelClass: this });
266
+ }
267
+ static createValidationError(props) {
268
+ return new this.ValidationError({ ...props, modelClass: this });
269
+ }
270
+ static getTableName() {
271
+ let tableName = this.tableName;
272
+ if (isFunction(tableName)) {
273
+ tableName = this.tableName();
274
+ }
275
+ if (!isString(tableName)) {
276
+ throw new Error(`Model ${this.name} must have a static property tableName`);
277
+ }
278
+ return tableName;
279
+ }
280
+ static getIdColumn() {
281
+ let idColumn = this.idColumn;
282
+ if (isFunction(idColumn)) {
283
+ idColumn = this.idColumn();
284
+ }
285
+ return idColumn;
286
+ }
287
+ static getValidator() {
288
+ return cachedGet(this, '$$validator', getValidator);
289
+ }
290
+ static getJsonSchema() {
291
+ return cachedGet(this, '$$jsonSchema', getJsonSchema);
292
+ }
293
+ static getJsonAttributes() {
294
+ return cachedGet(this, '$$jsonAttributes', getJsonAttributes);
295
+ }
296
+ static getColumnNameMappers() {
297
+ return cachedGet(this, '$$columnNameMappers', getColumnNameMappers);
298
+ }
299
+ static getConcurrency(knex) {
300
+ const DEFAULT_CONCURRENCY = 4;
301
+ if (this.concurrency === null) {
302
+ if (!knex) {
303
+ return DEFAULT_CONCURRENCY;
304
+ }
305
+ // The mssql driver is shit, and we cannot have concurrent queries.
306
+ // On MySQL, concurrent graph updates and deletes deadlock: MySQL needs
307
+ // them wrapped in a subquery, which locks the rows of the join tables
308
+ // it reads.
309
+ if (isMsSql(knex) || isMySql(knex)) {
310
+ return 1;
311
+ }
312
+ else {
313
+ return DEFAULT_CONCURRENCY;
314
+ }
315
+ }
316
+ else {
317
+ if (isFunction(this.concurrency)) {
318
+ return this.concurrency();
319
+ }
320
+ else {
321
+ return this.concurrency;
322
+ }
323
+ }
324
+ }
325
+ static getModifiers() {
326
+ return this.modifiers || {};
327
+ }
328
+ static columnNameToPropertyName(columnName) {
329
+ const colToProp = cachedGet(this, '$$colToProp', () => new Map());
330
+ let propertyName = colToProp.get(columnName);
331
+ if (!propertyName) {
332
+ propertyName = columnNameToPropertyName(this, columnName);
333
+ colToProp.set(columnName, propertyName);
334
+ }
335
+ return propertyName;
336
+ }
337
+ static propertyNameToColumnName(propertyName) {
338
+ const propToCol = cachedGet(this, '$$propToCol', () => new Map());
339
+ let columnName = propToCol.get(propertyName);
340
+ if (!columnName) {
341
+ columnName = propertyNameToColumnName(this, propertyName);
342
+ propToCol.set(propertyName, columnName);
343
+ }
344
+ return columnName;
345
+ }
346
+ static getReadOnlyAttributes() {
347
+ return cachedGet(this, '$$readOnlyAttributes', getReadOnlyAttributes);
348
+ }
349
+ static getIdRelationProperty() {
350
+ return cachedGet(this, '$$idRelationProperty', getIdRelationProperty);
351
+ }
352
+ static getIdColumnArray() {
353
+ return this.getIdRelationProperty().cols;
354
+ }
355
+ static getIdPropertyArray() {
356
+ return this.getIdRelationProperty().props;
357
+ }
358
+ static getIdProperty() {
359
+ const idProps = this.getIdPropertyArray();
360
+ if (idProps.length === 1) {
361
+ return idProps[0];
362
+ }
363
+ else {
364
+ return idProps;
365
+ }
366
+ }
367
+ static getRelationMappings() {
368
+ return cachedGet(this, '$$relationMappings', getRelationMappings);
369
+ }
370
+ static getRelations() {
371
+ const relations = Object.create(null);
372
+ for (const relationName of this.getRelationNames()) {
373
+ relations[relationName] = this.getRelation(relationName);
374
+ }
375
+ return relations;
376
+ }
377
+ static getRelationNames() {
378
+ return cachedGet(this, '$$relationNames', getRelationNames);
379
+ }
380
+ static getVirtualAttributes() {
381
+ return cachedGet(this, '$$virtualAttributes', getVirtualAttributes);
382
+ }
383
+ static getDefaultGraphOptions() {
384
+ return this.defaultGraphOptions;
385
+ }
386
+ static getRelatedFindQueryMutates() {
387
+ return this.relatedFindQueryMutates;
388
+ }
389
+ static getRelatedInsertQueryMutates() {
390
+ return this.relatedInsertQueryMutates;
391
+ }
392
+ static query(trx) {
393
+ const query = this.QueryBuilder.forClass(this).transacting(trx);
394
+ this.onCreateQuery(query);
395
+ return query;
396
+ }
397
+ static relatedQuery(relationName, trx) {
398
+ return relatedQuery({
399
+ modelClass: this,
400
+ relationName,
401
+ transaction: trx,
402
+ alwaysReturnArray: true,
403
+ });
404
+ }
405
+ static fetchTableMetadata(opt) {
406
+ return fetchTableMetadata(this, opt);
407
+ }
408
+ static tableMetadata(opt) {
409
+ return tableMetadata(this, opt);
410
+ }
411
+ static knex(...args) {
412
+ if (args.length) {
413
+ defineNonEnumerableProperty(this, '$$knex', args[0]);
414
+ }
415
+ else {
416
+ return this.$$knex;
417
+ }
418
+ }
419
+ static transaction(knexOrTrx, cb) {
420
+ if (!cb) {
421
+ cb = knexOrTrx;
422
+ knexOrTrx = null;
423
+ }
424
+ return (knexOrTrx || this.knex()).transaction(cb);
425
+ }
426
+ static startTransaction(knexOrTrx) {
427
+ const { transaction } = require('../transaction');
428
+ return transaction.start(knexOrTrx || this.knex());
429
+ }
430
+ static get raw() {
431
+ return raw;
432
+ }
433
+ static get ref() {
434
+ return (...args) => {
435
+ return ref(...args).model(this);
436
+ };
437
+ }
438
+ static get fn() {
439
+ return fn;
440
+ }
441
+ static knexQuery() {
442
+ return this.knex().table(this.getTableName());
443
+ }
444
+ static uniqueTag() {
445
+ if (this.name) {
446
+ return `${this.getTableName()}_${this.name}`;
447
+ }
448
+ else {
449
+ return this.getTableName();
450
+ }
451
+ }
452
+ static bindKnex(knex) {
453
+ return bindKnex(this, knex);
454
+ }
455
+ static bindTransaction(trx) {
456
+ return bindKnex(this, trx);
457
+ }
458
+ static ensureModel(model, options) {
459
+ const modelClass = this;
460
+ if (!model) {
461
+ return null;
462
+ }
463
+ if (model instanceof modelClass) {
464
+ return parseRelationsIntoModelInstances(model, model, options);
465
+ }
466
+ else {
467
+ return modelClass.fromJson(model, options);
468
+ }
469
+ }
470
+ static ensureModelArray(input, options) {
471
+ if (!input) {
472
+ return [];
473
+ }
474
+ if (Array.isArray(input)) {
475
+ const models = new Array(input.length);
476
+ for (let i = 0, l = input.length; i < l; ++i) {
477
+ models[i] = this.ensureModel(input[i], options);
478
+ }
479
+ return models;
480
+ }
481
+ else {
482
+ return [this.ensureModel(input, options)];
483
+ }
484
+ }
485
+ static getRelationUnsafe(name) {
486
+ const mapping = this.getRelationMappings()[name];
487
+ if (!mapping) {
488
+ return null;
489
+ }
490
+ if (!Object.hasOwn(this, '$$relations')) {
491
+ defineNonEnumerableProperty(this, '$$relations', Object.create(null));
492
+ }
493
+ if (!this.$$relations[name]) {
494
+ this.$$relations[name] = new mapping.relation(name, this);
495
+ this.$$relations[name].setMapping(mapping);
496
+ }
497
+ return this.$$relations[name];
498
+ }
499
+ static getRelation(name) {
500
+ const relation = this.getRelationUnsafe(name);
501
+ if (!relation) {
502
+ throw new Error(`A model class ${this.name} doesn't have relation ${name}`);
503
+ }
504
+ return relation;
505
+ }
506
+ static fetchGraph($models, expression, options = {}) {
507
+ return this.query(options.transaction)
508
+ .resolve(this.ensureModelArray($models))
509
+ .findOptions({ dontCallFindHooks: true })
510
+ .withGraphFetched(expression, options)
511
+ .runAfter((models) => (Array.isArray($models) ? models : models[0]));
512
+ }
513
+ static traverse(...args) {
514
+ const { traverser, models, filterConstructor } = getTraverseArgs(...args);
515
+ if (!asSingle(models)) {
516
+ return;
517
+ }
518
+ const modelClass = asSingle(models).constructor;
519
+ visitModels(models, modelClass, (model, _, parent, relation) => {
520
+ if (!filterConstructor || model instanceof filterConstructor) {
521
+ traverser(model, parent, relation && relation.name);
522
+ }
523
+ });
524
+ return this;
525
+ }
526
+ static traverseAsync(...args) {
527
+ const { traverser, models, filterConstructor } = getTraverseArgs(...args);
528
+ if (!asSingle(models)) {
529
+ return Promise.resolve();
530
+ }
531
+ const modelClass = asSingle(models).constructor;
532
+ const promises = [];
533
+ visitModels(models, modelClass, (model, _, parent, relation) => {
534
+ if (!filterConstructor || model instanceof filterConstructor) {
535
+ const maybePromise = traverser(model, parent, relation && relation.name);
536
+ promises.push(maybePromise);
537
+ }
538
+ });
539
+ return promiseMap(promises, (it) => it, { concurrency: this.getConcurrency(this.knex()) });
540
+ }
680
541
  }
681
-
682
542
  Object.defineProperties(Model, {
683
- isObjectionModelClass: {
684
- enumerable: false,
685
- writable: false,
686
- value: true,
687
- },
543
+ isObjectionModelClass: {
544
+ enumerable: false,
545
+ writable: false,
546
+ value: true,
547
+ },
688
548
  });
689
-
690
549
  Object.defineProperties(Model.prototype, {
691
- $isObjectionModel: {
692
- enumerable: false,
693
- writable: false,
694
- value: true,
695
- },
696
-
697
- $objectionModelClass: {
698
- enumerable: false,
699
- writable: false,
700
- value: Model,
701
- },
550
+ $isObjectionModel: {
551
+ enumerable: false,
552
+ writable: false,
553
+ value: true,
554
+ },
555
+ $objectionModelClass: {
556
+ enumerable: false,
557
+ writable: false,
558
+ value: Model,
559
+ },
702
560
  });
703
-
561
+ for (const hookName of [
562
+ 'beforeFind',
563
+ 'afterFind',
564
+ 'beforeInsert',
565
+ 'afterInsert',
566
+ 'beforeUpdate',
567
+ 'afterUpdate',
568
+ 'beforeDelete',
569
+ 'afterDelete',
570
+ ]) {
571
+ markDefaultStaticHook(Model[hookName]);
572
+ }
573
+ setDefaultGetConcurrency(Model.getConcurrency);
704
574
  Model.QueryBuilder = QueryBuilder;
705
-
706
575
  Model.HasOneRelation = HasOneRelation;
707
576
  Model.HasManyRelation = HasManyRelation;
708
577
  Model.ManyToManyRelation = ManyToManyRelation;
709
578
  Model.BelongsToOneRelation = BelongsToOneRelation;
710
579
  Model.HasOneThroughRelation = HasOneThroughRelation;
711
-
712
580
  Model.JoinEagerAlgorithm = 'JoinEagerAlgorithm';
713
581
  Model.NaiveEagerAlgorithm = 'NaiveEagerAlgorithm';
714
582
  Model.WhereInEagerAlgorithm = 'WhereInEagerAlgorithm';
715
-
716
583
  Model.ValidationError = ValidationError;
717
584
  Model.NotFoundError = NotFoundError;
718
585
  Model.ModifierNotFoundError = ModifierNotFoundError;
719
-
720
586
  Model.tableName = null;
721
587
  Model.jsonSchema = null;
722
588
  Model.idColumn = 'id';
723
589
  Model.uidProp = '#id';
724
590
  Model.uidRefProp = '#ref';
725
591
  Model.dbRefProp = '#dbRef';
726
- Model.propRefRegex = /#ref{([^\.]+)\.([^}]+)}/g;
592
+ Model.propRefRegex = /#ref{([^.]+)\.([^}]+)}/g;
727
593
  Model.jsonAttributes = null;
728
594
  Model.cloneObjectAttributes = true;
729
595
  Model.virtualAttributes = null;
@@ -738,205 +604,169 @@ Model.columnNameMappers = null;
738
604
  Model.relatedFindQueryMutates = false;
739
605
  Model.relatedInsertQueryMutates = false;
740
606
  Model.concurrency = null;
741
-
742
607
  function instanceQuery({ instance, transaction }) {
743
- const modelClass = instance.constructor;
744
-
745
- return modelClass
746
- .query(transaction)
747
- .findOperationFactory(() => {
748
- return new InstanceFindOperation('find', { instance });
608
+ const modelClass = instance.constructor;
609
+ return modelClass
610
+ .query(transaction)
611
+ .findOperationFactory(() => {
612
+ return new InstanceFindOperation('find', { instance });
749
613
  })
750
- .insertOperationFactory(() => {
751
- return new InstanceInsertOperation('insert', { instance });
614
+ .insertOperationFactory(() => {
615
+ return new InstanceInsertOperation('insert', { instance });
752
616
  })
753
- .updateOperationFactory(() => {
754
- return new InstanceUpdateOperation('update', { instance });
617
+ .updateOperationFactory(() => {
618
+ return new InstanceUpdateOperation('update', { instance });
755
619
  })
756
- .patchOperationFactory(() => {
757
- return new InstanceUpdateOperation('patch', {
758
- instance,
759
- modelOptions: { patch: true },
760
- });
620
+ .patchOperationFactory(() => {
621
+ return new InstanceUpdateOperation('patch', {
622
+ instance,
623
+ modelOptions: { patch: true },
624
+ });
761
625
  })
762
- .deleteOperationFactory(() => {
763
- return new InstanceDeleteOperation('delete', { instance });
626
+ .deleteOperationFactory(() => {
627
+ return new InstanceDeleteOperation('delete', { instance });
764
628
  })
765
- .relateOperationFactory(() => {
766
- throw new Error('`relate` makes no sense in this context');
629
+ .relateOperationFactory(() => {
630
+ throw new Error('`relate` makes no sense in this context');
767
631
  })
768
- .unrelateOperationFactory(() => {
769
- throw new Error('`unrelate` makes no sense in this context');
632
+ .unrelateOperationFactory(() => {
633
+ throw new Error('`unrelate` makes no sense in this context');
770
634
  });
771
635
  }
772
-
773
636
  function relatedQuery({ modelClass, relationName, transaction, alwaysReturnArray } = {}) {
774
- const relation = modelClass.getRelation(relationName);
775
- const relatedModelClass = relation.relatedModelClass;
776
-
777
- const query = relatedModelClass
778
- .query(transaction)
779
- .findOperationFactory((builder) => {
780
- const isSubQuery = !builder.for();
781
- const owner = isSubQuery
782
- ? RelationOwner.createParentReference(builder, relation)
783
- : RelationOwner.create(builder.for());
784
-
785
- const operation = relation.find(builder, owner);
786
-
787
- operation.assignResultToOwner = modelClass.getRelatedFindQueryMutates();
788
- operation.alwaysReturnArray = alwaysReturnArray;
789
- operation.alias = isSubQuery ? relation.name : null;
790
-
791
- return operation;
637
+ const relation = modelClass.getRelation(relationName);
638
+ const relatedModelClass = relation.relatedModelClass;
639
+ const query = relatedModelClass
640
+ .query(transaction)
641
+ .findOperationFactory((builder) => {
642
+ const isSubQuery = !builder.for();
643
+ const owner = isSubQuery
644
+ ? RelationOwner.createParentReference(builder, relation)
645
+ : RelationOwner.create(builder.for());
646
+ const operation = relation.find(builder, owner);
647
+ operation.assignResultToOwner = modelClass.getRelatedFindQueryMutates();
648
+ operation.alwaysReturnArray = alwaysReturnArray;
649
+ operation.alias = isSubQuery ? relation.name : null;
650
+ return operation;
792
651
  })
793
- .insertOperationFactory((builder) => {
794
- const owner = writeOperationOwner(builder, 'insert');
795
- const operation = relation.insert(builder, owner);
796
-
797
- operation.assignResultToOwner = modelClass.getRelatedInsertQueryMutates();
798
- return operation;
652
+ .insertOperationFactory((builder) => {
653
+ const owner = writeOperationOwner(builder, 'insert');
654
+ const operation = relation.insert(builder, owner);
655
+ operation.assignResultToOwner = modelClass.getRelatedInsertQueryMutates();
656
+ return operation;
799
657
  })
800
- .updateOperationFactory((builder) => {
801
- const owner = writeOperationOwner(builder, 'update');
802
- return relation.update(builder, owner);
658
+ .updateOperationFactory((builder) => {
659
+ const owner = writeOperationOwner(builder, 'update');
660
+ return relation.update(builder, owner);
803
661
  })
804
- .patchOperationFactory((builder) => {
805
- const owner = writeOperationOwner(builder, 'patch');
806
- return relation.patch(builder, owner);
662
+ .patchOperationFactory((builder) => {
663
+ const owner = writeOperationOwner(builder, 'patch');
664
+ return relation.patch(builder, owner);
807
665
  })
808
- .deleteOperationFactory((builder) => {
809
- const owner = writeOperationOwner(builder, 'delete');
810
- return relation.delete(builder, owner);
666
+ .deleteOperationFactory((builder) => {
667
+ const owner = writeOperationOwner(builder, 'delete');
668
+ return relation.delete(builder, owner);
811
669
  })
812
- .relateOperationFactory((builder) => {
813
- const owner = writeOperationOwner(builder, 'relate');
814
- return relation.relate(builder, owner);
670
+ .relateOperationFactory((builder) => {
671
+ const owner = writeOperationOwner(builder, 'relate');
672
+ return relation.relate(builder, owner);
815
673
  })
816
- .unrelateOperationFactory((builder) => {
817
- const owner = writeOperationOwner(builder, 'unrelate');
818
- return relation.unrelate(builder, owner);
674
+ .unrelateOperationFactory((builder) => {
675
+ const owner = writeOperationOwner(builder, 'unrelate');
676
+ return relation.unrelate(builder, owner);
819
677
  });
820
-
821
- query._isRelatedQuery = true;
822
- return query;
678
+ query._isRelatedQuery = true;
679
+ return query;
823
680
  }
824
-
825
681
  function writeOperationOwner(builder, method) {
826
- const owner = builder.for();
827
-
828
- if ((owner === null || owner === undefined) && builder._forError === null) {
829
- // Without an owner the write would silently do nothing or, in the case
830
- // of inserts, create rows with null foreign keys. The error is thrown
831
- // when the query is built or executed.
832
- builder._forError = new Error(`relatedQuery(): for() must be called before ${method}()`);
833
- }
834
-
835
- return RelationOwner.create(owner);
682
+ const owner = builder.for();
683
+ if ((owner === null || owner === undefined) && builder._forError === null) {
684
+ // Without an owner the write would silently do nothing or, in the case
685
+ // of inserts, create rows with null foreign keys. The error is thrown
686
+ // when the query is built or executed.
687
+ builder._forError = new Error(`relatedQuery(): for() must be called before ${method}()`);
688
+ }
689
+ return RelationOwner.create(owner);
836
690
  }
837
-
838
691
  function cachedGet(target, hiddenPropertyName, creator) {
839
- if (!target.hasOwnProperty(hiddenPropertyName)) {
840
- defineNonEnumerableProperty(target, hiddenPropertyName, creator(target));
841
- }
842
-
843
- return target[hiddenPropertyName];
692
+ if (!Object.hasOwn(target, hiddenPropertyName)) {
693
+ defineNonEnumerableProperty(target, hiddenPropertyName, creator(target));
694
+ }
695
+ return target[hiddenPropertyName];
844
696
  }
845
-
846
697
  function getValidator(modelClass) {
847
- return modelClass.createValidator();
698
+ return modelClass.createValidator();
848
699
  }
849
-
850
700
  function getJsonSchema(modelClass) {
851
- return modelClass.jsonSchema;
701
+ return modelClass.jsonSchema;
852
702
  }
853
-
854
703
  function getColumnNameMappers(modelClass) {
855
- return modelClass.columnNameMappers;
704
+ return modelClass.columnNameMappers;
856
705
  }
857
-
858
706
  function getIdRelationProperty(modelClass) {
859
- const idColumn = asArray(modelClass.getIdColumn());
860
-
861
- return new RelationProperty(
862
- idColumn.map((idCol) => `${modelClass.getTableName()}.${idCol}`),
863
- () => modelClass,
864
- );
707
+ const idColumn = asArray(modelClass.getIdColumn());
708
+ return new RelationProperty(idColumn.map((idCol) => `${modelClass.getTableName()}.${idCol}`), () => modelClass);
865
709
  }
866
-
867
710
  function getReadOnlyAttributes(modelClass) {
868
- return [...new Set(getReadOnlyAttributesRecursively(modelClass))];
711
+ return [...new Set(getReadOnlyAttributesRecursively(modelClass))];
869
712
  }
870
-
871
713
  function getReadOnlyAttributesRecursively(modelClass) {
872
- if (modelClass === Model || modelClass.prototype == undefined) {
873
- // Stop recursion to the model class or its prototype is null or undefined.
874
- return [];
875
- }
876
-
877
- const propertyNames = Object.getOwnPropertyNames(modelClass.prototype);
878
-
879
- return [
880
- ...getReadOnlyAttributes(Object.getPrototypeOf(modelClass)),
881
- ...propertyNames.filter((propName) => {
882
- const desc = Object.getOwnPropertyDescriptor(modelClass.prototype, propName);
883
- return (desc.get && !desc.set) || desc.writable === false || isFunction(desc.value);
884
- }),
885
- ];
714
+ if (modelClass === Model || modelClass.prototype == undefined) {
715
+ // Stop recursion to the model class or its prototype is null or undefined.
716
+ return [];
717
+ }
718
+ const propertyNames = Object.getOwnPropertyNames(modelClass.prototype);
719
+ return [
720
+ ...getReadOnlyAttributes(Object.getPrototypeOf(modelClass)),
721
+ ...propertyNames.filter((propName) => {
722
+ const desc = Object.getOwnPropertyDescriptor(modelClass.prototype, propName);
723
+ return (desc.get && !desc.set) || desc.writable === false || isFunction(desc.value);
724
+ }),
725
+ ];
886
726
  }
887
-
888
727
  function getRelationMappings(modelClass) {
889
- let relationMappings = modelClass.relationMappings;
890
-
891
- if (isFunction(relationMappings)) {
892
- relationMappings = relationMappings.call(modelClass);
893
- }
894
-
895
- return relationMappings || {};
728
+ let relationMappings = modelClass.relationMappings;
729
+ if (isFunction(relationMappings)) {
730
+ relationMappings = relationMappings.call(modelClass);
731
+ }
732
+ return relationMappings || {};
896
733
  }
897
-
898
734
  function getRelationNames(modelClass) {
899
- return Object.keys(modelClass.getRelationMappings());
735
+ return Object.keys(modelClass.getRelationMappings());
900
736
  }
901
-
902
737
  function getVirtualAttributes(modelClass) {
903
- return modelClass.virtualAttributes || [];
738
+ return modelClass.virtualAttributes || [];
904
739
  }
905
-
906
740
  function getTraverseArgs(filterConstructor, models, traverser) {
907
- filterConstructor = filterConstructor || null;
908
-
909
- if (traverser === undefined) {
910
- traverser = models;
911
- models = filterConstructor;
912
- filterConstructor = null;
913
- }
914
-
915
- if (!isFunction(traverser)) {
916
- throw new Error('traverser must be a function');
917
- }
918
-
919
- return {
920
- traverser,
921
- models,
922
- filterConstructor,
923
- };
741
+ filterConstructor = filterConstructor || null;
742
+ if (traverser === undefined) {
743
+ traverser = models;
744
+ models = filterConstructor;
745
+ filterConstructor = null;
746
+ }
747
+ if (!isFunction(traverser)) {
748
+ throw new Error('traverser must be a function');
749
+ }
750
+ return {
751
+ traverser,
752
+ models,
753
+ filterConstructor,
754
+ };
924
755
  }
925
-
926
756
  function asPropsArray(props) {
927
- if (props.length === 1) {
928
- const arg = props[0];
929
- if (Array.isArray(arg)) {
930
- return arg;
931
- } else if (arg && typeof arg === 'object') {
932
- return Object.entries(arg)
933
- .filter(([, value]) => value)
934
- .map(([key]) => key);
935
- }
936
- }
937
- return props;
757
+ if (props.length === 1) {
758
+ const arg = props[0];
759
+ if (Array.isArray(arg)) {
760
+ return arg;
761
+ }
762
+ else if (arg && typeof arg === 'object') {
763
+ return Object.entries(arg)
764
+ .filter(([, value]) => value)
765
+ .map(([key]) => key);
766
+ }
767
+ }
768
+ return props;
938
769
  }
939
-
940
770
  module.exports = {
941
- Model,
771
+ Model,
942
772
  };