@abedmurrar/objection 0.0.0-stage → 4.0.0-alpha.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 (190) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +69 -2
  3. package/lib/.eslintrc.json +8 -0
  4. package/lib/initialize.js +14 -0
  5. package/lib/model/AjvValidator.js +325 -0
  6. package/lib/model/Model.js +942 -0
  7. package/lib/model/ModifierNotFoundError.js +12 -0
  8. package/lib/model/NotFoundError.js +23 -0
  9. package/lib/model/RelationDoesNotExistError.js +14 -0
  10. package/lib/model/ValidationError.js +54 -0
  11. package/lib/model/Validator.js +26 -0
  12. package/lib/model/getModel.js +9 -0
  13. package/lib/model/graph/ModelGraph.js +80 -0
  14. package/lib/model/graph/ModelGraphBuilder.js +241 -0
  15. package/lib/model/graph/ModelGraphEdge.js +52 -0
  16. package/lib/model/graph/ModelGraphNode.js +240 -0
  17. package/lib/model/inheritModel.js +28 -0
  18. package/lib/model/modelBindKnex.js +83 -0
  19. package/lib/model/modelClone.js +121 -0
  20. package/lib/model/modelColPropMap.js +34 -0
  21. package/lib/model/modelId.js +62 -0
  22. package/lib/model/modelJsonAttributes.js +92 -0
  23. package/lib/model/modelParseRelations.js +82 -0
  24. package/lib/model/modelQueryProps.js +147 -0
  25. package/lib/model/modelSet.js +136 -0
  26. package/lib/model/modelTableMetadata.js +83 -0
  27. package/lib/model/modelToJson.js +187 -0
  28. package/lib/model/modelUtils.js +47 -0
  29. package/lib/model/modelValidate.js +48 -0
  30. package/lib/model/modelValues.js +126 -0
  31. package/lib/model/modelVisitor.js +41 -0
  32. package/lib/objection.js +114 -0
  33. package/lib/queryBuilder/FunctionBuilder.js +339 -0
  34. package/lib/queryBuilder/InternalOptions.js +29 -0
  35. package/lib/queryBuilder/JoinBuilder.js +157 -0
  36. package/lib/queryBuilder/QueryBuilder.js +1398 -0
  37. package/lib/queryBuilder/QueryBuilderBase.js +884 -0
  38. package/lib/queryBuilder/QueryBuilderContext.js +27 -0
  39. package/lib/queryBuilder/QueryBuilderContextBase.js +35 -0
  40. package/lib/queryBuilder/QueryBuilderOperationSupport.js +558 -0
  41. package/lib/queryBuilder/QueryBuilderUserContext.js +31 -0
  42. package/lib/queryBuilder/RawBuilder.js +93 -0
  43. package/lib/queryBuilder/ReferenceBuilder.js +284 -0
  44. package/lib/queryBuilder/RelationExpression.js +431 -0
  45. package/lib/queryBuilder/StaticHookArguments.js +134 -0
  46. package/lib/queryBuilder/ValueBuilder.js +127 -0
  47. package/lib/queryBuilder/expressions.js +151 -0
  48. package/lib/queryBuilder/functions/mysql.js +817 -0
  49. package/lib/queryBuilder/graph/GraphAction.js +69 -0
  50. package/lib/queryBuilder/graph/GraphData.js +14 -0
  51. package/lib/queryBuilder/graph/GraphFetcher.js +191 -0
  52. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +184 -0
  53. package/lib/queryBuilder/graph/GraphOperation.js +27 -0
  54. package/lib/queryBuilder/graph/GraphOptions.js +207 -0
  55. package/lib/queryBuilder/graph/GraphUpsert.js +305 -0
  56. package/lib/queryBuilder/graph/delete/GraphDelete.js +20 -0
  57. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +74 -0
  58. package/lib/queryBuilder/graph/insert/GraphInsert.js +145 -0
  59. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +225 -0
  60. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +92 -0
  61. package/lib/queryBuilder/graph/patch/GraphPatch.js +20 -0
  62. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +258 -0
  63. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +31 -0
  64. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +126 -0
  65. package/lib/queryBuilder/join/JoinResultColumn.js +23 -0
  66. package/lib/queryBuilder/join/JoinResultParser.js +119 -0
  67. package/lib/queryBuilder/join/RelationJoiner.js +341 -0
  68. package/lib/queryBuilder/join/TableNode.js +163 -0
  69. package/lib/queryBuilder/join/TableTree.js +85 -0
  70. package/lib/queryBuilder/join/utils.js +25 -0
  71. package/lib/queryBuilder/operations/DelegateOperation.js +141 -0
  72. package/lib/queryBuilder/operations/DeleteOperation.js +51 -0
  73. package/lib/queryBuilder/operations/FindByIdOperation.js +37 -0
  74. package/lib/queryBuilder/operations/FindByIdsOperation.js +29 -0
  75. package/lib/queryBuilder/operations/FindOperation.js +164 -0
  76. package/lib/queryBuilder/operations/FirstOperation.js +27 -0
  77. package/lib/queryBuilder/operations/FromOperation.js +110 -0
  78. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +49 -0
  79. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +45 -0
  80. package/lib/queryBuilder/operations/InsertGraphOperation.js +108 -0
  81. package/lib/queryBuilder/operations/InsertOperation.js +206 -0
  82. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +46 -0
  83. package/lib/queryBuilder/operations/InstanceFindOperation.js +21 -0
  84. package/lib/queryBuilder/operations/InstanceInsertOperation.js +24 -0
  85. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +59 -0
  86. package/lib/queryBuilder/operations/JoinRelatedOperation.js +103 -0
  87. package/lib/queryBuilder/operations/KnexOperation.js +14 -0
  88. package/lib/queryBuilder/operations/MergeOperation.js +56 -0
  89. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +192 -0
  90. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +29 -0
  91. package/lib/queryBuilder/operations/OnBuildOperation.js +29 -0
  92. package/lib/queryBuilder/operations/OnErrorOperation.js +29 -0
  93. package/lib/queryBuilder/operations/QueryBuilderOperation.js +297 -0
  94. package/lib/queryBuilder/operations/RangeOperation.js +47 -0
  95. package/lib/queryBuilder/operations/RelateOperation.js +27 -0
  96. package/lib/queryBuilder/operations/ReturningOperation.js +30 -0
  97. package/lib/queryBuilder/operations/RunAfterOperation.js +29 -0
  98. package/lib/queryBuilder/operations/RunBeforeOperation.js +29 -0
  99. package/lib/queryBuilder/operations/UnrelateOperation.js +23 -0
  100. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +80 -0
  101. package/lib/queryBuilder/operations/UpdateOperation.js +155 -0
  102. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +45 -0
  103. package/lib/queryBuilder/operations/UpsertGraphOperation.js +66 -0
  104. package/lib/queryBuilder/operations/WhereCompositeOperation.js +57 -0
  105. package/lib/queryBuilder/operations/WhereInOperation.js +48 -0
  106. package/lib/queryBuilder/operations/eager/EagerOperation.js +61 -0
  107. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +51 -0
  108. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +13 -0
  109. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +285 -0
  110. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +36 -0
  111. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +53 -0
  112. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +31 -0
  113. package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +31 -0
  114. package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +167 -0
  115. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +164 -0
  116. package/lib/queryBuilder/operations/select/SelectOperation.js +66 -0
  117. package/lib/queryBuilder/operations/select/Selection.js +123 -0
  118. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +117 -0
  119. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +100 -0
  120. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +104 -0
  121. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +886 -0
  122. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +97 -0
  123. package/lib/queryBuilder/parsers/relationExpressionParser.js +1042 -0
  124. package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +141 -0
  125. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +22 -0
  126. package/lib/queryBuilder/transformations/QueryTransformation.js +11 -0
  127. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +71 -0
  128. package/lib/queryBuilder/transformations/index.js +15 -0
  129. package/lib/queryBuilder/whereScopes.js +227 -0
  130. package/lib/relations/Relation.js +401 -0
  131. package/lib/relations/RelationDeleteOperation.js +29 -0
  132. package/lib/relations/RelationFindOperation.js +149 -0
  133. package/lib/relations/RelationInsertOperation.js +33 -0
  134. package/lib/relations/RelationOwner.js +236 -0
  135. package/lib/relations/RelationProperty.js +247 -0
  136. package/lib/relations/RelationUpdateOperation.js +30 -0
  137. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +23 -0
  138. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +44 -0
  139. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +50 -0
  140. package/lib/relations/belongsToOne/BelongsToOneRelation.js +53 -0
  141. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +61 -0
  142. package/lib/relations/hasMany/HasManyInsertOperation.js +61 -0
  143. package/lib/relations/hasMany/HasManyRelateOperation.js +64 -0
  144. package/lib/relations/hasMany/HasManyRelation.js +49 -0
  145. package/lib/relations/hasMany/HasManyUnrelateOperation.js +33 -0
  146. package/lib/relations/hasOne/HasOneRelation.js +13 -0
  147. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +13 -0
  148. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +105 -0
  149. package/lib/relations/manyToMany/ManyToManyRelation.js +507 -0
  150. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +36 -0
  151. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +10 -0
  152. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +26 -0
  153. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +12 -0
  154. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +105 -0
  155. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +52 -0
  156. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +81 -0
  157. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +14 -0
  158. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +34 -0
  159. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +16 -0
  160. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +10 -0
  161. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +82 -0
  162. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +12 -0
  163. package/lib/transaction.js +96 -0
  164. package/lib/utils/assert.js +25 -0
  165. package/lib/utils/buildUtils.js +21 -0
  166. package/lib/utils/classUtils.js +13 -0
  167. package/lib/utils/clone.js +2329 -0
  168. package/lib/utils/createModifier.js +42 -0
  169. package/lib/utils/deprecate.js +15 -0
  170. package/lib/utils/identifierMapping.js +227 -0
  171. package/lib/utils/internalPropUtils.js +11 -0
  172. package/lib/utils/knexUtils.js +76 -0
  173. package/lib/utils/mixin.js +25 -0
  174. package/lib/utils/mysqlJsonPath.js +55 -0
  175. package/lib/utils/normalizeIds.js +144 -0
  176. package/lib/utils/objectUtils.js +416 -0
  177. package/lib/utils/parseFieldExpression.js +51 -0
  178. package/lib/utils/postgresJsonPath.js +110 -0
  179. package/lib/utils/promiseUtils/after.js +17 -0
  180. package/lib/utils/promiseUtils/afterReturn.js +17 -0
  181. package/lib/utils/promiseUtils/index.js +17 -0
  182. package/lib/utils/promiseUtils/isPromise.js +11 -0
  183. package/lib/utils/promiseUtils/map.js +110 -0
  184. package/lib/utils/promiseUtils/mapAfterAllReturn.js +29 -0
  185. package/lib/utils/promiseUtils/try.js +22 -0
  186. package/lib/utils/resolveModel.js +107 -0
  187. package/lib/utils/tmpColumnUtils.js +16 -0
  188. package/package.json +86 -4
  189. package/typings/objection/index.d.ts +4104 -0
  190. package/typings/objection/relation-expression.d.ts +237 -0
