objection 3.1.5 → 3.3.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.
- package/README.md +16 -16
- package/lib/model/AjvValidator.js +173 -18
- package/lib/model/Model.js +3 -1
- package/lib/model/graph/ModelGraphNode.js +12 -0
- package/lib/model/modelToJson.js +2 -1
- package/lib/queryBuilder/QueryBuilder.js +339 -47
- package/lib/queryBuilder/QueryBuilderOperationSupport.js +5 -0
- package/lib/queryBuilder/ReferenceBuilder.js +5 -3
- package/lib/queryBuilder/RelationExpression.js +21 -9
- package/lib/queryBuilder/StaticHookArguments.js +12 -1
- package/lib/queryBuilder/graph/GraphFetcher.js +3 -1
- package/lib/queryBuilder/graph/GraphOptions.js +21 -2
- package/lib/queryBuilder/graph/GraphUpsert.js +52 -0
- package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +20 -14
- package/lib/queryBuilder/graph/insert/DeferredRelationGraphInsertAction.js +57 -0
- package/lib/queryBuilder/graph/insert/GraphInsert.js +113 -8
- package/lib/queryBuilder/graph/insert/GraphInsertAction.js +10 -1
- package/lib/queryBuilder/graph/patch/GraphPatchAction.js +15 -3
- package/lib/queryBuilder/join/JoinResultParser.js +22 -0
- package/lib/queryBuilder/join/RelationJoiner.js +71 -5
- package/lib/queryBuilder/operations/DelegateOperation.js +4 -0
- package/lib/queryBuilder/operations/InsertAndFetchOperation.js +7 -1
- package/lib/queryBuilder/operations/InsertGraphOperation.js +2 -2
- package/lib/queryBuilder/operations/InsertOperation.js +121 -12
- package/lib/queryBuilder/operations/NoneOperation.js +37 -0
- package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +5 -0
- package/lib/queryBuilder/operations/QueryBuilderOperation.js +4 -0
- package/lib/queryBuilder/operations/ReturningOperation.js +28 -3
- package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +20 -0
- package/lib/queryBuilder/operations/UpdateOperation.js +3 -2
- package/lib/queryBuilder/operations/UpsertGraphOperation.js +5 -0
- package/lib/queryBuilder/operations/WhereGroupOperation.js +41 -0
- package/lib/queryBuilder/operations/eager/EagerOperation.js +7 -5
- package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +4 -2
- package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +9 -20
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasPostgresOperation.js +3 -3
- package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectPostgresOperation.js +1 -1
- package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +45 -32
- package/lib/queryBuilder/operations/select/Selection.js +95 -4
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +6 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +5 -1
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +9 -0
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +81 -43
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +5 -4
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +9 -0
- package/lib/queryBuilder/whereGroups.js +125 -0
- package/lib/relations/Relation.js +5 -2
- package/lib/relations/RelationProperty.js +7 -3
- package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +1 -0
- package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +5 -0
- package/lib/relations/hasMany/HasManyRelateOperation.js +6 -2
- package/lib/relations/hasMany/HasManyUnrelateOperation.js +5 -2
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +26 -3
- package/lib/relations/manyToMany/ManyToManyMySqlModifyMixin.js +66 -0
- package/lib/relations/manyToMany/ManyToManyPostgresModifyMixin.js +27 -0
- package/lib/relations/manyToMany/ManyToManyRelation.js +70 -48
- package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +6 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateMySqlOperation.js +16 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +5 -1
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelatePostgresOperation.js +16 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateMySqlOperation.js +12 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +8 -2
- package/lib/relations/manyToMany/update/ManyToManyUpdatePostgresOperation.js +12 -0
- package/lib/utils/deprecate.js +6 -0
- package/lib/utils/identifierMapping.js +23 -3
- package/lib/utils/objectUtils.js +9 -5
- package/lib/utils/parseFieldExpression.js +28 -0
- package/package.json +22 -14
- package/typings/objection/index.d.ts +339 -68
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ManyToManyUpdateOperationBase } = require('./ManyToManyUpdateOperationBase');
|
|
4
|
+
const { ManyToManyMySqlModifyMixin } = require('../ManyToManyMySqlModifyMixin');
|
|
5
|
+
|
|
6
|
+
class ManyToManyUpdateMySqlOperation extends ManyToManyMySqlModifyMixin(
|
|
7
|
+
ManyToManyUpdateOperationBase,
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
ManyToManyUpdateMySqlOperation,
|
|
12
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { UpdateOperation } = require('../../../queryBuilder/operations/UpdateOperation');
|
|
4
|
+
const { addWhereGroup } = require('../../../queryBuilder/whereGroups');
|
|
4
5
|
|
|
5
6
|
class ManyToManyUpdateOperationBase extends UpdateOperation {
|
|
6
7
|
constructor(name, opt) {
|
|
@@ -44,9 +45,14 @@ class ManyToManyUpdateOperationBase extends UpdateOperation {
|
|
|
44
45
|
.childQueryOf(builder)
|
|
45
46
|
.patch(this.joinTablePatch);
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
this.
|
|
48
|
+
addWhereGroup(joinTableUpdateQuery, () =>
|
|
49
|
+
this.applyModifyFilterForJoinTable(joinTableUpdateQuery),
|
|
49
50
|
);
|
|
51
|
+
addWhereGroup(joinTableUpdateQuery, () =>
|
|
52
|
+
joinTableUpdateQuery.modify(this.relation.joinTableModify),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
await joinTableUpdateQuery;
|
|
50
56
|
return result;
|
|
51
57
|
} else {
|
|
52
58
|
return result;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ManyToManyUpdateOperationBase } = require('./ManyToManyUpdateOperationBase');
|
|
4
|
+
const { ManyToManyPostgresModifyMixin } = require('../ManyToManyPostgresModifyMixin');
|
|
5
|
+
|
|
6
|
+
class ManyToManyUpdatePostgresOperation extends ManyToManyPostgresModifyMixin(
|
|
7
|
+
ManyToManyUpdateOperationBase,
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
ManyToManyUpdatePostgresOperation,
|
|
12
|
+
};
|
package/lib/utils/deprecate.js
CHANGED
|
@@ -10,6 +10,12 @@ function deprecate(message) {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
// Only meant for tests that need to see a deprecation message again.
|
|
14
|
+
function resetDeprecations() {
|
|
15
|
+
LOGGED_DEPRECATIONS.clear();
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
module.exports = {
|
|
14
19
|
deprecate,
|
|
20
|
+
resetDeprecations,
|
|
15
21
|
};
|
|
@@ -27,6 +27,7 @@ function snakeCase(
|
|
|
27
27
|
upperCase = false,
|
|
28
28
|
underscoreBeforeDigits = false,
|
|
29
29
|
underscoreBetweenUppercaseLetters = false,
|
|
30
|
+
noDoubleUnderscores = false,
|
|
30
31
|
} = {},
|
|
31
32
|
) {
|
|
32
33
|
if (str.length === 0) {
|
|
@@ -48,11 +49,16 @@ function snakeCase(
|
|
|
48
49
|
const lowerChar = lower[i];
|
|
49
50
|
const prevLowerChar = lower[i - 1];
|
|
50
51
|
|
|
52
|
+
// If noDoubleUnderscores is true, never insert an underscore directly
|
|
53
|
+
// after an existing one (e.g. "foo_1" stays "foo_1" instead of becoming
|
|
54
|
+
// "foo__1" when underscoreBeforeDigits is true).
|
|
55
|
+
const canInsertUnderscore = !noDoubleUnderscores || prevChar !== '_';
|
|
56
|
+
|
|
51
57
|
// If underScoreBeforeDigits is true then, well, insert an underscore
|
|
52
58
|
// before digits :). Only the first digit gets an underscore if
|
|
53
59
|
// there are multiple.
|
|
54
60
|
if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
|
|
55
|
-
out += '_' + char;
|
|
61
|
+
out += canInsertUnderscore ? '_' + char : char;
|
|
56
62
|
continue;
|
|
57
63
|
}
|
|
58
64
|
|
|
@@ -65,7 +71,7 @@ function snakeCase(
|
|
|
65
71
|
// If underscoreBetweenUppercaseLetters is true, we always place an underscore
|
|
66
72
|
// before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
|
|
67
73
|
// Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
|
|
68
|
-
if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
|
|
74
|
+
if (canInsertUnderscore && (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase)) {
|
|
69
75
|
out += '_' + lowerChar;
|
|
70
76
|
} else {
|
|
71
77
|
out += lowerChar;
|
|
@@ -162,10 +168,24 @@ function keyMapper(mapper) {
|
|
|
162
168
|
};
|
|
163
169
|
}
|
|
164
170
|
|
|
171
|
+
// Returns a function that only calls `mapper` for the part of the input string
|
|
172
|
+
// before the first `separator`, and leaves the rest untouched. For field
|
|
173
|
+
// expressions like `jsonColumn:some.jsonPath` this maps the column but keeps
|
|
174
|
+
// the json path as is. Column names can't contain `:`, so the first one marks
|
|
175
|
+
// the boundary.
|
|
176
|
+
function mapFirstPart(mapper, separator) {
|
|
177
|
+
return (str) => {
|
|
178
|
+
const idx = str.indexOf(separator);
|
|
179
|
+
return idx === -1 ? mapper(str) : mapper(str.slice(0, idx)) + str.slice(idx);
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
165
183
|
function snakeCaseMappers(opt = {}) {
|
|
184
|
+
const format = (str) => snakeCase(str, opt);
|
|
185
|
+
|
|
166
186
|
return {
|
|
167
187
|
parse: keyMapper(memoize((str) => camelCase(str, opt))),
|
|
168
|
-
format: keyMapper(memoize(
|
|
188
|
+
format: keyMapper(memoize(opt.preserveJsonKeys ? mapFirstPart(format, ':') : format)),
|
|
169
189
|
};
|
|
170
190
|
}
|
|
171
191
|
|
package/lib/utils/objectUtils.js
CHANGED
|
@@ -123,13 +123,17 @@ function union(arr1, arr2) {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
function unionSmall(arr1, arr2) {
|
|
126
|
-
const all =
|
|
126
|
+
const all = [];
|
|
127
127
|
|
|
128
|
-
for (let i = 0, l =
|
|
129
|
-
|
|
128
|
+
for (let i = 0, l = arr1.length; i < l; ++i) {
|
|
129
|
+
if (all.indexOf(arr1[i]) === -1) {
|
|
130
|
+
all.push(arr1[i]);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
130
133
|
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
for (let i = 0, l = arr2.length; i < l; ++i) {
|
|
135
|
+
if (all.indexOf(arr2[i]) === -1) {
|
|
136
|
+
all.push(arr2[i]);
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
|
|
@@ -46,6 +46,34 @@ function freezeParsedExpr(parsedExpr) {
|
|
|
46
46
|
return parsedExpr;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// Formats the json path of a parsed field expression as a Postgres text array
|
|
50
|
+
// literal, e.g. `{a,"",b}`. Keys that would otherwise be misread (empty keys,
|
|
51
|
+
// keys with whitespace, delimiters, quotes or backslashes and `NULL`) are
|
|
52
|
+
// double-quoted, with quotes and backslashes escaped.
|
|
53
|
+
function toPostgresJsonPath(access) {
|
|
54
|
+
const keys = access.map(({ ref }) => {
|
|
55
|
+
const key = String(ref);
|
|
56
|
+
return key === '' || /[{}",\\\s]/.test(key) || key.toUpperCase() === 'NULL'
|
|
57
|
+
? `"${key.replace(/["\\]/g, '\\$&')}"`
|
|
58
|
+
: key;
|
|
59
|
+
});
|
|
60
|
+
return `{${keys.join(',')}}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Formats the json path of a parsed field expression as a quoted string literal
|
|
64
|
+
// to be used in raw knex SQL, e.g. `'{a,b}'`. The path can't be passed as a
|
|
65
|
+
// binding, as knex doesn't keep the order of bindings in raw columns (e.g. in
|
|
66
|
+
// `whereIn(ref(...), values)`), so the keys need to be escaped instead: single
|
|
67
|
+
// quotes are doubled, and `?` is escaped so that knex doesn't read it as a
|
|
68
|
+
// binding placeholder. Backslashes are always doubled by `toPostgresJsonPath()`,
|
|
69
|
+
// so they can't escape the closing quote either.
|
|
70
|
+
function toPostgresJsonPathLiteral(access) {
|
|
71
|
+
const path = toPostgresJsonPath(access).replace(/'/g, "''").replace(/\?/g, '\\?');
|
|
72
|
+
return `'${path}'`;
|
|
73
|
+
}
|
|
74
|
+
|
|
49
75
|
module.exports = {
|
|
50
76
|
parseFieldExpression,
|
|
77
|
+
toPostgresJsonPath,
|
|
78
|
+
toPostgresJsonPathLiteral,
|
|
51
79
|
};
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "objection",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "An SQL-friendly ORM for Node.js",
|
|
5
5
|
"main": "lib/objection.js",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "npm run eslint && mocha --slow 10 --timeout 15000 --reporter spec --recursive tests --exclude \"tests/unit/relations/files/**\" && npm run test:typings",
|
|
9
9
|
"test:fast": "mocha --slow 10 --timeout 15000 --reporter spec --recursive tests --bail --exclude \"tests/unit/relations/files/**\"",
|
|
10
|
-
"test:typings": "tsc",
|
|
10
|
+
"test:typings": "tsc && prettier --check \"typings/**/*.ts\" \"tests/ts/**/*.ts\"",
|
|
11
11
|
"prettier": "prettier --write \"{examples,lib,tests,testUtils,typings,doc}/**/*.{js,ts}\"",
|
|
12
12
|
"eslint": "eslint --format codeframe \"examples/**/*.js\" \"lib/**/*.js\" \"tests/**/*.js\"",
|
|
13
|
-
"docs:dev": "
|
|
14
|
-
"docs:build": "
|
|
13
|
+
"docs:dev": "vitepress dev doc",
|
|
14
|
+
"docs:build": "vitepress build doc",
|
|
15
|
+
"docs:preview": "vitepress preview doc"
|
|
15
16
|
},
|
|
16
17
|
"publishConfig": {
|
|
17
18
|
"tag": "latest"
|
|
@@ -30,8 +31,12 @@
|
|
|
30
31
|
],
|
|
31
32
|
"repository": {
|
|
32
33
|
"type": "git",
|
|
33
|
-
"url": "git://github.com/
|
|
34
|
+
"url": "git+https://github.com/ditojs/objection.git"
|
|
34
35
|
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/ditojs/objection/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://ditojs.github.io/objection/",
|
|
35
40
|
"engines": {
|
|
36
41
|
"node": ">=14.0.0"
|
|
37
42
|
},
|
|
@@ -54,27 +59,30 @@
|
|
|
54
59
|
"types": "./typings/objection/index.d.ts",
|
|
55
60
|
"dependencies": {
|
|
56
61
|
"ajv": "^8.17.1",
|
|
57
|
-
"ajv-formats": "^
|
|
62
|
+
"ajv-formats": "^3.0.1",
|
|
58
63
|
"db-errors": "^0.2.3"
|
|
59
64
|
},
|
|
60
65
|
"peerDependencies": {
|
|
61
66
|
"knex": ">=1.0.1"
|
|
62
67
|
},
|
|
63
68
|
"devDependencies": {
|
|
64
|
-
"@types/node": "^22.
|
|
69
|
+
"@types/node": "^22.15.3",
|
|
70
|
+
"bluebird": "^3.7.2",
|
|
65
71
|
"chai": "^4.3.10",
|
|
66
72
|
"chai-subset": "^1.6.0",
|
|
67
73
|
"eslint": "^8.54.0",
|
|
68
74
|
"eslint-formatter-codeframe": "^7.32.1",
|
|
69
|
-
"eslint-plugin-prettier": "^5.
|
|
75
|
+
"eslint-plugin-prettier": "^5.3.1",
|
|
70
76
|
"expect.js": "^0.3.1",
|
|
71
|
-
"knex": "^3.
|
|
72
|
-
"
|
|
77
|
+
"knex": "^3.3.0",
|
|
78
|
+
"lodash": "^4.18.1",
|
|
79
|
+
"mocha": "^11.2.2",
|
|
73
80
|
"mysql": "^2.18.1",
|
|
74
|
-
"pg": "^8.
|
|
75
|
-
"prettier": "3.
|
|
81
|
+
"pg": "^8.15.6",
|
|
82
|
+
"prettier": "3.9.9",
|
|
76
83
|
"sqlite3": "^5.1.7",
|
|
77
|
-
"typescript": ">=5.
|
|
78
|
-
"
|
|
84
|
+
"typescript": ">=5.8.3",
|
|
85
|
+
"uuid": "^9.0.1",
|
|
86
|
+
"vitepress": "1.6.4"
|
|
79
87
|
}
|
|
80
88
|
}
|