@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,507 +1,405 @@
1
1
  'use strict';
2
-
3
2
  const { withWhereScope } = require('../../queryBuilder/whereScopes');
4
3
  const { getModel } = require('../../model/getModel');
5
4
  const { Relation } = require('../Relation');
6
5
  const { RelationProperty } = require('../RelationProperty');
7
-
8
6
  const { isSqlite } = require('../../utils/knexUtils');
9
7
  const { inheritModel } = require('../../model/inheritModel');
10
8
  const { resolveModel } = require('../../utils/resolveModel');
11
9
  const { mapAfterAllReturn } = require('../../utils/promiseUtils');
12
10
  const { isFunction, isObject, isString } = require('../../utils/objectUtils');
13
11
  const { createModifier } = require('../../utils/createModifier');
14
-
15
12
  const { ManyToManyFindOperation } = require('./find/ManyToManyFindOperation');
16
13
  const { ManyToManyInsertOperation } = require('./insert/ManyToManyInsertOperation');
17
14
  const { ManyToManyRelateOperation } = require('./relate/ManyToManyRelateOperation');
18
-
19
15
  const { ManyToManyUnrelateOperation } = require('./unrelate/ManyToManyUnrelateOperation');
20
- const {
21
- ManyToManyUnrelateSqliteOperation,
22
- } = require('./unrelate/ManyToManyUnrelateSqliteOperation');
23
-
16
+ const { ManyToManyUnrelateSqliteOperation, } = require('./unrelate/ManyToManyUnrelateSqliteOperation');
24
17
  const { ManyToManyUpdateOperation } = require('./update/ManyToManyUpdateOperation');
25
18
  const { ManyToManyUpdateSqliteOperation } = require('./update/ManyToManyUpdateSqliteOperation');
26
-
27
19
  const { ManyToManyDeleteOperation } = require('./delete/ManyToManyDeleteOperation');
28
20
  const { ManyToManyDeleteSqliteOperation } = require('./delete/ManyToManyDeleteSqliteOperation');
