objection 3.6.0 → 3.7.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/lib/model/AjvValidator.js +33 -10
- package/lib/model/modelClone.js +0 -2
- package/lib/queryBuilder/QueryBuilder.js +56 -10
- package/lib/queryBuilder/RelationExpression.js +6 -4
- package/lib/queryBuilder/graph/GraphOptions.js +27 -55
- package/lib/queryBuilder/graph/GraphUpsert.js +22 -0
- package/lib/queryBuilder/graph/insert/GraphInsert.js +2 -0
- package/lib/queryBuilder/operations/InstanceUpdateOperation.js +6 -1
- package/lib/queryBuilder/operations/UpdateOperation.js +11 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +3 -1
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +4 -9
- package/lib/queryBuilder/parsers/relationExpressionParser.js +1 -1
- package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +1 -1
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +4 -7
- package/lib/relations/Relation.js +1 -0
- package/lib/relations/RelationFindOperation.js +21 -39
- package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +4 -2
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +39 -15
- package/lib/relations/manyToMany/ManyToManyMySqlModifyMixin.js +31 -42
- package/lib/relations/manyToMany/ManyToManyRelation.js +8 -16
- package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +0 -13
- package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +2 -3
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateMySqlOperation.js +1 -5
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +1 -5
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +9 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +1 -5
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +7 -1
- package/lib/utils/identifierMapping.js +8 -17
- package/lib/utils/objectUtils.js +38 -6
- package/lib/utils/parseFieldExpression.js +10 -3
- package/package.json +1 -1
- package/typings/objection/index.d.ts +46 -26
- package/lib/relations/manyToMany/ManyToManyPostgresModifyMixin.js +0 -27
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelatePostgresOperation.js +0 -16
- package/lib/relations/manyToMany/update/ManyToManyUpdatePostgresOperation.js +0 -12
package/lib/utils/objectUtils.js
CHANGED
|
@@ -388,11 +388,43 @@ function mergeMaps(map1, map2) {
|
|
|
388
388
|
return map;
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
//
|
|
392
|
-
//
|
|
393
|
-
//
|
|
394
|
-
//
|
|
395
|
-
|
|
391
|
+
// Returns the tag of `value` like `Object.prototype.toString()`, but ignores a
|
|
392
|
+
// `Symbol.toStringTag` that can be overwritten, like lodash's `baseGetTag()`.
|
|
393
|
+
// Objects that define a writable tag, like decimal.js numbers, are plain
|
|
394
|
+
// objects then, while built-ins like `URL` keep their own tag.
|
|
395
|
+
function getRawTag(value) {
|
|
396
|
+
const tag = Object.prototype.toString.call(value);
|
|
397
|
+
|
|
398
|
+
if (!(Symbol.toStringTag in value)) {
|
|
399
|
+
return tag;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const isOwn = Object.prototype.hasOwnProperty.call(value, Symbol.toStringTag);
|
|
403
|
+
const ownTag = value[Symbol.toStringTag];
|
|
404
|
+
|
|
405
|
+
try {
|
|
406
|
+
value[Symbol.toStringTag] = undefined;
|
|
407
|
+
} catch (err) {
|
|
408
|
+
return tag;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const rawTag = Object.prototype.toString.call(value);
|
|
412
|
+
|
|
413
|
+
if (isOwn) {
|
|
414
|
+
value[Symbol.toStringTag] = ownTag;
|
|
415
|
+
} else {
|
|
416
|
+
delete value[Symbol.toStringTag];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return rawTag;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Clones `value` deeply, like lodash's `cloneDeep()`: plain objects and class
|
|
423
|
+
// instances keep their prototype and get copies of their own enumerable
|
|
424
|
+
// properties, symbols included. Arrays, dates, regular expressions, maps,
|
|
425
|
+
// sets, buffers, typed arrays and array buffers are copied, circular
|
|
426
|
+
// references are kept. Anything else, like functions, errors and built-ins
|
|
427
|
+
// with internal state like `URL`, is kept as it is.
|
|
396
428
|
function cloneDeep(value, clones = new Map()) {
|
|
397
429
|
if (!isObject(value)) {
|
|
398
430
|
return value;
|
|
@@ -401,7 +433,7 @@ function cloneDeep(value, clones = new Map()) {
|
|
|
401
433
|
}
|
|
402
434
|
|
|
403
435
|
const Ctor = value.constructor;
|
|
404
|
-
const tag =
|
|
436
|
+
const tag = getRawTag(value);
|
|
405
437
|
let copy;
|
|
406
438
|
|
|
407
439
|
if (tag === '[object Object]') {
|
|
@@ -66,10 +66,17 @@ function toPostgresJsonPath(access) {
|
|
|
66
66
|
// `whereIn(ref(...), values)`), so the keys need to be escaped instead: single
|
|
67
67
|
// quotes are doubled, and `?` is escaped so that knex doesn't read it as a
|
|
68
68
|
// binding placeholder. Backslashes are always doubled by `toPostgresJsonPath()`,
|
|
69
|
-
// so they can't escape the closing quote either.
|
|
69
|
+
// so they can't escape the closing quote either. But knex's Postgres dialect
|
|
70
|
+
// drops all backslashes in front of an escaped `?`, so if the path contains any,
|
|
71
|
+
// an escape string literal is used in which backslashes are written as `\134`.
|
|
70
72
|
function toPostgresJsonPathLiteral(access) {
|
|
71
|
-
const path = toPostgresJsonPath(access).replace(/'/g, "''")
|
|
72
|
-
|
|
73
|
+
const path = toPostgresJsonPath(access).replace(/'/g, "''");
|
|
74
|
+
|
|
75
|
+
if (path.includes('\\?')) {
|
|
76
|
+
return `E'${path.replace(/\\/g, '\\134').replace(/\?/g, '\\?')}'`;
|
|
77
|
+
} else {
|
|
78
|
+
return `'${path.replace(/\?/g, '\\?')}'`;
|
|
79
|
+
}
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
module.exports = {
|
package/package.json
CHANGED
|
@@ -374,7 +374,8 @@ declare namespace Objection {
|
|
|
374
374
|
|
|
375
375
|
/**
|
|
376
376
|
* Converts the query builder NQB to the same result kind as QB:
|
|
377
|
-
* array, single, maybe-single or page.
|
|
377
|
+
* array, single, maybe-single or page. Any other result type, e.g. after
|
|
378
|
+
* `castTo()` or `patch()`, falls back to QB, without narrowing.
|
|
378
379
|
*/
|
|
379
380
|
type WithResultKind<QB extends AnyQueryBuilder, NQB extends AnyQueryBuilder> = [
|
|
380
381
|
ResultType<QB>,
|
|
@@ -423,7 +424,9 @@ declare namespace Objection {
|
|
|
423
424
|
? I extends Model
|
|
424
425
|
? I[] | PartialModelObject<I>[]
|
|
425
426
|
: Expression<T[K]>
|
|
426
|
-
:
|
|
427
|
+
: NonNullable<T[K]> extends Model
|
|
428
|
+
? Expression<T[K]> | PartialModelObject<NonNullable<T[K]>> // nullable to-one relations
|
|
429
|
+
: Expression<T[K]>;
|
|
427
430
|
};
|
|
428
431
|
|
|
429
432
|
/**
|
|
@@ -1000,14 +1003,36 @@ declare namespace Objection {
|
|
|
1000
1003
|
includeTriggerModifications?: boolean;
|
|
1001
1004
|
}
|
|
1002
1005
|
|
|
1006
|
+
type ReturningColumn = string | Raw | readonly (string | Raw)[];
|
|
1007
|
+
|
|
1008
|
+
/**
|
|
1009
|
+
* The arguments of `returning()`: any number of columns or column arrays,
|
|
1010
|
+
* optionally followed by an options object.
|
|
1011
|
+
*/
|
|
1012
|
+
type ReturningArgs =
|
|
1013
|
+
ReturningColumn[] | [ReturningColumn, ...ReturningColumn[], ReturningOptions | undefined];
|
|
1014
|
+
|
|
1003
1015
|
interface ReturningMethod {
|
|
1004
1016
|
<QB extends AnyQueryBuilder>(
|
|
1005
1017
|
this: QB,
|
|
1006
|
-
|
|
1007
|
-
options?: ReturningOptions,
|
|
1018
|
+
...args: ReturningArgs
|
|
1008
1019
|
): QB extends NumberQueryBuilder<QB> ? ArrayQueryBuilder<QB> : QB;
|
|
1009
1020
|
}
|
|
1010
1021
|
|
|
1022
|
+
/**
|
|
1023
|
+
* With `returning()`, `relate()` returns the inserted join rows for
|
|
1024
|
+
* many-to-many relations, the updated related rows for has-many relations
|
|
1025
|
+
* and the updated owner rows for belongs-to-one relations. The typings can't
|
|
1026
|
+
* tell these apart, so the rows are typed as `any`.
|
|
1027
|
+
*/
|
|
1028
|
+
interface RelateReturningMethod<M extends Model> {
|
|
1029
|
+
(...args: ReturningArgs): QueryBuilder<M, any[]>;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
type RelateQueryBuilder<QB extends AnyQueryBuilder> = {
|
|
1033
|
+
returning: RelateReturningMethod<ModelType<QB>>;
|
|
1034
|
+
} & NumberQueryBuilder<QB>;
|
|
1035
|
+
|
|
1011
1036
|
interface TimeoutOptions {
|
|
1012
1037
|
cancel: boolean;
|
|
1013
1038
|
}
|
|
@@ -1060,6 +1085,7 @@ declare namespace Objection {
|
|
|
1060
1085
|
export interface InsertGraphOptions {
|
|
1061
1086
|
relate?: boolean | string | string[];
|
|
1062
1087
|
allowRefs?: boolean;
|
|
1088
|
+
allowMarkers?: boolean;
|
|
1063
1089
|
}
|
|
1064
1090
|
|
|
1065
1091
|
interface InsertGraphMethod<M extends Model> {
|
|
@@ -1087,6 +1113,7 @@ declare namespace Objection {
|
|
|
1087
1113
|
noRelate?: boolean | string | string[];
|
|
1088
1114
|
noUnrelate?: boolean | string | string[];
|
|
1089
1115
|
allowRefs?: boolean;
|
|
1116
|
+
allowMarkers?: boolean;
|
|
1090
1117
|
}
|
|
1091
1118
|
|
|
1092
1119
|
interface UpsertGraphMethod<M extends Model> {
|
|
@@ -1386,7 +1413,7 @@ declare namespace Objection {
|
|
|
1386
1413
|
|
|
1387
1414
|
relate(
|
|
1388
1415
|
ids: MaybeCompositeId | MaybeCompositeId[] | PartialModelObject<M> | PartialModelObject<M>[],
|
|
1389
|
-
):
|
|
1416
|
+
): RelateQueryBuilder<this>;
|
|
1390
1417
|
|
|
1391
1418
|
unrelate(): NumberQueryBuilder<this>;
|
|
1392
1419
|
for(ids: ForIdValue | ForIdValue[]): this;
|
|
@@ -1718,34 +1745,25 @@ declare namespace Objection {
|
|
|
1718
1745
|
constructor(config: AjvConfig);
|
|
1719
1746
|
}
|
|
1720
1747
|
|
|
1721
|
-
|
|
1748
|
+
/**
|
|
1749
|
+
* The options shared by `snakeCaseMappers` and `knexSnakeCaseMappers`.
|
|
1750
|
+
*/
|
|
1751
|
+
export interface SnakeCaseOptions {
|
|
1722
1752
|
upperCase?: boolean;
|
|
1723
1753
|
underscoreBeforeDigits?: boolean;
|
|
1724
1754
|
underscoreBetweenUppercaseLetters?: boolean;
|
|
1725
1755
|
noDoubleUnderscores?: boolean;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
export interface SnakeCaseMappersOptions extends SnakeCaseOptions {
|
|
1726
1759
|
/**
|
|
1727
1760
|
* Only convert the column part of field expressions like
|
|
1728
1761
|
* `jsonColumn:someKey` and keep their JSON keys as written.
|
|
1729
|
-
* Only used by `snakeCaseMappers`.
|
|
1730
1762
|
*/
|
|
1731
1763
|
preserveJsonKeys?: boolean;
|
|
1732
|
-
/**
|
|
1733
|
-
* Also convert the keys of plain objects one level down in the results,
|
|
1734
|
-
* e.g. the rows of knex's `nestTables: true` option on MySQL. Also applies
|
|
1735
|
-
* to JSON columns parsed by the driver.
|
|
1736
|
-
* Only used by `knexSnakeCaseMappers`.
|
|
1737
|
-
*/
|
|
1738
|
-
mapNestedKeys?: boolean;
|
|
1739
1764
|
}
|
|
1740
1765
|
|
|
1741
|
-
export interface
|
|
1742
|
-
/**
|
|
1743
|
-
* Also convert the keys of plain objects one level down in the results,
|
|
1744
|
-
* e.g. the rows of knex's `nestTables: true` option on MySQL. Also applies
|
|
1745
|
-
* to JSON columns parsed by the driver.
|
|
1746
|
-
*/
|
|
1747
|
-
mapNestedKeys?: boolean;
|
|
1748
|
-
}
|
|
1766
|
+
export interface KnexSnakeCaseMappersOptions extends SnakeCaseOptions {}
|
|
1749
1767
|
|
|
1750
1768
|
export interface ColumnNameMappers {
|
|
1751
1769
|
parse(json: Pojo): Pojo;
|
|
@@ -1762,11 +1780,11 @@ declare namespace Objection {
|
|
|
1762
1780
|
}
|
|
1763
1781
|
|
|
1764
1782
|
export interface KnexSnakeCaseMappersFactory {
|
|
1765
|
-
(options?:
|
|
1783
|
+
(options?: KnexSnakeCaseMappersOptions): KnexMappers;
|
|
1766
1784
|
}
|
|
1767
1785
|
|
|
1768
1786
|
export interface KnexIdentifierMappingFactory {
|
|
1769
|
-
(colToProp: Record<string, string
|
|
1787
|
+
(colToProp: Record<string, string>): KnexMappers;
|
|
1770
1788
|
}
|
|
1771
1789
|
|
|
1772
1790
|
export type ValidationErrorType =
|
|
@@ -2040,14 +2058,16 @@ declare namespace Objection {
|
|
|
2040
2058
|
static bindKnex<M>(this: M, trxOrKnex: TransactionOrKnex): M;
|
|
2041
2059
|
static bindTransaction<M>(this: M, trxOrKnex: TransactionOrKnex): M;
|
|
2042
2060
|
|
|
2043
|
-
|
|
2061
|
+
// E defaults to `string` so that `fetchGraph<Person>(...)` still compiles,
|
|
2062
|
+
// without narrowing, as TypeScript doesn't infer the remaining arguments.
|
|
2063
|
+
static fetchGraph<M extends Model, const E extends RelationExpression<M> = string>(
|
|
2044
2064
|
this: ConstructorType<M>,
|
|
2045
2065
|
modelOrObject: PartialModelObject<M>,
|
|
2046
2066
|
expression: E,
|
|
2047
2067
|
options?: FetchGraphOptions,
|
|
2048
2068
|
): SingleQueryBuilder<WithGraphModelQueryBuilder<M, E>>;
|
|
2049
2069
|
|
|
2050
|
-
static fetchGraph<M extends Model, const E extends RelationExpression<M
|
|
2070
|
+
static fetchGraph<M extends Model, const E extends RelationExpression<M> = string>(
|
|
2051
2071
|
this: ConstructorType<M>,
|
|
2052
2072
|
modelOrObject: PartialModelObject<M>[],
|
|
2053
2073
|
expression: E,
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { ManyToManyModifyMixin } = require('./ManyToManyModifyMixin');
|
|
4
|
-
|
|
5
|
-
// Like `ManyToManySqliteModifyMixin`, this identifies the join rows to modify
|
|
6
|
-
// by their physical row id, so that only the join rows that match the filters
|
|
7
|
-
// are modified (#1853). `tableoid` makes `ctid` unique for partitioned tables.
|
|
8
|
-
const ManyToManyPostgresModifyMixin = (Operation) => {
|
|
9
|
-
return class extends ManyToManyModifyMixin(Operation) {
|
|
10
|
-
applyModifyFilterForJoinTable(builder) {
|
|
11
|
-
const joinTableOwnerRefs = this.relation.joinTableOwnerProp.refs(builder);
|
|
12
|
-
const tableRef = builder.tableRefFor(this.relation.getJoinModelClass(builder));
|
|
13
|
-
const rowIdRefs = [`${tableRef}.tableoid`, `${tableRef}.ctid`];
|
|
14
|
-
|
|
15
|
-
const ownerValues = this.owner.getProps(this.relation);
|
|
16
|
-
const subquery = this.modifyFilterSubquery.clone().select(rowIdRefs);
|
|
17
|
-
|
|
18
|
-
return builder
|
|
19
|
-
.whereInComposite(rowIdRefs, subquery)
|
|
20
|
-
.whereInComposite(joinTableOwnerRefs, ownerValues);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
module.exports = {
|
|
26
|
-
ManyToManyPostgresModifyMixin,
|
|
27
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { ManyToManyUnrelateOperationBase } = require('./ManyToManyUnrelateOperationBase');
|
|
4
|
-
const { ManyToManyPostgresModifyMixin } = require('../ManyToManyPostgresModifyMixin');
|
|
5
|
-
|
|
6
|
-
class ManyToManyUnrelatePostgresOperation extends ManyToManyPostgresModifyMixin(
|
|
7
|
-
ManyToManyUnrelateOperationBase,
|
|
8
|
-
) {
|
|
9
|
-
get modifyMainQuery() {
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
module.exports = {
|
|
15
|
-
ManyToManyUnrelatePostgresOperation,
|
|
16
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
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
|
-
};
|