@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.
- package/README.md +103 -67
- package/lib/index.mjs +6 -0
- package/lib/initialize.js +6 -9
- package/lib/model/AjvValidator.js +235 -282
- package/lib/model/Model.js +653 -823
- package/lib/model/ModifierNotFoundError.js +5 -7
- package/lib/model/NotFoundError.js +14 -18
- package/lib/model/RelationDoesNotExistError.js +6 -9
- package/lib/model/ValidationError.js +33 -41
- package/lib/model/Validator.js +15 -21
- package/lib/model/getModel.js +1 -3
- package/lib/model/graph/ModelGraph.js +44 -64
- package/lib/model/graph/ModelGraphBuilder.js +164 -217
- package/lib/model/graph/ModelGraphEdge.js +31 -43
- package/lib/model/graph/ModelGraphNode.js +192 -231
- package/lib/model/inheritModel.js +9 -18
- package/lib/model/modelBindKnex.js +48 -62
- package/lib/model/modelClone.js +79 -98
- package/lib/model/modelColPropMap.js +16 -26
- package/lib/model/modelConcurrency.js +24 -0
- package/lib/model/modelId.js +44 -49
- package/lib/model/modelJsonAttributes.js +56 -76
- package/lib/model/modelParseRelations.js +68 -67
- package/lib/model/modelQueryProps.js +76 -107
- package/lib/model/modelSet.js +92 -112
- package/lib/model/modelTableMetadata.js +60 -72
- package/lib/model/modelToJson.js +120 -150
- package/lib/model/modelUtils.js +30 -37
- package/lib/model/modelValidate.js +34 -42
- package/lib/model/modelValues.js +78 -91
- package/lib/model/modelVisitor.js +22 -29
- package/lib/objection.js +42 -67
- package/lib/queryBuilder/FunctionBuilder.js +231 -279
- package/lib/queryBuilder/InternalOptions.js +19 -24
- package/lib/queryBuilder/JoinBuilder.js +116 -149
- package/lib/queryBuilder/QueryBuilder.js +1009 -1271
- package/lib/queryBuilder/QueryBuilderBase.js +647 -865
- package/lib/queryBuilder/QueryBuilderContext.js +14 -21
- package/lib/queryBuilder/QueryBuilderContextBase.js +20 -29
- package/lib/queryBuilder/QueryBuilderOperationSupport.js +462 -536
- package/lib/queryBuilder/QueryBuilderUserContext.js +19 -25
- package/lib/queryBuilder/RawBuilder.js +58 -73
- package/lib/queryBuilder/ReferenceBuilder.js +232 -270
- package/lib/queryBuilder/RelationExpression.js +322 -380
- package/lib/queryBuilder/StaticHookArguments.js +94 -106
- package/lib/queryBuilder/ValueBuilder.js +100 -112
- package/lib/queryBuilder/expressions.js +86 -116
- package/lib/queryBuilder/functions/mysql.js +642 -697
- package/lib/queryBuilder/graph/GraphAction.js +44 -59
- package/lib/queryBuilder/graph/GraphData.js +7 -9
- package/lib/queryBuilder/graph/GraphFetcher.js +115 -151
- package/lib/queryBuilder/graph/GraphNodeDbExistence.js +114 -152
- package/lib/queryBuilder/graph/GraphOperation.js +16 -22
- package/lib/queryBuilder/graph/GraphOptions.js +143 -185
- package/lib/queryBuilder/graph/GraphUpsert.js +167 -241
- package/lib/queryBuilder/graph/delete/GraphDelete.js +8 -13
- package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +44 -62
- package/lib/queryBuilder/graph/insert/GraphInsert.js +99 -128
- package/lib/queryBuilder/graph/insert/GraphInsertAction.js +151 -193
- package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +57 -79
- package/lib/queryBuilder/graph/patch/GraphPatch.js +8 -13
- package/lib/queryBuilder/graph/patch/GraphPatchAction.js +181 -234
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +16 -21
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +80 -110
- package/lib/queryBuilder/join/JoinResultColumn.js +14 -18
- package/lib/queryBuilder/join/JoinResultParser.js +88 -101
- package/lib/queryBuilder/join/RelationJoiner.js +205 -288
- package/lib/queryBuilder/join/TableNode.js +117 -144
- package/lib/queryBuilder/join/TableTree.js +60 -76
- package/lib/queryBuilder/join/utils.js +10 -16
- package/lib/queryBuilder/operations/DelegateOperation.js +93 -133
- package/lib/queryBuilder/operations/DeleteOperation.js +33 -37
- package/lib/queryBuilder/operations/FindByIdOperation.js +20 -28
- package/lib/queryBuilder/operations/FindByIdsOperation.js +17 -23
- package/lib/queryBuilder/operations/FindOperation.js +114 -131
- package/lib/queryBuilder/operations/FirstOperation.js +14 -19
- package/lib/queryBuilder/operations/FromOperation.js +69 -88
- package/lib/queryBuilder/operations/InsertAndFetchOperation.js +28 -39
- package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +25 -35
- package/lib/queryBuilder/operations/InsertGraphOperation.js +77 -98
- package/lib/queryBuilder/operations/InsertOperation.js +132 -165
- package/lib/queryBuilder/operations/InstanceDeleteOperation.js +27 -36
- package/lib/queryBuilder/operations/InstanceFindOperation.js +9 -13
- package/lib/queryBuilder/operations/InstanceInsertOperation.js +13 -17
- package/lib/queryBuilder/operations/InstanceUpdateOperation.js +32 -46
- package/lib/queryBuilder/operations/JoinRelatedOperation.js +66 -86
- package/lib/queryBuilder/operations/KnexOperation.js +4 -7
- package/lib/queryBuilder/operations/MergeOperation.js +32 -45
- package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +131 -150
- package/lib/queryBuilder/operations/OnBuildKnexOperation.js +17 -23
- package/lib/queryBuilder/operations/OnBuildOperation.js +17 -23
- package/lib/queryBuilder/operations/OnErrorOperation.js +17 -23
- package/lib/queryBuilder/operations/QueryBuilderOperation.js +231 -270
- package/lib/queryBuilder/operations/RangeOperation.js +30 -40
- package/lib/queryBuilder/operations/RelateOperation.js +14 -21
- package/lib/queryBuilder/operations/ReturningOperation.js +12 -18
- package/lib/queryBuilder/operations/RunAfterOperation.js +17 -23
- package/lib/queryBuilder/operations/RunBeforeOperation.js +17 -23
- package/lib/queryBuilder/operations/UnrelateOperation.js +12 -17
- package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +48 -65
- package/lib/queryBuilder/operations/UpdateOperation.js +104 -129
- package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +25 -35
- package/lib/queryBuilder/operations/UpsertGraphOperation.js +36 -55
- package/lib/queryBuilder/operations/WhereCompositeOperation.js +30 -39
- package/lib/queryBuilder/operations/WhereInOperation.js +34 -36
- package/lib/queryBuilder/operations/eager/EagerOperation.js +37 -52
- package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +34 -44
- package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +4 -7
- package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +193 -251
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +18 -25
- package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +25 -41
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +19 -20
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +23 -21
- package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +106 -118
- package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +79 -108
- package/lib/queryBuilder/operations/select/SelectOperation.js +37 -53
- package/lib/queryBuilder/operations/select/Selection.js +94 -105
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +68 -101
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +65 -75
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +75 -84
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +760 -859
- package/lib/queryBuilder/parsers/relationExpressionParser.js +840 -952
- package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +10 -15
- package/lib/queryBuilder/transformations/QueryTransformation.js +4 -6
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +35 -49
- package/lib/queryBuilder/transformations/index.js +3 -9
- package/lib/queryBuilder/whereScopes.js +158 -186
- package/lib/relations/Relation.js +293 -375
- package/lib/relations/RelationDeleteOperation.js +24 -28
- package/lib/relations/RelationFindOperation.js +108 -138
- package/lib/relations/RelationInsertOperation.js +24 -32
- package/lib/relations/RelationOwner.js +175 -209
- package/lib/relations/RelationProperty.js +186 -223
- package/lib/relations/RelationUpdateOperation.js +23 -29
- package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +16 -21
- package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +30 -41
- package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +36 -47
- package/lib/relations/belongsToOne/BelongsToOneRelation.js +42 -50
- package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +43 -58
- package/lib/relations/hasMany/HasManyInsertOperation.js +40 -56
- package/lib/relations/hasMany/HasManyRelateOperation.js +45 -61
- package/lib/relations/hasMany/HasManyRelation.js +38 -46
- package/lib/relations/hasMany/HasManyUnrelateOperation.js +25 -32
- package/lib/relations/hasOne/HasOneRelation.js +9 -12
- package/lib/relations/hasOneThrough/HasOneThroughRelation.js +9 -12
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +73 -95
- package/lib/relations/manyToMany/ManyToManyRelation.js +374 -473
- package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +23 -30
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +8 -10
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +20 -25
- package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +8 -12
- package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +77 -100
- package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +37 -49
- package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +58 -74
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +10 -13
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +26 -33
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +10 -15
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +8 -10
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +61 -78
- package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +8 -12
- package/lib/transaction.js +53 -83
- package/lib/utils/assert.js +15 -21
- package/lib/utils/buildUtils.js +17 -19
- package/lib/utils/classUtils.js +7 -11
- package/lib/utils/cloneDeep.js +365 -0
- package/lib/utils/createModifier.js +36 -41
- package/lib/utils/deprecate.js +8 -12
- package/lib/utils/identifierMapping.js +153 -192
- package/lib/utils/internalPropUtils.js +4 -8
- package/lib/utils/knexUtils.js +61 -56
- package/lib/utils/mixin.js +16 -23
- package/lib/utils/mysqlJsonPath.js +55 -40
- package/lib/utils/normalizeIds.js +110 -127
- package/lib/utils/objectUtils.js +236 -338
- package/lib/utils/parseFieldExpression.js +66 -44
- package/lib/utils/postgresJsonPath.js +48 -62
- package/lib/utils/promiseUtils/after.js +10 -13
- package/lib/utils/promiseUtils/afterReturn.js +10 -13
- package/lib/utils/promiseUtils/index.js +15 -17
- package/lib/utils/promiseUtils/isPromise.js +6 -9
- package/lib/utils/promiseUtils/map.js +75 -89
- package/lib/utils/promiseUtils/mapAfterAllReturn.js +17 -23
- package/lib/utils/promiseUtils/try.js +15 -18
- package/lib/utils/resolveModel.js +91 -94
- package/lib/utils/tmpColumnUtils.js +4 -13
- package/package.json +50 -23
- package/typings/objection/index.d.mts +362 -0
- package/typings/objection/index.d.ts +36 -9
- package/lib/.eslintrc.json +0 -8
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +0 -97
- package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +0 -141
- 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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
66
|
+
return node.parentEdge.relation.getJoinModelClass(builder.unsafeKnex());
|
|
88
67
|
}
|
|
89
|
-
|
|
90
68
|
module.exports = {
|
|
91
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
153
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
192
|
+
return {
|
|
193
|
+
fork: true,
|
|
194
|
+
isInternalQuery: true,
|
|
195
|
+
};
|
|
246
196
|
}
|
|
247
|
-
|
|
248
197
|
function nonStrictEquals(val1, val2) {
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
25
|
+
GraphRecursiveUpsert,
|
|
31
26
|
};
|