29
-
30
21
  class ManyToManyRelation extends Relation {
31
- setMapping(mapping) {
32
- const retVal = super.setMapping(mapping);
33
-
34
- let ctx = {
35
- mapping,
36
- ownerModelClass: this.ownerModelClass,
37
- relatedModelClass: this.relatedModelClass,
38
- ownerProp: this.ownerProp,
39
- relatedProp: this.relatedProp,
40
-
41
- joinTableModelClass: null,
42
- joinTableOwnerProp: null,
43
- joinTableRelatedProp: null,
44
- joinTableBeforeInsert: null,
45
- joinTableExtras: [],
46
-
47
- createError: (msg) => this.createError(msg),
48
- };
49
-
50
- ctx = checkThroughObject(ctx);
51
- ctx = resolveJoinModelClassIfDefined(ctx);
52
- ctx = createJoinProperties(ctx);
53
- ctx = parseExtras(ctx);
54
- ctx = parseModify(ctx);
55
- ctx = parseBeforeInsert(ctx);
56
- ctx = finalizeJoinModelClass(ctx);
57
-
58
- this.joinTableExtras = ctx.joinTableExtras;
59
- this.joinTableModify = ctx.joinTableModify;
60
- this.joinTableModelClass = ctx.joinTableModelClass;
61
- this.joinTableOwnerProp = ctx.joinTableOwnerProp;
62
- this.joinTableRelatedProp = ctx.joinTableRelatedProp;
63
- this.joinTableBeforeInsert = ctx.joinTableBeforeInsert;
64
-
65
- return retVal;
66
- }
67
-
68
- get forbiddenMappingProperties() {
69
- return [];
70
- }
71
-
72
- findQuery(builder, owner) {
73
- const joinTableOwnerRefs = this.joinTableOwnerProp.refs(builder);
74
- const joinTable = builder.tableNameFor(this.joinTable);
75
- const joinTableAlias = builder.tableRefFor(this.joinTable);
76
-
77
- let joinTableSelect = this.joinTableModelClass
78
- .query()
79
- .childQueryOf(builder)
80
- .modify(this.joinTableModify)
81
- .as(joinTableAlias);
82
- if (joinTableSelect.isSelectAll()) {
83
- joinTableSelect = aliasedTableName(joinTable, joinTableAlias);
84
- }
85
-
86
- builder.join(joinTableSelect, (join) => {
87
- this.relatedProp.forEach((i) => {
88
- const relatedRef = this.relatedProp.ref(builder, i);
89
- const joinTableRelatedRef = this.joinTableRelatedProp.ref(builder, i);
90
-
91
- join.on(relatedRef, joinTableRelatedRef);
92
- });
93
- });
94
-
95
- withWhereScope(builder, () => {
96
- owner.buildFindQuery(builder, this, joinTableOwnerRefs);
97
- });
98
-
99
- return this.applyModify(builder);
100
- }
101
-
102
- join(
103
- builder,
104
- {
105
- joinOperation = defaultJoinOperation(this, builder),
106
- relatedTableAlias = defaultRelatedTableAlias(this, builder),
107
- relatedJoinSelectQuery = defaultRelatedJoinSelectQuery(this, builder),
108
- relatedTable = defaultRelatedTable(this, builder),
109
- ownerTable = defaultOwnerTable(this, builder),
110
- joinTableAlias = defaultJoinTableAlias(this, relatedTableAlias, builder),
111
- } = {},
112
- ) {
113
- let relatedJoinSelect = this.applyModify(relatedJoinSelectQuery).as(relatedTableAlias);
114
-
115
- if (relatedJoinSelect.isSelectAll()) {
116
- // No need to join a subquery if the query is `select * from "RelatedTable"`.
117
- relatedJoinSelect = aliasedTableName(relatedTable, relatedTableAlias);
118
- }
119
-
120
- let joinTableSelect = this.joinTableModelClass
121
- .query()
122
- .childQueryOf(builder)
123
- .modify(this.joinTableModify)
124
- .as(joinTableAlias);
125
- if (joinTableSelect.isSelectAll()) {
126
- joinTableSelect = aliasedTableName(this.joinTable, joinTableAlias);
127
- }
128
-
129
- return builder[joinOperation](joinTableSelect, (join) => {
130
- const ownerProp = this.ownerProp;
131
- const joinTableOwnerProp = this.joinTableOwnerProp;
132
-
133
- ownerProp.forEach((i) => {
134
- const joinTableOwnerRef = joinTableOwnerProp.ref(builder, i).table(joinTableAlias);
135
- const ownerRef = ownerProp.ref(builder, i).table(ownerTable);
136
-
137
- join.on(joinTableOwnerRef, ownerRef);
138
- });
139
- })[joinOperation](relatedJoinSelect, (join) => {
140
- const relatedProp = this.relatedProp;
141
- const joinTableRelatedProp = this.joinTableRelatedProp;
142
-
143
- relatedProp.forEach((i) => {
144
- const joinTableRelatedRef = joinTableRelatedProp.ref(builder, i).table(joinTableAlias);
145
- const relatedRef = relatedProp.ref(builder, i).table(relatedTableAlias);
146
-
147
- join.on(joinTableRelatedRef, relatedRef);
148
- });
149
- });
150
- }
151
-
152
- find(_, owner) {
153
- return new ManyToManyFindOperation('find', {
154
- relation: this,
155
- owner,
156
- });
157
- }
158
-
159
- insert(_, owner) {
160
- return new ManyToManyInsertOperation('insert', {
161
- relation: this,
162
- owner,
163
- });
164
- }
165
-
166
- update(builder, owner) {
167
- if (isSqlite(builder.knex())) {
168
- return new ManyToManyUpdateSqliteOperation('update', {
169
- relation: this,
170
- owner,
171
- });
172
- } else {
173
- return new ManyToManyUpdateOperation('update', {
174
- relation: this,
175
- owner,
176
- });
177
- }
178
- }
179
-
180
- patch(builder, owner) {
181
- if (isSqlite(builder.knex())) {
182
- return new ManyToManyUpdateSqliteOperation('patch', {
183
- modelOptions: { patch: true },
184
- relation: this,
185
- owner,
186
- });
187
- } else {
188
- return new ManyToManyUpdateOperation('patch', {
189
- modelOptions: { patch: true },
190
- relation: this,
191
- owner,
192
- });
193
- }
194
- }
195
-
196
- delete(builder, owner) {
197
- if (isSqlite(builder.knex())) {
198
- return new ManyToManyDeleteSqliteOperation('delete', {
199
- relation: this,
200
- owner,
201
- });
202
- } else {
203
- return new ManyToManyDeleteOperation('delete', {
204
- relation: this,
205
- owner,
206
- });
207
- }
208
- }
209
-
210
- relate(builder, owner) {
211
- return new ManyToManyRelateOperation('relate', {
212
- relation: this,
213
- owner,
214
- });
215
- }
216
-
217
- unrelate(builder, owner) {
218
- if (isSqlite(builder.knex())) {
219
- return new ManyToManyUnrelateSqliteOperation('unrelate', {
220
- relation: this,
221
- owner,
222
- });
223
- } else {
224
- return new ManyToManyUnrelateOperation('unrelate', {
225
- relation: this,
226
- owner,
227
- });
228
- }
229
- }
230
-
231
- createJoinModels(ownerId, related) {
232
- return related.map((related) => this.createJoinModel(ownerId, related));
233
- }
234
-
235
- createJoinModel(ownerId, rel) {
236
- let joinModel = {};
237
-
238
- for (let j = 0, lp = this.joinTableOwnerProp.size; j < lp; ++j) {
239
- this.joinTableOwnerProp.setProp(joinModel, j, ownerId[j]);
240
- }
241
-
242
- for (let j = 0, lp = this.joinTableRelatedProp.size; j < lp; ++j) {
243
- const value = this.relatedProp.getProp(rel, j);
244
-
245
- if (value !== undefined) {
246
- this.joinTableRelatedProp.setProp(joinModel, j, value);
247
- }
248
- }
249
-
250
- for (const extra of this.joinTableExtras) {
251
- let extraValue = rel[extra.aliasProp];
252
-
253
- if (extraValue === undefined && rel.$$queryProps) {
254
- extraValue = rel.$$queryProps[extra.aliasProp];
255
- }
256
-
257
- if (extraValue !== undefined) {
258
- joinModel[extra.joinTableProp] = extraValue;
259
- }
260
- }
261
-
262
- return joinModel;
263
- }
264
-
265
- omitExtraProps(models) {
266
- if (this.joinTableExtras && this.joinTableExtras.length) {
267
- const props = this.joinTableExtras.map((extra) => extra.aliasProp);
268
-
269
- for (const model of models) {
270
- // Omit extra properties instead of deleting them from the models so that they can
271
- // be used in the `$before` and `$after` hooks.
272
- model.$omitFromDatabaseJson(props);
273
- }
274
- }
275
- }
276
-
277
- executeJoinTableBeforeInsert(models, queryContext, result) {
278
- return mapAfterAllReturn(
279
- models,
280
- (model) => this.joinTableBeforeInsert(model, queryContext),
281
- result,
282
- );
283
- }
22
+ setMapping(mapping) {
23
+ const retVal = super.setMapping(mapping);
24
+ let ctx = {
25
+ mapping,
26
+ ownerModelClass: this.ownerModelClass,
27
+ relatedModelClass: this.relatedModelClass,
28
+ ownerProp: this.ownerProp,
29
+ relatedProp: this.relatedProp,
30
+ joinTableModelClass: null,
31
+ joinTableOwnerProp: null,
32
+ joinTableRelatedProp: null,
33
+ joinTableBeforeInsert: null,
34
+ joinTableExtras: [],
35
+ createError: (msg) => this.createError(msg),
36
+ };
37
+ ctx = checkThroughObject(ctx);
38
+ ctx = resolveJoinModelClassIfDefined(ctx);
39
+ ctx = createJoinProperties(ctx);
40
+ ctx = parseExtras(ctx);
41
+ ctx = parseModify(ctx);
42
+ ctx = parseBeforeInsert(ctx);
43
+ ctx = finalizeJoinModelClass(ctx);
44
+ this.joinTableExtras = ctx.joinTableExtras;
45
+ this.joinTableModify = ctx.joinTableModify;
46
+ this.joinTableModelClass = ctx.joinTableModelClass;
47
+ this.joinTableOwnerProp = ctx.joinTableOwnerProp;
48
+ this.joinTableRelatedProp = ctx.joinTableRelatedProp;
49
+ this.joinTableBeforeInsert = ctx.joinTableBeforeInsert;
50
+ return retVal;
51
+ }
52
+ get forbiddenMappingProperties() {
53
+ return [];
54
+ }
55
+ findQuery(builder, owner) {
56
+ const joinTableOwnerRefs = this.joinTableOwnerProp.refs(builder);
57
+ const joinTable = builder.tableNameFor(this.joinTable);
58
+ const joinTableAlias = builder.tableRefFor(this.joinTable);
59
+ let joinTableSelect = this.joinTableModelClass
60
+ .query()
61
+ .childQueryOf(builder)
62
+ .modify(this.joinTableModify)
63
+ .as(joinTableAlias);
64
+ if (joinTableSelect.isSelectAll()) {
65
+ joinTableSelect = aliasedTableName(joinTable, joinTableAlias);
66
+ }
67
+ builder.join(joinTableSelect, (join) => {
68
+ this.relatedProp.forEach((i) => {
69
+ const relatedRef = this.relatedProp.ref(builder, i);
70
+ const joinTableRelatedRef = this.joinTableRelatedProp.ref(builder, i);
71
+ join.on(relatedRef, joinTableRelatedRef);
72
+ });
73
+ });
74
+ withWhereScope(builder, () => {
75
+ owner.buildFindQuery(builder, this, joinTableOwnerRefs);
76
+ });
77
+ return this.applyModify(builder);
78
+ }
79
+ join(builder, { joinOperation = defaultJoinOperation(this, builder), relatedTableAlias = defaultRelatedTableAlias(this, builder), relatedJoinSelectQuery = defaultRelatedJoinSelectQuery(this, builder), relatedTable = defaultRelatedTable(this, builder), ownerTable = defaultOwnerTable(this, builder), joinTableAlias = defaultJoinTableAlias(this, relatedTableAlias, builder), } = {}) {
80
+ let relatedJoinSelect = this.applyModify(relatedJoinSelectQuery).as(relatedTableAlias);
81
+ if (relatedJoinSelect.isSelectAll()) {
82
+ // No need to join a subquery if the query is `select * from "RelatedTable"`.
83
+ relatedJoinSelect = aliasedTableName(relatedTable, relatedTableAlias);
84
+ }
85
+ let joinTableSelect = this.joinTableModelClass
86
+ .query()
87
+ .childQueryOf(builder)
88
+ .modify(this.joinTableModify)
89
+ .as(joinTableAlias);
90
+ if (joinTableSelect.isSelectAll()) {
91
+ joinTableSelect = aliasedTableName(this.joinTable, joinTableAlias);
92
+ }
93
+ return builder[joinOperation](joinTableSelect, (join) => {
94
+ const ownerProp = this.ownerProp;
95
+ const joinTableOwnerProp = this.joinTableOwnerProp;
96
+ ownerProp.forEach((i) => {
97
+ const joinTableOwnerRef = joinTableOwnerProp.ref(builder, i).table(joinTableAlias);
98
+ const ownerRef = ownerProp.ref(builder, i).table(ownerTable);
99
+ join.on(joinTableOwnerRef, ownerRef);
100
+ });
101
+ })[joinOperation](relatedJoinSelect, (join) => {
102
+ const relatedProp = this.relatedProp;
103
+ const joinTableRelatedProp = this.joinTableRelatedProp;
104
+ relatedProp.forEach((i) => {
105
+ const joinTableRelatedRef = joinTableRelatedProp.ref(builder, i).table(joinTableAlias);
106
+ const relatedRef = relatedProp.ref(builder, i).table(relatedTableAlias);
107
+ join.on(joinTableRelatedRef, relatedRef);
108
+ });
109
+ });
110
+ }
111
+ find(_, owner) {
112
+ return new ManyToManyFindOperation('find', {
113
+ relation: this,
114
+ owner,
115
+ });
116
+ }
117
+ insert(_, owner) {
118
+ return new ManyToManyInsertOperation('insert', {
119
+ relation: this,
120
+ owner,
121
+ });
122
+ }
123
+ update(builder, owner) {
124
+ if (isSqlite(builder.knex())) {
125
+ return new ManyToManyUpdateSqliteOperation('update', {
126
+ relation: this,
127
+ owner,
128
+ });
129
+ }
130
+ else {
131
+ return new ManyToManyUpdateOperation('update', {
132
+ relation: this,
133
+ owner,
134
+ });
135
+ }
136
+ }
137
+ patch(builder, owner) {
138
+ if (isSqlite(builder.knex())) {
139
+ return new ManyToManyUpdateSqliteOperation('patch', {
140
+ modelOptions: { patch: true },
141
+ relation: this,
142
+ owner,
143
+ });
144
+ }
145
+ else {
146
+ return new ManyToManyUpdateOperation('patch', {
147
+ modelOptions: { patch: true },
148
+ relation: this,
149
+ owner,
150
+ });
151
+ }
152
+ }
153
+ delete(builder, owner) {
154
+ if (isSqlite(builder.knex())) {
155
+ return new ManyToManyDeleteSqliteOperation('delete', {
156
+ relation: this,
157
+ owner,
158
+ });
159
+ }
160
+ else {
161
+ return new ManyToManyDeleteOperation('delete', {
162
+ relation: this,
163
+ owner,
164
+ });
165
+ }
166
+ }
167
+ relate(builder, owner) {
168
+ return new ManyToManyRelateOperation('relate', {
169
+ relation: this,
170
+ owner,
171
+ });
172
+ }
173
+ unrelate(builder, owner) {
174
+ if (isSqlite(builder.knex())) {
175
+ return new ManyToManyUnrelateSqliteOperation('unrelate', {
176
+ relation: this,
177
+ owner,
178
+ });
179
+ }
180
+ else {
181
+ return new ManyToManyUnrelateOperation('unrelate', {
182
+ relation: this,
183
+ owner,
184
+ });
185
+ }
186
+ }
187
+ createJoinModels(ownerId, related) {
188
+ return related.map((related) => this.createJoinModel(ownerId, related));
189
+ }
190
+ createJoinModel(ownerId, rel) {
191
+ const joinModel = {};
192
+ for (let j = 0, lp = this.joinTableOwnerProp.size; j < lp; ++j) {
193
+ this.joinTableOwnerProp.setProp(joinModel, j, ownerId[j]);
194
+ }
195
+ for (let j = 0, lp = this.joinTableRelatedProp.size; j < lp; ++j) {
196
+ const value = this.relatedProp.getProp(rel, j);
197
+ if (value !== undefined) {
198
+ this.joinTableRelatedProp.setProp(joinModel, j, value);
199
+ }
200
+ }
201
+ for (const extra of this.joinTableExtras) {
202
+ let extraValue = rel[extra.aliasProp];
203
+ if (extraValue === undefined && rel.$$queryProps) {
204
+ extraValue = rel.$$queryProps[extra.aliasProp];
205
+ }
206
+ if (extraValue !== undefined) {
207
+ joinModel[extra.joinTableProp] = extraValue;
208
+ }
209
+ }
210
+ return joinModel;
211
+ }
212
+ omitExtraProps(models) {
213
+ if (this.joinTableExtras && this.joinTableExtras.length) {
214
+ const props = this.joinTableExtras.map((extra) => extra.aliasProp);
215
+ for (const model of models) {
216
+ // Omit extra properties instead of deleting them from the models so that they can
217
+ // be used in the `$before` and `$after` hooks.
218
+ model.$omitFromDatabaseJson(props);
219
+ }
220
+ }
221
+ }
222
+ executeJoinTableBeforeInsert(models, queryContext, result) {
223
+ return mapAfterAllReturn(models, (model) => this.joinTableBeforeInsert(model, queryContext), result);
224
+ }
284
225
  }
