@mikro-orm/core 7.0.0-dev.4 → 7.0.0-dev.41

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.
Files changed (117) hide show
  1. package/EntityManager.d.ts +84 -18
  2. package/EntityManager.js +265 -172
  3. package/MikroORM.d.ts +7 -5
  4. package/MikroORM.js +0 -1
  5. package/README.md +3 -2
  6. package/cache/FileCacheAdapter.d.ts +2 -1
  7. package/cache/FileCacheAdapter.js +6 -4
  8. package/connections/Connection.d.ts +4 -2
  9. package/connections/Connection.js +2 -2
  10. package/decorators/Check.d.ts +2 -2
  11. package/decorators/Embeddable.d.ts +5 -5
  12. package/decorators/Embeddable.js +1 -1
  13. package/decorators/Embedded.d.ts +6 -12
  14. package/decorators/Entity.d.ts +18 -3
  15. package/decorators/Enum.d.ts +1 -1
  16. package/decorators/Formula.d.ts +1 -2
  17. package/decorators/Indexed.d.ts +2 -2
  18. package/decorators/ManyToMany.d.ts +4 -2
  19. package/decorators/ManyToOne.d.ts +6 -2
  20. package/decorators/OneToMany.d.ts +4 -4
  21. package/decorators/OneToOne.d.ts +5 -1
  22. package/decorators/PrimaryKey.d.ts +2 -3
  23. package/decorators/Property.d.ts +54 -4
  24. package/decorators/Transactional.d.ts +1 -0
  25. package/decorators/Transactional.js +3 -3
  26. package/decorators/index.d.ts +1 -1
  27. package/drivers/DatabaseDriver.d.ts +4 -3
  28. package/drivers/IDatabaseDriver.d.ts +22 -2
  29. package/entity/ArrayCollection.d.ts +4 -2
  30. package/entity/ArrayCollection.js +18 -6
  31. package/entity/Collection.d.ts +1 -2
  32. package/entity/Collection.js +19 -10
  33. package/entity/EntityAssigner.d.ts +1 -1
  34. package/entity/EntityAssigner.js +9 -1
  35. package/entity/EntityFactory.d.ts +7 -0
  36. package/entity/EntityFactory.js +29 -9
  37. package/entity/EntityHelper.js +25 -3
  38. package/entity/EntityLoader.d.ts +5 -4
  39. package/entity/EntityLoader.js +74 -37
  40. package/entity/EntityRepository.d.ts +1 -1
  41. package/entity/EntityValidator.js +1 -1
  42. package/entity/Reference.d.ts +9 -7
  43. package/entity/Reference.js +30 -3
  44. package/entity/WrappedEntity.js +1 -1
  45. package/entity/defineEntity.d.ts +561 -0
  46. package/entity/defineEntity.js +537 -0
  47. package/entity/index.d.ts +2 -0
  48. package/entity/index.js +2 -0
  49. package/entity/utils.d.ts +7 -0
  50. package/entity/utils.js +15 -3
  51. package/enums.d.ts +16 -3
  52. package/enums.js +13 -0
  53. package/errors.d.ts +6 -0
  54. package/errors.js +14 -0
  55. package/events/EventSubscriber.d.ts +3 -1
  56. package/hydration/ObjectHydrator.d.ts +4 -4
  57. package/hydration/ObjectHydrator.js +35 -24
  58. package/index.d.ts +2 -1
  59. package/index.js +1 -1
  60. package/logging/DefaultLogger.d.ts +1 -1
  61. package/logging/SimpleLogger.d.ts +1 -1
  62. package/metadata/EntitySchema.d.ts +8 -4
  63. package/metadata/EntitySchema.js +39 -19
  64. package/metadata/MetadataDiscovery.d.ts +1 -1
  65. package/metadata/MetadataDiscovery.js +88 -32
  66. package/metadata/MetadataStorage.js +1 -1
  67. package/metadata/MetadataValidator.js +4 -3
  68. package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
  69. package/naming-strategy/AbstractNamingStrategy.js +7 -1
  70. package/naming-strategy/NamingStrategy.d.ts +11 -1
  71. package/package.json +5 -5
  72. package/platforms/Platform.d.ts +5 -3
  73. package/platforms/Platform.js +4 -8
  74. package/serialization/EntitySerializer.d.ts +2 -0
  75. package/serialization/EntitySerializer.js +2 -2
  76. package/serialization/EntityTransformer.js +1 -1
  77. package/serialization/SerializationContext.js +14 -11
  78. package/types/BigIntType.d.ts +9 -6
  79. package/types/BigIntType.js +3 -0
  80. package/types/BooleanType.d.ts +1 -1
  81. package/types/DecimalType.d.ts +6 -4
  82. package/types/DecimalType.js +1 -1
  83. package/types/DoubleType.js +1 -1
  84. package/types/JsonType.d.ts +1 -1
  85. package/types/JsonType.js +7 -2
  86. package/types/Type.d.ts +2 -1
  87. package/types/Type.js +1 -1
  88. package/types/index.d.ts +1 -1
  89. package/typings.d.ts +88 -39
  90. package/typings.js +24 -4
  91. package/unit-of-work/ChangeSetComputer.js +3 -1
  92. package/unit-of-work/ChangeSetPersister.d.ts +4 -2
  93. package/unit-of-work/ChangeSetPersister.js +37 -16
  94. package/unit-of-work/UnitOfWork.d.ts +8 -1
  95. package/unit-of-work/UnitOfWork.js +109 -41
  96. package/utils/Configuration.d.ts +23 -5
  97. package/utils/Configuration.js +17 -3
  98. package/utils/ConfigurationLoader.d.ts +0 -2
  99. package/utils/ConfigurationLoader.js +2 -24
  100. package/utils/Cursor.d.ts +3 -3
  101. package/utils/Cursor.js +3 -0
  102. package/utils/DataloaderUtils.d.ts +7 -2
  103. package/utils/DataloaderUtils.js +38 -7
  104. package/utils/EntityComparator.d.ts +6 -2
  105. package/utils/EntityComparator.js +104 -58
  106. package/utils/QueryHelper.d.ts +9 -1
  107. package/utils/QueryHelper.js +66 -5
  108. package/utils/RawQueryFragment.d.ts +36 -2
  109. package/utils/RawQueryFragment.js +35 -1
  110. package/utils/TransactionManager.d.ts +65 -0
  111. package/utils/TransactionManager.js +218 -0
  112. package/utils/Utils.d.ts +11 -5
  113. package/utils/Utils.js +76 -33
  114. package/utils/index.d.ts +1 -0
  115. package/utils/index.js +1 -0
  116. package/utils/upsert-utils.d.ts +7 -2
  117. package/utils/upsert-utils.js +52 -1