@@ -0,0 +1,401 @@
1
+ 'use strict';
2
+
3
+ const { withWhereScope } = require('../queryBuilder/whereScopes');
4
+ const { RelationProperty } = require('./RelationProperty');
5
+
6
+ const { RelationFindOperation } = require('./RelationFindOperation');
7
+ const { RelationUpdateOperation } = require('./RelationUpdateOperation');
8
+ const { RelationDeleteOperation } = require('./RelationDeleteOperation');
9
+
10
+ const { resolveModel } = require('../utils/resolveModel');
11
+ const { get, isFunction } = require('../utils/objectUtils');
12
+ const { mapAfterAllReturn } = require('../utils/promiseUtils');
13
+ const { createModifier } = require('../utils/createModifier');
14
+
15
+ class Relation {
16
+ constructor(relationName, OwnerClass) {
17
+ this.name = relationName;
18
+ this.ownerModelClass = OwnerClass;
19
+ this.relatedModelClass = null;
20
+
21
+ this.ownerProp = null;
22
+ this.relatedProp = null;
23
+
24
+ this.joinTableModelClass = null;
25
+ this.joinTableOwnerProp = null;
26
+ this.joinTableRelatedProp = null;
27
+ this.joinTableBeforeInsert = null;
28
+ this.joinTableExtras = [];
29
+
30
+ this.modify = null;
31
+ this.beforeInsert = null;
32
+ }
33
+
34
+ setMapping(mapping) {
35
+ let ctx = {
36
+ name: this.name,
37
+ mapping,
38
+ ownerModelClass: this.ownerModelClass,
39
+ relatedModelClass: null,
40
+ relatedProp: null,
41
+ ownerProp: null,
42
+ modify: null,
43
+ beforeInsert: null,
44
+ forbiddenMappingProperties: this.forbiddenMappingProperties,
45
+ createError: (msg) => this.createError(msg),
46
+ };
47
+
48
+ ctx = checkForbiddenProperties(ctx);
49
+ ctx = checkOwnerModelClass(ctx);
50
+ ctx = checkRelatedModelClass(ctx);
51
+ ctx = resolveRelatedModelClass(ctx);
52
+ ctx = checkRelation(ctx);
53
+ ctx = createJoinProperties(ctx);
54
+ ctx = parseModify(ctx);
55
+ ctx = parseBeforeInsert(ctx);
56
+
57
+ this.relatedModelClass = ctx.relatedModelClass;
58
+ this.ownerProp = ctx.ownerProp;
59
+ this.relatedProp = ctx.relatedProp;
60
+ this.modify = ctx.modify;
61
+ this.beforeInsert = ctx.beforeInsert;
62
+ }
63
+
64
+ get forbiddenMappingProperties() {
65
+ return ['join.through'];
66
+ }
67
+
68
+ get joinTable() {
69
+ return this.joinTableModelClass ? this.joinTableModelClass.getTableName() : null;
70
+ }
71
+
72
+ get joinModelClass() {
73
+ return this.getJoinModelClass(this.ownerModelClass.knex());
74
+ }
75
+
76
+ getJoinModelClass(knex) {
77
+ return this.joinTableModelClass && knex !== this.joinTableModelClass.knex()
78
+ ? this.joinTableModelClass.bindKnex(knex)
79
+ : this.joinTableModelClass;
80
+ }
81
+
82
+ isOneToOne() {
83
+ return false;
84
+ }
85
+
86
+ clone() {
87
+ const relation = new this.constructor(this.name, this.ownerModelClass);
88
+
89
+ relation.relatedModelClass = this.relatedModelClass;
90
+ relation.ownerProp = this.ownerProp;
91
+ relation.relatedProp = this.relatedProp;
92
+ relation.modify = this.modify;
93
+ relation.beforeInsert = this.beforeInsert;
94
+
95
+ relation.joinTableModelClass = this.joinTableModelClass;
96
+ relation.joinTableOwnerProp = this.joinTableOwnerProp;
97
+ relation.joinTableRelatedProp = this.joinTableRelatedProp;
98
+ relation.joinTableBeforeInsert = this.joinTableBeforeInsert;
99
+ relation.joinTableExtras = this.joinTableExtras;
100
+
101
+ return relation;
102
+ }
103
+
104
+ bindKnex(knex) {
105
+ const bound = this.clone();
106
+
107
+ bound.relatedModelClass = this.relatedModelClass.bindKnex(knex);
108
+ bound.ownerModelClass = this.ownerModelClass.bindKnex(knex);
109
+
110
+ if (this.joinTableModelClass) {
111
+ bound.joinTableModelClass = this.joinTableModelClass.bindKnex(knex);
112
+ }
113
+
114
+ return bound;
115
+ }
116
+
117
+ findQuery(builder, owner) {
118
+ const relatedRefs = this.relatedProp.refs(builder);
119
+
120
+ withWhereScope(builder, () => {
121
+ owner.buildFindQuery(builder, this, relatedRefs);
122
+ });
123
+
124
+ return this.applyModify(builder);
125
+ }
126
+
127
+ applyModify(builder) {
128
+ try {
129
+ // The relation's `modify` gets its own scope so that an `orWhere`
130
+ // in it can't escape the owner condition.
131
+ return withWhereScope(builder, () => builder.modify(this.modify));
132
+ } catch (err) {
133
+ if (err instanceof this.relatedModelClass.ModifierNotFoundError) {
134
+ throw this.createError(err.message);
135
+ } else {
136
+ throw err;
137
+ }
138
+ }
139
+ }
140
+
141
+ join(
142
+ builder,
143
+ {
144
+ joinOperation = 'join',
145
+ relatedTableAlias = builder.tableRefFor(this.relatedModelClass),
146
+ relatedJoinSelectQuery = this.relatedModelClass.query().childQueryOf(builder),
147
+ relatedTable = builder.tableNameFor(this.relatedModelClass),
148
+ ownerTable = builder.tableRefFor(this.ownerModelClass),
149
+ } = {},
150
+ ) {
151
+ let relatedJoinSelect = this.applyModify(relatedJoinSelectQuery).as(relatedTableAlias);
152
+
153
+ if (relatedJoinSelect.isSelectAll()) {
154
+ // No need to join a subquery if the query is `select * from "RelatedTable"`.
155
+ relatedJoinSelect = aliasedTableName(relatedTable, relatedTableAlias);
156
+ }
157
+
158
+ return builder[joinOperation](relatedJoinSelect, (join) => {
159
+ const relatedProp = this.relatedProp;
160
+ const ownerProp = this.ownerProp;
161
+
162
+ relatedProp.forEach((i) => {
163
+ const relatedRef = relatedProp.ref(builder, i).table(relatedTableAlias);
164
+ const ownerRef = ownerProp.ref(builder, i).table(ownerTable);
165
+
166
+ join.on(relatedRef, ownerRef);
167
+ });
168
+ });
169
+ }
170
+
171
+ find(_, owner) {
172
+ return new RelationFindOperation('find', {
173
+ relation: this,
174
+ owner,
175
+ });
176
+ }
177
+
178
+ insert(_, owner) {
179
+ /* istanbul ignore next */
180
+ throw this.createError('not implemented');
181
+ }
182
+
183
+ update(_, owner) {
184
+ return new RelationUpdateOperation('update', {
185
+ relation: this,
186
+ owner,
187
+ });
188
+ }
189
+
190
+ patch(_, owner) {
191
+ return new RelationUpdateOperation('patch', {
192
+ relation: this,
193
+ owner,
194
+ modelOptions: { patch: true },
195
+ });
196
+ }
197
+
198
+ delete(_, owner) {
199
+ return new RelationDeleteOperation('delete', {
200
+ relation: this,
201
+ owner,
202
+ });
203
+ }
204
+
205
+ relate() {
206
+ /* istanbul ignore next */
207
+ throw this.createError('not implemented');
208
+ }
209
+
210
+ unrelate() {
211
+ /* istanbul ignore next */
212
+ throw this.createError('not implemented');
213
+ }
214
+
215
+ hasRelateProp(model) {
216
+ return model.$hasProps(this.relatedProp.props);
217
+ }
218
+
219
+ setRelateProp(model, values) {
220
+ this.relatedProp.forEach((i) => {
221
+ this.relatedProp.setProp(model, i, values[i]);
222
+ });
223
+ }
224
+
225
+ executeBeforeInsert(models, queryContext, result) {
226
+ return mapAfterAllReturn(models, (model) => this.beforeInsert(model, queryContext), result);
227
+ }
228
+
229
+ createError(message) {
230
+ if (this.ownerModelClass && this.ownerModelClass.name && this.name) {
231
+ return new Error(`${this.ownerModelClass.name}.relationMappings.${this.name}: ${message}`);
232
+ } else {
233
+ return new Error(`${this.constructor.name}: ${message}`);
234
+ }
235
+ }
236
+ }
237
+
238
+ Object.defineProperties(Relation, {
239
+ isObjectionRelationClass: {
240
+ enumerable: false,
241
+ writable: false,
242
+ value: true,
243
+ },
244
+ });
245
+
246
+ Object.defineProperties(Relation.prototype, {
247
+ isObjectionRelation: {
248
+ enumerable: false,
249
+ writable: false,
250
+ value: true,
251
+ },
252
+ });
253
+
254
+ function checkForbiddenProperties(ctx) {
255
+ ctx.forbiddenMappingProperties.forEach((prop) => {
256
+ if (get(ctx.mapping, prop.split('.')) !== undefined) {
257
+ throw ctx.createError(`Property ${prop} is not supported for this relation type.`);
258
+ }
259
+ });
260
+
261
+ return ctx;
262
+ }
263
+
264
+ function checkOwnerModelClass(ctx) {
265
+ if (!isFunction(ctx.ownerModelClass) || !ctx.ownerModelClass.isObjectionModelClass) {
266
+ throw ctx.createError(`Relation's owner is not a subclass of Model`);
267
+ }
268
+
269
+ return ctx;
270
+ }
271
+
272
+ function checkRelatedModelClass(ctx) {
273
+ if (!ctx.mapping.modelClass) {
274
+ throw ctx.createError('modelClass is not defined');
275
+ }
276
+
277
+ return ctx;
278
+ }
279
+
280
+ function resolveRelatedModelClass(ctx) {
281
+ let relatedModelClass;
282
+
283
+ try {
284
+ relatedModelClass = resolveModel(
285
+ ctx.mapping.modelClass,
286
+ ctx.ownerModelClass.modelPaths,
287
+ 'modelClass',
288
+ );
289
+ } catch (err) {
290
+ throw ctx.createError(err.message);
291
+ }
292
+
293
+ return Object.assign(ctx, { relatedModelClass });
294
+ }
295
+
296
+ function checkRelation(ctx) {
297
+ if (!ctx.mapping.relation) {
298
+ throw ctx.createError('relation is not defined');
299
+ }
300
+
301
+ if (!isFunction(ctx.mapping.relation) || !ctx.mapping.relation.isObjectionRelationClass) {
302
+ throw ctx.createError('relation is not a subclass of Relation');
303
+ }
304
+
305
+ return ctx;
306
+ }
307
+
308
+ function createJoinProperties(ctx) {
309
+ const mapping = ctx.mapping;
310
+
311
+ if (!mapping.join || !mapping.join.from || !mapping.join.to) {
312
+ throw ctx.createError(
313
+ 'join must be an object that maps the columns of the related models together. For example: {from: "SomeTable.id", to: "SomeOtherTable.someModelId"}',
314
+ );
315
+ }
316
+
317
+ const fromProp = createRelationProperty(ctx, mapping.join.from, 'join.from');
318
+ const toProp = createRelationProperty(ctx, mapping.join.to, 'join.to');
319
+
320
+ let ownerProp;
321
+ let relatedProp;
322
+
323
+ if (fromProp.modelClass.getTableName() === ctx.ownerModelClass.getTableName()) {
324
+ ownerProp = fromProp;
325
+ relatedProp = toProp;
326
+ } else if (toProp.modelClass.getTableName() === ctx.ownerModelClass.getTableName()) {
327
+ ownerProp = toProp;
328
+ relatedProp = fromProp;
329
+ } else {
330
+ throw ctx.createError('join: either `from` or `to` must point to the owner model table.');
331
+ }
332
+
333
+ if (ownerProp.props.some((it) => it === ctx.name)) {
334
+ throw ctx.createError(
335
+ `join: relation name and join property '${ctx.name}' cannot have the same name. If you cannot change one or the other, you can use $parseDatabaseJson and $formatDatabaseJson methods to convert the column name.`,
336
+ );
337
+ }
338
+
339
+ if (relatedProp.modelClass.getTableName() !== ctx.relatedModelClass.getTableName()) {
340
+ throw ctx.createError('join: either `from` or `to` must point to the related model table.');
341
+ }
342
+
343
+ return Object.assign(ctx, { ownerProp, relatedProp });
344
+ }
345
+
346
+ function createRelationProperty(ctx, refString, propName) {
347
+ try {
348
+ return new RelationProperty(refString, (table) => {
349
+ return [ctx.ownerModelClass, ctx.relatedModelClass].find((it) => it.getTableName() === table);
350
+ });
351
+ } catch (err) {
352
+ if (err instanceof RelationProperty.ModelNotFoundError) {
353
+ throw ctx.createError(
354
+ `join: either \`from\` or \`to\` must point to the owner model table and the other one to the related table. It might be that specified table '${err.tableName}' is not correct`,
355
+ );
356
+ } else if (err instanceof RelationProperty.InvalidReferenceError) {
357
+ throw ctx.createError(
358
+ `${propName} must have format TableName.columnName. For example "SomeTable.id" or in case of composite key ["SomeTable.a", "SomeTable.b"].`,
359
+ );
360
+ } else {
361
+ throw err;
362
+ }
363
+ }
364
+ }
365
+
366
+ function parseModify(ctx) {
367
+ const mapping = ctx.mapping;
368
+ const modifier = mapping.modify || mapping.filter;
369
+ const modify =
370
+ modifier &&
371
+ createModifier({
372
+ modifier,
373
+ modelClass: ctx.relatedModelClass,
374
+ });
375
+
376
+ return Object.assign(ctx, { modify });
377
+ }
378
+
379
+ function parseBeforeInsert(ctx) {
380
+ let beforeInsert;
381
+
382
+ if (isFunction(ctx.mapping.beforeInsert)) {
383
+ beforeInsert = ctx.mapping.beforeInsert;
384
+ } else {
385
+ beforeInsert = (model) => model;
386
+ }
387
+
388
+ return Object.assign(ctx, { beforeInsert });
389
+ }
390
+
391
+ function aliasedTableName(tableName, alias) {
392
+ if (tableName === alias) {
393
+ return tableName;
394
+ } else {
395
+ return `${tableName} as ${alias}`;
396
+ }
397
+ }
398
+
399
+ module.exports = {
400
+ Relation,
401
+ };
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const { DeleteOperation } = require('../queryBuilder/operations/DeleteOperation');
4
+ const { RelationFindOperation } = require('./RelationFindOperation');
5
+
6
+ class RelationDeleteOperation extends DeleteOperation {
7
+ constructor(name, opt) {
8
+ super(name, opt);
9
+
10
+ this.relation = opt.relation;
11
+ this.owner = opt.owner;
12
+ }
13
+
14
+ onBuild(builder) {
15
+ super.onBuild(builder);
16
+ this.relation.findQuery(builder, this.owner);
17
+ }
18
+
19
+ toFindOperation() {
20
+ return new RelationFindOperation('find', {
21
+ relation: this.relation,
22
+ owner: this.owner,
23
+ });
24
+ }
25
+ }
26
+
27
+ module.exports = {
28
+ RelationDeleteOperation,
29
+ };
@@ -0,0 +1,149 @@
1
+ 'use strict';
2
+
3
+ const { FindOperation } = require('../queryBuilder/operations/FindOperation');
4
+
5
+ class RelationFindOperation extends FindOperation {
6
+ constructor(name, opt) {
7
+ super(name, opt);
8
+
9
+ this.relation = opt.relation;
10
+ this.owner = opt.owner;
11
+ this.alwaysReturnArray = false;
12
+ this.assignResultToOwner = true;
13
+ this.relationProperty = opt.relationProperty || this.relation.name;
14
+ this.omitProps = [];
15
+ this.alias = null;
16
+ }
17
+
18
+ onBuild(builder) {
19
+ this.maybeApplyAlias(builder);
20
+ this.relation.findQuery(builder, this.owner);
21
+
22
+ if (this.assignResultToOwner && this.owner.isModels) {
23
+ this.selectMissingJoinColumns(builder);
24
+ }
25
+ }
26
+
27
+ onAfter2(_, related) {
28
+ const isOneToOne = this.relation.isOneToOne();
29
+
30
+ if (this.assignResultToOwner && this.owner.isModels) {
31
+ const owners = this.owner.modelArray;
32
+ const relatedByOwnerId = new Map();
33
+
34
+ for (let i = 0, l = related.length; i < l; ++i) {
35
+ const rel = related[i];
36
+ const key = this.relation.relatedProp.propKey(rel);
37
+ let arr = relatedByOwnerId.get(key);
38
+
39
+ if (!arr) {
40
+ arr = [];
41
+ relatedByOwnerId.set(key, arr);
42
+ }
43
+
44
+ arr.push(rel);
45
+ }
46
+
47
+ for (let i = 0, l = owners.length; i < l; ++i) {
48
+ const own = owners[i];
49
+ const key = this.relation.ownerProp.propKey(own);
50
+ const related = relatedByOwnerId.get(key);
51
+
52
+ if (isOneToOne) {
53
+ own[this.relationProperty] = (related && related[0]) || null;
54
+ } else {
55
+ own[this.relationProperty] = related || [];
56
+ }
57
+ }
58
+ }
59
+
60
+ return related;
61
+ }
62
+
63
+ onAfter3(builder, related) {
64
+ const isOneToOne = this.relation.isOneToOne();
65
+ const intOpt = builder.internalOptions();
66
+
67
+ if (!intOpt.keepImplicitJoinProps) {
68
+ this.omitImplicitJoinProps(related);
69
+ }
70
+
71
+ if (!this.alwaysReturnArray && isOneToOne && related.length <= 1) {
72
+ related = related[0] || undefined;
73
+ }
74
+
75
+ return super.onAfter3(builder, related);
76
+ }
77
+
78
+ selectMissingJoinColumns(builder) {
79
+ const relatedProp = this.relation.relatedProp;
80
+ const addedSelects = [];
81
+
82
+ for (let c = 0, lc = relatedProp.size; c < lc; ++c) {
83
+ const fullCol = relatedProp.ref(builder, c).fullColumn(builder);
84
+ const prop = relatedProp.props[c];
85
+ const col = relatedProp.cols[c];
86
+
87
+ if (!builder.hasSelectionAs(fullCol, col) && addedSelects.indexOf(fullCol) === -1) {
88
+ this.omitProps.push(prop);
89
+ addedSelects.push(fullCol);
90
+ }
91
+ }
92
+
93
+ if (addedSelects.length) {
94
+ builder.select(addedSelects);
95
+ }
96
+ }
97
+
98
+ maybeApplyAlias(builder) {
99
+ if (!builder.alias() && this.alias) {
100
+ builder.alias(this.alias);
101
+ }
102
+ }
103
+
104
+ omitImplicitJoinProps(related) {
105
+ const relatedModelClass = this.relation.relatedModelClass;
106
+
107
+ if (!this.omitProps.length || !related) {
108
+ return related;
109
+ }
110
+
111
+ if (!Array.isArray(related)) {
112
+ return this.omitImplicitJoinPropsFromOne(relatedModelClass, related);
113
+ }
114
+
115
+ if (!related.length) {
116
+ return related;
117
+ }
118
+
119
+ for (let i = 0, l = related.length; i < l; ++i) {
120
+ this.omitImplicitJoinPropsFromOne(relatedModelClass, related[i]);
121
+ }
122
+
123
+ return related;
124
+ }
125
+
126
+ omitImplicitJoinPropsFromOne(relatedModelClass, model) {
127
+ for (let c = 0, lc = this.omitProps.length; c < lc; ++c) {
128
+ relatedModelClass.omitImpl(model, this.omitProps[c]);
129
+ }
130
+
131
+ return model;
132
+ }
133
+
134
+ clone() {
135
+ const clone = super.clone();
136
+
137
+ clone.alwaysReturnArray = this.alwaysReturnArray;
138
+ clone.assignResultToOwner = this.assignResultToOwner;
139
+ clone.relationProperty = this.relationProperty;
140
+ clone.omitProps = this.omitProps.slice();
141
+ clone.alias = this.alias;
142
+
143
+ return clone;
144
+ }
145
+ }
146
+
147
+ module.exports = {
148
+ RelationFindOperation,
149
+ };
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ const { InsertOperation } = require('../queryBuilder/operations/InsertOperation');
4
+
5
+ class RelationInsertOperation extends InsertOperation {
6
+ constructor(name, opt) {
7
+ super(name, opt);
8
+
9
+ this.relation = opt.relation;
10
+ this.owner = opt.owner;
11
+ this.assignResultToOwner = true;
12
+ }
13
+
14
+ async onBefore2(builder, result) {
15
+ const queryContext = builder.context();
16
+ result = await this.relation.executeBeforeInsert(this.models, queryContext, result);
17
+ return super.onBefore2(builder, result);
18
+ }
19
+
20
+ clone() {
21
+ const clone = super.clone();
22
+
23
+ clone.relation = this.relation;
24
+ clone.owner = this.owner;
25
+ clone.assignResultToOwner = this.assignResultToOwner;
26
+
27
+ return clone;
28
+ }
29
+ }
30
+
31
+ module.exports = {
32
+ RelationInsertOperation,
33
+ };