285
-
286
226
  Object.defineProperties(ManyToManyRelation.prototype, {
287
- isObjectionManyToManyRelation: {
288
- enumerable: false,
289
- writable: false,
290
- value: true,
291
- },
227
+ isObjectionManyToManyRelation: {
228
+ enumerable: false,
229
+ writable: false,
230
+ value: true,
231
+ },
292
232
  });
293
-
294
233
  function defaultJoinOperation() {
295
- return 'join';
234
+ return 'join';
296
235
  }
297
-
298
236
  function defaultRelatedTableAlias(relation, builder) {
299
- return builder.tableRefFor(relation.relatedModelClass);
237
+ return builder.tableRefFor(relation.relatedModelClass);
300
238
  }
301
-
302
239
  function defaultRelatedJoinSelectQuery(relation, builder) {
303
- return relation.relatedModelClass.query().childQueryOf(builder);
240
+ return relation.relatedModelClass.query().childQueryOf(builder);
304
241
  }
305
-
306
242
  function defaultRelatedTable(relation, builder) {
307
- return builder.tableNameFor(relation.relatedModelClass);
243
+ return builder.tableNameFor(relation.relatedModelClass);
308
244
  }
309
-
310
245
  function defaultOwnerTable(relation, builder) {
311
- return builder.tableRefFor(relation.ownerModelClass);
246
+ return builder.tableRefFor(relation.ownerModelClass);
312
247
  }