@@ -13,7 +13,7 @@ export class DecimalType extends Type {
13
13
  if ((this.mode ?? this.prop?.runtimeType) === 'number') {
14
14
  return +value;
15
15
  }
16
- return value;
16
+ return String(value);
17
17
  }
18
18
  compareValues(a, b) {
19
19
  return this.format(a) === this.format(b);
@@ -8,7 +8,7 @@ export class DoubleType extends Type {
8
8
  if (this.prop?.runtimeType === 'number') {
9
9
  return +value;
10
10
  }
11
- return value;
11
+ return String(value);
12
12
  }
13
13
  getColumnType(prop, platform) {
14
14
  return platform.getDoubleDeclarationSQL();
@@ -5,7 +5,7 @@ export declare class JsonType extends Type<unknown, string | null> {
5
5
  convertToDatabaseValue(value: unknown, platform: Platform, context?: TransformContext): string | null;
6
6
  convertToJSValueSQL(key: string, platform: Platform): string;
7
7
  convertToDatabaseValueSQL(key: string, platform: Platform): string;
8
- convertToJSValue(value: string | unknown, platform: Platform): unknown;
8
+ convertToJSValue(value: string | unknown, platform: Platform, context?: TransformContext): unknown;
9
9
  getColumnType(prop: EntityProperty, platform: Platform): string;
10
10
  ensureComparable<T extends object>(meta: EntityMetadata<T>, prop: EntityProperty<T>): boolean;
11
11
  compareAsType(): string;
package/types/JsonType.js CHANGED
@@ -12,8 +12,13 @@ export class JsonType extends Type {
12
12
  convertToDatabaseValueSQL(key, platform) {
13
13
  return key + platform.castColumn(this.prop);
14
14
  }
15
- convertToJSValue(value, platform) {
16
- return platform.convertJsonToJSValue(value, this.prop);
15
+ convertToJSValue(value, platform, context) {
16
+ const isJsonColumn = ['json', 'jsonb', platform.getJsonDeclarationSQL()].includes(this.prop.columnTypes[0]);
17
+ const isObjectEmbedded = this.prop.embedded && this.prop.object;
18
+ if ((platform.convertsJsonAutomatically() || isObjectEmbedded) && isJsonColumn && !context?.force) {
19
+ return value;
20
+ }
21
+ return platform.convertJsonToJSValue(value, context);
17
22
  }
18
23
  getColumnType(prop, platform) {
19
24
  return platform.getJsonDeclarationSQL();
package/types/Type.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { Platform } from '../platforms/Platform.js';
3
3
  import type { Constructor, EntityMetadata, EntityProperty } from '../typings.js';
4
4
  export interface TransformContext {
5
5
  fromQuery?: boolean;
6
+ force?: boolean;
6
7
  key?: string;
7
8
  mode?: 'hydration' | 'query' | 'query-data' | 'discovery' | 'serialization';
8
9
  }
@@ -23,7 +24,7 @@ export declare abstract class Type<JSType = string, DBType = JSType> {
23
24
  /**
24
25
  * Converts a value from its database representation to its JS representation of this type.
25
26
  */
26
- convertToJSValue(value: DBType, platform: Platform): JSType;
27
+ convertToJSValue(value: DBType, platform: Platform, context?: TransformContext): JSType;
27
28
  /**
28
29
  * Converts a value from its JS representation to its database representation of this type.
29
30
  */
package/types/Type.js CHANGED
@@ -13,7 +13,7 @@ export class Type {
13
13
  /**
14
14
  * Converts a value from its database representation to its JS representation of this type.
15
15
  */
16
- convertToJSValue(value, platform) {
16
+ convertToJSValue(value, platform, context) {
17
17
  return value;
18
18
  }
19
19
  /**
package/types/index.d.ts CHANGED
@@ -19,7 +19,7 @@ import { StringType } from './StringType.js';
19
19
  import { TextType } from './TextType.js';
20
20
  import { TimeType } from './TimeType.js';
21
21
  import { TinyIntType } from './TinyIntType.js';
22
- import { IType, TransformContext, Type } from './Type.js';
22
+ import { type IType, type TransformContext, Type } from './Type.js';
23
23
  import { Uint8ArrayType } from './Uint8ArrayType.js';
24
24
  import { UnknownType } from './UnknownType.js';
25
25
  import { UuidType } from './UuidType.js';
package/typings.d.ts CHANGED
@@ -19,7 +19,7 @@ import type { RawQueryFragment } from './utils/RawQueryFragment.js';
19
19
  import type { EntityManager } from './EntityManager.js';
20
20
  import type { EmbeddedPrefixMode } from './decorators/Embedded.js';
21
21
  import type { EventSubscriber } from './events/EventSubscriber.js';
22
- import type { FindOneOptions, FindOptions, LoadHint } from './drivers/IDatabaseDriver.js';
22
+ import type { FilterOptions, FindOneOptions, FindOptions, LoadHint } from './drivers/IDatabaseDriver.js';
23
23
  export type Constructor<T = unknown> = new (...args: any[]) => T;
24
24
  export type Dictionary<T = any> = {
25
25
  [k: string]: T;
@@ -52,18 +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
- declare const __optional: unique symbol;
56
- declare const __hidden: unique symbol;
57
- declare const __config: unique symbol;
58
- export type Opt<T = unknown> = T & {
59
- [__optional]?: 1;
60
- };
61
- export type Hidden<T = unknown> = T & {
62
- [__hidden]?: 1;
63
- };
64
- export type DefineConfig<T extends TypeConfig> = T & {
65
- [__config]?: 1;
66
- };
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
+ }
67
83
  export type CleanTypeConfig<T> = Compute<Pick<T, Extract<keyof T, keyof TypeConfig>>>;
68
84
  export interface TypeConfig {
69
85
  forceObject?: boolean;
@@ -75,13 +91,14 @@ type PrimaryPropToType<T, Keys extends (keyof T)[]> = {
75
91
  type ReadonlyPrimary<T> = T extends any[] ? Readonly<T> : T;
76
92
  export type Primary<T> = IsAny<T> extends true ? any : T extends {
77
93
  [PrimaryKeyProp]?: infer PK;
78
- } ? (PK extends keyof T ? ReadonlyPrimary<UnwrapPrimary<T[PK]>> : (PK extends (keyof T)[] ? ReadonlyPrimary<PrimaryPropToType<T, PK>> : PK)) : T extends {
94
+ } ? PK extends undefined ? Omit<T, typeof PrimaryKeyProp> : PK extends keyof T ? ReadonlyPrimary<UnwrapPrimary<T[PK]>> : PK extends (keyof T)[] ? ReadonlyPrimary<PrimaryPropToType<T, PK>> : PK : T extends {
79
95
  _id?: infer PK;
80
96
  } ? ReadonlyPrimary<PK> | string : T extends {
81
- uuid?: infer PK;
82
- } ? ReadonlyPrimary<PK> : T extends {
83
97
  id?: infer PK;
98
+ } ? ReadonlyPrimary<PK> : T extends {
99
+ uuid?: infer PK;
84
100
  } ? ReadonlyPrimary<PK> : T;
101
+ /** @internal */
85
102
  export type PrimaryProperty<T> = T extends {
86
103
  [PrimaryKeyProp]?: infer PK;
87
104
  } ? (PK extends keyof T ? PK : (PK extends any[] ? PK[number] : never)) : T extends {
@@ -89,10 +106,10 @@ export type PrimaryProperty<T> = T extends {
89
106
  } ? (T extends {
90
107
  id?: any;
91
108
  } ? 'id' | '_id' : '_id') : T extends {
92
- uuid?: any;
93
- } ? 'uuid' : T extends {
94
109
  id?: any;
95
- } ? 'id' : never;
110
+ } ? 'id' : T extends {
111
+ uuid?: any;
112
+ } ? 'uuid' : never;
96
113
  export type IPrimaryKeyValue = number | string | bigint | Date | {
97
114
  toHexString(): string;
98
115
  };
@@ -177,7 +194,7 @@ export interface IWrappedEntityInternal<Entity extends object> extends IWrappedE
177
194
  __touched: boolean;
178
195
  __originalEntityData?: EntityData<Entity>;
179
196
  __loadedProperties: Set<string>;
180
- __identifier?: EntityIdentifier;
197
+ __identifier?: EntityIdentifier | EntityIdentifier[];
181
198
  __managed: boolean;
182
199
  __processing: boolean;
183
200
  __schema?: string;
@@ -206,7 +223,7 @@ export type EntityName<T> = string | EntityClass<T> | EntitySchema<T, any> | {
206
223
  };
207
224
  export type GetRepository<Entity extends {
208
225
  [k: PropertyKey]: any;
209
- }, Fallback> = Entity[typeof EntityRepositoryType] extends EntityRepository<Entity> | undefined ? NonNullable<Entity[typeof EntityRepositoryType]> : Fallback;
226
+ }, Fallback> = Entity[typeof EntityRepositoryType] extends EntityRepository<any> | undefined ? NonNullable<Entity[typeof EntityRepositoryType]> : Fallback;
210
227
  export type EntityDataPropValue<T> = T | Primary<T>;
211
228
  type ExpandEntityProp<T, C extends boolean = false> = T extends Record<string, any> ? {
212
229
  [K in keyof T as CleanKeys<T, K>]?: EntityDataProp<ExpandProperty<T[K]>, C> | EntityDataPropValue<ExpandProperty<T[K]>> | null;
@@ -217,14 +234,17 @@ type ExpandRequiredEntityPropObject<T, I = never, C extends boolean = false> = {
217
234
  } & {
218
235
  [K in keyof T as OptionalKeys<T, K, I>]?: RequiredEntityDataProp<ExpandProperty<T[K]>, T, C> | EntityDataPropValue<ExpandProperty<T[K]>> | null | undefined;
219
236
  };
237
+ type NonArrayObject = object & {
238
+ [Symbol.iterator]?: never;
239
+ };
220
240
  export type EntityDataProp<T, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends {
221
241
  __runtime?: infer Runtime;
222
242
  __raw?: infer Raw;
223
- } ? (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 | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
224
- export type RequiredEntityDataProp<T, O, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends {
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>;
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 {
225
245
  __runtime?: infer Runtime;
226
246
  __raw?: infer Raw;
227
- } ? (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 | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : RequiredEntityDataNested<T, O, C>;
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>;
228
248
  export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
229
249
  type EntityDataItem<T, C extends boolean> = C extends false ? T | EntityDataProp<T, C> | null : EntityDataProp<T, C> | null;
230
250
  export type RequiredEntityDataNested<T, O, C extends boolean> = T extends any[] ? Readonly<T> : RequiredEntityData<T, O> | ExpandRequiredEntityProp<T, O, C>;
@@ -236,7 +256,10 @@ type ExplicitlyOptionalProps<T> = (T extends {
236
256
  type NullableKeys<T, V = null> = {
237
257
  [K in keyof T]: V extends T[K] ? K : never;
238
258
  }[keyof T];
239
- type ProbablyOptionalProps<T> = PrimaryProperty<T> | ExplicitlyOptionalProps<T> | NonNullable<NullableKeys<T, null | undefined>>;
259
+ type RequiredNullableKeys<T> = {
260
+ [K in keyof T]: Exclude<T[K], null> extends RequiredNullable.Brand ? K : never;
261
+ }[keyof T];
262
+ type ProbablyOptionalProps<T> = PrimaryProperty<T> | ExplicitlyOptionalProps<T> | Exclude<NonNullable<NullableKeys<T, null | undefined>>, RequiredNullableKeys<T>>;
240
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;
241
264
  type RequiredKeys<T, K extends keyof T, I> = IsOptional<T, K, I> extends false ? CleanKeys<T, K> : never;
242
265
  type OptionalKeys<T, K extends keyof T, I> = IsOptional<T, K, I> extends false ? never : CleanKeys<T, K>;
@@ -283,7 +306,7 @@ type PrimaryOrObject<T, U, C extends TypeConfig> = PreferExplicitConfig<C, Extra
283
306
  } : Primary<U>;
284
307
  export type EntityDTOProp<E, T, C extends TypeConfig = never> = T extends Scalar ? T : T extends {
285
308
  __serialized?: infer U;
286
- } ? U : T extends LoadedReference<infer U> ? EntityDTO<U, C> : T extends Reference<infer U> ? PrimaryOrObject<E, U, C> : T extends ScalarReference<infer U> ? U : T extends LoadedCollection<infer U> ? EntityDTO<U, C>[] : T extends Collection<infer U> ? PrimaryOrObject<E, U, C>[] : T extends readonly (infer U)[] ? (T extends readonly any[] ? T : U[]) : T extends Relation<T> ? EntityDTO<T, C> : T;
309
+ } ? (IsUnknown<U> extends false ? U : T) : T extends LoadedReference<infer U> ? EntityDTO<U, C> : T extends Reference<infer U> ? PrimaryOrObject<E, U, C> : T extends ScalarReference<infer U> ? U : T extends LoadedCollection<infer U> ? EntityDTO<U, C>[] : T extends Collection<infer U> ? PrimaryOrObject<E, U, C>[] : T extends readonly (infer U)[] ? (T extends readonly any[] ? T : U[]) : T extends Relation<T> ? EntityDTO<T, C> : T;
287
310
  type DTOProbablyOptionalProps<T> = NonNullable<NullableKeys<T, undefined>>;
288
311
  type DTOIsOptional<T, K extends keyof T> = T[K] extends LoadedCollection<any> ? false : K extends PrimaryProperty<T> ? false : K extends DTOProbablyOptionalProps<T> ? true : false;
289
312
  type DTORequiredKeys<T, K extends keyof T> = DTOIsOptional<T, K> extends false ? ExcludeHidden<T, K> & CleanKeys<T, K> : never;
@@ -293,8 +316,15 @@ export type EntityDTO<T, C extends TypeConfig = never> = {
293
316
  } & {
294
317
  [K in keyof T as DTOOptionalKeys<T, K>]?: EntityDTOProp<T, T[K], C> | AddOptional<T[K]>;
295
318
  };
296
- type CheckKey<T> = IsUnknown<T> extends false ? keyof T : string;
297
- export type CheckCallback<T> = (columns: Record<CheckKey<T>, string>) => string;
319
+ type TargetKeys<T> = T extends EntityClass<infer P> ? keyof P : keyof T;
320
+ type PropertyName<T> = IsUnknown<T> extends false ? TargetKeys<T> : string;
321
+ type TableName = {
322
+ name: string;
323
+ schema?: string;
324
+ toString: () => string;
325
+ };
326
+ export type IndexCallback<T> = (table: TableName, columns: Record<PropertyName<T>, string>, indexName: string) => string | RawQueryFragment;
327
+ export type CheckCallback<T> = (columns: Record<PropertyName<T>, string>) => string;
298
328
  export type GeneratedColumnCallback<T> = (columns: Record<keyof T, string>) => string;
299
329
  export interface CheckConstraint<T = any> {
300
330
  name?: string;
@@ -331,6 +361,7 @@ export interface EntityProperty<Owner = any, Target = any> {
331
361
  default?: string | number | boolean | null;
332
362
  defaultRaw?: string;
333
363
  formula?: (alias: string) => string;
364
+ filters?: FilterOptions;
334
365
  prefix?: string | boolean;
335
366
  prefixMode?: EmbeddedPrefixMode;
336
367
  embedded?: [EntityKey<Owner>, EntityKey<Owner>];
@@ -358,6 +389,7 @@ export interface EntityProperty<Owner = any, Target = any> {
358
389
  setter?: boolean;
359
390
  getter?: boolean;
360
391
  getterName?: keyof Owner;
392
+ accessor?: EntityKey<Owner>;
361
393
  cascade: Cascade[];
362
394
  orphanRemoval?: boolean;
363
395
  onCreate?: (entity: Owner, em: EntityManager) => any;
@@ -390,6 +422,8 @@ export interface EntityProperty<Owner = any, Target = any> {
390
422
  optional?: boolean;
391
423
  ignoreSchemaChanges?: ('type' | 'extra' | 'default')[];
392
424
  deferMode?: DeferMode;
425
+ createForeignKeyConstraint: boolean;
426
+ foreignKeyName?: string;
393
427
  }
394
428
  export declare class EntityMetadata<T = any> {
395
429
  private static counter;
@@ -398,8 +432,9 @@ export declare class EntityMetadata<T = any> {
398
432
  constructor(meta?: Partial<EntityMetadata>);
399
433
  addProperty(prop: Partial<EntityProperty<T>>, sync?: boolean): void;
400
434
  removeProperty(name: string, sync?: boolean): void;
401
- getPrimaryProps(): EntityProperty<T>[];
435
+ getPrimaryProps(flatten?: boolean): EntityProperty<T>[];
402
436
  getPrimaryProp(): EntityProperty<T>;
437
+ createColumnMappingObject(): Dictionary<any>;
403
438
  get tableName(): string;
404
439
  set tableName(name: string);
405
440
  sync(initIndexes?: boolean, config?: Configuration): void;
@@ -418,7 +453,7 @@ export interface EntityMetadata<T = any> {
418
453
  schema?: string;
419
454
  pivotTable?: boolean;
420
455
  virtual?: boolean;
421
- expression?: string | ((em: any, where: FilterQuery<T>, options: FindOptions<T, any, any, any>) => MaybePromise<RawQueryFragment | object | string>);
456
+ expression?: string | ((em: any, where: ObjectQuery<T>, options: FindOptions<T, any, any, any>, stream?: boolean) => MaybePromise<RawQueryFragment | object | string>);
422
457
  discriminatorColumn?: EntityKey<T> | AnyString;
423
458
  discriminatorValue?: number | string;
424
459
  discriminatorMap?: Dictionary<string>;
@@ -451,18 +486,18 @@ export interface EntityMetadata<T = any> {
451
486
  uniqueProps: EntityProperty<T>[];
452
487
  getterProps: EntityProperty<T>[];
453
488
  indexes: {
454
- properties: EntityKey<T> | EntityKey<T>[];
489
+ properties?: EntityKey<T> | EntityKey<T>[];
455
490
  name?: string;
456
491
  type?: string;
457
492
  options?: Dictionary;
458
- expression?: string;
493
+ expression?: string | IndexCallback<T>;
459
494
  }[];
460
495
  uniques: {
461
- properties: EntityKey<T> | EntityKey<T>[];
496
+ properties?: EntityKey<T> | EntityKey<T>[];
462
497
  name?: string;
463
498
  options?: Dictionary;
464
- expression?: string;
465
- deferMode?: DeferMode;
499
+ expression?: string | IndexCallback<T>;
500
+ deferMode?: DeferMode | `${DeferMode}`;
466
501
  }[];
467
502
  checks: CheckConstraint<T>[];
468
503
  repositoryClass?: string;
@@ -481,6 +516,7 @@ export interface EntityMetadata<T = any> {
481
516
  polymorphs?: EntityMetadata[];
482
517
  root: EntityMetadata<T>;
483
518
  definedProperties: Dictionary;
519
+ hasTriggers?: boolean;
484
520
  /** @internal can be used for computed numeric cache keys */
485
521
  readonly _id: number;
486
522
  }
@@ -553,7 +589,9 @@ export interface GenerateOptions {
553
589
  undefinedDefaults?: boolean;
554
590
  bidirectionalRelations?: boolean;
555
591
  identifiedReferences?: boolean;
556
- entitySchema?: boolean;
592
+ entityDefinition?: 'decorators' | 'defineEntity' | 'entitySchema';
593
+ inferEntityType?: boolean;
594
+ enumMode?: 'ts-enum' | 'union-type' | 'dictionary';
557
595
  esmImport?: boolean;
558
596
  scalarTypeInDecorator?: boolean;
559
597
  scalarPropertiesForRelations?: 'always' | 'never' | 'smart';
@@ -568,6 +606,8 @@ export interface GenerateOptions {
568
606
  coreImportsPrefix?: string;
569
607
  onInitialMetadata?: MetadataProcessor;
570
608
  onProcessedMetadata?: MetadataProcessor;
609
+ /** @deprecated use `entityDefinition: 'entitySchema'` instead */
610
+ entitySchema?: boolean;
571
611
  }
572
612
  export interface IEntityGenerator {
573
613
  generate(options?: GenerateOptions): Promise<string[]>;
@@ -687,6 +727,7 @@ export type FilterDef = {
687
727
  default?: boolean;
688
728
  entity?: string[];
689
729
  args?: boolean;
730
+ strict?: boolean;
690
731
  };
691
732
  export type Populate<T, P extends string = never> = readonly AutoPath<T, P, `${PopulatePath}`>[] | false;
692
733
  export type PopulateOptions<T> = {
@@ -694,6 +735,7 @@ export type PopulateOptions<T> = {
694
735
  strategy?: LoadStrategy;
695
736
  all?: boolean;
696
737
  filter?: boolean;
738
+ joinType?: 'inner join' | 'left join';
697
739
  children?: PopulateOptions<T[keyof T]>[];
698
740
  };
699
741
  type Loadable<T extends object> = Collection<T, any> | Reference<T> | Ref<T> | readonly T[];
@@ -728,7 +770,7 @@ export type MergeSelected<T, U, F extends string> = T extends Loaded<infer TT, i
728
770
  type MergeFields<F1 extends string, F2 extends string, P1, P2> = P1 | P2 extends '*' ? '*' : F1 | F2;
729
771
  type MergeExcludes<F extends string, E extends string> = F extends E ? never : Exclude<E, F>;
730
772
  export type MergeLoaded<T, U, P extends string, F extends string, E extends string, R extends boolean = false> = T extends Loaded<U, infer PP, infer FF, infer EE> ? string extends FF ? Loaded<T, P, F, AnyStringToNever<EE> | E> : string extends P ? Loaded<U, never, F | (FF & string), MergeExcludes<F | (FF & string), EE | E>> : Loaded<U, P | AnyStringToNever<PP>, MergeFields<F, AnyStringToNever<FF>, P, PP>, MergeExcludes<MergeFields<F, AnyStringToNever<FF>, P, PP>, (R extends true ? never : EE) | E>> : Loaded<T, P, F>;
731
- type AddOptional<T> = undefined | null extends T ? null | undefined : null extends T ? null : undefined extends T ? undefined : never;
773
+ export type AddOptional<T> = undefined | null extends T ? null | undefined : null extends T ? null : undefined extends T ? undefined : never;
732
774
  type LoadedProp<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedLoadable<T, Loaded<ExtractType<T>, L, F, E>>;
733
775
  export type AddEager<T> = ExtractEagerProps<T> & string;
734
776
  export type ExpandHint<T, L extends string> = L | AddEager<T>;
@@ -789,11 +831,11 @@ export interface IHydrator {
789
831
  * Hydrates the whole entity. This process handles custom type conversions, creating missing Collection instances,
790
832
  * mapping FKs to entity instances, as well as merging those entities.
791
833
  */
792
- hydrate<T extends object>(entity: T, meta: EntityMetadata<T>, data: EntityData<T>, factory: EntityFactory, type: 'full' | 'reference', newEntity?: boolean, convertCustomTypes?: boolean, schema?: string, parentSchema?: string): void;
834
+ hydrate<T extends object>(entity: T, meta: EntityMetadata<T>, data: EntityData<T>, factory: EntityFactory, type: 'full' | 'reference', newEntity?: boolean, convertCustomTypes?: boolean, schema?: string, parentSchema?: string, normalizeAccessors?: boolean): void;
793
835
  /**
794
836
  * Hydrates primary keys only
795
837
  */
796
- hydrateReference<T extends object>(entity: T, meta: EntityMetadata<T>, data: EntityData<T>, factory: EntityFactory, convertCustomTypes?: boolean, schema?: string, parentSchema?: string): void;
838
+ hydrateReference<T extends object>(entity: T, meta: EntityMetadata<T>, data: EntityData<T>, factory: EntityFactory, convertCustomTypes?: boolean, schema?: string, parentSchema?: string, normalizeAccessors?: boolean): void;
797
839
  isRunning(): boolean;
798
840
  }
799
841
  export interface HydratorConstructor {
@@ -816,4 +858,11 @@ export type MetadataProcessor = (metadata: EntityMetadata[], platform: Platform)
816
858
  export type ContextProvider<T> = MaybePromise<MikroORM> | ((type: T) => MaybePromise<MikroORM | EntityManager | EntityRepository<any> | {
817
859
  getEntityManager(): EntityManager;
818
860
  }>);
861
+ export type MaybeReturnType<T> = T extends (...args: any[]) => infer R ? R : T;
862
+ export interface EntitySchemaWithMeta<TName extends string = string, TTableName extends string = string, TEntity = any, TBase = never, TProperties extends Record<string, any> = Record<string, any>> extends EntitySchema<TEntity, TBase> {
863
+ readonly name: TName;
864
+ readonly properties: TProperties;
865
+ readonly tableName: TTableName;
866
+ }
867
+ export type InferEntity<Schema> = Schema extends EntitySchemaWithMeta<any, any, infer Entity, any, any> ? Entity : Schema extends EntitySchema<infer Entity> ? Entity : Schema extends EntityClass<infer Entity> ? Entity : Schema;
819
868
  export {};
package/typings.js CHANGED
@@ -45,12 +45,29 @@ export class EntityMetadata {
45
45
  this.sync();
46
46
  }
47
47
  }
48
- getPrimaryProps() {
49
- return this.primaryKeys.map(pk => this.properties[pk]);
48
+ getPrimaryProps(flatten = false) {
49
+ const pks = this.primaryKeys.map(pk => this.properties[pk]);
50
+ if (flatten) {
51
+ return pks.flatMap(pk => {
52
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(pk.kind)) {
53
+ return pk.targetMeta.getPrimaryProps(true);
54
+ }
55
+ return [pk];
56
+ });
57
+ }
58
+ return pks;
50
59
  }
51
60
  getPrimaryProp() {
52
61
  return this.properties[this.primaryKeys[0]];
53
62
  }
63
+ createColumnMappingObject() {
64
+ return Object.values(this.properties).reduce((o, prop) => {
65
+ if (prop.fieldNames) {
66
+ o[prop.name] = prop.fieldNames[0];
67
+ }
68
+ return o;
69
+ }, {});
70
+ }
54
71
  get tableName() {
55
72
  return this.collection;
56
73
  }
@@ -70,7 +87,7 @@ export class EntityMetadata {
70
87
  // `prop.userDefined` is either `undefined` or `false`
71
88
  const discriminator = this.root.discriminatorColumn === prop.name && prop.userDefined === false;
72
89
  // even if we don't have a setter, do not ignore value from database!
73
- const onlyGetter = prop.getter && !prop.setter;
90
+ const onlyGetter = prop.getter && !prop.setter && prop.persist === false;
74
91
  return !prop.inherited && prop.hydrate !== false && !discriminator && !prop.embedded && !onlyGetter;
75
92
  });
76
93
  this.trackingProps = this.hydrateProps
@@ -123,10 +140,13 @@ export class EntityMetadata {
123
140
  const hydrator = wrapped.hydrator;
124
141
  const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
125
142
  const old = Reference.unwrapReference(wrapped.__data[prop.name]);
143
+ if (old && old !== entity && prop.kind === ReferenceKind.MANY_TO_ONE && prop.inversedBy && old[prop.inversedBy]) {
144
+ old[prop.inversedBy].removeWithoutPropagation(this);
145
+ }
126
146
  wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
127
147
  // when propagation from inside hydration, we set the FK to the entity data immediately
128
148
  if (val && hydrator.isRunning() && wrapped.__originalEntityData && prop.owner) {
129
- wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, prop.targetMeta.primaryKeys, true);
149
+ wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, prop.targetMeta, true);
130
150
  }
131
151
  else {
132
152
  wrapped.__touched = !hydrator.isRunning();
@@ -141,7 +141,9 @@ export class ChangeSetComputer {
141
141
  if (!target.isDirty() && changeSet.type !== ChangeSetType.CREATE) {
142
142
  return;
143
143
  }
144
- this.collectionUpdates.add(target);
144
+ if (target.isDirty()) {
145
+ this.collectionUpdates.add(target);
146
+ }
145
147
  if (prop.owner && !this.platform.usesPivotTable()) {
146
148
  changeSet.payload[prop.name] = target.getItems(false).map((item) => item.__helper.__identifier ?? item.__helper.getPrimaryKey());
147
149
  }
@@ -5,6 +5,7 @@ import { type EntityValidator } from '../entity/EntityValidator.js';
5
5
  import { type ChangeSet } from './ChangeSet.js';
6
6
  import { type Configuration } from '../utils/Configuration.js';
7
7
  import type { DriverMethodOptions, IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
8
+ import type { EntityManager } from '../EntityManager.js';
8
9
  export declare class ChangeSetPersister {
9
10
  private readonly driver;
10
11
  private readonly metadata;
@@ -12,10 +13,11 @@ export declare class ChangeSetPersister {
12
13
  private readonly factory;
13
14
  private readonly validator;
14
15
  private readonly config;
16
+ private readonly em;
15
17
  private readonly platform;
16
18
  private readonly comparator;
17
19
  private readonly usesReturningStatement;
18
- constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, validator: EntityValidator, config: Configuration);
20
+ constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, validator: EntityValidator, config: Configuration, em: EntityManager);
19
21
  executeInserts<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
20
22
  executeUpdates<T extends object>(changeSets: ChangeSet<T>[], batched: boolean, options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
21
23
  executeDeletes<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
@@ -23,7 +25,7 @@ export declare class ChangeSetPersister {
23
25
  private processProperties;
24
26
  private persistNewEntity;
25
27
  private persistNewEntities;
26
- private propagateSchemaFromMetadata;
28
+ private prepareOptions;
27
29
  private persistNewEntitiesBatch;
28
30
  private persistManagedEntity;
29
31
  private persistManagedEntities;
@@ -12,16 +12,18 @@ export class ChangeSetPersister {
12
12
  factory;
13
13
  validator;
14
14
  config;
15
+ em;
15
16
  platform;
16
17
  comparator;
17
18
  usesReturningStatement;
18
- constructor(driver, metadata, hydrator, factory, validator, config) {
19
+ constructor(driver, metadata, hydrator, factory, validator, config, em) {
19
20
  this.driver = driver;
20
21
  this.metadata = metadata;
21
22
  this.hydrator = hydrator;
22
23
  this.factory = factory;
23
24
  this.validator = validator;
24
25
  this.config = config;
26
+ this.em = em;
25
27
  this.platform = this.driver.getPlatform();
26
28
  this.comparator = this.config.getComparator(this.metadata);
27
29
  this.usesReturningStatement = this.platform.usesReturningStatement() || this.platform.usesOutputStatement();
@@ -62,7 +64,7 @@ export class ChangeSetPersister {
62
64
  for (let i = 0; i < changeSets.length; i += size) {
63
65
  const chunk = changeSets.slice(i, i + size);
64
66
  const pks = chunk.map(cs => cs.getPrimaryKey());
65
- options = this.propagateSchemaFromMetadata(meta, options);
67
+ options = this.prepareOptions(meta, options);
66
68
  await this.driver.nativeDelete(meta.root.className, { [pk]: { $in: pks } }, options);
67
69
  }
68
70
  }
@@ -90,7 +92,7 @@ export class ChangeSetPersister {
90
92
  }
91
93
  async persistNewEntity(meta, changeSet, options) {
92
94
  const wrapped = helper(changeSet.entity);
93
- options = this.propagateSchemaFromMetadata(meta, options, {
95
+ options = this.prepareOptions(meta, options, {
94
96
  convertCustomTypes: false,
95
97
  });
96
98
  const res = await this.driver.nativeInsertMany(meta.className, [changeSet.payload], options);
@@ -116,15 +118,17 @@ export class ChangeSetPersister {
116
118
  }
117
119
  }
118
120
  }
119
- propagateSchemaFromMetadata(meta, options, additionalOptions) {
121
+ prepareOptions(meta, options, additionalOptions) {
122
+ const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
120
123
  return {
121
124
  ...options,
122
125
  ...additionalOptions,
123
126
  schema: options?.schema ?? meta.schema,
127
+ loggerContext,
124
128
  };
125
129
  }
126
130
  async persistNewEntitiesBatch(meta, changeSets, options) {
127
- options = this.propagateSchemaFromMetadata(meta, options, {
131
+ options = this.prepareOptions(meta, options, {
128
132
  convertCustomTypes: false,
129
133
  processCollections: false,
130
134
  });
@@ -175,7 +179,7 @@ export class ChangeSetPersister {
175
179
  }
176
180
  async persistManagedEntitiesBatch(meta, changeSets, options) {
177
181
  await this.checkOptimisticLocks(meta, changeSets, options);
178
- options = this.propagateSchemaFromMetadata(meta, options, {
182
+ options = this.prepareOptions(meta, options, {
179
183
  convertCustomTypes: false,
180
184
  processCollections: false,
181
185
  });
@@ -210,7 +214,9 @@ export class ChangeSetPersister {
210
214
  // of using the raw value from db, we convert it back to the db value explicitly
211
215
  value = prop.customType ? prop.customType.convertToDatabaseValue(insertId, this.platform, { mode: 'serialization' }) : value;
212
216
  changeSet.payload[wrapped.__meta.primaryKeys[0]] = value;
213
- wrapped.__identifier?.setValue(value);
217
+ if (wrapped.__identifier && !Array.isArray(wrapped.__identifier)) {
218
+ wrapped.__identifier.setValue(value);
219
+ }
214
220
  }
215
221
  /**
216
222
  * Sets populate flag to new entities so they are serialized like if they were loaded from the db
@@ -233,7 +239,7 @@ export class ChangeSetPersister {
233
239
  }
234
240
  async updateEntity(meta, changeSet, options) {
235
241
  const cond = changeSet.getPrimaryKey(true);
236
- options = this.propagateSchemaFromMetadata(meta, options, {
242
+ options = this.prepareOptions(meta, options, {
237
243
  convertCustomTypes: false,
238
244
  });
239
245
  if (meta.concurrencyCheckKeys.size === 0 && (!meta.versionProperty || changeSet.entity[meta.versionProperty] == null)) {
@@ -260,7 +266,7 @@ export class ChangeSetPersister {
260
266
  return cond;
261
267
  });
262
268
  const primaryKeys = meta.primaryKeys.concat(...meta.concurrencyCheckKeys);
263
- options = this.propagateSchemaFromMetadata(meta, options, {
269
+ options = this.prepareOptions(meta, options, {
264
270
  fields: primaryKeys,
265
271
  });
266
272
  const res = await this.driver.find(meta.root.className, { $or }, options);
@@ -284,11 +290,22 @@ export class ChangeSetPersister {
284
290
  async reloadVersionValues(meta, changeSets, options) {
285
291
  const reloadProps = meta.versionProperty && !this.usesReturningStatement ? [meta.properties[meta.versionProperty]] : [];
286
292
  if (changeSets[0].type === ChangeSetType.CREATE) {
287
- // do not reload things that already had a runtime value
288
- meta.props
289
- .filter(prop => prop.persist !== false && (prop.autoincrement || prop.generated || prop.defaultRaw))
290
- .filter(prop => (changeSets[0].entity[prop.name] == null && prop.defaultRaw !== 'null') || isRaw(changeSets[0].entity[prop.name]))
291
- .forEach(prop => reloadProps.push(prop));
293
+ for (const prop of meta.props) {
294
+ if (prop.persist === false) {
295
+ continue;
296
+ }
297
+ if (isRaw(changeSets[0].entity[prop.name])) {
298
+ reloadProps.push(prop);
299
+ continue;
300
+ }
301
+ // do not reload things that already had a runtime value
302
+ if (changeSets[0].entity[prop.name] != null || prop.defaultRaw === 'null') {
303
+ continue;
304
+ }
305
+ if (prop.autoincrement || prop.generated || prop.defaultRaw) {
306
+ reloadProps.push(prop);
307
+ }
308
+ }
292
309
  }
293
310
  if (changeSets[0].type === ChangeSetType.UPDATE) {
294
311
  const returning = new Set();
@@ -319,12 +336,12 @@ export class ChangeSetPersister {
319
336
  }
320
337
  return val;
321
338
  });
322
- options = this.propagateSchemaFromMetadata(meta, options, {
339
+ options = this.prepareOptions(meta, options, {
323
340
  fields: Utils.unique(reloadProps.map(prop => prop.name)),
324
341
  });
325
342
  const data = await this.driver.find(meta.className, { [pk]: { $in: pks } }, options);
326
343
  const map = new Map();
327
- data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, true, this.platform, true), item));
344
+ data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, false, this.platform, true), item));
328
345
  for (const changeSet of changeSets) {
329
346
  const data = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
330
347
  this.hydrator.hydrate(changeSet.entity, meta, data, this.factory, 'full', false, true);
@@ -338,6 +355,10 @@ export class ChangeSetPersister {
338
355
  changeSet.payload[prop.name] = value.getValue();
339
356
  return;
340
357
  }
358
+ if (Array.isArray(value) && value.every(item => item instanceof EntityIdentifier)) {
359
+ changeSet.payload[prop.name] = value.map(item => item.getValue());
360
+ return;
361
+ }
341
362
  if (prop.kind === ReferenceKind.MANY_TO_MANY && Array.isArray(value)) {
342
363
  changeSet.payload[prop.name] = value.map(val => val instanceof EntityIdentifier ? val.getValue() : val);
343
364
  return;