@mikro-orm/core 7.0.0-dev.300 → 7.0.0-dev.301
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/EntityManager.d.ts +1 -1
- package/EntityManager.js +94 -43
- package/MikroORM.js +4 -4
- package/cache/FileCacheAdapter.js +1 -3
- package/connections/Connection.js +16 -3
- package/drivers/DatabaseDriver.js +25 -7
- package/entity/Collection.js +43 -17
- package/entity/EntityAssigner.js +23 -11
- package/entity/EntityFactory.js +32 -12
- package/entity/EntityHelper.js +12 -8
- package/entity/EntityLoader.js +55 -22
- package/entity/Reference.d.ts +1 -1
- package/entity/Reference.js +37 -8
- package/entity/WrappedEntity.js +5 -1
- package/entity/defineEntity.d.ts +5 -7
- package/entity/utils.js +28 -26
- package/entity/validators.js +2 -1
- package/enums.js +12 -17
- package/errors.js +18 -8
- package/events/EventManager.js +1 -1
- package/exceptions.js +7 -2
- package/hydration/ObjectHydrator.js +27 -13
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/logging/DefaultLogger.js +3 -5
- package/logging/colors.js +3 -6
- package/metadata/EntitySchema.js +12 -2
- package/metadata/MetadataDiscovery.js +101 -46
- package/metadata/MetadataProvider.js +6 -1
- package/metadata/MetadataStorage.js +1 -3
- package/metadata/MetadataValidator.js +20 -5
- package/metadata/types.d.ts +2 -2
- package/naming-strategy/AbstractNamingStrategy.js +5 -2
- package/not-supported.js +5 -1
- package/package.json +38 -38
- package/platforms/Platform.js +46 -23
- package/serialization/EntitySerializer.js +7 -3
- package/serialization/SerializationContext.js +1 -1
- package/typings.d.ts +23 -23
- package/typings.js +9 -9
- package/unit-of-work/ChangeSet.js +4 -4
- package/unit-of-work/ChangeSetComputer.js +8 -6
- package/unit-of-work/ChangeSetPersister.js +13 -8
- package/unit-of-work/CommitOrderCalculator.js +4 -2
- package/unit-of-work/UnitOfWork.d.ts +7 -1
- package/unit-of-work/UnitOfWork.js +51 -22
- package/utils/AbstractMigrator.js +3 -5
- package/utils/AbstractSchemaGenerator.js +2 -1
- package/utils/AsyncContext.js +1 -1
- package/utils/Configuration.js +8 -4
- package/utils/Cursor.js +4 -2
- package/utils/DataloaderUtils.js +15 -12
- package/utils/EntityComparator.js +51 -43
- package/utils/QueryHelper.js +38 -26
- package/utils/RawQueryFragment.js +3 -2
- package/utils/TransactionManager.js +2 -1
- package/utils/Utils.d.ts +1 -1
- package/utils/Utils.js +36 -30
- package/utils/env-vars.js +6 -5
- package/utils/fs-utils.js +2 -5
- package/utils/upsert-utils.js +6 -3
package/platforms/Platform.js
CHANGED
|
@@ -198,35 +198,58 @@ export class Platform {
|
|
|
198
198
|
}
|
|
199
199
|
switch (this.extractSimpleType(type)) {
|
|
200
200
|
case 'character':
|
|
201
|
-
case 'char':
|
|
201
|
+
case 'char':
|
|
202
|
+
return Type.getType(CharacterType);
|
|
202
203
|
case 'string':
|
|
203
|
-
case 'varchar':
|
|
204
|
-
|
|
205
|
-
case '
|
|
204
|
+
case 'varchar':
|
|
205
|
+
return Type.getType(StringType);
|
|
206
|
+
case 'interval':
|
|
207
|
+
return Type.getType(IntervalType);
|
|
208
|
+
case 'text':
|
|
209
|
+
return Type.getType(TextType);
|
|
206
210
|
case 'int':
|
|
207
|
-
case 'number':
|
|
208
|
-
|
|
209
|
-
case '
|
|
210
|
-
|
|
211
|
-
case '
|
|
212
|
-
|
|
213
|
-
case '
|
|
214
|
-
|
|
211
|
+
case 'number':
|
|
212
|
+
return Type.getType(IntegerType);
|
|
213
|
+
case 'bigint':
|
|
214
|
+
return Type.getType(BigIntType);
|
|
215
|
+
case 'smallint':
|
|
216
|
+
return Type.getType(SmallIntType);
|
|
217
|
+
case 'tinyint':
|
|
218
|
+
return Type.getType(TinyIntType);
|
|
219
|
+
case 'mediumint':
|
|
220
|
+
return Type.getType(MediumIntType);
|
|
221
|
+
case 'float':
|
|
222
|
+
return Type.getType(FloatType);
|
|
223
|
+
case 'double':
|
|
224
|
+
return Type.getType(DoubleType);
|
|
225
|
+
case 'integer':
|
|
226
|
+
return Type.getType(IntegerType);
|
|
215
227
|
case 'decimal':
|
|
216
|
-
case 'numeric':
|
|
217
|
-
|
|
228
|
+
case 'numeric':
|
|
229
|
+
return Type.getType(DecimalType);
|
|
230
|
+
case 'boolean':
|
|
231
|
+
return Type.getType(BooleanType);
|
|
218
232
|
case 'blob':
|
|
219
|
-
case 'buffer':
|
|
220
|
-
|
|
221
|
-
case '
|
|
222
|
-
|
|
233
|
+
case 'buffer':
|
|
234
|
+
return Type.getType(BlobType);
|
|
235
|
+
case 'uint8array':
|
|
236
|
+
return Type.getType(Uint8ArrayType);
|
|
237
|
+
case 'uuid':
|
|
238
|
+
return Type.getType(UuidType);
|
|
239
|
+
case 'date':
|
|
240
|
+
return Type.getType(DateType);
|
|
223
241
|
case 'datetime':
|
|
224
|
-
case 'timestamp':
|
|
225
|
-
|
|
242
|
+
case 'timestamp':
|
|
243
|
+
return Type.getType(DateTimeType);
|
|
244
|
+
case 'time':
|
|
245
|
+
return Type.getType(TimeType);
|
|
226
246
|
case 'object':
|
|
227
|
-
case 'json':
|
|
228
|
-
|
|
229
|
-
|
|
247
|
+
case 'json':
|
|
248
|
+
return Type.getType(JsonType);
|
|
249
|
+
case 'enum':
|
|
250
|
+
return Type.getType(EnumType);
|
|
251
|
+
default:
|
|
252
|
+
return Type.getType(UnknownType);
|
|
230
253
|
}
|
|
231
254
|
}
|
|
232
255
|
supportsMultipleCascadePaths() {
|
|
@@ -9,7 +9,8 @@ function isVisible(meta, propName, options) {
|
|
|
9
9
|
if (options.groups && prop?.groups) {
|
|
10
10
|
return prop.groups.some(g => options.groups.includes(g));
|
|
11
11
|
}
|
|
12
|
-
if (Array.isArray(options.populate) &&
|
|
12
|
+
if (Array.isArray(options.populate) &&
|
|
13
|
+
options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
|
|
13
14
|
return true;
|
|
14
15
|
}
|
|
15
16
|
if (options.exclude?.find(item => item === propName)) {
|
|
@@ -20,7 +21,8 @@ function isVisible(meta, propName, options) {
|
|
|
20
21
|
return visible && !prefixed;
|
|
21
22
|
}
|
|
22
23
|
function isPopulated(propName, options) {
|
|
23
|
-
if (typeof options.populate !== 'boolean' &&
|
|
24
|
+
if (typeof options.populate !== 'boolean' &&
|
|
25
|
+
options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
|
|
24
26
|
return true;
|
|
25
27
|
}
|
|
26
28
|
if (typeof options.populate === 'boolean') {
|
|
@@ -176,7 +178,9 @@ export class EntitySerializer {
|
|
|
176
178
|
static extractChildOptions(options, prop) {
|
|
177
179
|
return {
|
|
178
180
|
...options,
|
|
179
|
-
populate: Array.isArray(options.populate)
|
|
181
|
+
populate: Array.isArray(options.populate)
|
|
182
|
+
? Utils.extractChildElements(options.populate, prop, '*')
|
|
183
|
+
: options.populate,
|
|
180
184
|
exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop) : options.exclude,
|
|
181
185
|
};
|
|
182
186
|
}
|
|
@@ -104,7 +104,7 @@ export class SerializationContext {
|
|
|
104
104
|
}
|
|
105
105
|
fields = fields
|
|
106
106
|
.filter(field => field.startsWith(`${segment[1]}.`) || field === '*')
|
|
107
|
-
.map(field => field === '*' ? field : field.substring(segment[1].length + 1));
|
|
107
|
+
.map(field => (field === '*' ? field : field.substring(segment[1].length + 1)));
|
|
108
108
|
}
|
|
109
109
|
return fields.some(p => p === prop || p === '*');
|
|
110
110
|
}
|
package/typings.d.ts
CHANGED
|
@@ -36,11 +36,11 @@ export type Compute<T> = {
|
|
|
36
36
|
[K in keyof T]: T[K];
|
|
37
37
|
} & {};
|
|
38
38
|
type InternalKeys = 'EntityRepositoryType' | 'PrimaryKeyProp' | 'OptionalProps' | 'EagerProps' | 'HiddenProps' | '__selectedType' | '__loadedType';
|
|
39
|
-
export type CleanKeys<T, K extends keyof T, B extends boolean = false> =
|
|
39
|
+
export type CleanKeys<T, K extends keyof T, B extends boolean = false> = T[K] & {} extends Function ? never : K extends symbol | InternalKeys ? never : B extends true ? T[K] & {} extends Scalar ? never : K : K;
|
|
40
40
|
export type FunctionKeys<T, K extends keyof T> = T[K] extends Function ? K : never;
|
|
41
41
|
export type Cast<T, R> = T extends R ? T : R;
|
|
42
|
-
export type IsUnknown<T> = T extends unknown ? unknown extends T ? true : never : never;
|
|
43
|
-
export type IsAny<T> = 0 extends
|
|
42
|
+
export type IsUnknown<T> = T extends unknown ? (unknown extends T ? true : never) : never;
|
|
43
|
+
export type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
44
44
|
export type IsNever<T, True = true, False = false> = [T] extends [never] ? True : False;
|
|
45
45
|
export type MaybePromise<T> = T | Promise<T>;
|
|
46
46
|
/**
|
|
@@ -98,9 +98,9 @@ type LoadableShape = CollectionShape | ReferenceShape | readonly any[];
|
|
|
98
98
|
export type UnionKeys<T> = T extends any ? keyof T : never;
|
|
99
99
|
export type UnionPropertyType<T, K extends PropertyKey> = T extends any ? (K extends keyof T ? T[K] : never) : never;
|
|
100
100
|
type IsUnion<T, U = T> = T extends any ? ([U] extends [T] ? false : true) : false;
|
|
101
|
-
export type MergeUnion<T> = [T] extends [object] ?
|
|
101
|
+
export type MergeUnion<T> = [T] extends [object] ? T extends Scalar ? T : IsUnion<T> extends true ? {
|
|
102
102
|
[K in UnionKeys<T>]: UnionPropertyType<T, K>;
|
|
103
|
-
} : T
|
|
103
|
+
} : T : T;
|
|
104
104
|
export type DeepPartial<T> = T & {
|
|
105
105
|
[P in keyof T]?: T[P] extends (infer U)[] ? DeepPartial<U>[] : T[P] extends Readonly<infer U>[] ? Readonly<DeepPartial<U>>[] : DeepPartial<T[P]>;
|
|
106
106
|
};
|
|
@@ -113,7 +113,7 @@ export declare const Config: unique symbol;
|
|
|
113
113
|
export declare const EntityName: unique symbol;
|
|
114
114
|
export type InferEntityName<T> = T extends {
|
|
115
115
|
[EntityName]?: infer Name;
|
|
116
|
-
} ? Name extends string ? Name : never : never;
|
|
116
|
+
} ? (Name extends string ? Name : never) : never;
|
|
117
117
|
export type Opt<T = unknown> = T & Opt.Brand;
|
|
118
118
|
export declare namespace Opt {
|
|
119
119
|
const __optional: unique symbol;
|
|
@@ -173,11 +173,11 @@ export type Primary<T> = IsAny<T> extends true ? any : T extends {
|
|
|
173
173
|
/** @internal */
|
|
174
174
|
export type PrimaryProperty<T> = T extends {
|
|
175
175
|
[PrimaryKeyProp]?: infer PK;
|
|
176
|
-
} ?
|
|
176
|
+
} ? PK extends keyof T ? PK : PK extends any[] ? PK[number] : never : T extends {
|
|
177
177
|
_id?: any;
|
|
178
|
-
} ?
|
|
178
|
+
} ? T extends {
|
|
179
179
|
id?: any;
|
|
180
|
-
} ? 'id' | '_id' : '_id'
|
|
180
|
+
} ? 'id' | '_id' : '_id' : T extends {
|
|
181
181
|
id?: any;
|
|
182
182
|
} ? 'id' : T extends {
|
|
183
183
|
uuid?: any;
|
|
@@ -237,7 +237,7 @@ type ExpandQueryMerged<T> = [T] extends [object] ? [T] extends [Scalar] ? never
|
|
|
237
237
|
export type FilterObject<T> = {
|
|
238
238
|
-readonly [K in EntityKey<T>]?: ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>> | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>> | FilterValue<ExpandProperty<FilterObjectProp<T, K>>> | null;
|
|
239
239
|
};
|
|
240
|
-
export type ExpandQuery<T> = T extends object ? T extends Scalar ? never : FilterQuery<T> : FilterValue<T>;
|
|
240
|
+
export type ExpandQuery<T> = T extends object ? (T extends Scalar ? never : FilterQuery<T>) : FilterValue<T>;
|
|
241
241
|
export type EntityProps<T> = {
|
|
242
242
|
-readonly [K in EntityKey<T>]?: T[K];
|
|
243
243
|
};
|
|
@@ -324,11 +324,11 @@ type NonArrayObject = object & {
|
|
|
324
324
|
export type EntityDataProp<T, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends ScalarReference<infer U> ? EntityDataProp<U, C> : T extends {
|
|
325
325
|
__runtime?: infer Runtime;
|
|
326
326
|
__raw?: infer Raw;
|
|
327
|
-
} ?
|
|
327
|
+
} ? C extends true ? Raw : Runtime : T extends ReferenceShape<infer U> ? EntityDataNested<U, C> : T extends CollectionShape<infer U> ? U | U[] | EntityDataNested<U & object, C> | EntityDataNested<U & object, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : U[] | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
|
|
328
328
|
export type RequiredEntityDataProp<T, O, C extends boolean> = T extends Date ? string | Date : Exclude<T, null> extends RequiredNullable.Brand ? T | null : T extends Scalar ? T : T extends ScalarReference<infer U> ? RequiredEntityDataProp<U, O, C> : T extends {
|
|
329
329
|
__runtime?: infer Runtime;
|
|
330
330
|
__raw?: infer Raw;
|
|
331
|
-
} ?
|
|
331
|
+
} ? C extends true ? Raw : Runtime : T extends ReferenceShape<infer U> ? RequiredEntityDataNested<U, O, C> : T extends CollectionShape<infer U> ? U | U[] | RequiredEntityDataNested<U & object, O, C> | RequiredEntityDataNested<U & object, O, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : U[] | RequiredEntityDataNested<U, O, C>[] : RequiredEntityDataNested<T, O, C>;
|
|
332
332
|
export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
|
|
333
333
|
type UnwrapScalarRef<T> = T extends ScalarReference<infer U> ? U : T;
|
|
334
334
|
type EntityDataItem<T, C extends boolean> = C extends false ? UnwrapScalarRef<T> | EntityDataProp<T, C> | Raw | null : EntityDataProp<T, C> | Raw | null;
|
|
@@ -368,9 +368,9 @@ export type Rel<T> = T;
|
|
|
368
368
|
/** Alias for `ScalarReference` (see {@apilink Ref}). */
|
|
369
369
|
export type ScalarRef<T> = ScalarReference<T>;
|
|
370
370
|
/** Alias for `Reference<T> & { id: number }` (see {@apilink Ref}). */
|
|
371
|
-
export type EntityRef<T extends object> = true extends IsUnknown<PrimaryProperty<T>> ? Reference<T> : IsAny<T> extends true ? Reference<T> :
|
|
371
|
+
export type EntityRef<T extends object> = true extends IsUnknown<PrimaryProperty<T>> ? Reference<T> : IsAny<T> extends true ? Reference<T> : {
|
|
372
372
|
[K in PrimaryProperty<T> & keyof T]: T[K];
|
|
373
|
-
} & Reference<T
|
|
373
|
+
} & Reference<T>;
|
|
374
374
|
/**
|
|
375
375
|
* Ref type represents a `Reference` instance, and adds the primary keys to its prototype automatically, so you can do
|
|
376
376
|
* `ref.id` instead of `ref.unwrap().id`. It resolves to either `ScalarRef` or `EntityRef`, based on the type argument.
|
|
@@ -384,7 +384,7 @@ type ExtractHiddenProps<T> = (T extends {
|
|
|
384
384
|
type ExcludeHidden<T, K extends keyof T> = K extends ExtractHiddenProps<T> ? never : K;
|
|
385
385
|
type ExtractConfig<T> = T extends {
|
|
386
386
|
[Config]?: infer K;
|
|
387
|
-
} ?
|
|
387
|
+
} ? K & TypeConfig : TypeConfig;
|
|
388
388
|
type PreferExplicitConfig<E, I> = IsNever<E, I, E>;
|
|
389
389
|
type PrimaryOrObject<T, U, C extends TypeConfig> = PreferExplicitConfig<C, ExtractConfig<T>>['forceObject'] extends true ? {
|
|
390
390
|
[K in PrimaryProperty<U> & keyof U]: U[K];
|
|
@@ -392,7 +392,7 @@ type PrimaryOrObject<T, U, C extends TypeConfig> = PreferExplicitConfig<C, Extra
|
|
|
392
392
|
type DTOWrapper<T, C extends TypeConfig, Flat extends boolean> = Flat extends true ? EntityDTOFlat<T, C> : EntityDTO<T, C>;
|
|
393
393
|
export type EntityDTOProp<E, T, C extends TypeConfig = never, Flat extends boolean = false> = T extends Scalar ? T : T extends ScalarReference<infer U> ? U : T extends {
|
|
394
394
|
__serialized?: infer U;
|
|
395
|
-
} ?
|
|
395
|
+
} ? IsUnknown<U> extends false ? U : T : T extends LoadedReferenceShape<infer U> ? DTOWrapper<U, C, Flat> : T extends ReferenceShape<infer U> ? PrimaryOrObject<E, U, C> : T extends LoadedCollectionShape<infer U> ? DTOWrapper<U & object, C, Flat>[] : T extends CollectionShape<infer U> ? PrimaryOrObject<E, U & object, C>[] : T extends readonly (infer U)[] ? U extends Scalar ? T : EntityDTOProp<E, U, C, Flat>[] : T extends Relation<T> ? DTOWrapper<T, C, Flat> : T;
|
|
396
396
|
type UnwrapLoadedEntity<T> = T extends {
|
|
397
397
|
[__loadedType]?: infer U;
|
|
398
398
|
} ? NonNullable<U> : T;
|
|
@@ -422,7 +422,7 @@ export type EntityDTOFlat<T, C extends TypeConfig = never> = {
|
|
|
422
422
|
*/
|
|
423
423
|
type SerializeTopHints<H extends string> = H extends `${infer Top}.${string}` ? Top : H;
|
|
424
424
|
type SerializeSubHints<K extends string, H extends string> = H extends `${K}.${infer Rest}` ? Rest : never;
|
|
425
|
-
type SerializePropValue<T, K extends keyof T, H extends string, C extends TypeConfig = never> =
|
|
425
|
+
type SerializePropValue<T, K extends keyof T, H extends string, C extends TypeConfig = never> = K & string extends SerializeTopHints<H> ? NonNullable<T[K]> extends CollectionShape<infer U> ? SerializeDTO<U & object, SerializeSubHints<K & string, H>, never, C>[] : SerializeDTO<ExpandProperty<T[K]>, SerializeSubHints<K & string, H>, never, C> | Extract<T[K], null | undefined> : EntityDTOProp<T, T[K], C>;
|
|
426
426
|
export type SerializeDTO<T, H extends string = never, E extends string = never, C extends TypeConfig = never> = string extends H ? EntityDTOFlat<T, C> : {
|
|
427
427
|
[K in keyof T as ExcludeHidden<T, K> & CleanKeys<T, K> & (IsNever<E> extends true ? K : Exclude<K, E>)]: SerializePropValue<T, K, H, C> | Extract<T[K], null | undefined>;
|
|
428
428
|
};
|
|
@@ -975,7 +975,7 @@ type ExtractStringKeys<T> = {
|
|
|
975
975
|
* Simplified to just check `T extends object` since ExtractType handles the unwrapping.
|
|
976
976
|
*/
|
|
977
977
|
type StringKeys<T, E extends string = never> = T extends object ? ExtractStringKeys<ExtractType<T>> | E : never;
|
|
978
|
-
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractType<T[K]> :
|
|
978
|
+
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractType<T[K]> : K extends E ? keyof T : never;
|
|
979
979
|
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
980
980
|
type RelationKeys<T> = T extends object ? {
|
|
981
981
|
[K in keyof T]-?: CleanKeys<T, K, true>;
|
|
@@ -985,12 +985,12 @@ export type UnboxArray<T> = T extends any[] ? ArrayElement<T> : T;
|
|
|
985
985
|
export type ArrayElement<ArrayType extends unknown[]> = ArrayType extends (infer ElementType)[] ? ElementType : never;
|
|
986
986
|
export type ExpandProperty<T> = T extends ReferenceShape<infer U> ? NonNullable<U> : T extends CollectionShape<infer U> ? NonNullable<U> : T extends (infer U)[] ? NonNullable<U> : NonNullable<T>;
|
|
987
987
|
type LoadedLoadable<T, E extends object> = T extends CollectionShape ? LoadedCollection<E> : T extends ScalarReference<infer U> ? LoadedScalarReference<U> : T extends ReferenceShape ? T & LoadedReference<E> : T extends Scalar ? T : T extends (infer U)[] ? U extends Scalar ? T : E[] : E;
|
|
988
|
-
type IsTrue<T> = IsNever<T> extends true ? false : T extends boolean ? T extends true ? true : false : false;
|
|
989
|
-
type StringLiteral<T> = T extends string ? string extends T ? never : T : never;
|
|
990
|
-
type Prefix<T, K> = K extends `${infer S}.${string}` ? S :
|
|
988
|
+
type IsTrue<T> = IsNever<T> extends true ? false : T extends boolean ? (T extends true ? true : false) : false;
|
|
989
|
+
type StringLiteral<T> = T extends string ? (string extends T ? never : T) : never;
|
|
990
|
+
type Prefix<T, K> = K extends `${infer S}.${string}` ? S : K extends '*' ? keyof T : K;
|
|
991
991
|
type IsPrefixedExclude<T, K extends keyof T, E extends string> = K extends E ? never : K;
|
|
992
|
-
export type IsPrefixed<T, K extends keyof T, L extends string, E extends string = never> = IsNever<E> extends false ? IsPrefixedExclude<T, K, E> : K extends symbol ? never : IsTrue<L> extends true ?
|
|
993
|
-
type Suffix<Key, Hint extends string, All = true | '*'> = Hint extends `${infer Pref}.${infer Suf}` ?
|
|
992
|
+
export type IsPrefixed<T, K extends keyof T, L extends string, E extends string = never> = IsNever<E> extends false ? IsPrefixedExclude<T, K, E> : K extends symbol ? never : IsTrue<L> extends true ? T[K] & {} extends LoadableShape ? K : never : IsNever<StringLiteral<L>> extends true ? never : '*' extends L ? K : K extends Prefix<T, L> ? K : K extends PrimaryProperty<T> ? K : never;
|
|
993
|
+
type Suffix<Key, Hint extends string, All = true | '*'> = Hint extends `${infer Pref}.${infer Suf}` ? Pref extends Key ? Suf : never : Hint extends All ? Hint : never;
|
|
994
994
|
export type IsSubset<T, U> = keyof U extends keyof T ? {} : string extends keyof U ? {} : {
|
|
995
995
|
[K in keyof U as K extends keyof T ? never : CleanKeys<U, K>]: never;
|
|
996
996
|
};
|
package/typings.js
CHANGED
|
@@ -31,11 +31,9 @@ export class EntityMetadata {
|
|
|
31
31
|
Object.assign(this, meta);
|
|
32
32
|
const name = meta.className ?? meta.name;
|
|
33
33
|
if (!this.class && name) {
|
|
34
|
-
const Class = this.extends === BaseEntity
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
: ({ [name]: class {
|
|
38
|
-
} })[name];
|
|
34
|
+
const Class = this.extends === BaseEntity ? { [name]: class extends BaseEntity {
|
|
35
|
+
} }[name] : { [name]: class {
|
|
36
|
+
} }[name];
|
|
39
37
|
this.class = Class;
|
|
40
38
|
}
|
|
41
39
|
}
|
|
@@ -108,9 +106,7 @@ export class EntityMetadata {
|
|
|
108
106
|
*/
|
|
109
107
|
createSchemaColumnMappingObject() {
|
|
110
108
|
// For TPT entities, only include properties that belong to this entity's table
|
|
111
|
-
const props = this.inheritanceType === 'tpt' && this.ownProps
|
|
112
|
-
? this.ownProps
|
|
113
|
-
: Object.values(this.properties);
|
|
109
|
+
const props = this.inheritanceType === 'tpt' && this.ownProps ? this.ownProps : Object.values(this.properties);
|
|
114
110
|
return props.reduce((o, prop) => {
|
|
115
111
|
if (prop.fieldNames) {
|
|
116
112
|
o[prop.name] = prop.fieldNames[0];
|
|
@@ -208,7 +204,11 @@ export class EntityMetadata {
|
|
|
208
204
|
const hydrator = wrapped.hydrator;
|
|
209
205
|
const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
|
|
210
206
|
const old = Reference.unwrapReference(wrapped.__data[prop.name]);
|
|
211
|
-
if (old &&
|
|
207
|
+
if (old &&
|
|
208
|
+
old !== entity &&
|
|
209
|
+
prop.kind === ReferenceKind.MANY_TO_ONE &&
|
|
210
|
+
prop.inversedBy &&
|
|
211
|
+
old[prop.inversedBy]) {
|
|
212
212
|
old[prop.inversedBy].removeWithoutPropagation(this);
|
|
213
213
|
}
|
|
214
214
|
wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
|
|
@@ -27,10 +27,10 @@ export class ChangeSet {
|
|
|
27
27
|
else {
|
|
28
28
|
this.primaryKey = this.originalEntity[this.meta.primaryKeys[0]];
|
|
29
29
|
}
|
|
30
|
-
if (!this.meta.compositePK
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (!this.meta.compositePK &&
|
|
31
|
+
this.meta.getPrimaryProp().targetMeta?.compositePK &&
|
|
32
|
+
typeof this.primaryKey === 'object' &&
|
|
33
|
+
this.primaryKey !== null) {
|
|
34
34
|
this.primaryKey = this.meta.getPrimaryProp().targetMeta.primaryKeys.map(childPK => {
|
|
35
35
|
return this.primaryKey[childPK];
|
|
36
36
|
});
|
|
@@ -31,7 +31,8 @@ export class ChangeSetComputer {
|
|
|
31
31
|
const map = new Map();
|
|
32
32
|
// Execute `onCreate` and `onUpdate` on properties recursively, saves `onUpdate` results
|
|
33
33
|
// to the `map` as we want to apply those only if something else changed.
|
|
34
|
-
if (type === ChangeSetType.CREATE) {
|
|
34
|
+
if (type === ChangeSetType.CREATE) {
|
|
35
|
+
// run update hooks only after we know there are other changes
|
|
35
36
|
for (const prop of meta.hydrateProps) {
|
|
36
37
|
this.processPropertyInitializers(entity, prop, type, map);
|
|
37
38
|
}
|
|
@@ -74,10 +75,10 @@ export class ChangeSetComputer {
|
|
|
74
75
|
* Traverses entity graph and executes `onCreate` and `onUpdate` methods, assigning the values to given properties.
|
|
75
76
|
*/
|
|
76
77
|
processPropertyInitializers(entity, prop, type, map, nested) {
|
|
77
|
-
if (prop.onCreate
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
if (prop.onCreate &&
|
|
79
|
+
type === ChangeSetType.CREATE &&
|
|
80
|
+
(entity[prop.name] == null ||
|
|
81
|
+
(Utils.isScalarReference(entity[prop.name]) && entity[prop.name].unwrap() == null))) {
|
|
81
82
|
entity[prop.name] = prop.onCreate(entity, this.em);
|
|
82
83
|
}
|
|
83
84
|
if (prop.onUpdate && type === ChangeSetType.UPDATE) {
|
|
@@ -120,7 +121,8 @@ export class ChangeSetComputer {
|
|
|
120
121
|
targets.forEach(([t]) => this.processProperty(changeSet, prop, t));
|
|
121
122
|
return;
|
|
122
123
|
}
|
|
123
|
-
if (Utils.isCollection(target)) {
|
|
124
|
+
if (Utils.isCollection(target)) {
|
|
125
|
+
// m:n or 1:m
|
|
124
126
|
this.processToMany(prop, changeSet);
|
|
125
127
|
}
|
|
126
128
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
@@ -49,7 +49,10 @@ export class ChangeSetPersister {
|
|
|
49
49
|
// For STI with conflicting fieldNames (renamedFrom properties), we can't batch mixed child types
|
|
50
50
|
const hasSTIConflicts = meta.root.props.some(p => p.renamedFrom);
|
|
51
51
|
const hasMixedTypes = hasSTIConflicts && changeSets.some(cs => cs.meta.class !== meta.class);
|
|
52
|
-
if (batched &&
|
|
52
|
+
if (batched &&
|
|
53
|
+
changeSets.length > 1 &&
|
|
54
|
+
!hasMixedTypes &&
|
|
55
|
+
this.config.get('useBatchUpdates', this.platform.usesBatchUpdates())) {
|
|
53
56
|
return this.persistManagedEntities(meta, changeSets, options);
|
|
54
57
|
}
|
|
55
58
|
for (const changeSet of changeSets) {
|
|
@@ -238,7 +241,9 @@ export class ChangeSetPersister {
|
|
|
238
241
|
// some drivers might be returning bigint PKs as numbers when the number is small enough,
|
|
239
242
|
// but we need to have it as string so comparison works in change set tracking, so instead
|
|
240
243
|
// of using the raw value from db, we convert it back to the db value explicitly
|
|
241
|
-
value = prop.customType
|
|
244
|
+
value = prop.customType
|
|
245
|
+
? prop.customType.convertToDatabaseValue(insertId, this.platform, { mode: 'serialization' })
|
|
246
|
+
: value;
|
|
242
247
|
changeSet.payload[wrapped.__meta.primaryKeys[0]] = value;
|
|
243
248
|
if (wrapped.__identifier && !Array.isArray(wrapped.__identifier)) {
|
|
244
249
|
wrapped.__identifier.setValue(value);
|
|
@@ -268,7 +273,8 @@ export class ChangeSetPersister {
|
|
|
268
273
|
options = this.prepareOptions(meta, options, {
|
|
269
274
|
convertCustomTypes: false,
|
|
270
275
|
});
|
|
271
|
-
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
276
|
+
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
277
|
+
(!meta.versionProperty || changeSet.entity[meta.versionProperty] == null)) {
|
|
272
278
|
return this.driver.nativeUpdate(changeSet.meta.class, cond, changeSet.payload, options);
|
|
273
279
|
}
|
|
274
280
|
if (meta.versionProperty) {
|
|
@@ -278,7 +284,8 @@ export class ChangeSetPersister {
|
|
|
278
284
|
return this.driver.nativeUpdate(changeSet.meta.class, cond, changeSet.payload, options);
|
|
279
285
|
}
|
|
280
286
|
async checkOptimisticLocks(meta, changeSets, options) {
|
|
281
|
-
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
287
|
+
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
288
|
+
(!meta.versionProperty || changeSets.every(cs => cs.entity[meta.versionProperty] == null))) {
|
|
282
289
|
return;
|
|
283
290
|
}
|
|
284
291
|
// skip entity references as they don't have version values loaded
|
|
@@ -344,9 +351,7 @@ export class ChangeSetPersister {
|
|
|
344
351
|
});
|
|
345
352
|
// reload generated columns
|
|
346
353
|
if (!this.usesReturningStatement) {
|
|
347
|
-
meta.props
|
|
348
|
-
.filter(prop => prop.generated && !prop.primary)
|
|
349
|
-
.forEach(prop => reloadProps.push(prop));
|
|
354
|
+
meta.props.filter(prop => prop.generated && !prop.primary).forEach(prop => reloadProps.push(prop));
|
|
350
355
|
reloadProps.push(...returning);
|
|
351
356
|
}
|
|
352
357
|
}
|
|
@@ -407,7 +412,7 @@ export class ChangeSetPersister {
|
|
|
407
412
|
return;
|
|
408
413
|
}
|
|
409
414
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && Array.isArray(value)) {
|
|
410
|
-
changeSet.payload[prop.name] = value.map(val => val instanceof EntityIdentifier ? val.getValue() : val);
|
|
415
|
+
changeSet.payload[prop.name] = value.map(val => (val instanceof EntityIdentifier ? val.getValue() : val));
|
|
411
416
|
return;
|
|
412
417
|
}
|
|
413
418
|
if (prop.name in changeSet.payload) {
|
|
@@ -78,11 +78,13 @@ export class CommitOrderCalculator {
|
|
|
78
78
|
for (const edge of node.dependencies.values()) {
|
|
79
79
|
const target = this.nodes.get(edge.to);
|
|
80
80
|
switch (target.state) {
|
|
81
|
-
case 2 /* NodeState.VISITED */:
|
|
81
|
+
case 2 /* NodeState.VISITED */:
|
|
82
|
+
break; // Do nothing, since node was already visited
|
|
82
83
|
case 1 /* NodeState.IN_PROGRESS */:
|
|
83
84
|
this.visitOpenNode(node, target, edge);
|
|
84
85
|
break;
|
|
85
|
-
case 0 /* NodeState.NOT_VISITED */:
|
|
86
|
+
case 0 /* NodeState.NOT_VISITED */:
|
|
87
|
+
this.visit(target);
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
if (node.state !== 2 /* NodeState.VISITED */) {
|
|
@@ -72,7 +72,13 @@ export declare class UnitOfWork {
|
|
|
72
72
|
getRemoveStack(): Set<AnyEntity>;
|
|
73
73
|
getChangeSets(): ChangeSet<AnyEntity>[];
|
|
74
74
|
getCollectionUpdates(): Collection<AnyEntity>[];
|
|
75
|
-
getExtraUpdates(): Set<[
|
|
75
|
+
getExtraUpdates(): Set<[
|
|
76
|
+
AnyEntity,
|
|
77
|
+
string | string[],
|
|
78
|
+
AnyEntity | AnyEntity[] | Reference<any> | Collection<any>,
|
|
79
|
+
ChangeSet<any> | undefined,
|
|
80
|
+
ChangeSetType
|
|
81
|
+
]>;
|
|
76
82
|
shouldAutoFlush<T extends object>(meta: EntityMetadata<T>): boolean;
|
|
77
83
|
clearActionsQueue(): void;
|
|
78
84
|
computeChangeSet<T extends object>(entity: T, type?: ChangeSetType): void;
|
|
@@ -76,7 +76,8 @@ export class UnitOfWork {
|
|
|
76
76
|
if (!prop) {
|
|
77
77
|
continue;
|
|
78
78
|
}
|
|
79
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
79
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
80
|
+
Utils.isPlainObject(data[prop.name])) {
|
|
80
81
|
// Skip polymorphic relations - they use PolymorphicRef wrapper
|
|
81
82
|
if (!prop.polymorphic) {
|
|
82
83
|
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
@@ -86,12 +87,16 @@ export class UnitOfWork {
|
|
|
86
87
|
for (const p of prop.targetMeta.props) {
|
|
87
88
|
/* v8 ignore next */
|
|
88
89
|
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
89
|
-
data[prefix + p.name] = data[prop.name][p.name];
|
|
90
|
+
data[(prefix + p.name)] = data[prop.name][p.name];
|
|
90
91
|
}
|
|
91
92
|
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
92
93
|
}
|
|
93
94
|
if (prop.hydrate === false && prop.customType?.ensureComparable(meta, prop)) {
|
|
94
|
-
const converted = prop.customType.convertToJSValue(data[key], this.platform, {
|
|
95
|
+
const converted = prop.customType.convertToJSValue(data[key], this.platform, {
|
|
96
|
+
key,
|
|
97
|
+
mode: 'hydration',
|
|
98
|
+
force: true,
|
|
99
|
+
});
|
|
95
100
|
data[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { key, mode: 'hydration' });
|
|
96
101
|
}
|
|
97
102
|
if (forceUndefined) {
|
|
@@ -423,7 +428,10 @@ export class UnitOfWork {
|
|
|
423
428
|
if (Utils.isCollection(rel)) {
|
|
424
429
|
rel.removeWithoutPropagation(entity);
|
|
425
430
|
}
|
|
426
|
-
else if (rel &&
|
|
431
|
+
else if (rel &&
|
|
432
|
+
(prop.mapToPk
|
|
433
|
+
? helper(this.em.getReference(prop.targetMeta.class, rel)).getSerializedPrimaryKey() === serializedPK
|
|
434
|
+
: rel === entity)) {
|
|
427
435
|
if (prop.formula) {
|
|
428
436
|
delete referrer[prop.name];
|
|
429
437
|
}
|
|
@@ -512,7 +520,13 @@ export class UnitOfWork {
|
|
|
512
520
|
if (!conflicts) {
|
|
513
521
|
return;
|
|
514
522
|
}
|
|
515
|
-
this.extraUpdates.add([
|
|
523
|
+
this.extraUpdates.add([
|
|
524
|
+
changeSet.entity,
|
|
525
|
+
props.map(p => p.name),
|
|
526
|
+
props.map(p => changeSet.entity[p.name]),
|
|
527
|
+
changeSet,
|
|
528
|
+
type,
|
|
529
|
+
]);
|
|
516
530
|
for (const p of props) {
|
|
517
531
|
delete changeSet.entity[p.name];
|
|
518
532
|
delete changeSet.payload[p.name];
|
|
@@ -633,7 +647,7 @@ export class UnitOfWork {
|
|
|
633
647
|
// when changing a unique nullable property (or a 1:1 relation), we can't do it in a single
|
|
634
648
|
// query as it would cause unique constraint violations
|
|
635
649
|
const uniqueProps = changeSet.meta.uniqueProps.filter(prop => {
|
|
636
|
-
return
|
|
650
|
+
return prop.nullable || changeSet.type !== ChangeSetType.CREATE;
|
|
637
651
|
});
|
|
638
652
|
this.scheduleExtraUpdate(changeSet, uniqueProps);
|
|
639
653
|
return changeSet.type === ChangeSetType.UPDATE && !Utils.hasObjectKeys(changeSet.payload);
|
|
@@ -643,25 +657,33 @@ export class UnitOfWork {
|
|
|
643
657
|
if (!wrapped.__meta.hasUniqueProps) {
|
|
644
658
|
return [];
|
|
645
659
|
}
|
|
646
|
-
const simpleUniqueHashes = wrapped.__meta.uniqueProps
|
|
660
|
+
const simpleUniqueHashes = wrapped.__meta.uniqueProps
|
|
661
|
+
.map(prop => {
|
|
647
662
|
if (entity[prop.name] != null) {
|
|
648
|
-
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
663
|
+
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
664
|
+
? entity[prop.name]
|
|
665
|
+
: helper(entity[prop.name]).getSerializedPrimaryKey();
|
|
649
666
|
}
|
|
650
667
|
if (wrapped.__originalEntityData?.[prop.name] != null) {
|
|
651
668
|
return Utils.getPrimaryKeyHash(Utils.asArray(wrapped.__originalEntityData[prop.name]));
|
|
652
669
|
}
|
|
653
670
|
return undefined;
|
|
654
|
-
})
|
|
655
|
-
|
|
671
|
+
})
|
|
672
|
+
.filter(i => i);
|
|
673
|
+
const compoundUniqueHashes = wrapped.__meta.uniques
|
|
674
|
+
.map(unique => {
|
|
656
675
|
const props = Utils.asArray(unique.properties);
|
|
657
676
|
if (props.every(prop => entity[prop] != null)) {
|
|
658
677
|
return Utils.getPrimaryKeyHash(props.map(p => {
|
|
659
678
|
const prop = wrapped.__meta.properties[p];
|
|
660
|
-
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
679
|
+
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
680
|
+
? entity[prop.name]
|
|
681
|
+
: helper(entity[prop.name]).getSerializedPrimaryKey();
|
|
661
682
|
}));
|
|
662
683
|
}
|
|
663
684
|
return undefined;
|
|
664
|
-
})
|
|
685
|
+
})
|
|
686
|
+
.filter(i => i);
|
|
665
687
|
return simpleUniqueHashes.concat(compoundUniqueHashes);
|
|
666
688
|
}
|
|
667
689
|
initIdentifier(entity) {
|
|
@@ -693,7 +715,8 @@ export class UnitOfWork {
|
|
|
693
715
|
return this.processToOneReference(kind, visited, processed, idx);
|
|
694
716
|
}
|
|
695
717
|
if (Utils.isCollection(kind)) {
|
|
696
|
-
kind
|
|
718
|
+
kind
|
|
719
|
+
.getItems(false)
|
|
697
720
|
.filter(item => !item.__helper.__originalEntityData)
|
|
698
721
|
.forEach(item => {
|
|
699
722
|
// propagate schema from parent
|
|
@@ -717,7 +740,8 @@ export class UnitOfWork {
|
|
|
717
740
|
parent[prop.name] = coll;
|
|
718
741
|
return;
|
|
719
742
|
}
|
|
720
|
-
collection
|
|
743
|
+
collection
|
|
744
|
+
.getItems(false)
|
|
721
745
|
.filter(item => !item.__helper.__originalEntityData)
|
|
722
746
|
.forEach(item => this.findNewEntities(item, visited, 0, processed));
|
|
723
747
|
}
|
|
@@ -809,7 +833,8 @@ export class UnitOfWork {
|
|
|
809
833
|
return filtered.some(items => processed.has(items));
|
|
810
834
|
}
|
|
811
835
|
shouldCascade(prop, type) {
|
|
812
|
-
if ([Cascade.REMOVE, Cascade.SCHEDULE_ORPHAN_REMOVAL, Cascade.CANCEL_ORPHAN_REMOVAL, Cascade.ALL].includes(type) &&
|
|
836
|
+
if ([Cascade.REMOVE, Cascade.SCHEDULE_ORPHAN_REMOVAL, Cascade.CANCEL_ORPHAN_REMOVAL, Cascade.ALL].includes(type) &&
|
|
837
|
+
prop.orphanRemoval) {
|
|
813
838
|
return true;
|
|
814
839
|
}
|
|
815
840
|
// ignore user settings for merge, it is kept only for back compatibility, this should have never been configurable
|
|
@@ -845,7 +870,9 @@ export class UnitOfWork {
|
|
|
845
870
|
const target = Reference.unwrapReference(reference);
|
|
846
871
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && target && !prop.mapToPk) {
|
|
847
872
|
if (!Utils.isEntity(target)) {
|
|
848
|
-
entity[prop.name] = this.em.getReference(prop.targetMeta.class, target, {
|
|
873
|
+
entity[prop.name] = this.em.getReference(prop.targetMeta.class, target, {
|
|
874
|
+
wrapped: !!prop.ref,
|
|
875
|
+
});
|
|
849
876
|
}
|
|
850
877
|
else if (!helper(target).__initialized && !helper(target).__em) {
|
|
851
878
|
const pk = helper(target).getPrimaryKey();
|
|
@@ -907,9 +934,9 @@ export class UnitOfWork {
|
|
|
907
934
|
return;
|
|
908
935
|
}
|
|
909
936
|
const props = changeSets[0].meta.root.relations.filter(prop => {
|
|
910
|
-
return (prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner)
|
|
911
|
-
|
|
912
|
-
|
|
937
|
+
return ((prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner) ||
|
|
938
|
+
prop.kind === ReferenceKind.MANY_TO_ONE ||
|
|
939
|
+
(prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && !this.platform.usesPivotTable()));
|
|
913
940
|
});
|
|
914
941
|
for (const changeSet of changeSets) {
|
|
915
942
|
this.findExtraUpdates(changeSet, props);
|
|
@@ -984,7 +1011,8 @@ export class UnitOfWork {
|
|
|
984
1011
|
wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
|
|
985
1012
|
if (!wrapped.__initialized) {
|
|
986
1013
|
for (const prop of changeSet.meta.relations) {
|
|
987
|
-
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
|
|
1014
|
+
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
|
|
1015
|
+
changeSet.entity[prop.name] == null) {
|
|
988
1016
|
changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
|
|
989
1017
|
}
|
|
990
1018
|
}
|
|
@@ -1013,7 +1041,7 @@ export class UnitOfWork {
|
|
|
1013
1041
|
continue;
|
|
1014
1042
|
}
|
|
1015
1043
|
if (Array.isArray(extraUpdate[1])) {
|
|
1016
|
-
extraUpdate[1].forEach((p, i) => extraUpdate[0][p] = extraUpdate[2][i]);
|
|
1044
|
+
extraUpdate[1].forEach((p, i) => (extraUpdate[0][p] = extraUpdate[2][i]));
|
|
1017
1045
|
}
|
|
1018
1046
|
else {
|
|
1019
1047
|
extraUpdate[0][extraUpdate[1]] = extraUpdate[2];
|
|
@@ -1075,7 +1103,8 @@ export class UnitOfWork {
|
|
|
1075
1103
|
};
|
|
1076
1104
|
const addToGroup = (cs) => {
|
|
1077
1105
|
// Skip stub TPT changesets with empty payload (e.g. leaf with no own-property changes on UPDATE)
|
|
1078
|
-
if ((cs.type === ChangeSetType.UPDATE || cs.type === ChangeSetType.UPDATE_EARLY) &&
|
|
1106
|
+
if ((cs.type === ChangeSetType.UPDATE || cs.type === ChangeSetType.UPDATE_EARLY) &&
|
|
1107
|
+
!Utils.hasObjectKeys(cs.payload)) {
|
|
1079
1108
|
return;
|
|
1080
1109
|
}
|
|
1081
1110
|
const group = groups[cs.type];
|