313
-
314
248
  function defaultJoinTableAlias(relation, relatedTableAlias, builder) {
315
- const alias = builder.tableRefFor(relation.joinTable);
316
-
317
- if (alias === relation.joinTable) {
318
- return relation.ownerModelClass.joinTableAlias(relatedTableAlias);
319
- } else {
320
- return alias;
321
- }
249
+ const alias = builder.tableRefFor(relation.joinTable);
250
+ if (alias === relation.joinTable) {
251
+ return relation.ownerModelClass.joinTableAlias(relatedTableAlias);
252
+ }
253
+ else {
254
+ return alias;
255
+ }
322
256
  }
323
-
324
257
  function aliasedTableName(tableName, alias) {
325
- if (tableName === alias) {
326
- return tableName;
327
- } else {
328
- return `${tableName} as ${alias}`;
329
- }
258
+ if (tableName === alias) {
259
+ return tableName;
260
+ }
261
+ else {
262
+ return `${tableName} as ${alias}`;
263
+ }
330
264
  }
331
-
332
265
  function checkThroughObject(ctx) {
333
- const mapping = ctx.mapping;
334
-
335
- if (!isObject(mapping.join.through)) {
336
- throw ctx.createError('join must have a `through` object that describes the join table.');
337
- }
338
-
339
- if (!mapping.join.through.from || !mapping.join.through.to) {
340
- throw ctx.createError(
341
- 'join.through must be an object that describes the join table. For example: {from: "JoinTable.someId", to: "JoinTable.someOtherId"}',
342
- );
343
- }
344
-
345
- return ctx;
266
+ const mapping = ctx.mapping;
267
+ if (!isObject(mapping.join.through)) {
268
+ throw ctx.createError('join must have a `through` object that describes the join table.');
269
+ }
270
+ if (!mapping.join.through.from || !mapping.join.through.to) {
271
+ throw ctx.createError('join.through must be an object that describes the join table. For example: {from: "JoinTable.someId", to: "JoinTable.someOtherId"}');
272
+ }
273
+ return ctx;
346
274
  }
