@mikro-orm/core 7.0.0-dev.27 → 7.0.0-dev.29
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 +25 -0
- package/EntityManager.js +51 -14
- package/MikroORM.js +0 -1
- package/cache/FileCacheAdapter.d.ts +2 -1
- package/cache/FileCacheAdapter.js +4 -2
- package/entity/EntityLoader.js +8 -11
- package/entity/EntityValidator.js +1 -1
- package/entity/defineEntity.d.ts +7 -7
- package/entity/defineEntity.js +3 -0
- package/hydration/ObjectHydrator.js +8 -1
- package/index.js +1 -1
- package/metadata/MetadataDiscovery.js +1 -1
- package/metadata/MetadataStorage.js +1 -1
- package/package.json +3 -3
- package/types/BigIntType.d.ts +8 -6
- package/types/DecimalType.d.ts +6 -4
- package/typings.d.ts +35 -27
- package/utils/Configuration.d.ts +6 -2
- package/utils/Configuration.js +4 -5
- package/utils/ConfigurationLoader.d.ts +0 -2
- package/utils/ConfigurationLoader.js +0 -22
- package/utils/EntityComparator.js +3 -1
- package/utils/TransactionManager.js +22 -1
- package/utils/Utils.d.ts +1 -3
- package/utils/Utils.js +5 -19
package/EntityManager.d.ts
CHANGED
|
@@ -270,6 +270,29 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
270
270
|
upsertMany<Entity extends object, Fields extends string = any>(entityNameOrEntity: EntityName<Entity> | Entity[], data?: (EntityData<Entity> | NoInfer<Entity>)[], options?: UpsertManyOptions<Entity, Fields>): Promise<Entity[]>;
|
|
271
271
|
/**
|
|
272
272
|
* Runs your callback wrapped inside a database transaction.
|
|
273
|
+
*
|
|
274
|
+
* If a transaction is already active, a new savepoint (nested transaction) will be created by default. This behavior
|
|
275
|
+
* can be controlled via the `propagation` option. Use the provided EntityManager instance for all operations that
|
|
276
|
+
* should be part of the transaction. You can safely use a global EntityManager instance from a DI container, as this
|
|
277
|
+
* method automatically creates an async context for the transaction.
|
|
278
|
+
*
|
|
279
|
+
* **Concurrency note:** When running multiple transactions concurrently (e.g. in parallel requests or jobs), use the
|
|
280
|
+
* `clear: true` option. This ensures the callback runs in a clear fork of the EntityManager, providing full isolation
|
|
281
|
+
* between concurrent transactional handlers. Using `clear: true` is an alternative to forking explicitly and calling
|
|
282
|
+
* the method on the new fork – it already provides the necessary isolation for safe concurrent usage.
|
|
283
|
+
*
|
|
284
|
+
* **Propagation note:** Changes made within a transaction (whether top-level or nested) are always propagated to the
|
|
285
|
+
* parent context, unless the parent context is a global one. If you want to avoid that, fork the EntityManager first
|
|
286
|
+
* and then call this method on the fork.
|
|
287
|
+
*
|
|
288
|
+
* **Example:**
|
|
289
|
+
* ```ts
|
|
290
|
+
* await em.transactional(async (em) => {
|
|
291
|
+
* const author = new Author('Jon');
|
|
292
|
+
* em.persist(author);
|
|
293
|
+
* // flush is called automatically at the end of the callback
|
|
294
|
+
* });
|
|
295
|
+
* ```
|
|
273
296
|
*/
|
|
274
297
|
transactional<T>(cb: (em: this) => T | Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
275
298
|
/**
|
|
@@ -562,6 +585,8 @@ export interface MergeOptions {
|
|
|
562
585
|
schema?: string;
|
|
563
586
|
disableContextResolution?: boolean;
|
|
564
587
|
keepIdentity?: boolean;
|
|
588
|
+
validate?: boolean;
|
|
589
|
+
cascade?: boolean; /** @default true */
|
|
565
590
|
}
|
|
566
591
|
export interface ForkOptions {
|
|
567
592
|
/** do we want a clear identity map? defaults to true */
|
package/EntityManager.js
CHANGED
|
@@ -506,18 +506,24 @@ export class EntityManager {
|
|
|
506
506
|
flushMode: FlushMode.COMMIT,
|
|
507
507
|
});
|
|
508
508
|
const em = this.getContext();
|
|
509
|
-
if (reloaded) {
|
|
510
|
-
for (const e of fork.unitOfWork.getIdentityMap()) {
|
|
511
|
-
const ref = em.getReference(e.constructor.name, helper(e).getPrimaryKey());
|
|
512
|
-
const data = this.comparator.prepareEntity(e);
|
|
513
|
-
em.config.getHydrator(this.metadata).hydrate(ref, helper(ref).__meta, helper(e).serialize({ ignoreSerializers: true, includeHidden: true }), em.entityFactory, 'full', false, true);
|
|
514
|
-
helper(ref).__originalEntityData = data;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
else {
|
|
509
|
+
if (!reloaded) {
|
|
518
510
|
em.unitOfWork.unsetIdentity(entity);
|
|
511
|
+
return null;
|
|
519
512
|
}
|
|
520
|
-
|
|
513
|
+
let found = false;
|
|
514
|
+
for (const e of fork.unitOfWork.getIdentityMap()) {
|
|
515
|
+
const ref = em.getReference(e.constructor.name, helper(e).getPrimaryKey());
|
|
516
|
+
const data = helper(e).serialize({ ignoreSerializers: true, includeHidden: true });
|
|
517
|
+
em.config.getHydrator(this.metadata).hydrate(ref, helper(ref).__meta, data, em.entityFactory, 'full', false, true);
|
|
518
|
+
helper(ref).__originalEntityData = this.comparator.prepareEntity(e);
|
|
519
|
+
found ||= ref === entity;
|
|
520
|
+
}
|
|
521
|
+
if (!found) {
|
|
522
|
+
const data = helper(reloaded).serialize({ ignoreSerializers: true, includeHidden: true });
|
|
523
|
+
em.config.getHydrator(this.metadata).hydrate(entity, helper(entity).__meta, data, em.entityFactory, 'full', false, true);
|
|
524
|
+
helper(entity).__originalEntityData = this.comparator.prepareEntity(reloaded);
|
|
525
|
+
}
|
|
526
|
+
return entity;
|
|
521
527
|
}
|
|
522
528
|
/**
|
|
523
529
|
* Finds first entity matching your `where` query.
|
|
@@ -979,6 +985,29 @@ export class EntityManager {
|
|
|
979
985
|
}
|
|
980
986
|
/**
|
|
981
987
|
* Runs your callback wrapped inside a database transaction.
|
|
988
|
+
*
|
|
989
|
+
* If a transaction is already active, a new savepoint (nested transaction) will be created by default. This behavior
|
|
990
|
+
* can be controlled via the `propagation` option. Use the provided EntityManager instance for all operations that
|
|
991
|
+
* should be part of the transaction. You can safely use a global EntityManager instance from a DI container, as this
|
|
992
|
+
* method automatically creates an async context for the transaction.
|
|
993
|
+
*
|
|
994
|
+
* **Concurrency note:** When running multiple transactions concurrently (e.g. in parallel requests or jobs), use the
|
|
995
|
+
* `clear: true` option. This ensures the callback runs in a clear fork of the EntityManager, providing full isolation
|
|
996
|
+
* between concurrent transactional handlers. Using `clear: true` is an alternative to forking explicitly and calling
|
|
997
|
+
* the method on the new fork – it already provides the necessary isolation for safe concurrent usage.
|
|
998
|
+
*
|
|
999
|
+
* **Propagation note:** Changes made within a transaction (whether top-level or nested) are always propagated to the
|
|
1000
|
+
* parent context, unless the parent context is a global one. If you want to avoid that, fork the EntityManager first
|
|
1001
|
+
* and then call this method on the fork.
|
|
1002
|
+
*
|
|
1003
|
+
* **Example:**
|
|
1004
|
+
* ```ts
|
|
1005
|
+
* await em.transactional(async (em) => {
|
|
1006
|
+
* const author = new Author('Jon');
|
|
1007
|
+
* em.persist(author);
|
|
1008
|
+
* // flush is called automatically at the end of the callback
|
|
1009
|
+
* });
|
|
1010
|
+
* ```
|
|
982
1011
|
*/
|
|
983
1012
|
async transactional(cb, options = {}) {
|
|
984
1013
|
const em = this.getContext(false);
|
|
@@ -1171,8 +1200,12 @@ export class EntityManager {
|
|
|
1171
1200
|
}
|
|
1172
1201
|
const em = options.disableContextResolution ? this : this.getContext();
|
|
1173
1202
|
options.schema ??= em._schema;
|
|
1203
|
+
options.validate ??= true;
|
|
1204
|
+
options.cascade ??= true;
|
|
1174
1205
|
entityName = Utils.className(entityName);
|
|
1175
|
-
|
|
1206
|
+
if (options.validate) {
|
|
1207
|
+
em.validator.validatePrimaryKey(data, em.metadata.get(entityName));
|
|
1208
|
+
}
|
|
1176
1209
|
let entity = em.unitOfWork.tryGetById(entityName, data, options.schema, false);
|
|
1177
1210
|
if (entity && helper(entity).__managed && helper(entity).__initialized && !options.refresh) {
|
|
1178
1211
|
return entity;
|
|
@@ -1181,12 +1214,16 @@ export class EntityManager {
|
|
|
1181
1214
|
const childMeta = em.metadata.getByDiscriminatorColumn(meta, data);
|
|
1182
1215
|
const dataIsEntity = Utils.isEntity(data);
|
|
1183
1216
|
if (options.keepIdentity && entity && dataIsEntity && entity !== data) {
|
|
1184
|
-
|
|
1217
|
+
helper(entity).__data = helper(data).__data;
|
|
1218
|
+
helper(entity).__originalEntityData = helper(data).__originalEntityData;
|
|
1185
1219
|
return entity;
|
|
1186
1220
|
}
|
|
1187
1221
|
entity = dataIsEntity ? data : em.entityFactory.create(entityName, data, { merge: true, ...options });
|
|
1188
|
-
|
|
1189
|
-
|
|
1222
|
+
if (options.validate) {
|
|
1223
|
+
em.validator.validate(entity, data, childMeta ?? meta);
|
|
1224
|
+
}
|
|
1225
|
+
const visited = options.cascade ? undefined : new Set([entity]);
|
|
1226
|
+
em.unitOfWork.merge(entity, visited);
|
|
1190
1227
|
return entity;
|
|
1191
1228
|
}
|
|
1192
1229
|
/**
|
package/MikroORM.js
CHANGED
|
@@ -3,12 +3,13 @@ export declare class FileCacheAdapter implements SyncCacheAdapter {
|
|
|
3
3
|
private readonly options;
|
|
4
4
|
private readonly baseDir;
|
|
5
5
|
private readonly pretty;
|
|
6
|
+
private readonly hashAlgorithm;
|
|
6
7
|
private readonly VERSION;
|
|
7
8
|
private cache;
|
|
8
9
|
constructor(options: {
|
|
9
10
|
cacheDir: string;
|
|
10
11
|
combined?: boolean | string;
|
|
11
|
-
}, baseDir: string, pretty?: boolean);
|
|
12
|
+
}, baseDir: string, pretty?: boolean, hashAlgorithm?: 'md5' | 'sha256');
|
|
12
13
|
/**
|
|
13
14
|
* @inheritDoc
|
|
14
15
|
*/
|
|
@@ -5,12 +5,14 @@ export class FileCacheAdapter {
|
|
|
5
5
|
options;
|
|
6
6
|
baseDir;
|
|
7
7
|
pretty;
|
|
8
|
+
hashAlgorithm;
|
|
8
9
|
VERSION = Utils.getORMVersion();
|
|
9
10
|
cache = {};
|
|
10
|
-
constructor(options, baseDir, pretty = false) {
|
|
11
|
+
constructor(options, baseDir, pretty = false, hashAlgorithm = 'md5') {
|
|
11
12
|
this.options = options;
|
|
12
13
|
this.baseDir = baseDir;
|
|
13
14
|
this.pretty = pretty;
|
|
15
|
+
this.hashAlgorithm = hashAlgorithm;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* @inheritDoc
|
|
@@ -77,6 +79,6 @@ export class FileCacheAdapter {
|
|
|
77
79
|
return null;
|
|
78
80
|
}
|
|
79
81
|
const contents = readFileSync(origin);
|
|
80
|
-
return Utils.hash(contents.toString() + this.VERSION);
|
|
82
|
+
return Utils.hash(contents.toString() + this.VERSION, undefined, this.hashAlgorithm);
|
|
81
83
|
}
|
|
82
84
|
}
|
package/entity/EntityLoader.js
CHANGED
|
@@ -466,23 +466,20 @@ export class EntityLoader {
|
|
|
466
466
|
}
|
|
467
467
|
getChildReferences(entities, prop, options, ref) {
|
|
468
468
|
const filtered = this.filterCollections(entities, prop.name, options, ref);
|
|
469
|
-
const children = [];
|
|
470
469
|
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
471
|
-
|
|
470
|
+
return filtered.map(e => e[prop.name].owner);
|
|
472
471
|
}
|
|
473
|
-
|
|
474
|
-
|
|
472
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner) {
|
|
473
|
+
return filtered.reduce((a, b) => {
|
|
475
474
|
a.push(...b[prop.name].getItems());
|
|
476
475
|
return a;
|
|
477
|
-
}, [])
|
|
478
|
-
}
|
|
479
|
-
else if (prop.kind === ReferenceKind.MANY_TO_MANY) { // inverse side
|
|
480
|
-
children.push(...filtered);
|
|
476
|
+
}, []);
|
|
481
477
|
}
|
|
482
|
-
|
|
483
|
-
|
|
478
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) { // inverse side
|
|
479
|
+
return filtered;
|
|
484
480
|
}
|
|
485
|
-
|
|
481
|
+
// MANY_TO_ONE or ONE_TO_ONE
|
|
482
|
+
return this.filterReferences(entities, prop.name, options, ref);
|
|
486
483
|
}
|
|
487
484
|
filterCollections(entities, field, options, ref) {
|
|
488
485
|
if (options.refresh) {
|
|
@@ -11,7 +11,7 @@ export class EntityValidator {
|
|
|
11
11
|
}
|
|
12
12
|
validate(entity, payload, meta) {
|
|
13
13
|
meta.props.forEach(prop => {
|
|
14
|
-
if (prop.inherited) {
|
|
14
|
+
if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
package/entity/defineEntity.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ export declare class PropertyOptionsBuilder<Value> {
|
|
|
73
73
|
/**
|
|
74
74
|
* Explicitly specify the auto increment of the primary key.
|
|
75
75
|
*/
|
|
76
|
-
autoincrement(autoincrement?:
|
|
76
|
+
autoincrement<T extends boolean = true>(autoincrement?: T): PropertyOptionsBuilder<T extends true ? Opt<Value> : Value>;
|
|
77
77
|
/**
|
|
78
78
|
* Add the property to the `returning` statement.
|
|
79
79
|
*/
|
|
@@ -443,6 +443,9 @@ export declare class OneToOneOptionsBuilder<TargetValue extends object> extends
|
|
|
443
443
|
deferMode(deferMode: DeferMode | `${DeferMode}`): OneToOneOptionsBuilder<TargetValue>;
|
|
444
444
|
}
|
|
445
445
|
declare const propertyBuilders: {
|
|
446
|
+
bigint: <Mode extends "bigint" | "number" | "string" = "bigint">(mode?: Mode) => PropertyOptionsBuilder<(Mode extends "bigint" ? bigint : Mode extends "number" ? number : string) & {}>;
|
|
447
|
+
array: <T = string>(toJsValue?: (i: string) => T, toDbValue?: (i: T) => string) => PropertyOptionsBuilder<T[]>;
|
|
448
|
+
decimal: <Mode extends "number" | "string" = "string">(mode?: Mode) => PropertyOptionsBuilder<NonNullable<Mode extends "number" ? number : string>>;
|
|
446
449
|
json: <T>() => PropertyOptionsBuilder<T>;
|
|
447
450
|
formula: <T>(formula: string | ((alias: string) => string)) => PropertyOptionsBuilder<T>;
|
|
448
451
|
type: <T extends PropertyValueType>(type: T) => PropertyOptionsBuilder<InferPropertyValueType<T>>;
|
|
@@ -455,10 +458,8 @@ declare const propertyBuilders: {
|
|
|
455
458
|
date: () => PropertyOptionsBuilder<string>;
|
|
456
459
|
time: () => PropertyOptionsBuilder<any>;
|
|
457
460
|
datetime: () => PropertyOptionsBuilder<Date>;
|
|
458
|
-
bigint: () => PropertyOptionsBuilder<NonNullable<string | number | bigint | null | undefined>>;
|
|
459
461
|
blob: () => PropertyOptionsBuilder<NonNullable<Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike> | null>>;
|
|
460
462
|
uint8array: () => PropertyOptionsBuilder<Uint8Array<ArrayBufferLike>>;
|
|
461
|
-
array: () => PropertyOptionsBuilder<unknown[]>;
|
|
462
463
|
enumArray: () => PropertyOptionsBuilder<(string | number)[]>;
|
|
463
464
|
integer: () => PropertyOptionsBuilder<number>;
|
|
464
465
|
smallint: () => PropertyOptionsBuilder<number>;
|
|
@@ -467,7 +468,6 @@ declare const propertyBuilders: {
|
|
|
467
468
|
float: () => PropertyOptionsBuilder<number>;
|
|
468
469
|
double: () => PropertyOptionsBuilder<NonNullable<string | number>>;
|
|
469
470
|
boolean: () => PropertyOptionsBuilder<NonNullable<boolean | null | undefined>>;
|
|
470
|
-
decimal: () => PropertyOptionsBuilder<NonNullable<string | number>>;
|
|
471
471
|
character: () => PropertyOptionsBuilder<string>;
|
|
472
472
|
string: () => PropertyOptionsBuilder<string>;
|
|
473
473
|
uuid: () => PropertyOptionsBuilder<string>;
|
|
@@ -481,6 +481,9 @@ export declare function defineEntity<Properties extends Record<string, any>>(met
|
|
|
481
481
|
}): EntitySchema<InferEntityFromProperties<Properties>, never>;
|
|
482
482
|
export declare namespace defineEntity {
|
|
483
483
|
var properties: {
|
|
484
|
+
bigint: <Mode extends "bigint" | "number" | "string" = "bigint">(mode?: Mode) => PropertyOptionsBuilder<(Mode extends "bigint" ? bigint : Mode extends "number" ? number : string) & {}>;
|
|
485
|
+
array: <T = string>(toJsValue?: (i: string) => T, toDbValue?: (i: T) => string) => PropertyOptionsBuilder<T[]>;
|
|
486
|
+
decimal: <Mode extends "number" | "string" = "string">(mode?: Mode) => PropertyOptionsBuilder<NonNullable<Mode extends "number" ? number : string>>;
|
|
484
487
|
json: <T>() => PropertyOptionsBuilder<T>;
|
|
485
488
|
formula: <T>(formula: string | ((alias: string) => string)) => PropertyOptionsBuilder<T>;
|
|
486
489
|
type: <T extends PropertyValueType>(type: T) => PropertyOptionsBuilder<InferPropertyValueType<T>>;
|
|
@@ -493,10 +496,8 @@ export declare namespace defineEntity {
|
|
|
493
496
|
date: () => PropertyOptionsBuilder<string>;
|
|
494
497
|
time: () => PropertyOptionsBuilder<any>;
|
|
495
498
|
datetime: () => PropertyOptionsBuilder<Date>;
|
|
496
|
-
bigint: () => PropertyOptionsBuilder<NonNullable<string | number | bigint | null | undefined>>;
|
|
497
499
|
blob: () => PropertyOptionsBuilder<NonNullable<Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike> | null>>;
|
|
498
500
|
uint8array: () => PropertyOptionsBuilder<Uint8Array<ArrayBufferLike>>;
|
|
499
|
-
array: () => PropertyOptionsBuilder<unknown[]>;
|
|
500
501
|
enumArray: () => PropertyOptionsBuilder<(string | number)[]>;
|
|
501
502
|
integer: () => PropertyOptionsBuilder<number>;
|
|
502
503
|
smallint: () => PropertyOptionsBuilder<number>;
|
|
@@ -505,7 +506,6 @@ export declare namespace defineEntity {
|
|
|
505
506
|
float: () => PropertyOptionsBuilder<number>;
|
|
506
507
|
double: () => PropertyOptionsBuilder<NonNullable<string | number>>;
|
|
507
508
|
boolean: () => PropertyOptionsBuilder<NonNullable<boolean | null | undefined>>;
|
|
508
|
-
decimal: () => PropertyOptionsBuilder<NonNullable<string | number>>;
|
|
509
509
|
character: () => PropertyOptionsBuilder<string>;
|
|
510
510
|
string: () => PropertyOptionsBuilder<string>;
|
|
511
511
|
uuid: () => PropertyOptionsBuilder<string>;
|
package/entity/defineEntity.js
CHANGED
|
@@ -622,6 +622,9 @@ function createPropertyBuilders(options) {
|
|
|
622
622
|
}
|
|
623
623
|
const propertyBuilders = {
|
|
624
624
|
...createPropertyBuilders(types),
|
|
625
|
+
bigint: (mode) => new PropertyOptionsBuilder({ type: new types.bigint(mode) }),
|
|
626
|
+
array: (toJsValue = i => i, toDbValue = i => i) => new PropertyOptionsBuilder({ type: new types.array(toJsValue, toDbValue) }),
|
|
627
|
+
decimal: (mode) => new PropertyOptionsBuilder({ type: new types.decimal(mode) }),
|
|
625
628
|
json: () => new PropertyOptionsBuilder({ type: types.json }),
|
|
626
629
|
formula: (formula) => new PropertyOptionsBuilder({ formula }),
|
|
627
630
|
type: (type) => new PropertyOptionsBuilder({ type }),
|
|
@@ -71,7 +71,14 @@ export class ObjectHydrator extends Hydrator {
|
|
|
71
71
|
ret.push(` const oldValue_${idx} = entity${entityKey};`);
|
|
72
72
|
}
|
|
73
73
|
ret.push(` if (data${dataKey} === null) {`);
|
|
74
|
-
|
|
74
|
+
if (prop.ref) {
|
|
75
|
+
ret.push(` entity${entityKey} = new ScalarReference();`);
|
|
76
|
+
ret.push(` entity${entityKey}.bind(entity, '${prop.name}');`);
|
|
77
|
+
ret.push(` entity${entityKey}.set(${nullVal});`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
ret.push(` entity${entityKey} = ${nullVal};`);
|
|
81
|
+
}
|
|
75
82
|
ret.push(` } else if (typeof data${dataKey} !== 'undefined') {`);
|
|
76
83
|
if (prop.customType) {
|
|
77
84
|
registerCustomType(prop, convertorKey, 'convertToJSValue', context);
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
|
-
export { PrimaryKeyProp, EntityMetadata, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, } from './typings.js';
|
|
5
|
+
export { PrimaryKeyProp, EntityMetadata, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Opt, Hidden, Config, DefineConfig, RequiredNullable, } from './typings.js';
|
|
6
6
|
export * from './enums.js';
|
|
7
7
|
export * from './errors.js';
|
|
8
8
|
export * from './exceptions.js';
|
|
@@ -1152,7 +1152,7 @@ export class MetadataDiscovery {
|
|
|
1152
1152
|
if (prop.fieldNames?.length === 1 && !prop.customType) {
|
|
1153
1153
|
[BigIntType, DoubleType, DecimalType, IntervalType, DateType]
|
|
1154
1154
|
.filter(type => mappedType instanceof type)
|
|
1155
|
-
.forEach(type => prop.customType = new type());
|
|
1155
|
+
.forEach((type) => prop.customType = new type());
|
|
1156
1156
|
}
|
|
1157
1157
|
if (prop.customType && !prop.columnTypes) {
|
|
1158
1158
|
const mappedType = this.getMappedType({ columnTypes: [prop.customType.getColumnType(prop, this.platform)] });
|
|
@@ -10,7 +10,7 @@ export class MetadataStorage {
|
|
|
10
10
|
this.metadata = Utils.copy(metadata, false);
|
|
11
11
|
}
|
|
12
12
|
static getMetadata(entity, path) {
|
|
13
|
-
const key = entity && path ? entity + '-' + Utils.hash(path) : null;
|
|
13
|
+
const key = entity && path ? entity + '-' + Utils.hash(path, undefined, 'sha256') : null;
|
|
14
14
|
if (key && !MetadataStorage.metadata[key]) {
|
|
15
15
|
MetadataStorage.metadata[key] = new EntityMetadata({ className: entity, path });
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.0.0-dev.
|
|
4
|
+
"version": "7.0.0-dev.29",
|
|
5
5
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./package.json": "./package.json",
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"dataloader": "2.2.3",
|
|
55
|
-
"dotenv": "17.2.
|
|
55
|
+
"dotenv": "17.2.3",
|
|
56
56
|
"esprima": "4.0.1",
|
|
57
|
-
"mikro-orm": "7.0.0-dev.
|
|
57
|
+
"mikro-orm": "7.0.0-dev.29",
|
|
58
58
|
"reflect-metadata": "0.2.2",
|
|
59
59
|
"tinyglobby": "0.2.13"
|
|
60
60
|
}
|
package/types/BigIntType.d.ts
CHANGED
|
@@ -5,13 +5,15 @@ import type { EntityProperty } from '../typings.js';
|
|
|
5
5
|
* This type will automatically convert string values returned from the database to native JS bigints (default)
|
|
6
6
|
* or numbers (safe only for values up to `Number.MAX_SAFE_INTEGER`), or strings, depending on the `mode`.
|
|
7
7
|
*/
|
|
8
|
-
export declare class BigIntType extends
|
|
9
|
-
mode?:
|
|
10
|
-
constructor(mode?:
|
|
11
|
-
convertToDatabaseValue(value:
|
|
12
|
-
convertToJSValue(value: string | bigint | null | undefined):
|
|
13
|
-
toJSON(value:
|
|
8
|
+
export declare class BigIntType<Mode extends 'bigint' | 'number' | 'string' = 'bigint'> extends Type<JSTypeByMode<Mode> | null | undefined, string | null | undefined> {
|
|
9
|
+
mode?: Mode | undefined;
|
|
10
|
+
constructor(mode?: Mode | undefined);
|
|
11
|
+
convertToDatabaseValue(value: JSTypeByMode<Mode> | null | undefined): string | null | undefined;
|
|
12
|
+
convertToJSValue(value: string | bigint | null | undefined): JSTypeByMode<Mode> | null | undefined;
|
|
13
|
+
toJSON(value: JSTypeByMode<Mode> | null | undefined): JSTypeByMode<Mode> | null | undefined;
|
|
14
14
|
getColumnType(prop: EntityProperty, platform: Platform): string;
|
|
15
15
|
compareAsType(): string;
|
|
16
16
|
compareValues(a: string, b: string): boolean;
|
|
17
17
|
}
|
|
18
|
+
type JSTypeByMode<Mode extends 'bigint' | 'number' | 'string'> = Mode extends 'bigint' ? bigint : Mode extends 'number' ? number : string;
|
|
19
|
+
export {};
|
package/types/DecimalType.d.ts
CHANGED
|
@@ -4,12 +4,14 @@ import type { EntityProperty } from '../typings.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* Type that maps an SQL DECIMAL to a JS string or number.
|
|
6
6
|
*/
|
|
7
|
-
export declare class DecimalType extends
|
|
8
|
-
mode?:
|
|
9
|
-
constructor(mode?:
|
|
10
|
-
convertToJSValue(value: string):
|
|
7
|
+
export declare class DecimalType<Mode extends 'number' | 'string' = 'string'> extends Type<JSTypeByMode<Mode>, string> {
|
|
8
|
+
mode?: Mode | undefined;
|
|
9
|
+
constructor(mode?: Mode | undefined);
|
|
10
|
+
convertToJSValue(value: string): JSTypeByMode<Mode>;
|
|
11
11
|
compareValues(a: string, b: string): boolean;
|
|
12
12
|
private format;
|
|
13
13
|
getColumnType(prop: EntityProperty, platform: Platform): string;
|
|
14
14
|
compareAsType(): string;
|
|
15
15
|
}
|
|
16
|
+
type JSTypeByMode<Mode extends 'number' | 'string'> = Mode extends 'number' ? number : string;
|
|
17
|
+
export {};
|
package/typings.d.ts
CHANGED
|
@@ -52,22 +52,34 @@ export declare const OptionalProps: unique symbol;
|
|
|
52
52
|
export declare const EagerProps: unique symbol;
|
|
53
53
|
export declare const HiddenProps: unique symbol;
|
|
54
54
|
export declare const Config: unique symbol;
|
|
55
|
-
|
|
56
|
-
declare
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
export type RequiredNullable<T = never> = (T &
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
55
|
+
export type Opt<T = unknown> = T & Opt.Brand;
|
|
56
|
+
export declare namespace Opt {
|
|
57
|
+
const __optional: unique symbol;
|
|
58
|
+
interface Brand {
|
|
59
|
+
[__optional]?: 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export type RequiredNullable<T = never> = (T & RequiredNullable.Brand) | null;
|
|
63
|
+
export declare namespace RequiredNullable {
|
|
64
|
+
const __requiredNullable: unique symbol;
|
|
65
|
+
interface Brand {
|
|
66
|
+
[__requiredNullable]?: 1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export type Hidden<T = unknown> = T & Hidden.Brand;
|
|
70
|
+
export declare namespace Hidden {
|
|
71
|
+
const __hidden: unique symbol;
|
|
72
|
+
interface Brand {
|
|
73
|
+
[__hidden]?: 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export type DefineConfig<T extends TypeConfig> = T & DefineConfig.Brand;
|
|
77
|
+
export declare namespace DefineConfig {
|
|
78
|
+
const __config: unique symbol;
|
|
79
|
+
interface Brand {
|
|
80
|
+
[__config]?: 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
71
83
|
export type CleanTypeConfig<T> = Compute<Pick<T, Extract<keyof T, keyof TypeConfig>>>;
|
|
72
84
|
export interface TypeConfig {
|
|
73
85
|
forceObject?: boolean;
|
|
@@ -82,9 +94,9 @@ export type Primary<T> = IsAny<T> extends true ? any : T extends {
|
|
|
82
94
|
} ? (PK extends keyof T ? ReadonlyPrimary<UnwrapPrimary<T[PK]>> : (PK extends (keyof T)[] ? ReadonlyPrimary<PrimaryPropToType<T, PK>> : PK)) : T extends {
|
|
83
95
|
_id?: infer PK;
|
|
84
96
|
} ? ReadonlyPrimary<PK> | string : T extends {
|
|
85
|
-
uuid?: infer PK;
|
|
86
|
-
} ? ReadonlyPrimary<PK> : T extends {
|
|
87
97
|
id?: infer PK;
|
|
98
|
+
} ? ReadonlyPrimary<PK> : T extends {
|
|
99
|
+
uuid?: infer PK;
|
|
88
100
|
} ? ReadonlyPrimary<PK> : T;
|
|
89
101
|
/** @internal */
|
|
90
102
|
export type PrimaryProperty<T> = T extends {
|
|
@@ -94,10 +106,10 @@ export type PrimaryProperty<T> = T extends {
|
|
|
94
106
|
} ? (T extends {
|
|
95
107
|
id?: any;
|
|
96
108
|
} ? 'id' | '_id' : '_id') : T extends {
|
|
97
|
-
uuid?: any;
|
|
98
|
-
} ? 'uuid' : T extends {
|
|
99
109
|
id?: any;
|
|
100
|
-
} ? 'id' :
|
|
110
|
+
} ? 'id' : T extends {
|
|
111
|
+
uuid?: any;
|
|
112
|
+
} ? 'uuid' : never;
|
|
101
113
|
export type IPrimaryKeyValue = number | string | bigint | Date | {
|
|
102
114
|
toHexString(): string;
|
|
103
115
|
};
|
|
@@ -229,9 +241,7 @@ export type EntityDataProp<T, C extends boolean> = T extends Date ? string | Dat
|
|
|
229
241
|
__runtime?: infer Runtime;
|
|
230
242
|
__raw?: infer Raw;
|
|
231
243
|
} ? (C extends true ? Raw : Runtime) : T extends Reference<infer U> ? EntityDataNested<U, C> : T extends ScalarReference<infer U> ? EntityDataProp<U, C> : T extends Collection<infer U, any> ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : U[] | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
|
|
232
|
-
export type RequiredEntityDataProp<T, O, C extends boolean> = T extends Date ? string | Date : Exclude<T, null> extends {
|
|
233
|
-
[__requiredNullable]?: 1;
|
|
234
|
-
} ? T | null : T extends Scalar ? T : T extends {
|
|
244
|
+
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 {
|
|
235
245
|
__runtime?: infer Runtime;
|
|
236
246
|
__raw?: infer Raw;
|
|
237
247
|
} ? (C extends true ? Raw : Runtime) : T extends Reference<infer U> ? RequiredEntityDataNested<U, O, C> : T extends ScalarReference<infer U> ? RequiredEntityDataProp<U, O, C> : T extends Collection<infer U, any> ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, 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>;
|
|
@@ -247,9 +257,7 @@ type NullableKeys<T, V = null> = {
|
|
|
247
257
|
[K in keyof T]: V extends T[K] ? K : never;
|
|
248
258
|
}[keyof T];
|
|
249
259
|
type RequiredNullableKeys<T> = {
|
|
250
|
-
[K in keyof T]: Exclude<T[K], null> extends
|
|
251
|
-
[__requiredNullable]?: 1;
|
|
252
|
-
} ? K : never;
|
|
260
|
+
[K in keyof T]: Exclude<T[K], null> extends RequiredNullable.Brand ? K : never;
|
|
253
261
|
}[keyof T];
|
|
254
262
|
type ProbablyOptionalProps<T> = PrimaryProperty<T> | ExplicitlyOptionalProps<T> | Exclude<NonNullable<NullableKeys<T, null | undefined>>, RequiredNullableKeys<T>>;
|
|
255
263
|
type IsOptional<T, K extends keyof T, I> = T[K] extends Collection<any, any> ? true : ExtractType<T[K]> extends I ? true : K extends ProbablyOptionalProps<T> ? true : false;
|
package/utils/Configuration.d.ts
CHANGED
|
@@ -82,6 +82,7 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
82
82
|
ensureDatabase: true;
|
|
83
83
|
ensureIndexes: false;
|
|
84
84
|
batchSize: number;
|
|
85
|
+
hashAlgorithm: "md5";
|
|
85
86
|
debug: false;
|
|
86
87
|
ignoreDeprecations: false;
|
|
87
88
|
verbose: false;
|
|
@@ -104,6 +105,8 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
104
105
|
disableForeignKeys: false;
|
|
105
106
|
createForeignKeyConstraints: true;
|
|
106
107
|
ignoreSchema: never[];
|
|
108
|
+
skipTables: never[];
|
|
109
|
+
skipColumns: {};
|
|
107
110
|
};
|
|
108
111
|
embeddables: {
|
|
109
112
|
prefixMode: "relative";
|
|
@@ -143,7 +146,6 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
143
146
|
fileName: (className: string) => string;
|
|
144
147
|
};
|
|
145
148
|
preferReadReplicas: true;
|
|
146
|
-
dynamicImportProvider: (id: string) => Promise<any>;
|
|
147
149
|
};
|
|
148
150
|
private readonly options;
|
|
149
151
|
private readonly logger;
|
|
@@ -380,6 +382,8 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
380
382
|
disableForeignKeys?: boolean;
|
|
381
383
|
createForeignKeyConstraints?: boolean;
|
|
382
384
|
ignoreSchema?: string[];
|
|
385
|
+
skipTables?: (string | RegExp)[];
|
|
386
|
+
skipColumns?: Dictionary<(string | RegExp)[]>;
|
|
383
387
|
managementDbName?: string;
|
|
384
388
|
};
|
|
385
389
|
embeddables: {
|
|
@@ -408,6 +412,6 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
408
412
|
};
|
|
409
413
|
seeder: SeederOptions;
|
|
410
414
|
preferReadReplicas: boolean;
|
|
411
|
-
|
|
415
|
+
hashAlgorithm: 'md5' | 'sha256';
|
|
412
416
|
}
|
|
413
417
|
export type Options<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = D[typeof EntityManagerType] & EntityManager> = Pick<MikroORMOptions<D, EM>, Exclude<keyof MikroORMOptions<D, EM>, keyof typeof Configuration.DEFAULTS>> & Partial<MikroORMOptions<D, EM>>;
|
package/utils/Configuration.js
CHANGED
|
@@ -72,6 +72,7 @@ export class Configuration {
|
|
|
72
72
|
ensureDatabase: true,
|
|
73
73
|
ensureIndexes: false,
|
|
74
74
|
batchSize: 300,
|
|
75
|
+
hashAlgorithm: 'md5',
|
|
75
76
|
debug: false,
|
|
76
77
|
ignoreDeprecations: false,
|
|
77
78
|
verbose: false,
|
|
@@ -94,6 +95,8 @@ export class Configuration {
|
|
|
94
95
|
disableForeignKeys: false,
|
|
95
96
|
createForeignKeyConstraints: true,
|
|
96
97
|
ignoreSchema: [],
|
|
98
|
+
skipTables: [],
|
|
99
|
+
skipColumns: {},
|
|
97
100
|
},
|
|
98
101
|
embeddables: {
|
|
99
102
|
prefixMode: 'relative',
|
|
@@ -131,7 +134,6 @@ export class Configuration {
|
|
|
131
134
|
fileName: (className) => className,
|
|
132
135
|
},
|
|
133
136
|
preferReadReplicas: true,
|
|
134
|
-
dynamicImportProvider: /* v8 ignore next */ (id) => import(id),
|
|
135
137
|
};
|
|
136
138
|
options;
|
|
137
139
|
logger;
|
|
@@ -140,9 +142,6 @@ export class Configuration {
|
|
|
140
142
|
cache = new Map();
|
|
141
143
|
extensions = new Map();
|
|
142
144
|
constructor(options, validate = true) {
|
|
143
|
-
if (options.dynamicImportProvider) {
|
|
144
|
-
Utils.setDynamicImportProvider(options.dynamicImportProvider);
|
|
145
|
-
}
|
|
146
145
|
this.options = Utils.mergeConfig({}, Configuration.DEFAULTS, options);
|
|
147
146
|
this.options.baseDir = Utils.absolutePath(this.options.baseDir);
|
|
148
147
|
this.options.preferTs ??= options.preferTs;
|
|
@@ -269,7 +268,7 @@ export class Configuration {
|
|
|
269
268
|
* Gets instance of metadata CacheAdapter. (cached)
|
|
270
269
|
*/
|
|
271
270
|
getMetadataCacheAdapter() {
|
|
272
|
-
return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty);
|
|
271
|
+
return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty, this.options.hashAlgorithm);
|
|
273
272
|
}
|
|
274
273
|
/**
|
|
275
274
|
* Gets instance of CacheAdapter for result cache. (cached)
|
|
@@ -40,8 +40,6 @@ export declare class ConfigurationLoader {
|
|
|
40
40
|
static loadEnvironmentVars<D extends IDatabaseDriver>(): Promise<Partial<Options<D>>>;
|
|
41
41
|
static loadEnvironmentVarsSync<D extends IDatabaseDriver>(): Partial<Options<D>>;
|
|
42
42
|
static getORMPackages(): Set<string>;
|
|
43
|
-
/** @internal */
|
|
44
|
-
static commonJSCompat(options: Partial<Options>): void;
|
|
45
43
|
static getORMPackageVersion(name: string): string | undefined;
|
|
46
44
|
static checkPackageVersion(): string;
|
|
47
45
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import dotenv from 'dotenv';
|
|
2
2
|
import { realpathSync } from 'node:fs';
|
|
3
|
-
import { platform } from 'node:os';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
3
|
import { colors } from '../logging/colors.js';
|
|
6
4
|
import { Configuration } from './Configuration.js';
|
|
7
5
|
import { Utils } from './Utils.js';
|
|
@@ -12,7 +10,6 @@ export class ConfigurationLoader {
|
|
|
12
10
|
static async getConfiguration(contextName = 'default', paths = ConfigurationLoader.getConfigPaths(), options = {}) {
|
|
13
11
|
// Backwards compatibility layer
|
|
14
12
|
if (typeof contextName === 'boolean' || !Array.isArray(paths)) {
|
|
15
|
-
this.commonJSCompat(options);
|
|
16
13
|
this.registerDotenv(options);
|
|
17
14
|
const configPathFromArg = ConfigurationLoader.configPathsFromArg();
|
|
18
15
|
const configPaths = configPathFromArg ?? (Array.isArray(paths) ? paths : ConfigurationLoader.getConfigPaths());
|
|
@@ -300,25 +297,6 @@ export class ConfigurationLoader {
|
|
|
300
297
|
...Object.keys(pkg.devDependencies ?? {}),
|
|
301
298
|
]);
|
|
302
299
|
}
|
|
303
|
-
/** @internal */
|
|
304
|
-
static commonJSCompat(options) {
|
|
305
|
-
if (this.isESM()) {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
/* v8 ignore next 11 */
|
|
309
|
-
options.dynamicImportProvider ??= id => {
|
|
310
|
-
if (platform() === 'win32') {
|
|
311
|
-
try {
|
|
312
|
-
id = fileURLToPath(id);
|
|
313
|
-
}
|
|
314
|
-
catch {
|
|
315
|
-
// ignore
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return Utils.requireFrom(id);
|
|
319
|
-
};
|
|
320
|
-
Utils.setDynamicImportProvider(options.dynamicImportProvider);
|
|
321
|
-
}
|
|
322
300
|
static getORMPackageVersion(name) {
|
|
323
301
|
try {
|
|
324
302
|
const pkg = Utils.requireFrom(`${name}/package.json`);
|
|
@@ -562,7 +562,9 @@ export class EntityComparator {
|
|
|
562
562
|
return comparator;
|
|
563
563
|
}
|
|
564
564
|
getGenericComparator(prop, cond) {
|
|
565
|
-
return ` if (current${prop}
|
|
565
|
+
return ` if (current${prop} === null && last${prop} === undefined) {\n` +
|
|
566
|
+
` diff${prop} = current${prop};\n` +
|
|
567
|
+
` } else if (current${prop} == null && last${prop} == null) {\n\n` +
|
|
566
568
|
` } else if ((current${prop} != null && last${prop} == null) || (current${prop} == null && last${prop} != null)) {\n` +
|
|
567
569
|
` diff${prop} = current${prop};\n` +
|
|
568
570
|
` } else if (${cond}) {\n` +
|
|
@@ -3,6 +3,7 @@ import { TransactionEventBroadcaster } from '../events/TransactionEventBroadcast
|
|
|
3
3
|
import { TransactionContext } from '../utils/TransactionContext.js';
|
|
4
4
|
import { ChangeSetType } from '../unit-of-work/ChangeSet.js';
|
|
5
5
|
import { TransactionStateError } from '../errors.js';
|
|
6
|
+
import { helper } from '../entity/wrap.js';
|
|
6
7
|
/**
|
|
7
8
|
* Manages transaction lifecycle and propagation for EntityManager.
|
|
8
9
|
*/
|
|
@@ -149,8 +150,28 @@ export class TransactionManager {
|
|
|
149
150
|
* Merges entities from fork to parent EntityManager.
|
|
150
151
|
*/
|
|
151
152
|
mergeEntitiesToParent(fork, parent) {
|
|
153
|
+
const parentUoW = parent.getUnitOfWork(false);
|
|
154
|
+
// perf: if parent is empty, we can just move all entities from the fork to skip the `em.merge` overhead
|
|
155
|
+
if (parentUoW.getIdentityMap().keys().length === 0) {
|
|
156
|
+
for (const entity of fork.getUnitOfWork(false).getIdentityMap()) {
|
|
157
|
+
parentUoW.getIdentityMap().store(entity);
|
|
158
|
+
helper(entity).__em = parent;
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
152
162
|
for (const entity of fork.getUnitOfWork(false).getIdentityMap()) {
|
|
153
|
-
|
|
163
|
+
const wrapped = helper(entity);
|
|
164
|
+
const meta = wrapped.__meta;
|
|
165
|
+
// eslint-disable-next-line dot-notation
|
|
166
|
+
const parentEntity = parentUoW.getById(meta.className, wrapped.getPrimaryKey(), parent['_schema'], true);
|
|
167
|
+
if (parentEntity && parentEntity !== entity) {
|
|
168
|
+
const parentWrapped = helper(parentEntity);
|
|
169
|
+
parentWrapped.__data = helper(entity).__data;
|
|
170
|
+
parentWrapped.__originalEntityData = helper(entity).__originalEntityData;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
parentUoW.merge(entity, new Set([entity]));
|
|
174
|
+
}
|
|
154
175
|
}
|
|
155
176
|
}
|
|
156
177
|
/**
|
package/utils/Utils.d.ts
CHANGED
|
@@ -15,7 +15,6 @@ export declare function equals(a: any, b: any): boolean;
|
|
|
15
15
|
export declare function parseJsonSafe<T = unknown>(value: unknown): T;
|
|
16
16
|
export declare class Utils {
|
|
17
17
|
static readonly PK_SEPARATOR = "~~~";
|
|
18
|
-
static dynamicImportProvider: (id: string) => Promise<any>;
|
|
19
18
|
/**
|
|
20
19
|
* Checks if the argument is not undefined
|
|
21
20
|
*/
|
|
@@ -206,7 +205,7 @@ export declare class Utils {
|
|
|
206
205
|
* If either `path` or `baseDir` are `file:` URLs, they are converted to local paths.
|
|
207
206
|
*/
|
|
208
207
|
static absolutePath(path: string, baseDir?: string): string;
|
|
209
|
-
static hash(data: string, length?: number): string;
|
|
208
|
+
static hash(data: string, length?: number, algorithm?: 'md5' | 'sha256'): string;
|
|
210
209
|
static runIfNotEmpty(clause: () => any, data: any): void;
|
|
211
210
|
static defaultValue<T extends Dictionary>(prop: T, option: keyof T, defaultValue: any): void;
|
|
212
211
|
static findDuplicates<T>(items: T[]): T[];
|
|
@@ -237,7 +236,6 @@ export declare class Utils {
|
|
|
237
236
|
*/
|
|
238
237
|
static resolveModulePath(id: string, from?: string): string;
|
|
239
238
|
static dynamicImport<T = any>(id: string): Promise<T>;
|
|
240
|
-
static setDynamicImportProvider(provider: (id: string) => Promise<unknown>): void;
|
|
241
239
|
static ensureDir(path: string): void;
|
|
242
240
|
static pathExistsSync(path: string): boolean;
|
|
243
241
|
static readJSONSync(path: string): Dictionary;
|
package/utils/Utils.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import { glob, isDynamicPattern } from 'tinyglobby';
|
|
3
3
|
import { extname, isAbsolute, join, normalize, relative, resolve } from 'node:path';
|
|
4
|
-
import { platform } from 'node:os';
|
|
5
4
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
5
|
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
7
6
|
import { createHash } from 'node:crypto';
|
|
@@ -132,8 +131,6 @@ export function parseJsonSafe(value) {
|
|
|
132
131
|
}
|
|
133
132
|
export class Utils {
|
|
134
133
|
static PK_SEPARATOR = '~~~';
|
|
135
|
-
/* v8 ignore next */
|
|
136
|
-
static dynamicImportProvider = (id) => import(id);
|
|
137
134
|
/**
|
|
138
135
|
* Checks if the argument is not undefined
|
|
139
136
|
*/
|
|
@@ -789,8 +786,9 @@ export class Utils {
|
|
|
789
786
|
}
|
|
790
787
|
return Utils.normalizePath(path);
|
|
791
788
|
}
|
|
792
|
-
static hash(data, length) {
|
|
793
|
-
const
|
|
789
|
+
static hash(data, length, algorithm) {
|
|
790
|
+
const hashAlgorithm = algorithm || 'sha256';
|
|
791
|
+
const hash = createHash(hashAlgorithm).update(data).digest('hex');
|
|
794
792
|
if (length) {
|
|
795
793
|
return hash.substring(0, length);
|
|
796
794
|
}
|
|
@@ -907,21 +905,9 @@ export class Utils {
|
|
|
907
905
|
return parts.join('/');
|
|
908
906
|
}
|
|
909
907
|
static async dynamicImport(id) {
|
|
910
|
-
/* v8 ignore next 7 */
|
|
911
|
-
if (platform() === 'win32') {
|
|
912
|
-
try {
|
|
913
|
-
id = pathToFileURL(id).toString();
|
|
914
|
-
}
|
|
915
|
-
catch {
|
|
916
|
-
// ignore
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
908
|
/* v8 ignore next */
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
/* v8 ignore next 3 */
|
|
923
|
-
static setDynamicImportProvider(provider) {
|
|
924
|
-
this.dynamicImportProvider = provider;
|
|
909
|
+
const specifier = id.startsWith('file://') ? id : pathToFileURL(id).href;
|
|
910
|
+
return import(specifier);
|
|
925
911
|
}
|
|
926
912
|
static ensureDir(path) {
|
|
927
913
|
if (!existsSync(path)) {
|