objection 3.1.3 → 3.1.4
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/lib/model/Model.js
CHANGED
|
@@ -219,27 +219,27 @@ class Model {
|
|
|
219
219
|
return this.constructor.traverseAsync(filterConstructor, this, callback);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
$omitFromJson(props) {
|
|
222
|
+
$omitFromJson(...props) {
|
|
223
223
|
if (arguments.length === 0) {
|
|
224
224
|
return this.$$omitFromJson;
|
|
225
225
|
} else {
|
|
226
226
|
if (!this.hasOwnProperty('$$omitFromJson')) {
|
|
227
|
-
defineNonEnumerableProperty(this, '$$omitFromJson',
|
|
228
|
-
} else {
|
|
229
|
-
this.$$omitFromJson = this.$$omitFromJson.concat(props);
|
|
227
|
+
defineNonEnumerableProperty(this, '$$omitFromJson', []);
|
|
230
228
|
}
|
|
229
|
+
this.$$omitFromJson = this.$$omitFromJson.concat(asPropsArray(props));
|
|
230
|
+
return this;
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
$omitFromDatabaseJson(props) {
|
|
234
|
+
$omitFromDatabaseJson(...props) {
|
|
235
235
|
if (arguments.length === 0) {
|
|
236
236
|
return this.$$omitFromDatabaseJson;
|
|
237
237
|
} else {
|
|
238
238
|
if (!this.hasOwnProperty('$$omitFromDatabaseJson')) {
|
|
239
|
-
defineNonEnumerableProperty(this, '$$omitFromDatabaseJson',
|
|
240
|
-
} else {
|
|
241
|
-
this.$$omitFromDatabaseJson = this.$$omitFromDatabaseJson.concat(props);
|
|
239
|
+
defineNonEnumerableProperty(this, '$$omitFromDatabaseJson', []);
|
|
242
240
|
}
|
|
241
|
+
this.$$omitFromDatabaseJson = this.$$omitFromDatabaseJson.concat(asPropsArray(props));
|
|
242
|
+
return this;
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
|
|
@@ -907,6 +907,20 @@ function getTraverseArgs(filterConstructor, models, traverser) {
|
|
|
907
907
|
};
|
|
908
908
|
}
|
|
909
909
|
|
|
910
|
+
function asPropsArray(props) {
|
|
911
|
+
if (props.length === 1) {
|
|
912
|
+
const arg = props[0];
|
|
913
|
+
if (Array.isArray(arg)) {
|
|
914
|
+
return arg;
|
|
915
|
+
} else if (arg && typeof arg === 'object') {
|
|
916
|
+
return Object.entries(arg)
|
|
917
|
+
.filter(([, value]) => value)
|
|
918
|
+
.map(([key]) => key);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return props;
|
|
922
|
+
}
|
|
923
|
+
|
|
910
924
|
module.exports = {
|
|
911
925
|
Model,
|
|
912
926
|
};
|
|
@@ -4,6 +4,7 @@ class InternalOptions {
|
|
|
4
4
|
constructor() {
|
|
5
5
|
this.skipUndefined = false;
|
|
6
6
|
this.keepImplicitJoinProps = false;
|
|
7
|
+
this.returnImmediatelyValue = undefined;
|
|
7
8
|
this.isInternalQuery = false;
|
|
8
9
|
this.debug = false;
|
|
9
10
|
this.schema = undefined;
|
|
@@ -14,6 +15,7 @@ class InternalOptions {
|
|
|
14
15
|
|
|
15
16
|
copy.skipUndefined = this.skipUndefined;
|
|
16
17
|
copy.keepImplicitJoinProps = this.keepImplicitJoinProps;
|
|
18
|
+
copy.returnImmediatelyValue = this.returnImmediatelyValue;
|
|
17
19
|
copy.isInternalQuery = this.isInternalQuery;
|
|
18
20
|
copy.debug = this.debug;
|
|
19
21
|
copy.schema = this.schema;
|
|
@@ -1119,7 +1119,24 @@ function afterExecute(builder, result) {
|
|
|
1119
1119
|
return promise;
|
|
1120
1120
|
}
|
|
1121
1121
|
|
|
1122
|
+
class ReturnImmediatelyException {
|
|
1123
|
+
constructor(value) {
|
|
1124
|
+
this.value = value;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
function handleReturnImmediatelyValue(builder) {
|
|
1129
|
+
const { returnImmediatelyValue } = builder.internalOptions();
|
|
1130
|
+
if (returnImmediatelyValue !== undefined) {
|
|
1131
|
+
throw new ReturnImmediatelyException(returnImmediatelyValue);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1122
1135
|
function handleExecuteError(builder, err) {
|
|
1136
|
+
if (err instanceof ReturnImmediatelyException) {
|
|
1137
|
+
return Promise.resolve(err.value);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1123
1140
|
let promise = Promise.reject(wrapError(err));
|
|
1124
1141
|
|
|
1125
1142
|
builder.forEachOperation(true, (op) => {
|
|
@@ -1139,9 +1156,11 @@ function chainOperationHooks(promise, builder, hookName) {
|
|
|
1139
1156
|
|
|
1140
1157
|
builder.forEachOperation(true, (op) => {
|
|
1141
1158
|
if (op.hasHook(hookName)) {
|
|
1142
|
-
promise = promise.then((result) =>
|
|
1143
|
-
builder.callAsyncOperationMethod(op, hookName, [builder, result])
|
|
1144
|
-
|
|
1159
|
+
promise = promise.then((result) => {
|
|
1160
|
+
const res = builder.callAsyncOperationMethod(op, hookName, [builder, result]);
|
|
1161
|
+
handleReturnImmediatelyValue(builder);
|
|
1162
|
+
return res;
|
|
1163
|
+
});
|
|
1145
1164
|
}
|
|
1146
1165
|
});
|
|
1147
1166
|
|
|
@@ -1261,7 +1280,11 @@ async function chainHooks(promise, builder, func) {
|
|
|
1261
1280
|
let promise = Promise.resolve(result);
|
|
1262
1281
|
|
|
1263
1282
|
if (isFunction(func)) {
|
|
1264
|
-
promise = promise.then((result) =>
|
|
1283
|
+
promise = promise.then((result) => {
|
|
1284
|
+
const res = func.call(builder, result, builder);
|
|
1285
|
+
handleReturnImmediatelyValue(builder);
|
|
1286
|
+
return res;
|
|
1287
|
+
});
|
|
1265
1288
|
} else if (Array.isArray(func)) {
|
|
1266
1289
|
func.forEach((func) => {
|
|
1267
1290
|
promise = chainHooks(promise, builder, func);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { getModel } = require('../../../model/getModel');
|
|
4
4
|
const { GraphAction } = require('../GraphAction');
|
|
5
5
|
const { isInternalProp } = require('../../../utils/internalPropUtils');
|
|
6
|
-
const {
|
|
6
|
+
const { difference, isObject, jsonEquals } = require('../../../utils/objectUtils');
|
|
7
7
|
const promiseUtils = require('../../../utils/promiseUtils');
|
|
8
8
|
|
|
9
9
|
class GraphPatchAction extends GraphAction {
|
|
@@ -33,7 +33,7 @@ class GraphPatchAction extends GraphAction {
|
|
|
33
33
|
|
|
34
34
|
const handleUpdate = () => {
|
|
35
35
|
const { changedProps, unchangedProps } = this._findChanges(node);
|
|
36
|
-
const allProps =
|
|
36
|
+
const allProps = [...changedProps, ...unchangedProps];
|
|
37
37
|
|
|
38
38
|
const propsToUpdate = difference(
|
|
39
39
|
shouldPatch || shouldUpdate
|
|
@@ -59,12 +59,16 @@ class GraphPatchAction extends GraphAction {
|
|
|
59
59
|
// See if the model defines a beforeUpdate or $beforeUpdate hook. If it does
|
|
60
60
|
// not, we can check for updated properties now and drop out immediately if
|
|
61
61
|
// there is nothing to update. Otherwise, we need to wait for the hook to be
|
|
62
|
-
// called before calling handleUpdate
|
|
62
|
+
// called before calling handleUpdate, but only if the node contains changes
|
|
63
|
+
// that aren't id properties (relates). See issues #2233, #2605.
|
|
63
64
|
const hasBeforeUpdate =
|
|
64
65
|
node.obj.constructor.beforeUpdate !== Model.beforeUpdate ||
|
|
65
66
|
node.obj.$beforeUpdate !== Model.prototype.$beforeUpdate;
|
|
66
67
|
|
|
67
|
-
if (
|
|
68
|
+
if (
|
|
69
|
+
(hasBeforeUpdate && !this._hasNonIdPropertyChanges(node)) ||
|
|
70
|
+
(!hasBeforeUpdate && !handleUpdate())
|
|
71
|
+
) {
|
|
68
72
|
return null;
|
|
69
73
|
}
|
|
70
74
|
|
|
@@ -82,24 +86,15 @@ class GraphPatchAction extends GraphAction {
|
|
|
82
86
|
.copyFrom(builder, GraphAction.ReturningAllSelector);
|
|
83
87
|
|
|
84
88
|
if (hasBeforeUpdate) {
|
|
85
|
-
updateBuilder
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
},
|
|
95
|
-
})
|
|
96
|
-
.onError((error) => {
|
|
97
|
-
if (error instanceof ReturnNullException) {
|
|
98
|
-
return null;
|
|
99
|
-
} else {
|
|
100
|
-
return Promise.reject(error);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
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;
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
});
|
|
103
98
|
}
|
|
104
99
|
|
|
105
100
|
if (shouldPatch) {
|
|
@@ -216,6 +211,11 @@ class GraphPatchAction extends GraphAction {
|
|
|
216
211
|
};
|
|
217
212
|
}
|
|
218
213
|
|
|
214
|
+
_hasNonIdPropertyChanges(node) {
|
|
215
|
+
const idProps = node.modelClass.getIdPropertyArray();
|
|
216
|
+
return this._findChanges(node).changedProps.some((prop) => !idProps.includes(prop));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
219
|
_createBuilder(node) {
|
|
220
220
|
if (node.parentEdge && !node.parentEdge.relation.isObjectionHasManyRelation) {
|
|
221
221
|
return this._createRelatedBuilder(node);
|
|
@@ -235,8 +235,6 @@ class GraphPatchAction extends GraphAction {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
class ReturnNullException {}
|
|
239
|
-
|
|
240
238
|
function childQueryOptions() {
|
|
241
239
|
return {
|
|
242
240
|
fork: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "objection",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.4",
|
|
4
4
|
"description": "An SQL-friendly ORM for Node.js",
|
|
5
5
|
"main": "lib/objection.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"mocha": "^10.2.0",
|
|
73
73
|
"mysql": "^2.18.1",
|
|
74
74
|
"pg": "^8.11.3",
|
|
75
|
-
"prettier": "3.
|
|
75
|
+
"prettier": "3.2.5",
|
|
76
76
|
"sqlite3": "^5.1.6",
|
|
77
77
|
"typescript": ">=5.3.2",
|
|
78
78
|
"vuepress": "1.9.10"
|
|
@@ -229,13 +229,14 @@ declare namespace Objection {
|
|
|
229
229
|
}
|
|
230
230
|
: never;
|
|
231
231
|
|
|
232
|
-
type PartialModelGraphField<F> =
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
?
|
|
237
|
-
|
|
238
|
-
|
|
232
|
+
type PartialModelGraphField<F> =
|
|
233
|
+
Defined<F> extends Model
|
|
234
|
+
? PartialModelGraph<Defined<F>>
|
|
235
|
+
: Defined<F> extends Array<infer I>
|
|
236
|
+
? I extends Model
|
|
237
|
+
? PartialModelGraph<I>[]
|
|
238
|
+
: Expression<F>
|
|
239
|
+
: Expression<F>;
|
|
239
240
|
|
|
240
241
|
/**
|
|
241
242
|
* Extracts the property names (excluding relations) of a model class.
|
|
@@ -1699,13 +1700,13 @@ declare namespace Objection {
|
|
|
1699
1700
|
): this;
|
|
1700
1701
|
|
|
1701
1702
|
$set(obj: Pojo): this;
|
|
1702
|
-
$omit(keys: string | string[] | { [key: string]: boolean }): this;
|
|
1703
|
-
$pick(keys: string | string[] | { [key: string]: boolean }): this;
|
|
1704
1703
|
$clone(opt?: CloneOptions): this;
|
|
1705
1704
|
$traverse(filterConstructor: typeof Model, traverser: TraverserFunction): this;
|
|
1706
1705
|
$traverse(traverser: TraverserFunction): this;
|
|
1707
1706
|
$traverseAsync(filterConstructor: typeof Model, traverser: TraverserFunction): Promise<this>;
|
|
1708
1707
|
$traverseAsync(traverser: TraverserFunction): Promise<this>;
|
|
1708
|
+
$omitFromJson(keys: string | string[] | { [key: string]: boolean }): this;
|
|
1709
|
+
$omitFromDatabaseJson(keys: string | string[] | { [key: string]: boolean }): this;
|
|
1709
1710
|
|
|
1710
1711
|
$knex(): Knex;
|
|
1711
1712
|
$transaction(): Knex;
|