347
-
348
275
  function resolveJoinModelClassIfDefined(ctx) {
349
- let joinTableModelClass = null;
350
-
351
- if (ctx.mapping.join.through.modelClass) {
352
- try {
353
- joinTableModelClass = resolveModel(
354
- ctx.mapping.join.through.modelClass,
355
- ctx.ownerModelClass.modelPaths,
356
- 'join.through.modelClass',
357
- );
358
- } catch (err) {
359
- throw ctx.createError(err.message);
360
- }
361
- }
362
-
363
- return Object.assign(ctx, { joinTableModelClass });
276
+ let joinTableModelClass = null;
277
+ if (ctx.mapping.join.through.modelClass) {
278
+ try {
279
+ joinTableModelClass = resolveModel(ctx.mapping.join.through.modelClass, ctx.ownerModelClass.modelPaths, 'join.through.modelClass');
280
+ }
281
+ catch (err) {
282
+ throw ctx.createError(err.message);
283
+ }
284
+ }
285
+ return Object.assign(ctx, { joinTableModelClass });
364
286
  }
365
-
366
287
  function createJoinProperties(ctx) {
367
- let ret;
368
-
369
- let fromProp;
370
- let toProp;
371
-
372
- let relatedProp;
373
- let ownerProp;
374
-
375
- ret = createRelationProperty(ctx, ctx.mapping.join.through.from, 'join.through.from');
376
- fromProp = ret.prop;
377
- ctx = ret.ctx;
378
-
379
- ret = createRelationProperty(ctx, ctx.mapping.join.through.to, 'join.through.to');
380
- toProp = ret.prop;
381
- ctx = ret.ctx;
382
-
383
- if (fromProp.modelClass.getTableName() !== toProp.modelClass.getTableName()) {
384
- throw ctx.createError('join.through `from` and `to` must point to the same join table.');
385
- }
386
-
387
- if (ctx.relatedProp.modelClass.getTableName() === fromProp.modelClass.getTableName()) {
388
- relatedProp = fromProp;
389
- ownerProp = toProp;
390
- } else {
391
- relatedProp = toProp;
392
- ownerProp = fromProp;
393
- }
394
-
395
- return Object.assign(ctx, {
396
- joinTableOwnerProp: ownerProp,
397
- joinTableRelatedProp: relatedProp,
398
- });
288
+ let ret;
289
+ let fromProp;
290
+ let toProp;
291
+ let relatedProp;
292
+ let ownerProp;
293
+ ret = createRelationProperty(ctx, ctx.mapping.join.through.from, 'join.through.from');
294
+ fromProp = ret.prop;
295
+ ctx = ret.ctx;
296
+ ret = createRelationProperty(ctx, ctx.mapping.join.through.to, 'join.through.to');
297
+ toProp = ret.prop;
298
+ ctx = ret.ctx;
299
+ if (fromProp.modelClass.getTableName() !== toProp.modelClass.getTableName()) {
300
+ throw ctx.createError('join.through `from` and `to` must point to the same join table.');
301
+ }
302
+ if (ctx.relatedProp.modelClass.getTableName() === fromProp.modelClass.getTableName()) {
303
+ relatedProp = fromProp;
304
+ ownerProp = toProp;
305
+ }
306
+ else {
307
+ relatedProp = toProp;
308
+ ownerProp = fromProp;
309
+ }
310
+ return Object.assign(ctx, {
311
+ joinTableOwnerProp: ownerProp,
312
+ joinTableRelatedProp: relatedProp,
313
+ });
399
314
  }
