@mikro-orm/core 7.0.0-dev.2 → 7.0.0-dev.21
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 +13 -5
- package/EntityManager.js +60 -40
- package/MikroORM.js +2 -2
- package/cache/FileCacheAdapter.js +2 -2
- package/decorators/Check.d.ts +2 -2
- package/decorators/CreateRequestContext.js +4 -1
- package/decorators/Embeddable.d.ts +5 -5
- package/decorators/Embeddable.js +1 -1
- package/decorators/Embedded.d.ts +6 -12
- package/decorators/Entity.d.ts +5 -5
- package/decorators/Entity.js +0 -1
- package/decorators/Enum.d.ts +1 -1
- package/decorators/Formula.d.ts +1 -2
- package/decorators/Indexed.d.ts +9 -7
- package/decorators/Indexed.js +1 -1
- package/decorators/ManyToMany.d.ts +2 -2
- package/decorators/ManyToOne.d.ts +4 -2
- package/decorators/OneToMany.d.ts +4 -4
- package/decorators/OneToOne.d.ts +3 -1
- package/decorators/PrimaryKey.d.ts +2 -3
- package/decorators/Property.d.ts +1 -1
- package/drivers/IDatabaseDriver.d.ts +4 -1
- package/entity/ArrayCollection.d.ts +1 -1
- package/entity/ArrayCollection.js +11 -4
- package/entity/Collection.d.ts +1 -2
- package/entity/Collection.js +14 -9
- package/entity/EntityFactory.js +4 -1
- package/entity/EntityHelper.js +3 -0
- package/entity/EntityLoader.d.ts +3 -2
- package/entity/EntityLoader.js +20 -6
- package/entity/Reference.d.ts +3 -7
- package/enums.d.ts +1 -1
- package/events/EventSubscriber.d.ts +3 -1
- package/exports.d.ts +24 -0
- package/exports.js +23 -0
- package/hydration/ObjectHydrator.js +1 -0
- package/index.d.ts +1 -1
- package/metadata/EntitySchema.d.ts +6 -4
- package/metadata/EntitySchema.js +23 -17
- package/metadata/MetadataDiscovery.js +25 -12
- package/metadata/MetadataValidator.js +4 -3
- package/package.json +7 -6
- package/types/BigIntType.d.ts +1 -0
- package/types/BigIntType.js +3 -0
- package/typings.d.ts +17 -10
- package/typings.js +3 -0
- package/unit-of-work/ChangeSetPersister.js +7 -1
- package/unit-of-work/UnitOfWork.js +25 -9
- package/utils/AbstractSchemaGenerator.js +5 -2
- package/utils/Configuration.d.ts +1 -1
- package/utils/Configuration.js +1 -1
- package/utils/Cursor.d.ts +3 -3
- package/utils/DataloaderUtils.d.ts +1 -1
- package/utils/DataloaderUtils.js +19 -5
- package/utils/EntityComparator.js +65 -49
- package/utils/QueryHelper.js +1 -1
- package/utils/RawQueryFragment.js +6 -1
- package/utils/Utils.d.ts +8 -2
- package/utils/Utils.js +26 -6
package/entity/Collection.js
CHANGED
|
@@ -7,7 +7,6 @@ import { helper } from './wrap.js';
|
|
|
7
7
|
export class Collection extends ArrayCollection {
|
|
8
8
|
readonly;
|
|
9
9
|
_populated;
|
|
10
|
-
_em;
|
|
11
10
|
// this is for some reason needed for TS, otherwise it can fail with `Type instantiation is excessively deep and possibly infinite.`
|
|
12
11
|
_snapshot;
|
|
13
12
|
constructor(owner, items, initialized = true) {
|
|
@@ -220,11 +219,20 @@ export class Collection extends ArrayCollection {
|
|
|
220
219
|
const em = this.getEntityManager();
|
|
221
220
|
if (options.dataloader ?? [DataloaderType.ALL, DataloaderType.COLLECTION].includes(em.config.getDataloaderType())) {
|
|
222
221
|
const order = [...this.items]; // copy order of references
|
|
223
|
-
const
|
|
222
|
+
const orderBy = this.createOrderBy(options.orderBy);
|
|
223
|
+
const customOrder = orderBy.length > 0;
|
|
224
224
|
// eslint-disable-next-line dot-notation
|
|
225
|
-
const items = await em['colLoader'].load([
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
const items = await em['colLoader'].load([
|
|
226
|
+
this,
|
|
227
|
+
{ ...options, orderBy },
|
|
228
|
+
]);
|
|
229
|
+
if (this.property.kind === ReferenceKind.MANY_TO_MANY) {
|
|
230
|
+
this.initialized = true;
|
|
231
|
+
this.dirty = false;
|
|
232
|
+
if (!customOrder) {
|
|
233
|
+
this.reorderItems(items, order);
|
|
234
|
+
}
|
|
235
|
+
return this;
|
|
228
236
|
}
|
|
229
237
|
this.items.clear();
|
|
230
238
|
let i = 0;
|
|
@@ -254,7 +262,7 @@ export class Collection extends ArrayCollection {
|
|
|
254
262
|
}
|
|
255
263
|
getEntityManager(items = [], required = true) {
|
|
256
264
|
const wrapped = helper(this.owner);
|
|
257
|
-
let em =
|
|
265
|
+
let em = wrapped.__em;
|
|
258
266
|
if (!em) {
|
|
259
267
|
for (const i of items) {
|
|
260
268
|
if (i && helper(i).__em) {
|
|
@@ -263,9 +271,6 @@ export class Collection extends ArrayCollection {
|
|
|
263
271
|
}
|
|
264
272
|
}
|
|
265
273
|
}
|
|
266
|
-
if (em) {
|
|
267
|
-
Object.defineProperty(this, '_em', { value: em });
|
|
268
|
-
}
|
|
269
274
|
if (!em && required) {
|
|
270
275
|
throw ValidationError.entityNotManaged(this.owner);
|
|
271
276
|
}
|
package/entity/EntityFactory.js
CHANGED
|
@@ -45,6 +45,7 @@ export class EntityFactory {
|
|
|
45
45
|
let wrapped = exists && helper(exists);
|
|
46
46
|
if (wrapped && !options.refresh) {
|
|
47
47
|
wrapped.__processing = true;
|
|
48
|
+
Utils.dropUndefinedProperties(data);
|
|
48
49
|
this.mergeData(meta2, exists, data, options);
|
|
49
50
|
wrapped.__processing = false;
|
|
50
51
|
if (wrapped.isInitialized()) {
|
|
@@ -86,7 +87,9 @@ export class EntityFactory {
|
|
|
86
87
|
}
|
|
87
88
|
if (options.merge && wrapped.hasPrimaryKey()) {
|
|
88
89
|
this.unitOfWork.register(entity, data, {
|
|
89
|
-
refresh
|
|
90
|
+
// Always refresh to ensure the payload is in correct shape for joined strategy. When loading nested relations,
|
|
91
|
+
// they will be created early without `Type.ensureComparable` being properly handled, resulting in extra updates.
|
|
92
|
+
refresh: options.initialized,
|
|
90
93
|
newEntity: options.newEntity,
|
|
91
94
|
loaded: options.initialized,
|
|
92
95
|
});
|
package/entity/EntityHelper.js
CHANGED
|
@@ -146,6 +146,9 @@ export class EntityHelper {
|
|
|
146
146
|
set(val) {
|
|
147
147
|
const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
|
|
148
148
|
const old = Reference.unwrapReference(wrapped.__data[prop.name]);
|
|
149
|
+
if (old && old !== entity && prop.kind === ReferenceKind.MANY_TO_ONE && prop.inversedBy && old[prop.inversedBy]) {
|
|
150
|
+
old[prop.inversedBy].removeWithoutPropagation(this);
|
|
151
|
+
}
|
|
149
152
|
wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
|
|
150
153
|
// when propagation from inside hydration, we set the FK to the entity data immediately
|
|
151
154
|
if (val && hydrator.isRunning() && wrapped.__originalEntityData && prop.owner) {
|
package/entity/EntityLoader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectionType, Dictionary, FilterQuery, PopulateOptions } from '../typings.js';
|
|
1
|
+
import type { AnyEntity, ConnectionType, Dictionary, EntityProperty, FilterQuery, PopulateOptions } from '../typings.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
3
|
import { LoadStrategy, type LockMode, type PopulateHint, PopulatePath, type QueryOrderMap } from '../enums.js';
|
|
4
4
|
import type { EntityField } from '../drivers/IDatabaseDriver.js';
|
|
@@ -49,7 +49,8 @@ export declare class EntityLoader {
|
|
|
49
49
|
private findChildren;
|
|
50
50
|
private mergePrimaryCondition;
|
|
51
51
|
private populateField;
|
|
52
|
-
|
|
52
|
+
/** @internal */
|
|
53
|
+
findChildrenFromPivotTable<Entity extends object>(filtered: Entity[], prop: EntityProperty<Entity>, options: Required<EntityLoaderOptions<Entity>>, orderBy?: QueryOrderMap<Entity>[], populate?: PopulateOptions<Entity>, pivotJoin?: boolean): Promise<AnyEntity[][]>;
|
|
53
54
|
private extractChildCondition;
|
|
54
55
|
private buildFields;
|
|
55
56
|
private getChildReferences;
|
package/entity/EntityLoader.js
CHANGED
|
@@ -141,7 +141,8 @@ export class EntityLoader {
|
|
|
141
141
|
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils.isObject(orderBy[prop.name]))
|
|
142
142
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
143
143
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
144
|
-
|
|
144
|
+
const res = await this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
145
|
+
return Utils.flatten(res);
|
|
145
146
|
}
|
|
146
147
|
const where = await this.extractChildCondition(options, prop);
|
|
147
148
|
const data = await this.findChildren(entities, prop, populate, { ...options, where, orderBy: innerOrderBy }, !!(ref || prop.mapToPk));
|
|
@@ -249,9 +250,13 @@ export class EntityLoader {
|
|
|
249
250
|
}
|
|
250
251
|
}
|
|
251
252
|
}
|
|
253
|
+
const orderBy = [...Utils.asArray(options.orderBy), ...propOrderBy].filter((order, idx, array) => {
|
|
254
|
+
// skip consecutive ordering with the same key to get around mongo issues
|
|
255
|
+
return idx === 0 || !Utils.equals(Object.keys(array[idx - 1]), Object.keys(order));
|
|
256
|
+
});
|
|
252
257
|
const items = await this.em.find(prop.type, where, {
|
|
253
258
|
filters, convertCustomTypes, lockMode, populateWhere, logging,
|
|
254
|
-
orderBy
|
|
259
|
+
orderBy,
|
|
255
260
|
populate: populate.children ?? populate.all ?? [],
|
|
256
261
|
exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude,
|
|
257
262
|
strategy, fields, schema, connectionType,
|
|
@@ -310,9 +315,16 @@ export class EntityLoader {
|
|
|
310
315
|
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
311
316
|
.filter(orderBy => Utils.isObject(orderBy[prop.name]))
|
|
312
317
|
.map(orderBy => orderBy[prop.name]);
|
|
313
|
-
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging } = options;
|
|
318
|
+
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging, schema } = options;
|
|
314
319
|
const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
|
|
315
|
-
const
|
|
320
|
+
const visited = options.visited;
|
|
321
|
+
for (const entity of entities) {
|
|
322
|
+
visited.delete(entity);
|
|
323
|
+
}
|
|
324
|
+
const filtered = Utils.unique(children.filter(e => !visited.has(e)));
|
|
325
|
+
for (const entity of entities) {
|
|
326
|
+
visited.add(entity);
|
|
327
|
+
}
|
|
316
328
|
await this.populate(prop.type, filtered, populate.children ?? populate.all, {
|
|
317
329
|
where: await this.extractChildCondition(options, prop, false),
|
|
318
330
|
orderBy: innerOrderBy,
|
|
@@ -325,12 +337,14 @@ export class EntityLoader {
|
|
|
325
337
|
populateWhere,
|
|
326
338
|
connectionType,
|
|
327
339
|
logging,
|
|
340
|
+
schema,
|
|
328
341
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
329
342
|
refresh: refresh && !filtered.every(item => options.visited.has(item)),
|
|
330
343
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
331
344
|
visited: options.visited,
|
|
332
345
|
});
|
|
333
346
|
}
|
|
347
|
+
/** @internal */
|
|
334
348
|
async findChildrenFromPivotTable(filtered, prop, options, orderBy, populate, pivotJoin) {
|
|
335
349
|
const ids = filtered.map(e => e.__helper.__primaryKeys);
|
|
336
350
|
const refresh = options.refresh;
|
|
@@ -368,7 +382,7 @@ export class EntityLoader {
|
|
|
368
382
|
return this.em.getUnitOfWork().register(entity, item, { refresh, loaded: true });
|
|
369
383
|
});
|
|
370
384
|
entity[prop.name].hydrate(items, true);
|
|
371
|
-
children.push(
|
|
385
|
+
children.push(items);
|
|
372
386
|
}
|
|
373
387
|
return children;
|
|
374
388
|
}
|
|
@@ -514,7 +528,7 @@ export class EntityLoader {
|
|
|
514
528
|
if (refresh) {
|
|
515
529
|
return entities;
|
|
516
530
|
}
|
|
517
|
-
return entities.filter(e => !e[field]?.__helper?.__initialized);
|
|
531
|
+
return entities.filter(e => e[field] !== null && !e[field]?.__helper?.__initialized);
|
|
518
532
|
}
|
|
519
533
|
lookupAllRelationships(entityName) {
|
|
520
534
|
const ret = [];
|
package/entity/Reference.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { inspect } from 'node:util';
|
|
2
|
-
import type { AddEager, Dictionary, EntityClass, EntityKey, EntityProperty, Loaded, LoadedReference, Primary, Ref } from '../typings.js';
|
|
2
|
+
import type { AddEager, AddOptional, Dictionary, EntityClass, EntityKey, EntityProperty, Loaded, LoadedReference, Primary, Ref } from '../typings.js';
|
|
3
3
|
import type { FindOneOptions, FindOneOrFailOptions } from '../drivers/IDatabaseDriver.js';
|
|
4
4
|
export declare class Reference<T extends object> {
|
|
5
5
|
private entity;
|
|
@@ -72,15 +72,11 @@ export interface LoadReferenceOrFailOptions<T extends object, P extends string =
|
|
|
72
72
|
/**
|
|
73
73
|
* shortcut for `wrap(entity).toReference()`
|
|
74
74
|
*/
|
|
75
|
-
export declare function ref<
|
|
75
|
+
export declare function ref<I extends unknown | Ref<unknown> | undefined | null, T extends I & {}>(entity: I): Ref<T> & LoadedReference<Loaded<T, AddEager<T>>> | AddOptional<typeof entity>;
|
|
76
76
|
/**
|
|
77
77
|
* shortcut for `Reference.createFromPK(entityType, pk)`
|
|
78
78
|
*/
|
|
79
|
-
export declare function ref<T, PKV extends Primary<T> = Primary<T>>(entityType: EntityClass<T>, pk
|
|
80
|
-
/**
|
|
81
|
-
* shortcut for `wrap(entity).toReference()`
|
|
82
|
-
*/
|
|
83
|
-
export declare function ref<T>(value: T | Ref<T>): Ref<T> & LoadedReference<Loaded<T, AddEager<T>>>;
|
|
79
|
+
export declare function ref<I extends unknown | undefined | null, T, PKV extends Primary<T> = Primary<T>>(entityType: EntityClass<T>, pk: I): Ref<T> | AddOptional<typeof pk>;
|
|
84
80
|
/**
|
|
85
81
|
* shortcut for `Reference.createNakedFromPK(entityType, pk)`
|
|
86
82
|
*/
|
package/enums.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export declare enum QueryOrderNumeric {
|
|
|
66
66
|
ASC = 1,
|
|
67
67
|
DESC = -1
|
|
68
68
|
}
|
|
69
|
-
export type QueryOrderKeysFlat = QueryOrder | QueryOrderNumeric |
|
|
69
|
+
export type QueryOrderKeysFlat = QueryOrder | QueryOrderNumeric | `${QueryOrder}`;
|
|
70
70
|
export type QueryOrderKeys<T> = QueryOrderKeysFlat | QueryOrderMap<T>;
|
|
71
71
|
export type QueryOrderMap<T> = {
|
|
72
72
|
[K in EntityKey<T>]?: QueryOrderKeys<ExpandProperty<T[K]>>;
|
|
@@ -13,7 +13,9 @@ export interface FlushEventArgs extends Omit<EventArgs<any>, 'entity' | 'changeS
|
|
|
13
13
|
uow: UnitOfWork;
|
|
14
14
|
}
|
|
15
15
|
export interface TransactionEventArgs extends Omit<EventArgs<any>, 'entity' | 'meta' | 'changeSet'> {
|
|
16
|
-
transaction?: Transaction
|
|
16
|
+
transaction?: Transaction & {
|
|
17
|
+
savepointName?: string;
|
|
18
|
+
};
|
|
17
19
|
uow?: UnitOfWork;
|
|
18
20
|
}
|
|
19
21
|
export interface EventSubscriber<T = any> {
|
package/exports.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* @module core
|
|
4
|
+
*/
|
|
5
|
+
export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, } from './typings.js';
|
|
6
|
+
export * from './enums.js';
|
|
7
|
+
export * from './errors.js';
|
|
8
|
+
export * from './exceptions.js';
|
|
9
|
+
export * from './entity/index.js';
|
|
10
|
+
export * from './serialization/index.js';
|
|
11
|
+
export * from './events/index.js';
|
|
12
|
+
export { CreateOptions, MergeOptions, ForkOptions } from './EntityManager.js';
|
|
13
|
+
export * from './unit-of-work/index.js';
|
|
14
|
+
export * from './utils/index.js';
|
|
15
|
+
export * from './logging/index.js';
|
|
16
|
+
export * from './hydration/index.js';
|
|
17
|
+
export * from './drivers/index.js';
|
|
18
|
+
export * from './connections/index.js';
|
|
19
|
+
export * from './platforms/index.js';
|
|
20
|
+
export * from './types/index.js';
|
|
21
|
+
export * from './naming-strategy/index.js';
|
|
22
|
+
export * from './metadata/index.js';
|
|
23
|
+
export * from './cache/index.js';
|
|
24
|
+
export * from './decorators/index.js';
|
package/exports.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* @module core
|
|
4
|
+
*/
|
|
5
|
+
export { PrimaryKeyProp, EntityMetadata, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, } from './typings.js';
|
|
6
|
+
export * from './enums.js';
|
|
7
|
+
export * from './errors.js';
|
|
8
|
+
export * from './exceptions.js';
|
|
9
|
+
export * from './entity/index.js';
|
|
10
|
+
export * from './serialization/index.js';
|
|
11
|
+
export * from './events/index.js';
|
|
12
|
+
export * from './unit-of-work/index.js';
|
|
13
|
+
export * from './utils/index.js';
|
|
14
|
+
export * from './logging/index.js';
|
|
15
|
+
export * from './hydration/index.js';
|
|
16
|
+
export * from './drivers/index.js';
|
|
17
|
+
export * from './connections/index.js';
|
|
18
|
+
export * from './platforms/index.js';
|
|
19
|
+
export * from './types/index.js';
|
|
20
|
+
export * from './naming-strategy/index.js';
|
|
21
|
+
export * from './metadata/index.js';
|
|
22
|
+
export * from './cache/index.js';
|
|
23
|
+
export * from './decorators/index.js';
|
|
@@ -256,6 +256,7 @@ export class ObjectHydrator extends Hydrator {
|
|
|
256
256
|
...prop2,
|
|
257
257
|
name: childProp.name,
|
|
258
258
|
embedded: childProp.embedded,
|
|
259
|
+
embeddedProps: childProp.embeddedProps,
|
|
259
260
|
};
|
|
260
261
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
261
262
|
ret.push(...hydrateProperty(prop3, childProp.object, [...path, childProp.embedded[1]], childDataKey).map(l => ' ' + l));
|
package/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
|
-
export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, } from './typings.js';
|
|
5
|
+
export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, } from './typings.js';
|
|
6
6
|
export * from './enums.js';
|
|
7
7
|
export * from './errors.js';
|
|
8
8
|
export * from './exceptions.js';
|
|
@@ -31,7 +31,7 @@ export type EntitySchemaProperty<Target, Owner> = ({
|
|
|
31
31
|
kind: ReferenceKind.MANY_TO_MANY | 'm:n';
|
|
32
32
|
} & TypeDef<Target> & ManyToManyOptions<Owner, Target>) | ({
|
|
33
33
|
kind: ReferenceKind.EMBEDDED | 'embedded';
|
|
34
|
-
} & EmbeddedTypeDef<Target> & EmbeddedOptions & PropertyOptions<Owner>) | ({
|
|
34
|
+
} & EmbeddedTypeDef<Target> & EmbeddedOptions<Owner, Target> & PropertyOptions<Owner>) | ({
|
|
35
35
|
enum: true;
|
|
36
36
|
} & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
|
|
37
37
|
type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
|
|
@@ -63,13 +63,13 @@ export declare class EntitySchema<Entity = any, Base = never> {
|
|
|
63
63
|
addVersion(name: EntityKey<Entity>, type: TypeType, options?: PropertyOptions<Entity>): void;
|
|
64
64
|
addPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: PrimaryKeyOptions<Entity>): void;
|
|
65
65
|
addSerializedPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: SerializedPrimaryKeyOptions<Entity>): void;
|
|
66
|
-
addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions): void;
|
|
66
|
+
addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions<Entity, Target>): void;
|
|
67
67
|
addManyToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToOneOptions<Entity, Target>): void;
|
|
68
68
|
addManyToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToManyOptions<Entity, Target>): void;
|
|
69
69
|
addOneToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToManyOptions<Entity, Target>): void;
|
|
70
70
|
addOneToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToOneOptions<Entity, Target>): void;
|
|
71
|
-
addIndex(options: IndexOptions<Entity>): void;
|
|
72
|
-
addUnique(options: UniqueOptions<Entity>): void;
|
|
71
|
+
addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
|
|
72
|
+
addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
|
|
73
73
|
setCustomRepository(repository: () => Constructor): void;
|
|
74
74
|
setExtends(base: string | EntitySchema): void;
|
|
75
75
|
setClass(proto: EntityClass<Entity>): void;
|
|
@@ -83,5 +83,7 @@ export declare class EntitySchema<Entity = any, Base = never> {
|
|
|
83
83
|
private initPrimaryKeys;
|
|
84
84
|
private normalizeType;
|
|
85
85
|
private createProperty;
|
|
86
|
+
private rename;
|
|
87
|
+
private renameCompositeOptions;
|
|
86
88
|
}
|
|
87
89
|
export {};
|
package/metadata/EntitySchema.js
CHANGED
|
@@ -34,23 +34,7 @@ export class EntitySchema {
|
|
|
34
34
|
return schema;
|
|
35
35
|
}
|
|
36
36
|
addProperty(name, type, options = {}) {
|
|
37
|
-
|
|
38
|
-
if (from in options && !(to in options)) {
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
options[to] = [options[from]];
|
|
41
|
-
// @ts-ignore
|
|
42
|
-
delete options[from];
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
if (name !== options.name) {
|
|
46
|
-
Utils.renameKey(options, 'name', 'fieldName');
|
|
47
|
-
}
|
|
48
|
-
rename(options, 'fieldName', 'fieldNames');
|
|
49
|
-
rename(options, 'ref', 'ref');
|
|
50
|
-
rename(options, 'joinColumn', 'joinColumns');
|
|
51
|
-
rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
|
|
52
|
-
rename(options, 'referenceColumnName', 'referencedColumnNames');
|
|
53
|
-
rename(options, 'columnType', 'columnTypes');
|
|
37
|
+
this.renameCompositeOptions(name, options);
|
|
54
38
|
const prop = { name, kind: ReferenceKind.SCALAR, ...options, type: this.normalizeType(options, type) };
|
|
55
39
|
if (type && Type.isMappedType(type.prototype)) {
|
|
56
40
|
prop.type = type;
|
|
@@ -94,6 +78,7 @@ export class EntitySchema {
|
|
|
94
78
|
this.addProperty(name, type, options);
|
|
95
79
|
}
|
|
96
80
|
addEmbedded(name, options) {
|
|
81
|
+
this.renameCompositeOptions(name, options);
|
|
97
82
|
Utils.defaultValue(options, 'prefix', true);
|
|
98
83
|
if (options.array) {
|
|
99
84
|
options.object = true; // force object mode for arrays
|
|
@@ -289,4 +274,25 @@ export class EntitySchema {
|
|
|
289
274
|
...options,
|
|
290
275
|
};
|
|
291
276
|
}
|
|
277
|
+
rename(data, from, to) {
|
|
278
|
+
if (from in data && !(to in data)) {
|
|
279
|
+
// @ts-ignore
|
|
280
|
+
data[to] = [data[from]];
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
delete data[from];
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
renameCompositeOptions(name, options = {}) {
|
|
286
|
+
if (name !== options.name && !options.fieldNames) {
|
|
287
|
+
Utils.renameKey(options, 'name', 'fieldName');
|
|
288
|
+
}
|
|
289
|
+
else if (options.name && (options.fieldNames?.length ?? 0) > 1) {
|
|
290
|
+
delete options.name;
|
|
291
|
+
}
|
|
292
|
+
this.rename(options, 'fieldName', 'fieldNames');
|
|
293
|
+
this.rename(options, 'joinColumn', 'joinColumns');
|
|
294
|
+
this.rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
|
|
295
|
+
this.rename(options, 'referenceColumnName', 'referencedColumnNames');
|
|
296
|
+
this.rename(options, 'columnType', 'columnTypes');
|
|
297
|
+
}
|
|
292
298
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { basename, extname } from 'node:path';
|
|
2
|
-
import
|
|
2
|
+
import { glob } from 'tinyglobby';
|
|
3
3
|
import { EntityMetadata, } from '../typings.js';
|
|
4
4
|
import { Utils } from '../utils/Utils.js';
|
|
5
5
|
import { MetadataValidator } from './MetadataValidator.js';
|
|
@@ -7,7 +7,7 @@ import { MetadataStorage } from './MetadataStorage.js';
|
|
|
7
7
|
import { EntitySchema } from './EntitySchema.js';
|
|
8
8
|
import { Cascade, ReferenceKind } from '../enums.js';
|
|
9
9
|
import { MetadataError } from '../errors.js';
|
|
10
|
-
import { ArrayType, BigIntType, BlobType, DecimalType, DoubleType, EnumArrayType, IntervalType, JsonType, t, Type, Uint8ArrayType, UnknownType, } from '../types/index.js';
|
|
10
|
+
import { ArrayType, BigIntType, BlobType, DateType, DecimalType, DoubleType, EnumArrayType, IntervalType, JsonType, t, Type, Uint8ArrayType, UnknownType, } from '../types/index.js';
|
|
11
11
|
import { colors } from '../logging/colors.js';
|
|
12
12
|
import { raw, RawQueryFragment } from '../utils/RawQueryFragment.js';
|
|
13
13
|
export class MetadataDiscovery {
|
|
@@ -181,7 +181,7 @@ export class MetadataDiscovery {
|
|
|
181
181
|
}
|
|
182
182
|
async discoverDirectories(paths) {
|
|
183
183
|
paths = paths.map(path => Utils.normalizePath(path));
|
|
184
|
-
const files = await
|
|
184
|
+
const files = await glob(paths, { cwd: Utils.normalizePath(this.config.get('baseDir')) });
|
|
185
185
|
this.logger.log('discovery', `- processing ${colors.cyan('' + files.length)} files`);
|
|
186
186
|
const found = [];
|
|
187
187
|
for (const filepath of files) {
|
|
@@ -264,7 +264,8 @@ export class MetadataDiscovery {
|
|
|
264
264
|
// initialize global metadata for given entity
|
|
265
265
|
MetadataStorage.getMetadata(entity.meta.className, filepath);
|
|
266
266
|
}
|
|
267
|
-
|
|
267
|
+
const meta = Utils.copy(entity.meta, false);
|
|
268
|
+
return EntitySchema.fromMetadata(meta);
|
|
268
269
|
}
|
|
269
270
|
const path = entity[MetadataStorage.PATH_SYMBOL];
|
|
270
271
|
if (path) {
|
|
@@ -765,6 +766,7 @@ export class MetadataDiscovery {
|
|
|
765
766
|
delete prop.default;
|
|
766
767
|
if (properties[prop.name] && properties[prop.name].type !== prop.type) {
|
|
767
768
|
properties[prop.name].type = `${properties[prop.name].type} | ${prop.type}`;
|
|
769
|
+
properties[prop.name].runtimeType = 'any';
|
|
768
770
|
return properties[prop.name];
|
|
769
771
|
}
|
|
770
772
|
return properties[prop.name] = prop;
|
|
@@ -872,6 +874,7 @@ export class MetadataDiscovery {
|
|
|
872
874
|
meta.properties[name].persist = false; // only virtual as we store the whole object
|
|
873
875
|
meta.properties[name].userDefined = false; // mark this as a generated/internal property, so we can distinguish from user-defined non-persist properties
|
|
874
876
|
meta.properties[name].object = true;
|
|
877
|
+
this.initCustomType(meta, meta.properties[name], true);
|
|
875
878
|
}
|
|
876
879
|
this.initEmbeddables(meta, meta.properties[name], visited);
|
|
877
880
|
}
|
|
@@ -905,11 +908,13 @@ export class MetadataDiscovery {
|
|
|
905
908
|
}
|
|
906
909
|
if (!meta.root.discriminatorMap) {
|
|
907
910
|
meta.root.discriminatorMap = {};
|
|
908
|
-
const children = metadata
|
|
909
|
-
|
|
911
|
+
const children = metadata
|
|
912
|
+
.filter(m => m.root.className === meta.root.className && !m.abstract)
|
|
913
|
+
.sort((a, b) => a.className.localeCompare(b.className));
|
|
914
|
+
for (const m of children) {
|
|
910
915
|
const name = m.discriminatorValue ?? this.namingStrategy.classToTableName(m.className);
|
|
911
916
|
meta.root.discriminatorMap[name] = m.className;
|
|
912
|
-
}
|
|
917
|
+
}
|
|
913
918
|
}
|
|
914
919
|
meta.discriminatorValue = Object.entries(meta.root.discriminatorMap).find(([, className]) => className === meta.className)?.[0];
|
|
915
920
|
if (!meta.root.properties[meta.root.discriminatorColumn]) {
|
|
@@ -922,7 +927,7 @@ export class MetadataDiscovery {
|
|
|
922
927
|
}
|
|
923
928
|
let i = 1;
|
|
924
929
|
Object.values(meta.properties).forEach(prop => {
|
|
925
|
-
const newProp =
|
|
930
|
+
const newProp = { ...prop };
|
|
926
931
|
if (meta.root.properties[prop.name] && meta.root.properties[prop.name].type !== prop.type) {
|
|
927
932
|
const name = newProp.name;
|
|
928
933
|
this.initFieldName(newProp, newProp.object);
|
|
@@ -944,6 +949,7 @@ export class MetadataDiscovery {
|
|
|
944
949
|
meta.collection = meta.root.collection;
|
|
945
950
|
meta.root.indexes = Utils.unique([...meta.root.indexes, ...meta.indexes]);
|
|
946
951
|
meta.root.uniques = Utils.unique([...meta.root.uniques, ...meta.uniques]);
|
|
952
|
+
meta.root.checks = Utils.unique([...meta.root.checks, ...meta.checks]);
|
|
947
953
|
}
|
|
948
954
|
createDiscriminatorProperty(meta) {
|
|
949
955
|
meta.addProperty({
|
|
@@ -1095,7 +1101,7 @@ export class MetadataDiscovery {
|
|
|
1095
1101
|
meta.concurrencyCheckKeys.add(prop.name);
|
|
1096
1102
|
}
|
|
1097
1103
|
}
|
|
1098
|
-
initCustomType(meta, prop) {
|
|
1104
|
+
initCustomType(meta, prop, objectEmbeddable = false) {
|
|
1099
1105
|
// `prop.type` might be actually instance of custom type class
|
|
1100
1106
|
if (Type.isMappedType(prop.type) && !prop.customType) {
|
|
1101
1107
|
prop.customType = prop.type;
|
|
@@ -1115,12 +1121,16 @@ export class MetadataDiscovery {
|
|
|
1115
1121
|
if (!prop.customType && prop.array && prop.items) {
|
|
1116
1122
|
prop.customType = new EnumArrayType(`${meta.className}.${prop.name}`, prop.items);
|
|
1117
1123
|
}
|
|
1124
|
+
const isArray = prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]');
|
|
1125
|
+
if (objectEmbeddable && !prop.customType && isArray) {
|
|
1126
|
+
prop.customType = new JsonType();
|
|
1127
|
+
}
|
|
1118
1128
|
// for number arrays we make sure to convert the items to numbers
|
|
1119
1129
|
if (!prop.customType && prop.type === 'number[]') {
|
|
1120
1130
|
prop.customType = new ArrayType(i => +i);
|
|
1121
1131
|
}
|
|
1122
1132
|
// `string[]` can be returned via ts-morph, while reflect metadata will give us just `array`
|
|
1123
|
-
if (!prop.customType &&
|
|
1133
|
+
if (!prop.customType && isArray) {
|
|
1124
1134
|
prop.customType = new ArrayType();
|
|
1125
1135
|
}
|
|
1126
1136
|
if (!prop.customType && prop.type?.toLowerCase() === 'buffer') {
|
|
@@ -1131,7 +1141,7 @@ export class MetadataDiscovery {
|
|
|
1131
1141
|
}
|
|
1132
1142
|
const mappedType = this.getMappedType(prop);
|
|
1133
1143
|
if (prop.fieldNames?.length === 1 && !prop.customType) {
|
|
1134
|
-
[BigIntType, DoubleType, DecimalType, IntervalType]
|
|
1144
|
+
[BigIntType, DoubleType, DecimalType, IntervalType, DateType]
|
|
1135
1145
|
.filter(type => mappedType instanceof type)
|
|
1136
1146
|
.forEach(type => prop.customType = new type());
|
|
1137
1147
|
}
|
|
@@ -1144,6 +1154,9 @@ export class MetadataDiscovery {
|
|
|
1144
1154
|
prop.runtimeType ??= prop.customType.runtimeType;
|
|
1145
1155
|
}
|
|
1146
1156
|
}
|
|
1157
|
+
else if (prop.runtimeType === 'object') {
|
|
1158
|
+
prop.runtimeType = mappedType.runtimeType;
|
|
1159
|
+
}
|
|
1147
1160
|
else {
|
|
1148
1161
|
prop.runtimeType ??= mappedType.runtimeType;
|
|
1149
1162
|
}
|
|
@@ -1158,7 +1171,7 @@ export class MetadataDiscovery {
|
|
|
1158
1171
|
prop.customType.mode = prop.runtimeType.toLowerCase();
|
|
1159
1172
|
}
|
|
1160
1173
|
}
|
|
1161
|
-
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !
|
|
1174
|
+
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !isArray) {
|
|
1162
1175
|
prop.type = prop.customType.name;
|
|
1163
1176
|
}
|
|
1164
1177
|
if (!prop.customType && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && this.metadata.get(prop.type).compositePK) {
|
|
@@ -100,14 +100,15 @@ export class MetadataValidator {
|
|
|
100
100
|
if (!prop.type) {
|
|
101
101
|
throw MetadataError.fromWrongTypeDefinition(meta, prop);
|
|
102
102
|
}
|
|
103
|
+
const targetMeta = metadata.find(prop.type);
|
|
103
104
|
// references do have type of known entity
|
|
104
|
-
if (!
|
|
105
|
+
if (!targetMeta) {
|
|
105
106
|
throw MetadataError.fromWrongTypeDefinition(meta, prop);
|
|
106
107
|
}
|
|
107
|
-
if (
|
|
108
|
+
if (targetMeta.abstract && !targetMeta.discriminatorColumn && !targetMeta.embeddable) {
|
|
108
109
|
throw MetadataError.targetIsAbstract(meta, prop);
|
|
109
110
|
}
|
|
110
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.persist === false &&
|
|
111
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.persist === false && targetMeta.compositePK && options.checkNonPersistentCompositeProps) {
|
|
111
112
|
throw MetadataError.nonPersistentCompositeProp(meta, prop);
|
|
112
113
|
}
|
|
113
114
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.0.0-dev.
|
|
4
|
+
"version": "7.0.0-dev.21",
|
|
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",
|
|
8
|
-
".": "./index.js"
|
|
8
|
+
".": "./index.js",
|
|
9
|
+
"./exports.js": "./exports.js"
|
|
9
10
|
},
|
|
10
11
|
"repository": {
|
|
11
12
|
"type": "git",
|
|
@@ -52,10 +53,10 @@
|
|
|
52
53
|
},
|
|
53
54
|
"dependencies": {
|
|
54
55
|
"dataloader": "2.2.3",
|
|
55
|
-
"dotenv": "16.
|
|
56
|
+
"dotenv": "16.5.0",
|
|
56
57
|
"esprima": "4.0.1",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
58
|
+
"mikro-orm": "7.0.0-dev.21",
|
|
59
|
+
"reflect-metadata": "0.2.2",
|
|
60
|
+
"tinyglobby": "0.2.13"
|
|
60
61
|
}
|
|
61
62
|
}
|
package/types/BigIntType.d.ts
CHANGED
|
@@ -13,4 +13,5 @@ export declare class BigIntType extends Type<string | bigint | number | null | u
|
|
|
13
13
|
toJSON(value: string | bigint | null | undefined): string | bigint | null | undefined;
|
|
14
14
|
getColumnType(prop: EntityProperty, platform: Platform): string;
|
|
15
15
|
compareAsType(): string;
|
|
16
|
+
compareValues(a: string, b: string): boolean;
|
|
16
17
|
}
|