@mikro-orm/core 7.1.0-dev.29 → 7.1.0-dev.30
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.js +7 -4
- package/entity/defineEntity.d.ts +14 -7
- package/metadata/MetadataDiscovery.js +1 -1
- package/package.json +1 -1
- package/typings.d.ts +7 -4
- package/typings.js +1 -1
- package/utils/AbstractMigrator.d.ts +2 -2
- package/utils/AbstractMigrator.js +15 -13
- package/utils/EntityComparator.js +1 -1
- package/utils/Utils.js +1 -1
package/EntityManager.js
CHANGED
|
@@ -354,7 +354,8 @@ export class EntityManager {
|
|
|
354
354
|
const field = hint.field.split(':')[0];
|
|
355
355
|
const prop = meta.properties[field];
|
|
356
356
|
const strategy = getLoadingStrategy(prop.strategy || hint.strategy || options.strategy || this.config.get('loadStrategy'), prop.kind);
|
|
357
|
-
const joined = strategy === LoadStrategy.JOINED
|
|
357
|
+
const joined = (strategy === LoadStrategy.JOINED || (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner)) &&
|
|
358
|
+
prop.kind !== ReferenceKind.SCALAR;
|
|
358
359
|
if (!joined && !hint.filter) {
|
|
359
360
|
continue;
|
|
360
361
|
}
|
|
@@ -423,11 +424,13 @@ export class EntityManager {
|
|
|
423
424
|
const populated = options.populate.filter(({ field }) => field.split(':')[0] === prop.name);
|
|
424
425
|
let found = false;
|
|
425
426
|
for (const hint of populated) {
|
|
426
|
-
|
|
427
|
+
const strategy = getLoadingStrategy(prop.strategy || hint.strategy || options.strategy || this.config.get('loadStrategy'), prop.kind);
|
|
428
|
+
// inverse 1:1 always produces a JOIN (forced by `joinedProps()`), regardless of strategy
|
|
429
|
+
const willJoin = strategy === LoadStrategy.JOINED || (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner);
|
|
430
|
+
if (!hint.all || willJoin) {
|
|
427
431
|
hint.filter = true;
|
|
428
432
|
}
|
|
429
|
-
|
|
430
|
-
if (hint.field === `${prop.name}:ref` || (hint.filter && strategy === LoadStrategy.JOINED)) {
|
|
433
|
+
if (hint.field === `${prop.name}:ref` || (hint.filter && willJoin)) {
|
|
431
434
|
found = true;
|
|
432
435
|
}
|
|
433
436
|
}
|
package/entity/defineEntity.d.ts
CHANGED
|
@@ -615,12 +615,15 @@ export type PropertyBuilders = {
|
|
|
615
615
|
/** Own keys + base entity keys (when TBase is not `never`). Guards against `keyof never = string | number | symbol`. */
|
|
616
616
|
type AllKeys<TProperties, TBase> = keyof TProperties | (IsNever<TBase> extends true ? never : keyof TBase);
|
|
617
617
|
/** Metadata descriptor for `defineEntity()`, combining entity options with property definitions. */
|
|
618
|
-
export interface EntityMetadataWithProperties<TName extends string, TTableName extends string, TProperties extends Record<string, any>, TPK extends (keyof TProperties)[] | undefined = undefined, TBase = never, TRepository = never, TForceObject extends boolean = false> extends Omit<Partial<EntityMetadata<InferEntityFromProperties<TProperties, TPK, TBase, TRepository>>>, 'properties' | 'extends' | 'primaryKeys' | 'hooks' | 'discriminatorColumn' | 'versionProperty' | 'concurrencyCheckKeys' | 'serializedPrimaryKey' | 'indexes' | 'uniques' | 'triggers' | 'repository' | 'filters' | 'orderBy'> {
|
|
618
|
+
export interface EntityMetadataWithProperties<TName extends string, TTableName extends string, TProperties extends Record<string, any>, TPK extends (keyof TProperties)[] | undefined = undefined, TBase = never, TRepository = never, TForceObject extends boolean = false, TDiscriminatorColumn extends string | undefined = undefined, TDiscriminatorValue extends string | number | undefined = undefined, TBaseDiscriminatorColumn extends string | undefined = undefined> extends Omit<Partial<EntityMetadata<InferEntityFromProperties<TProperties, TPK, TBase, TRepository>>>, 'properties' | 'extends' | 'primaryKeys' | 'hooks' | 'discriminatorColumn' | 'discriminatorValue' | 'versionProperty' | 'concurrencyCheckKeys' | 'serializedPrimaryKey' | 'indexes' | 'uniques' | 'triggers' | 'repository' | 'filters' | 'orderBy'> {
|
|
619
619
|
name: TName;
|
|
620
620
|
tableName?: TTableName;
|
|
621
621
|
extends?: {
|
|
622
622
|
'~entity': TBase;
|
|
623
|
-
|
|
623
|
+
'~discriminatorColumn'?: TBaseDiscriminatorColumn;
|
|
624
|
+
} | (EntityCtor<TBase> & {
|
|
625
|
+
'~discriminatorColumn'?: TBaseDiscriminatorColumn;
|
|
626
|
+
});
|
|
624
627
|
properties: TProperties | ((properties: PropertyBuilders) => TProperties);
|
|
625
628
|
primaryKeys?: TPK & InferPrimaryKeyConstraint<TProperties>[];
|
|
626
629
|
hooks?: DefineEntityHooks;
|
|
@@ -640,7 +643,8 @@ export interface EntityMetadataWithProperties<TName extends string, TTableName e
|
|
|
640
643
|
} | {
|
|
641
644
|
[K in Extract<AllKeys<TProperties, TBase>, string>]?: QueryOrderKeysFlat;
|
|
642
645
|
}[];
|
|
643
|
-
discriminatorColumn?:
|
|
646
|
+
discriminatorColumn?: TDiscriminatorColumn;
|
|
647
|
+
discriminatorValue?: TDiscriminatorValue;
|
|
644
648
|
versionProperty?: AllKeys<TProperties, TBase>;
|
|
645
649
|
concurrencyCheckKeys?: Set<AllKeys<TProperties, TBase>>;
|
|
646
650
|
serializedPrimaryKey?: AllKeys<TProperties, TBase>;
|
|
@@ -681,7 +685,7 @@ export interface EntityMetadataWithProperties<TName extends string, TTableName e
|
|
|
681
685
|
}[];
|
|
682
686
|
}
|
|
683
687
|
/** Defines an entity schema using property builders, with full type inference from the property definitions. */
|
|
684
|
-
export declare function defineEntity<const TName extends string, const TTableName extends string, const TProperties extends Record<string, any>, const TPK extends (keyof TProperties)[] | undefined = undefined, const TBase = never, const TRepository = never, const TForceObject extends boolean = false>(meta: EntityMetadataWithProperties<TName, TTableName, TProperties, TPK, TBase, TRepository, TForceObject>): EntitySchemaWithMeta<TName, TTableName, InferEntityFromProperties<TProperties, TPK, TBase, TRepository, TForceObject>, TBase, TProperties>;
|
|
688
|
+
export declare function defineEntity<const TName extends string, const TTableName extends string, const TProperties extends Record<string, any>, const TPK extends (keyof TProperties)[] | undefined = undefined, const TBase = never, const TRepository = never, const TForceObject extends boolean = false, const TDiscriminatorColumn extends string | undefined = undefined, const TDiscriminatorValue extends string | number | undefined = undefined, const TBaseDiscriminatorColumn extends string | undefined = undefined>(meta: EntityMetadataWithProperties<TName, TTableName, TProperties, TPK, TBase, TRepository, TForceObject, TDiscriminatorColumn, TDiscriminatorValue, TBaseDiscriminatorColumn>): EntitySchemaWithMeta<TName, TTableName, InferEntityFromProperties<TProperties, TPK, TBase, TRepository, TForceObject, TBaseDiscriminatorColumn, TDiscriminatorValue>, TBase, TProperties, EntityCtor<InferEntityFromProperties<TProperties, TPK, TBase, TRepository, TForceObject, TBaseDiscriminatorColumn, TDiscriminatorValue>>, TDiscriminatorColumn>;
|
|
685
689
|
/** Defines an entity schema for an existing class, combining the class with property builders. */
|
|
686
690
|
export declare function defineEntity<const TEntity = any, const TProperties extends Record<string, any> = Record<string, any>, const TClassName extends string = string, const TTableName extends string = string, const TBase = never, const TClass extends EntityCtor = EntityCtor<TEntity>>(meta: Omit<Partial<EntityMetadata<TEntity>>, 'properties' | 'extends' | 'className' | 'tableName' | 'hooks'> & {
|
|
687
691
|
class: TClass;
|
|
@@ -717,7 +721,7 @@ type InferJSType<T> = T extends typeof Type<infer TValue, any> ? NonNullable<TVa
|
|
|
717
721
|
type InferColumnType<T extends string> = T extends 'int' | 'int4' | 'integer' | 'bigint' | 'int8' | 'int2' | 'tinyint' | 'smallint' | 'mediumint' ? number : T extends 'double' | 'double precision' | 'real' | 'float8' | 'decimal' | 'numeric' | 'float' | 'float4' ? number : T extends 'datetime' | 'time' | 'time with time zone' | 'timestamp' | 'timestamp with time zone' | 'timetz' | 'timestamptz' | 'date' | 'interval' ? Date : T extends 'ObjectId' | 'objectId' | 'character varying' | 'varchar' | 'char' | 'character' | 'uuid' | 'text' | 'tinytext' | 'mediumtext' | 'longtext' | 'enum' ? string : T extends 'boolean' | 'bool' | 'bit' ? boolean : T extends 'blob' | 'tinyblob' | 'mediumblob' | 'longblob' | 'bytea' ? Buffer : T extends 'point' | 'line' | 'lseg' | 'box' | 'circle' | 'path' | 'polygon' | 'geometry' ? number[] : T extends 'tsvector' | 'tsquery' ? string[] : T extends 'json' | 'jsonb' ? any : any;
|
|
718
722
|
type BaseEntityMethodKeys = 'toObject' | 'toPOJO' | 'serialize' | 'assign' | 'populate' | 'init' | 'toReference';
|
|
719
723
|
/** Infers the entity type from a `defineEntity()` properties map, resolving builders, base classes, and primary keys. */
|
|
720
|
-
export type InferEntityFromProperties<Properties extends Record<string, any>, PK extends (keyof Properties)[] | undefined = undefined, Base = never, Repository = never, ForceObject extends boolean = false> = (IsNever<Base> extends true ? {} : Base extends {
|
|
724
|
+
export type InferEntityFromProperties<Properties extends Record<string, any>, PK extends (keyof Properties)[] | undefined = undefined, Base = never, Repository = never, ForceObject extends boolean = false, BaseDiscriminatorColumn extends string | undefined = undefined, DiscriminatorValue extends string | number | undefined = undefined> = (IsNever<Base> extends true ? {} : Base extends {
|
|
721
725
|
toObject(...args: any[]): any;
|
|
722
726
|
} ? Pick<IWrappedEntity<{
|
|
723
727
|
-readonly [K in keyof Properties]: InferBuilderValue<MaybeReturnType<Properties[K]>>;
|
|
@@ -725,19 +729,22 @@ export type InferEntityFromProperties<Properties extends Record<string, any>, PK
|
|
|
725
729
|
[PrimaryKeyProp]?: InferCombinedPrimaryKey<Properties, PK, Base>;
|
|
726
730
|
} & (IsNever<Repository> extends true ? {} : {
|
|
727
731
|
[EntityRepositoryType]?: Repository extends Constructor<infer R> ? R : Repository;
|
|
728
|
-
}) & Omit<Base, typeof PrimaryKeyProp>>, BaseEntityMethodKeys> : {}) & {
|
|
732
|
+
}) & NarrowDiscriminator<Omit<Base, typeof PrimaryKeyProp>, BaseDiscriminatorColumn, DiscriminatorValue>>, BaseEntityMethodKeys> : {}) & {
|
|
729
733
|
-readonly [K in keyof Properties]: InferBuilderValue<MaybeReturnType<Properties[K]>>;
|
|
730
734
|
} & {
|
|
731
735
|
[PrimaryKeyProp]?: InferCombinedPrimaryKey<Properties, PK, Base>;
|
|
732
736
|
} & (IsNever<Repository> extends true ? {} : {
|
|
733
737
|
[EntityRepositoryType]?: Repository extends Constructor<infer R> ? R : Repository;
|
|
734
|
-
}) & (IsNever<Base> extends true ? {} : Omit<Base, typeof PrimaryKeyProp>) & (ForceObject extends true ? {
|
|
738
|
+
}) & (IsNever<Base> extends true ? {} : NarrowDiscriminator<Omit<Base, typeof PrimaryKeyProp>, BaseDiscriminatorColumn, DiscriminatorValue>) & (ForceObject extends true ? {
|
|
735
739
|
[Config]?: DefineConfig<{
|
|
736
740
|
forceObject: true;
|
|
737
741
|
}>;
|
|
738
742
|
} : {}) & {
|
|
739
743
|
[IndexHints]?: [Properties];
|
|
740
744
|
};
|
|
745
|
+
type NarrowDiscriminator<Base, DiscColumn extends string | undefined, DiscValue> = DiscColumn extends string ? DiscColumn extends keyof Base ? DiscValue extends string | number ? Omit<Base, DiscColumn> & {
|
|
746
|
+
[K in DiscColumn]: DiscValue;
|
|
747
|
+
} : Base : Base : Base;
|
|
741
748
|
type InferCombinedPrimaryKey<Properties extends Record<string, any>, PK, Base> = PK extends undefined ? CombinePrimaryKeys<InferPrimaryKey<Properties>, ExtractBasePrimaryKey<Base>> : PK;
|
|
742
749
|
type ExtractBasePrimaryKey<Base> = Base extends {
|
|
743
750
|
[PrimaryKeyProp]?: infer BasePK;
|
|
@@ -1840,7 +1840,7 @@ export class MetadataDiscovery {
|
|
|
1840
1840
|
if (!prop.customType && prop.array && prop.items) {
|
|
1841
1841
|
prop.customType = new t.enumArray(`${meta.className}.${prop.name}`, prop.items);
|
|
1842
1842
|
}
|
|
1843
|
-
const isArray = prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]');
|
|
1843
|
+
const isArray = prop.array || prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]');
|
|
1844
1844
|
if (objectEmbeddable && !prop.customType && isArray) {
|
|
1845
1845
|
prop.customType = new t.json();
|
|
1846
1846
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.1.0-dev.
|
|
3
|
+
"version": "7.1.0-dev.30",
|
|
4
4
|
"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.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
package/typings.d.ts
CHANGED
|
@@ -1129,7 +1129,7 @@ export type MigrationRow = {
|
|
|
1129
1129
|
* @internal
|
|
1130
1130
|
*/
|
|
1131
1131
|
export interface IMigrationRunner {
|
|
1132
|
-
run(migration: Migration, method: 'up' | 'down'): Promise<void>;
|
|
1132
|
+
run(migration: Migration, method: 'up' | 'down', afterRun?: (tx?: Transaction) => Promise<void>): Promise<void>;
|
|
1133
1133
|
setMasterMigration(trx: Transaction): void;
|
|
1134
1134
|
unsetMasterMigration(): void;
|
|
1135
1135
|
setRunSchema?(schema?: string): void;
|
|
@@ -1140,8 +1140,8 @@ export interface IMigrationRunner {
|
|
|
1140
1140
|
*/
|
|
1141
1141
|
export interface IMigratorStorage {
|
|
1142
1142
|
executed(): Promise<string[]>;
|
|
1143
|
-
logMigration(params: Dictionary): Promise<void>;
|
|
1144
|
-
unlogMigration(params: Dictionary): Promise<void>;
|
|
1143
|
+
logMigration(params: Dictionary, tx?: Transaction): Promise<void>;
|
|
1144
|
+
unlogMigration(params: Dictionary, tx?: Transaction): Promise<void>;
|
|
1145
1145
|
getExecutedMigrations(): Promise<MigrationRow[]>;
|
|
1146
1146
|
ensureTable?(): Promise<void>;
|
|
1147
1147
|
setMasterMigration(trx: Transaction): void;
|
|
@@ -1477,15 +1477,18 @@ export type MaybeReturnType<T> = T extends (...args: any[]) => infer R ? R : T;
|
|
|
1477
1477
|
* Extended `EntitySchema` interface that carries additional type-level metadata (entity name, properties, table name).
|
|
1478
1478
|
* Returned by `defineEntity()` to provide strong type inference without explicit generics.
|
|
1479
1479
|
*/
|
|
1480
|
-
export interface EntitySchemaWithMeta<TName extends string = string, TTableName extends string = string, TEntity = any, TBase = never, TProperties extends Record<string, any> = Record<string, any>, TClass extends EntityCtor = EntityCtor<TEntity
|
|
1480
|
+
export interface EntitySchemaWithMeta<TName extends string = string, TTableName extends string = string, TEntity = any, TBase = never, TProperties extends Record<string, any> = Record<string, any>, TClass extends EntityCtor = EntityCtor<TEntity>, TDiscriminatorColumn extends string | undefined = undefined> extends EntitySchema<TEntity, TBase, TClass> {
|
|
1481
1481
|
readonly name: TName;
|
|
1482
1482
|
readonly properties: TProperties;
|
|
1483
1483
|
readonly tableName: TTableName;
|
|
1484
1484
|
/** @internal Direct entity type access - avoids expensive pattern matching */
|
|
1485
1485
|
readonly '~entity': TEntity;
|
|
1486
|
+
/** @internal Type-level marker carrying the discriminator column name, used by `defineEntity()` to narrow inherited discriminator properties to the literal `discriminatorValue` of each child schema. */
|
|
1487
|
+
readonly '~discriminatorColumn'?: TDiscriminatorColumn;
|
|
1486
1488
|
/** @internal */
|
|
1487
1489
|
readonly class: TClass & {
|
|
1488
1490
|
'~entityName'?: TName;
|
|
1491
|
+
'~discriminatorColumn'?: TDiscriminatorColumn;
|
|
1489
1492
|
};
|
|
1490
1493
|
}
|
|
1491
1494
|
/**
|
package/typings.js
CHANGED
|
@@ -166,7 +166,7 @@ export class EntityMetadata {
|
|
|
166
166
|
if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
|
|
167
167
|
return false;
|
|
168
168
|
}
|
|
169
|
-
return prop.kind === ReferenceKind.SCALAR && ['string', 'number', 'boolean', 'Date'].includes(prop.type);
|
|
169
|
+
return (prop.kind === ReferenceKind.SCALAR && !prop.array && ['string', 'number', 'boolean', 'Date'].includes(prop.type));
|
|
170
170
|
});
|
|
171
171
|
this.hydrateProps = this.props.filter(prop => {
|
|
172
172
|
// `prop.userDefined` is either `undefined` or `false`
|
|
@@ -5,8 +5,8 @@ import type { EntityManagerType, IDatabaseDriver } from '../drivers/IDatabaseDri
|
|
|
5
5
|
interface RunnableMigration {
|
|
6
6
|
name: string;
|
|
7
7
|
path?: string;
|
|
8
|
-
up: () => MaybePromise<void>;
|
|
9
|
-
down: () => MaybePromise<void>;
|
|
8
|
+
up: (afterRun?: (tx?: Transaction) => Promise<void>) => MaybePromise<void>;
|
|
9
|
+
down: (afterRun?: (tx?: Transaction) => Promise<void>) => MaybePromise<void>;
|
|
10
10
|
}
|
|
11
11
|
type MigrateOptions = {
|
|
12
12
|
from?: string | number;
|
|
@@ -331,26 +331,26 @@ export class AbstractMigrator {
|
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
resolve(params) {
|
|
334
|
-
const createMigrationHandler = async (method) => {
|
|
334
|
+
const createMigrationHandler = async (method, afterRun) => {
|
|
335
335
|
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
336
336
|
const migration = await fs.dynamicImport(params.path);
|
|
337
337
|
const MigrationClass = Object.values(migration).find(cls => typeof cls === 'function' && typeof cls.constructor === 'function');
|
|
338
338
|
const instance = new MigrationClass(this.driver, this.config);
|
|
339
|
-
await this.runner.run(instance, method);
|
|
339
|
+
await this.runner.run(instance, method, afterRun);
|
|
340
340
|
};
|
|
341
341
|
return {
|
|
342
342
|
name: this.storage.getMigrationName(params.name),
|
|
343
343
|
path: params.path,
|
|
344
|
-
up:
|
|
345
|
-
down:
|
|
344
|
+
up: afterRun => createMigrationHandler('up', afterRun),
|
|
345
|
+
down: afterRun => createMigrationHandler('down', afterRun),
|
|
346
346
|
};
|
|
347
347
|
}
|
|
348
348
|
initialize(MigrationClass, name) {
|
|
349
349
|
const instance = new MigrationClass(this.driver, this.config);
|
|
350
350
|
return {
|
|
351
351
|
name: this.storage.getMigrationName(name),
|
|
352
|
-
up:
|
|
353
|
-
down:
|
|
352
|
+
up: afterRun => this.runner.run(instance, 'up', afterRun),
|
|
353
|
+
down: afterRun => this.runner.run(instance, 'down', afterRun),
|
|
354
354
|
};
|
|
355
355
|
}
|
|
356
356
|
/**
|
|
@@ -429,13 +429,15 @@ export class AbstractMigrator {
|
|
|
429
429
|
for (const migration of toRun) {
|
|
430
430
|
const event = { name: migration.name, path: migration.path };
|
|
431
431
|
await this.emit(eventBefore, event);
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
432
|
+
// log inside the runner's tx (if any) so a logMigration failure rolls the migration back
|
|
433
|
+
await migration[method](async (tx) => {
|
|
434
|
+
if (method === 'up') {
|
|
435
|
+
await this.storage.logMigration({ name: migration.name }, tx);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
await this.storage.unlogMigration({ name: migration.name }, tx);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
439
441
|
await this.emit(eventAfter, event);
|
|
440
442
|
result.push(event);
|
|
441
443
|
}
|
|
@@ -536,7 +536,7 @@ export class EntityComparator {
|
|
|
536
536
|
ret += ` && entity${path.map(k => this.wrap(k)).join('')}?.isInitialized()`;
|
|
537
537
|
}
|
|
538
538
|
ret += `) {\n`;
|
|
539
|
-
if (['number', 'string', 'boolean'].includes(prop.type.toLowerCase())) {
|
|
539
|
+
if (!prop.array && ['number', 'string', 'boolean'].includes(prop.type.toLowerCase())) {
|
|
540
540
|
return ret + ` ret${dataKey} = entity${entityKey}${unwrap};\n }\n`;
|
|
541
541
|
}
|
|
542
542
|
if (prop.kind === ReferenceKind.EMBEDDED) {
|
package/utils/Utils.js
CHANGED
|
@@ -141,7 +141,7 @@ export function parseJsonSafe(value) {
|
|
|
141
141
|
/** Collection of general-purpose utility methods used throughout the ORM. */
|
|
142
142
|
export class Utils {
|
|
143
143
|
static PK_SEPARATOR = '~~~';
|
|
144
|
-
static #ORM_VERSION = '7.1.0-dev.
|
|
144
|
+
static #ORM_VERSION = '7.1.0-dev.30';
|
|
145
145
|
/**
|
|
146
146
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
147
147
|
*/
|