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

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 +293 -375
  129. package/lib/relations/RelationDeleteOperation.js +24 -28
  130. package/lib/relations/RelationFindOperation.js +108 -138
  131. package/lib/relations/RelationInsertOperation.js +24 -32
  132. package/lib/relations/RelationOwner.js +175 -209
  133. package/lib/relations/RelationProperty.js +186 -223
  134. package/lib/relations/RelationUpdateOperation.js +23 -29
  135. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +16 -21
  136. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +30 -41
  137. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +36 -47
  138. package/lib/relations/belongsToOne/BelongsToOneRelation.js +42 -50
  139. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +43 -58
  140. package/lib/relations/hasMany/HasManyInsertOperation.js +40 -56
  141. package/lib/relations/hasMany/HasManyRelateOperation.js +45 -61
  142. package/lib/relations/hasMany/HasManyRelation.js +38 -46
  143. package/lib/relations/hasMany/HasManyUnrelateOperation.js +25 -32
  144. package/lib/relations/hasOne/HasOneRelation.js +9 -12
  145. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +9 -12
  146. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +73 -95
  147. package/lib/relations/manyToMany/ManyToManyRelation.js +374 -473
  148. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +23 -30
  149. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +8 -10
  150. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +20 -25
  151. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +8 -12
  152. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +77 -100
  153. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +37 -49
  154. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +58 -74
  155. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +10 -13
  156. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +26 -33
  157. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +10 -15
  158. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +8 -10
  159. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +61 -78
  160. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +8 -12
  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,92 +1,70 @@
1
1
  'use strict';
2
-
3
2
  const { GraphAction } = require('../GraphAction');
4
3
  const { groupBy, chunk } = require('../../../utils/objectUtils');
5
4
  const promiseUtils = require('../../../utils/promiseUtils');