400
-
401
315
  function createRelationProperty(ctx, refString, messagePrefix) {
402
- let prop = null;
403
- let joinTableModelClass = ctx.joinTableModelClass;
404
-
405
- const resolveModelClass = (table) => {
406
- if (joinTableModelClass === null) {
407
- joinTableModelClass = inheritModel(getModel());
408
- joinTableModelClass.tableName = table;
409
- joinTableModelClass.idColumn = null;
410
- joinTableModelClass.concurrency = ctx.ownerModelClass.concurrency;
411
- }
412
-
413
- if (joinTableModelClass.getTableName() === table) {
414
- return joinTableModelClass;
415
- } else {
416
- return null;
417
- }
418
- };
419
-
420
- try {
421
- prop = new RelationProperty(refString, resolveModelClass);
422
- } catch (err) {
423
- if (err instanceof RelationProperty.ModelNotFoundError) {
424
- throw ctx.createError('join.through `from` and `to` must point to the same join table.');
425
- } else {
426
- throw ctx.createError(
427
- `${messagePrefix} must have format JoinTable.columnName. For example "JoinTable.someId" or in case of composite key ["JoinTable.a", "JoinTable.b"].`,
428
- );
429
- }
430
- }
431
-
432
- return {
433
- ctx: Object.assign(ctx, { joinTableModelClass }),
434
- prop,
435
- };
436
- }
437
-
438
- function parseExtras(ctx) {
439
- let extraDef = ctx.mapping.join.through.extra;
440
-
441
- if (!extraDef) {
442
- return ctx;
443
- }
444
-
445
- if (isString(extraDef)) {
446
- extraDef = {
447
- [extraDef]: extraDef,
316
+ let prop = null;
317
+ let joinTableModelClass = ctx.joinTableModelClass;
318
+ const resolveModelClass = (table) => {
319
+ if (joinTableModelClass === null) {
320
+ joinTableModelClass = inheritModel(getModel());
321
+ joinTableModelClass.tableName = table;
322
+ joinTableModelClass.idColumn = null;
323
+ joinTableModelClass.concurrency = ctx.ownerModelClass.concurrency;
324
+ }
325
+ if (joinTableModelClass.getTableName() === table) {
326
+ return joinTableModelClass;
327
+ }
328
+ else {
329
+ return null;
330
+ }
448
331
  };
449
- } else if (Array.isArray(extraDef)) {
450
- extraDef = extraDef.reduce((extraDef, col) => {
451
- extraDef[col] = col;
452
- return extraDef;
453
- }, {});
454
- }
455
-
456
- const joinTableExtras = Object.keys(extraDef).map((key) => {
457
- const val = extraDef[key];
458
-
332
+ try {
333
+ prop = new RelationProperty(refString, resolveModelClass);
334
+ }
335
+ catch (err) {
336
+ if (err instanceof RelationProperty.ModelNotFoundError) {
337
+ throw ctx.createError('join.through `from` and `to` must point to the same join table.');
338
+ }
339
+ else {
340
+ throw ctx.createError(`${messagePrefix} must have format JoinTable.columnName. For example "JoinTable.someId" or in case of composite key ["JoinTable.a", "JoinTable.b"].`);
341
+ }
342
+ }
459
343
  return {
460
- joinTableCol: val,
461
- joinTableProp: ctx.joinTableModelClass.columnNameToPropertyName(val),
462
- aliasCol: key,
463
- aliasProp: ctx.joinTableModelClass.columnNameToPropertyName(key),
344
+ ctx: Object.assign(ctx, { joinTableModelClass }),
345
+ prop,
464
346
  };
465
- });
466
-
467
- return Object.assign(ctx, { joinTableExtras });
468
347
  }
469
-
470
- function parseModify(ctx) {
471
- const mapping = ctx.mapping.join.through;
472
- const modifier = mapping.modify || mapping.filter;
473
- const joinTableModify =
474
- modifier &&
475
- createModifier({
476
- modifier,
477
- modelClass: ctx.relatedModelClass,
348
+ function parseExtras(ctx) {
349
+ let extraDef = ctx.mapping.join.through.extra;
350
+ if (!extraDef) {
351
+ return ctx;
352
+ }
353
+ if (isString(extraDef)) {
354
+ extraDef = {
355
+ [extraDef]: extraDef,
356
+ };
357
+ }
358
+ else if (Array.isArray(extraDef)) {
359
+ extraDef = extraDef.reduce((extraDef, col) => {
360
+ extraDef[col] = col;
361
+ return extraDef;
362
+ }, {});
363
+ }
364
+ const joinTableExtras = Object.keys(extraDef).map((key) => {
365
+ const val = extraDef[key];
366
+ return {
367
+ joinTableCol: val,
368
+ joinTableProp: ctx.joinTableModelClass.columnNameToPropertyName(val),
369
+ aliasCol: key,
370
+ aliasProp: ctx.joinTableModelClass.columnNameToPropertyName(key),
371
+ };
478
372
  });
479
-
480
- return Object.assign(ctx, { joinTableModify });
373
+ return Object.assign(ctx, { joinTableExtras });
374
+ }
375
+ function parseModify(ctx) {
376
+ const mapping = ctx.mapping.join.through;
377
+ const modifier = mapping.modify || mapping.filter;
378
+ const joinTableModify = modifier &&
379
+ createModifier({
380
+ modifier,
381
+ modelClass: ctx.relatedModelClass,
382
+ });
383
+ return Object.assign(ctx, { joinTableModify });
481
384
  }
482
-
483
385
  function parseBeforeInsert(ctx) {
484
- let joinTableBeforeInsert;
485
-
486
- if (isFunction(ctx.mapping.join.through.beforeInsert)) {
487
- joinTableBeforeInsert = ctx.mapping.join.through.beforeInsert;
488
- } else {
489
- joinTableBeforeInsert = (model) => model;
490
- }
491
-
492
- return Object.assign(ctx, { joinTableBeforeInsert });
386
+ let joinTableBeforeInsert;
387
+ if (isFunction(ctx.mapping.join.through.beforeInsert)) {
388
+ joinTableBeforeInsert = ctx.mapping.join.through.beforeInsert;
389
+ }
390
+ else {
391
+ joinTableBeforeInsert = (model) => model;
392
+ }
393
+ return Object.assign(ctx, { joinTableBeforeInsert });
493
394
  }
494
-
495
395
  function finalizeJoinModelClass(ctx) {
496
- if (ctx.joinTableModelClass.getIdColumn() === null) {
497
- // We cannot know if the join table has a primary key. Therefore we set some
498
- // known column as the idColumn so that inserts will work.
499
- ctx.joinTableModelClass.idColumn = ctx.joinTableRelatedProp.cols;
500
- }
501
-
502
- return ctx;
396
+ if (ctx.joinTableModelClass.getIdColumn() === null) {
397
+ // We cannot know if the join table has a primary key. Therefore we set some
398
+ // known column as the idColumn so that inserts will work.
399
+ ctx.joinTableModelClass.idColumn = ctx.joinTableRelatedProp.cols;
400
+ }
401
+ return ctx;
503
402
  }
504
-
505
403
  module.exports = {
506
- ManyToManyRelation,
404
+ ManyToManyRelation,
507
405
  };