6
-
7
5
  class JoinRowGraphInsertAction extends GraphAction {
8
- constructor(graphData, { nodes }) {
9
- super(graphData);
10
- this.nodes = nodes;
11
- }
12
-
13
- run(builder) {
14
- const batches = this._createInsertBatches(builder);
15
- const concurrency = this._getConcurrency(builder, this.nodes);
16
-
17
- return promiseUtils.map(batches, (batch) => this._insertBatch(builder, batch), { concurrency });
18
- }
19
-
20
- _createInsertBatches(builder) {
21
- const batches = [];
22
- const batchSize = this._getBatchSize(builder);
23
- const nodesByModel = groupBy(this.nodes, (node) => getJoinTableModel(builder, node));
24
-
25
- for (const [joinTableModelClass, nodes] of nodesByModel.entries()) {
26
- for (const nodeBatch of chunk(nodes, batchSize)) {
27
- batches.push(this._createBatch(joinTableModelClass, nodeBatch));
28
- }
6
+ constructor(graphData, { nodes }) {
7
+ super(graphData);
8
+ this.nodes = nodes;
29
9
  }
30
-
31
- return batches;
32
- }
33
-
34
- _createBatch(joinTableModelClass, nodes) {
35
- return nodes
36
- .filter((node) => {
37
- return this.graphOptions.shouldRelate(node, this.graphData) || node.userData.inserted;
38
- })
39
- .map((node) => ({
40
- node,
41
- joinTableModelClass,
42
- joinTableObj: this._createJoinTableObj(joinTableModelClass, node),
43
- }));
44
- }
45
-
46
- _createJoinTableObj(joinTableModelClass, node) {
47
- const { parentEdge, parentNode } = node;
48
- const { relation } = parentEdge;
49
-
50
- this._resolveReferences(node);
51
-
52
- return joinTableModelClass.fromJson(
53
- relation.createJoinModel(relation.ownerProp.getProps(parentNode.obj), node.obj),
54
- );
55
- }
56
-
57
- _insertBatch(parentBuilder, batch) {
58
- return this._beforeInsert(parentBuilder, batch).then(() => this._insert(parentBuilder, batch));
59
- }
60
-
61
- _beforeInsert(parentBuilder, batch) {
62
- return Promise.all(
63
- batch.map(({ node, joinTableObj }) => {
64
- if (node.parentEdge) {
65
- return node.parentEdge.relation.joinTableBeforeInsert(
66
- joinTableObj,
67
- parentBuilder.context(),
68
- );
69
- } else {
70
- return null;
10
+ run(builder) {
11
+ const batches = this._createInsertBatches(builder);
12
+ const concurrency = this._getConcurrency(builder, this.nodes);
13
+ return promiseUtils.map(batches, (batch) => this._insertBatch(builder, batch), { concurrency });
14
+ }
15
+ _createInsertBatches(builder) {
16
+ const batches = [];
17
+ const batchSize = this._getBatchSize(builder);
18
+ const nodesByModel = groupBy(this.nodes, (node) => getJoinTableModel(builder, node));
19
+ for (const [joinTableModelClass, nodes] of nodesByModel.entries()) {
20
+ for (const nodeBatch of chunk(nodes, batchSize)) {
21
+ batches.push(this._createBatch(joinTableModelClass, nodeBatch));
22
+ }
23
+ }
24
+ return batches;
25
+ }
26
+ _createBatch(joinTableModelClass, nodes) {
27
+ return nodes
28
+ .filter((node) => {
29
+ return this.graphOptions.shouldRelate(node, this.graphData) || node.userData.inserted;
30
+ })
31
+ .map((node) => ({
32
+ node,
33
+ joinTableModelClass,
34
+ joinTableObj: this._createJoinTableObj(joinTableModelClass, node),
35
+ }));
36
+ }
37
+ _createJoinTableObj(joinTableModelClass, node) {
38
+ const { parentEdge, parentNode } = node;
39
+ const { relation } = parentEdge;
40
+ this._resolveReferences(node);
41
+ return joinTableModelClass.fromJson(relation.createJoinModel(relation.ownerProp.getProps(parentNode.obj), node.obj));
42
+ }
43
+ _insertBatch(parentBuilder, batch) {
44
+ return this._beforeInsert(parentBuilder, batch).then(() => this._insert(parentBuilder, batch));
45
+ }
46
+ _beforeInsert(parentBuilder, batch) {
47
+ return Promise.all(batch.map(({ node, joinTableObj }) => {
48
+ if (node.parentEdge) {
49
+ return node.parentEdge.relation.joinTableBeforeInsert(joinTableObj, parentBuilder.context());
50
+ }
51
+ else {
52
+ return null;
53
+ }
54
+ }));
55
+ }
56
+ _insert(parentBuilder, batch) {
57
+ if (batch.length > 0) {
58
+ return batch[0].joinTableModelClass
59
+ .query()
60
+ .childQueryOf(parentBuilder)
61
+ .insert(batch.map((it) => it.joinTableObj));
71
62
  }
72
- }),
73
- );
74
- }
75
-
76
- _insert(parentBuilder, batch) {
77
- if (batch.length > 0) {
78
- return batch[0].joinTableModelClass
79
- .query()
80
- .childQueryOf(parentBuilder)
81
- .insert(batch.map((it) => it.joinTableObj));
82
63
  }
83
- }
84
64
  }
85
-
86
65
  function getJoinTableModel(builder, node) {
87
- return node.parentEdge.relation.getJoinModelClass(builder.unsafeKnex());
66
+ return node.parentEdge.relation.getJoinModelClass(builder.unsafeKnex());
88
67
  }
89
-
90
68
  module.exports = {
91
- JoinRowGraphInsertAction,
69
+ JoinRowGraphInsertAction,
92
70
  };
@@ -1,20 +1,15 @@
1
1
  'use strict';
2
-
3
2
  const { GraphOperation } = require('../GraphOperation');
4
3
  const { GraphPatchAction } = require('./GraphPatchAction');
5
-
6
4
  class GraphPatch extends GraphOperation {
7
- createActions() {
8
- return [
9
- new GraphPatchAction(this.graphData, {
10
- nodes: this.graph.nodes.filter((node) =>
11
- this.graphOptions.shouldPatchOrUpdateIgnoreDisable(node, this.graphData),
12
- ),
13
- }),
14
- ];
15
- }
5
+ createActions() {
6
+ return [
7
+ new GraphPatchAction(this.graphData, {
8
+ nodes: this.graph.nodes.filter((node) => this.graphOptions.shouldPatchOrUpdateIgnoreDisable(node, this.graphData)),
9
+ }),
10
+ ];
11
+ }
16
12
  }
17
-
18
13
  module.exports = {
19
- GraphPatch,
14
+ GraphPatch,
20
15
  };
@@ -1,258 +1,205 @@
1
1
  'use strict';
2
-
3
2
  const { getModel } = require('../../../model/getModel');
4
3
  const { GraphAction } = require('../GraphAction');
5
4
  const { isInternalProp } = require('../../../utils/internalPropUtils');
6
5
  const { difference, isObject, jsonEquals } = require('../../../utils/objectUtils');
7
6
  const promiseUtils = require('../../../utils/promiseUtils');
8
-
9
7
  class GraphPatchAction extends GraphAction {
10
- constructor(graphData, { nodes }) {
11
- super(graphData);
12
- // Nodes to patch.
13
- this.nodes = nodes;
14
- }
15
-
16
- run(builder) {
17
- return promiseUtils.map(this.nodes, (node) => this._runForNode(builder, node), {
18
- concurrency: this._getConcurrency(builder, this.nodes),
19
- });
20
- }
21
-
22
- _runForNode(builder, node) {
23
- const shouldPatch = this.graphOptions.shouldPatch(node, this.graphData);
24
- const shouldUpdate = this.graphOptions.shouldUpdate(node, this.graphData);
25
-
26
- // BelongsToOneRelation inserts and relates change the parent object's
27
- // properties. That's why we handle them here.
28
- const changedPropsBecauseOfBelongsToOneInsert = this._handleBelongsToOneInserts(node);
29
-
30
- // BelongsToOneRelation deletes and unrelates change the parent object's
31
- // properties. That's why we handle them here.
32
- const changePropsBecauseOfBelongsToOneDelete = this._handleBelongsToOneDeletes(node);
33
-
34
- const handleUpdate = () => {
35
- const { changedProps, unchangedProps } = this._findChanges(node);
36
- const allProps = [...changedProps, ...unchangedProps];
37
-
38
- const propsToUpdate = difference(
39
- shouldPatch || shouldUpdate
40
- ? changedProps
41
- : [...changedPropsBecauseOfBelongsToOneInsert, ...changePropsBecauseOfBelongsToOneDelete],
42
-
43
- // Remove id properties from the props to update. With upsertGraph
44
- // it never makes sense to change the id.
45
- node.modelClass.getIdPropertyArray(),
46
- );
47
-
48
- const update = propsToUpdate.length > 0;
49
- if (update) {
50
- // Don't update the fields that we know not to change.
51
- node.obj.$omitFromDatabaseJson(difference(allProps, propsToUpdate));
52
- node.userData.updated = true;
53
- }
54
-
55
- return update;
56
- };
57
-
58
- const Model = getModel();
59
- // See if the model defines a beforeUpdate or $beforeUpdate hook. If it does
60
- // not, we can check for updated properties now and drop out immediately if
61
- // there is nothing to update. Otherwise, we need to wait for the hook to be
62
- // called before calling handleUpdate, but only if the node contains changes
63
- // that aren't id properties (relates). See issues #2233, #2605.
64
- const hasBeforeUpdate =
65
- node.obj.constructor.beforeUpdate !== Model.beforeUpdate ||
66
- node.obj.$beforeUpdate !== Model.prototype.$beforeUpdate;
67
-
68
- if (
69
- (hasBeforeUpdate && !this._hasNonIdPropertyChanges(node)) ||
70
- (!hasBeforeUpdate && !handleUpdate())
71
- ) {
72
- return null;
8
+ constructor(graphData, { nodes }) {
9
+ super(graphData);
10
+ // Nodes to patch.
11
+ this.nodes = nodes;
12
+ }
13
+ run(builder) {
14
+ return promiseUtils.map(this.nodes, (node) => this._runForNode(builder, node), {
15
+ concurrency: this._getConcurrency(builder, this.nodes),
16
+ });
73
17
  }
74
-
75
- delete node.obj[node.modelClass.uidProp];
76
- delete node.obj[node.modelClass.uidRefProp];
77
- delete node.obj[node.modelClass.dbRefProp];
78
-
79
- node.obj.$validate(null, {
80
- dataPath: node.dataPathKey,
81
- patch: shouldPatch || (!shouldPatch && !shouldUpdate),
82
- });
83
-
84
- const updateBuilder = this._createBuilder(node)
85
- .childQueryOf(builder, childQueryOptions())
86
- .copyFrom(builder, GraphAction.ReturningAllSelector);
87
-
88
- if (hasBeforeUpdate) {
89
- updateBuilder.internalContext().runBefore.push((result, builder) => {
90
- // Call handleUpdate in the runBefore hook which runs after the
91
- // $beforeUpdate hook, allowing it to modify the object before the
92
- // updated properties are determined. See issue #2233.
93
- if (hasBeforeUpdate && !handleUpdate()) {
94
- builder.internalOptions().returnImmediatelyValue = null;
18
+ _runForNode(builder, node) {
19
+ const shouldPatch = this.graphOptions.shouldPatch(node, this.graphData);
20
+ const shouldUpdate = this.graphOptions.shouldUpdate(node, this.graphData);
21
+ // BelongsToOneRelation inserts and relates change the parent object's
22
+ // properties. That's why we handle them here.
23
+ const changedPropsBecauseOfBelongsToOneInsert = this._handleBelongsToOneInserts(node);
24
+ // BelongsToOneRelation deletes and unrelates change the parent object's
25
+ // properties. That's why we handle them here.
26
+ const changePropsBecauseOfBelongsToOneDelete = this._handleBelongsToOneDeletes(node);
27
+ const handleUpdate = () => {
28
+ const { changedProps, unchangedProps } = this._findChanges(node);
29
+ const allProps = [...changedProps, ...unchangedProps];
30
+ const propsToUpdate = difference(shouldPatch || shouldUpdate
31
+ ? changedProps
32
+ : [...changedPropsBecauseOfBelongsToOneInsert, ...changePropsBecauseOfBelongsToOneDelete],
33
+ // Remove id properties from the props to update. With upsertGraph
34
+ // it never makes sense to change the id.
35
+ node.modelClass.getIdPropertyArray());
36
+ const update = propsToUpdate.length > 0;
37
+ if (update) {
38
+ // Don't update the fields that we know not to change.
39
+ node.obj.$omitFromDatabaseJson(difference(allProps, propsToUpdate));
40
+ node.userData.updated = true;
41
+ }
42
+ return update;
43
+ };
44
+ const Model = getModel();
45
+ // See if the model defines a beforeUpdate or $beforeUpdate hook. If it does
46
+ // not, we can check for updated properties now and drop out immediately if
47
+ // there is nothing to update. Otherwise, we need to wait for the hook to be
48
+ // called before calling handleUpdate, but only if the node contains changes
49
+ // that aren't id properties (relates). See issues #2233, #2605.
50
+ const hasBeforeUpdate = node.obj.constructor.beforeUpdate !== Model.beforeUpdate ||
51
+ node.obj.$beforeUpdate !== Model.prototype.$beforeUpdate;
52
+ if ((hasBeforeUpdate && !this._hasNonIdPropertyChanges(node)) ||
53
+ (!hasBeforeUpdate && !handleUpdate())) {
54
+ return null;
55
+ }
56
+ delete node.obj[node.modelClass.uidProp];
57
+ delete node.obj[node.modelClass.uidRefProp];
58
+ delete node.obj[node.modelClass.dbRefProp];
59
+ node.obj.$validate(null, {
60
+ dataPath: node.dataPathKey,
61
+ patch: shouldPatch || (!shouldPatch && !shouldUpdate),
62
+ });
63
+ const updateBuilder = this._createBuilder(node)
64
+ .childQueryOf(builder, childQueryOptions())
65
+ .copyFrom(builder, GraphAction.ReturningAllSelector);
66
+ if (hasBeforeUpdate) {
67
+ updateBuilder.internalContext().runBefore.push((result, builder) => {
68
+ // Call handleUpdate in the runBefore hook which runs after the
69
+ // $beforeUpdate hook, allowing it to modify the object before the
70
+ // updated properties are determined. See issue #2233.
71
+ if (hasBeforeUpdate && !handleUpdate()) {
72
+ builder.internalOptions().returnImmediatelyValue = null;
73
+ }
74
+ return result;
75
+ });
76
+ }
77
+ if (shouldPatch) {
78
+ updateBuilder.patch(node.obj);
95
79
  }
96
- return result;
97
- });
80
+ else {
81
+ updateBuilder.update(node.obj);
82
+ }
83
+ return updateBuilder.execute().then((result) => {
84
+ if (isObject(result) && result.$isObjectionModel) {
85
+ // Handle returning('*').
86
+ node.obj.$set(result);
87
+ }
88
+ return result;
89
+ });
98
90
  }
99
-
100
- if (shouldPatch) {
101
- updateBuilder.patch(node.obj);
102
- } else {
103
- updateBuilder.update(node.obj);
91
+ _handleBelongsToOneInserts(node) {
92
+ const currentNode = this.currentGraph.nodeForNode(node);
93
+ const updatedProps = [];
94
+ for (const edge of node.edges) {
95
+ if (edge.isOwnerNode(node) &&
96
+ edge.relation &&
97
+ edge.relation.isObjectionBelongsToOneRelation &&
98
+ edge.relation.relatedProp.hasProps(edge.relatedNode.obj)) {
99
+ const { relation } = edge;
100
+ relation.ownerProp.forEach((i) => {
101
+ const currentValue = currentNode && relation.ownerProp.getProp(currentNode.obj, i);
102
+ const relatedValue = relation.relatedProp.getProp(edge.relatedNode.obj, i);
103
+ if (currentValue != relatedValue) {
104
+ relation.ownerProp.setProp(node.obj, i, relatedValue);
105
+ updatedProps.push(relation.ownerProp.props[i]);
106
+ }
107
+ });
108
+ }
109
+ }
110
+ return updatedProps;
104
111
  }
105
-
106
- return updateBuilder.execute().then((result) => {
107
- if (isObject(result) && result.$isObjectionModel) {
108
- // Handle returning('*').
109
- node.obj.$set(result);
110
- }
111
-
112
- return result;
113
- });
114
- }
115
-
116
- _handleBelongsToOneInserts(node) {
117
- const currentNode = this.currentGraph.nodeForNode(node);
118
- const updatedProps = [];
119
-
120
- for (const edge of node.edges) {
121
- if (
122
- edge.isOwnerNode(node) &&
123
- edge.relation &&
124
- edge.relation.isObjectionBelongsToOneRelation &&
125
- edge.relation.relatedProp.hasProps(edge.relatedNode.obj)
126
- ) {
127
- const { relation } = edge;
128
-
129
- relation.ownerProp.forEach((i) => {
130
- const currentValue = currentNode && relation.ownerProp.getProp(currentNode.obj, i);
131
- const relatedValue = relation.relatedProp.getProp(edge.relatedNode.obj, i);
132
-
133
- if (currentValue != relatedValue) {
134
- relation.ownerProp.setProp(node.obj, i, relatedValue);
135
- updatedProps.push(relation.ownerProp.props[i]);
136
- }
137
- });
138
- }
112
+ _handleBelongsToOneDeletes(node) {
113
+ const currentNode = this.currentGraph.nodeForNode(node);
114
+ const updatedProps = [];
115
+ if (!currentNode) {
116
+ return updatedProps;
117
+ }
118
+ for (const edge of currentNode.edges) {
119
+ if (edge.isOwnerNode(currentNode) &&
120
+ edge.relation.isObjectionBelongsToOneRelation &&
121
+ node.obj[edge.relation.name] === null &&
122
+ this.graphOptions.shouldDeleteOrUnrelate(edge.relatedNode, this.graphData)) {
123
+ const { relation } = edge;
124
+ relation.ownerProp.forEach((i) => {
125
+ const currentValue = relation.ownerProp.getProp(currentNode.obj, i);
126
+ if (currentValue != null) {
127
+ relation.ownerProp.setProp(node.obj, i, null);
128
+ updatedProps.push(relation.ownerProp.props[i]);
129
+ }
130
+ });
131
+ }
132
+ }
133
+ return updatedProps;
139
134
  }
140
-
141
- return updatedProps;
142
- }
143
-
144
- _handleBelongsToOneDeletes(node) {
145
- const currentNode = this.currentGraph.nodeForNode(node);
146
- const updatedProps = [];
147
-
148
- if (!currentNode) {
149
- return updatedProps;
135
+ _findChanges(node) {
136
+ const obj = node.obj;
137
+ const currentNode = this.currentGraph.nodeForNode(node);
138
+ const currentObj = (currentNode && currentNode.obj) || {};
139
+ const relationNames = node.modelClass.getRelationNames();
140
+ const unchangedProps = [];
141
+ const changedProps = [];
142
+ for (const prop of Object.keys(obj)) {
143
+ if (isInternalProp(prop) || relationNames.includes(prop)) {
144
+ continue;
145
+ }
146
+ const value = obj[prop];
147
+ const currentValue = currentObj[prop];
148
+ // If the current object doesn't have the property, we have to assume
149
+ // it changes (we cannot know if it will). If the object does have the
150
+ // property, we test non-strict equality. See issue #732.
151
+ if (currentValue === undefined || !nonStrictEquals(currentValue, value)) {
152
+ changedProps.push(prop);
153
+ }
154
+ else {
155
+ unchangedProps.push(prop);
156
+ }
157
+ }
158
+ // We cannot know if the query properties cause changes to the values.
159
+ // We must assume that they do.
160
+ if (obj.$$queryProps) {
161
+ changedProps.push(...Object.keys(obj.$$queryProps));
162
+ }
163
+ return {
164
+ changedProps,
165
+ unchangedProps,
166
+ };
150
167
  }
151
-
152
- for (const edge of currentNode.edges) {
153
- if (
154
- edge.isOwnerNode(currentNode) &&
155
- edge.relation.isObjectionBelongsToOneRelation &&
156
- node.obj[edge.relation.name] === null &&
157
- this.graphOptions.shouldDeleteOrUnrelate(edge.relatedNode, this.graphData)
158
- ) {
159
- const { relation } = edge;
160
-
161
- relation.ownerProp.forEach((i) => {
162
- const currentValue = relation.ownerProp.getProp(currentNode.obj, i);
163
-
164
- if (currentValue != null) {
165
- relation.ownerProp.setProp(node.obj, i, null);
166
- updatedProps.push(relation.ownerProp.props[i]);
167
- }
168
- });
169
- }
168
+ _hasNonIdPropertyChanges(node) {
169
+ const idProps = node.modelClass.getIdPropertyArray();
170
+ return this._findChanges(node).changedProps.some((prop) => !idProps.includes(prop));
170
171
  }
171
-
172
- return updatedProps;
173
- }
174
-
175
- _findChanges(node) {
176
- const obj = node.obj;
177
- const currentNode = this.currentGraph.nodeForNode(node);
178
- const currentObj = (currentNode && currentNode.obj) || {};
179
- const relationNames = node.modelClass.getRelationNames();
180
-
181
- const unchangedProps = [];
182
- const changedProps = [];
183
-
184
- for (const prop of Object.keys(obj)) {
185
- if (isInternalProp(prop) || relationNames.includes(prop)) {
186
- continue;
187
- }
188
-
189
- const value = obj[prop];
190
- const currentValue = currentObj[prop];
191
-
192
- // If the current object doesn't have the property, we have to assume
193
- // it changes (we cannot know if it will). If the object does have the
194
- // property, we test non-strict equality. See issue #732.
195
- if (currentValue === undefined || !nonStrictEquals(currentValue, value)) {
196
- changedProps.push(prop);
197
- } else {
198
- unchangedProps.push(prop);
199
- }
172
+ _createBuilder(node) {
173
+ if (node.parentEdge && !node.parentEdge.relation.isObjectionHasManyRelation) {
174
+ return this._createRelatedBuilder(node);
175
+ }
176
+ else {
177
+ return this._createRootBuilder(node);
178
+ }
200
179
  }
201
-
202
- // We cannot know if the query properties cause changes to the values.
203
- // We must assume that they do.
204
- if (obj.$$queryProps) {
205
- changedProps.push(...Object.keys(obj.$$queryProps));
180
+ _createRelatedBuilder(node) {
181
+ return node.parentNode.obj
182
+ .$relatedQuery(node.parentEdge.relation.name)
183
+ .findById(node.obj.$id());
206
184
  }
207
-
208
- return {
209
- changedProps,
210
- unchangedProps,
211
- };
212
- }
213
-
214
- _hasNonIdPropertyChanges(node) {
215
- const idProps = node.modelClass.getIdPropertyArray();
216
- return this._findChanges(node).changedProps.some((prop) => !idProps.includes(prop));
217
- }
218
-
219
- _createBuilder(node) {
220
- if (node.parentEdge && !node.parentEdge.relation.isObjectionHasManyRelation) {
221
- return this._createRelatedBuilder(node);
222
- } else {
223
- return this._createRootBuilder(node);
185
+ _createRootBuilder(node) {
186
+ const currentNode = this.currentGraph.nodeForNode(node);
187
+ const currentObj = currentNode && currentNode.obj;
188
+ return currentObj ? currentObj.$query() : node.obj.$query();
224
189
  }
225
- }
226
-
227
- _createRelatedBuilder(node) {
228
- return node.parentNode.obj
229
- .$relatedQuery(node.parentEdge.relation.name)
230
- .findById(node.obj.$id());
231
- }
232
-
233
- _createRootBuilder(node) {
234
- const currentNode = this.currentGraph.nodeForNode(node);
235
- const currentObj = currentNode && currentNode.obj;
236
-
237
- return currentObj ? currentObj.$query() : node.obj.$query();
238
- }
239
190
  }
240
-
241
191
  function childQueryOptions() {
242
- return {
243
- fork: true,
244
- isInternalQuery: true,
245
- };
192
+ return {
193
+ fork: true,
194
+ isInternalQuery: true,
195
+ };
246
196
  }
247
-
248
197
  function nonStrictEquals(val1, val2) {
249
- if (val1 == val2) {
250
- return true;
251
- }
252
-
253
- return jsonEquals(val1, val2);
198
+ if (val1 == val2) {
199
+ return true;
200
+ }
201
+ return jsonEquals(val1, val2);
254
202
  }
255
-
256
203
  module.exports = {
257
- GraphPatchAction,
204
+ GraphPatchAction,
258
205
  };
@@ -1,31 +1,26 @@
1
1
  'use strict';
2
-
3
2
  const { GraphOperation } = require('../GraphOperation');
4
3
  const { GraphRecursiveUpsertAction } = require('./GraphRecursiveUpsertAction');
5
-
6
4
  class GraphRecursiveUpsert extends GraphOperation {
7
- createActions() {
8
- return [
9
- new GraphRecursiveUpsertAction(this.graphData, {
10
- nodes: this.graph.nodes.filter((node) => {
11
- const shouldRelate = this.graphOptions.shouldRelate(node, this.graphData);
12
- return shouldRelate && hasRelations(node.obj);
13
- }),
14
- }),
15
- ];
16
- }
5
+ createActions() {
6
+ return [
7
+ new GraphRecursiveUpsertAction(this.graphData, {
8
+ nodes: this.graph.nodes.filter((node) => {
9
+ const shouldRelate = this.graphOptions.shouldRelate(node, this.graphData);
10
+ return shouldRelate && hasRelations(node.obj);
11
+ }),
12
+ }),
13
+ ];
14
+ }
17
15
  }
18
-
19
16
  function hasRelations(obj) {
20
- for (const relationName of obj.constructor.getRelationNames()) {
21
- if (obj[relationName] !== undefined) {
22
- return true;
17
+ for (const relationName of obj.constructor.getRelationNames()) {
18
+ if (obj[relationName] !== undefined) {
19
+ return true;
20
+ }
23
21
  }
24
- }
25
-
26
- return false;
22
+ return false;
27
23
  }
28
-
29
24
  module.exports = {
30
- GraphRecursiveUpsert,
25
+ GraphRecursiveUpsert,
31
26
  };