@mikro-orm/core 7.0.0-dev.3 → 7.0.0-dev.31

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 (102) hide show
  1. package/EntityManager.d.ts +50 -7
  2. package/EntityManager.js +141 -97
  3. package/MikroORM.js +0 -1
  4. package/README.md +1 -2
  5. package/cache/FileCacheAdapter.d.ts +2 -1
  6. package/cache/FileCacheAdapter.js +6 -4
  7. package/connections/Connection.d.ts +4 -2
  8. package/connections/Connection.js +2 -2
  9. package/decorators/Check.d.ts +2 -2
  10. package/decorators/Embeddable.d.ts +5 -5
  11. package/decorators/Embeddable.js +1 -1
  12. package/decorators/Embedded.d.ts +6 -12
  13. package/decorators/Entity.d.ts +20 -5
  14. package/decorators/Entity.js +0 -1
  15. package/decorators/Enum.d.ts +1 -1
  16. package/decorators/Formula.d.ts +1 -2
  17. package/decorators/Indexed.d.ts +10 -8
  18. package/decorators/Indexed.js +1 -1
  19. package/decorators/ManyToMany.d.ts +4 -2
  20. package/decorators/ManyToOne.d.ts +6 -2
  21. package/decorators/OneToMany.d.ts +4 -4
  22. package/decorators/OneToOne.d.ts +5 -1
  23. package/decorators/PrimaryKey.d.ts +2 -3
  24. package/decorators/Property.d.ts +1 -1
  25. package/decorators/Transactional.d.ts +1 -0
  26. package/decorators/Transactional.js +3 -3
  27. package/drivers/IDatabaseDriver.d.ts +8 -1
  28. package/entity/ArrayCollection.d.ts +4 -2
  29. package/entity/ArrayCollection.js +18 -6
  30. package/entity/Collection.d.ts +1 -2
  31. package/entity/Collection.js +16 -10
  32. package/entity/EntityAssigner.d.ts +1 -1
  33. package/entity/EntityAssigner.js +9 -1
  34. package/entity/EntityFactory.d.ts +6 -0
  35. package/entity/EntityFactory.js +21 -7
  36. package/entity/EntityHelper.js +8 -1
  37. package/entity/EntityLoader.d.ts +3 -2
  38. package/entity/EntityLoader.js +54 -35
  39. package/entity/EntityRepository.d.ts +1 -1
  40. package/entity/EntityValidator.js +1 -1
  41. package/entity/Reference.d.ts +8 -7
  42. package/entity/Reference.js +22 -1
  43. package/entity/WrappedEntity.js +1 -1
  44. package/entity/defineEntity.d.ts +537 -0
  45. package/entity/defineEntity.js +693 -0
  46. package/entity/index.d.ts +2 -0
  47. package/entity/index.js +2 -0
  48. package/entity/utils.d.ts +7 -0
  49. package/entity/utils.js +15 -3
  50. package/enums.d.ts +16 -3
  51. package/enums.js +13 -0
  52. package/errors.d.ts +6 -0
  53. package/errors.js +14 -0
  54. package/events/EventSubscriber.d.ts +3 -1
  55. package/hydration/ObjectHydrator.js +10 -2
  56. package/index.d.ts +1 -1
  57. package/metadata/EntitySchema.d.ts +6 -4
  58. package/metadata/EntitySchema.js +33 -19
  59. package/metadata/MetadataDiscovery.d.ts +0 -1
  60. package/metadata/MetadataDiscovery.js +51 -29
  61. package/metadata/MetadataStorage.js +1 -1
  62. package/metadata/MetadataValidator.js +4 -3
  63. package/package.json +5 -5
  64. package/platforms/Platform.d.ts +3 -1
  65. package/serialization/EntitySerializer.d.ts +2 -0
  66. package/serialization/EntitySerializer.js +1 -1
  67. package/serialization/SerializationContext.js +13 -10
  68. package/types/BigIntType.d.ts +9 -6
  69. package/types/BigIntType.js +3 -0
  70. package/types/BooleanType.d.ts +1 -1
  71. package/types/DecimalType.d.ts +6 -4
  72. package/types/DecimalType.js +1 -1
  73. package/types/DoubleType.js +1 -1
  74. package/typings.d.ts +72 -35
  75. package/typings.js +24 -4
  76. package/unit-of-work/ChangeSetComputer.js +3 -1
  77. package/unit-of-work/ChangeSetPersister.d.ts +4 -2
  78. package/unit-of-work/ChangeSetPersister.js +21 -11
  79. package/unit-of-work/UnitOfWork.d.ts +2 -1
  80. package/unit-of-work/UnitOfWork.js +71 -24
  81. package/utils/AbstractSchemaGenerator.js +5 -2
  82. package/utils/Configuration.d.ts +15 -5
  83. package/utils/Configuration.js +7 -7
  84. package/utils/ConfigurationLoader.d.ts +0 -2
  85. package/utils/ConfigurationLoader.js +2 -24
  86. package/utils/Cursor.d.ts +3 -3
  87. package/utils/Cursor.js +3 -0
  88. package/utils/DataloaderUtils.d.ts +7 -2
  89. package/utils/DataloaderUtils.js +38 -7
  90. package/utils/EntityComparator.d.ts +6 -2
  91. package/utils/EntityComparator.js +98 -59
  92. package/utils/QueryHelper.d.ts +6 -0
  93. package/utils/QueryHelper.js +48 -5
  94. package/utils/RawQueryFragment.d.ts +34 -0
  95. package/utils/RawQueryFragment.js +40 -1
  96. package/utils/TransactionManager.d.ts +65 -0
  97. package/utils/TransactionManager.js +220 -0
  98. package/utils/Utils.d.ts +11 -7
  99. package/utils/Utils.js +67 -33
  100. package/utils/index.d.ts +1 -0
  101. package/utils/index.js +1 -0
  102. package/utils/upsert-utils.js +9 -1
@@ -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 (!metadata.find(prop.type)) {
105
+ if (!targetMeta) {
105
106
  throw MetadataError.fromWrongTypeDefinition(meta, prop);
106
107
  }
107
- if (metadata.find(prop.type).abstract && !metadata.find(prop.type).discriminatorColumn) {
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 && metadata.find(prop.type).compositePK && options.checkNonPersistentCompositeProps) {
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,7 +1,7 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
3
  "type": "module",
4
- "version": "7.0.0-dev.3",
4
+ "version": "7.0.0-dev.31",
5
5
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
6
6
  "exports": {
7
7
  "./package.json": "./package.json",
@@ -52,10 +52,10 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "dataloader": "2.2.3",
55
- "dotenv": "16.4.7",
55
+ "dotenv": "17.2.3",
56
56
  "esprima": "4.0.1",
57
- "globby": "11.1.0",
58
- "mikro-orm": "7.0.0-dev.3",
59
- "reflect-metadata": "0.2.2"
57
+ "mikro-orm": "7.0.0-dev.31",
58
+ "reflect-metadata": "0.2.2",
59
+ "tinyglobby": "0.2.13"
60
60
  }
61
61
  }
@@ -175,7 +175,9 @@ export declare abstract class Platform {
175
175
  getExtension<T>(extensionName: string, extensionKey: string, moduleName: string, em: EntityManager): T;
176
176
  getSchemaGenerator(driver: IDatabaseDriver, em?: EntityManager): ISchemaGenerator;
177
177
  processDateProperty(value: unknown): string | number | Date;
178
- quoteIdentifier(id: string, quote?: string): string;
178
+ quoteIdentifier(id: string | {
179
+ toString: () => string;
180
+ }, quote?: string): string;
179
181
  quoteValue(value: any): string;
180
182
  escape(value: any): string;
181
183
  formatQuery(sql: string, params: readonly any[]): string;
@@ -17,6 +17,8 @@ export interface SerializeOptions<T, P extends string = never, E extends string
17
17
  forceObject?: boolean;
18
18
  /** Ignore custom property serializers. */
19
19
  ignoreSerializers?: boolean;
20
+ /** Include properties marked as `hidden`. */
21
+ includeHidden?: boolean;
20
22
  /** Skip properties with `null` value. */
21
23
  skipNull?: boolean;
22
24
  /** Only include properties for a specific group. If a property does not specify any group, it will be included, otherwise only properties with a matching group are included. */
@@ -15,7 +15,7 @@ function isVisible(meta, propName, options) {
15
15
  if (options.exclude?.find(item => item === propName)) {
16
16
  return false;
17
17
  }
18
- const visible = prop && !prop.hidden;
18
+ const visible = prop && !(prop.hidden && !options.includeHidden);
19
19
  const prefixed = prop && !prop.primary && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
20
20
  return visible && !prefixed;
21
21
  }
@@ -73,18 +73,21 @@ export class SerializationContext {
73
73
  }
74
74
  }
75
75
  isMarkedAsPopulated(entityName, prop) {
76
- let populate = this.populate;
76
+ let populate = this.populate ?? [];
77
77
  for (const segment of this.path) {
78
- if (!populate) {
79
- return false;
80
- }
81
- const exists = populate.find(p => p.field === segment[1]);
82
- if (exists) {
83
- // we need to check for cycles here too, as we could fall into endless loops for bidirectional relations
84
- if (exists.all) {
85
- return !this.path.find(([cls, item]) => entityName === cls && prop === item);
78
+ const hints = populate.filter(p => p.field === segment[1]);
79
+ if (hints.length > 0) {
80
+ const childHints = [];
81
+ for (const hint of hints) {
82
+ // we need to check for cycles here too, as we could fall into endless loops for bidirectional relations
83
+ if (hint.all) {
84
+ return !this.path.find(([cls, item]) => entityName === cls && prop === item);
85
+ }
86
+ if (hint.children) {
87
+ childHints.push(...hint.children);
88
+ }
86
89
  }
87
- populate = exists.children;
90
+ populate = childHints;
88
91
  }
89
92
  }
90
93
  return !!populate?.some(p => p.field === prop);
@@ -5,12 +5,15 @@ import type { EntityProperty } from '../typings.js';
5
5
  * This type will automatically convert string values returned from the database to native JS bigints (default)
6
6
  * or numbers (safe only for values up to `Number.MAX_SAFE_INTEGER`), or strings, depending on the `mode`.
7
7
  */
8
- export declare class BigIntType extends Type<string | bigint | number | null | undefined, string | null | undefined> {
9
- mode?: "bigint" | "number" | "string" | undefined;
10
- constructor(mode?: "bigint" | "number" | "string" | undefined);
11
- convertToDatabaseValue(value: string | bigint | null | undefined): string | null | undefined;
12
- convertToJSValue(value: string | bigint | null | undefined): bigint | number | string | null | undefined;
13
- toJSON(value: string | bigint | null | undefined): string | bigint | null | undefined;
8
+ export declare class BigIntType<Mode extends 'bigint' | 'number' | 'string' = 'bigint'> extends Type<JSTypeByMode<Mode> | null | undefined, string | null | undefined> {
9
+ mode?: Mode | undefined;
10
+ constructor(mode?: Mode | undefined);
11
+ convertToDatabaseValue(value: JSTypeByMode<Mode> | null | undefined): string | null | undefined;
12
+ convertToJSValue(value: string | bigint | null | undefined): JSTypeByMode<Mode> | null | undefined;
13
+ toJSON(value: JSTypeByMode<Mode> | null | undefined): JSTypeByMode<Mode> | null | undefined;
14
14
  getColumnType(prop: EntityProperty, platform: Platform): string;
15
15
  compareAsType(): string;
16
+ compareValues(a: string, b: string): boolean;
16
17
  }
18
+ type JSTypeByMode<Mode extends 'bigint' | 'number' | 'string'> = Mode extends 'bigint' ? bigint : Mode extends 'number' ? number : string;
19
+ export {};
@@ -42,4 +42,7 @@ export class BigIntType extends Type {
42
42
  compareAsType() {
43
43
  return this.mode ?? 'bigint';
44
44
  }
45
+ compareValues(a, b) {
46
+ return String(a) === String(b);
47
+ }
45
48
  }
@@ -1,7 +1,7 @@
1
1
  import { Type } from './Type.js';
2
2
  import type { Platform } from '../platforms/Platform.js';
3
3
  import type { EntityProperty } from '../typings.js';
4
- export declare class BooleanType extends Type<number | null | undefined, number | null | undefined> {
4
+ export declare class BooleanType extends Type<boolean | null | undefined, boolean | null | undefined> {
5
5
  getColumnType(prop: EntityProperty, platform: Platform): string;
6
6
  compareAsType(): string;
7
7
  ensureComparable(): boolean;
@@ -4,12 +4,14 @@ import type { EntityProperty } from '../typings.js';
4
4
  /**
5
5
  * Type that maps an SQL DECIMAL to a JS string or number.
6
6
  */
7
- export declare class DecimalType extends Type<string | number, string> {
8
- mode?: "number" | "string" | undefined;
9
- constructor(mode?: "number" | "string" | undefined);
10
- convertToJSValue(value: string): number | string;
7
+ export declare class DecimalType<Mode extends 'number' | 'string' = 'string'> extends Type<JSTypeByMode<Mode>, string> {
8
+ mode?: Mode | undefined;
9
+ constructor(mode?: Mode | undefined);
10
+ convertToJSValue(value: string): JSTypeByMode<Mode>;
11
11
  compareValues(a: string, b: string): boolean;
12
12
  private format;
13
13
  getColumnType(prop: EntityProperty, platform: Platform): string;
14
14
  compareAsType(): string;
15
15
  }
16
+ type JSTypeByMode<Mode extends 'number' | 'string'> = Mode extends 'number' ? number : string;
17
+ export {};
@@ -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();
package/typings.d.ts CHANGED
@@ -28,6 +28,7 @@ export type EntityKey<T = unknown, B extends boolean = false> = string & {
28
28
  [K in keyof T]-?: CleanKeys<T, K, B> extends never ? never : K;
29
29
  }[keyof T];
30
30
  export type EntityValue<T> = T[EntityKey<T>];
31
+ export type EntityDataValue<T> = EntityData<T>[EntityKey<T>];
31
32
  export type FilterKey<T> = keyof FilterQuery<T>;
32
33
  export type AsyncFunction<R = any, T = Dictionary> = (args: T) => Promise<T>;
33
34
  export type Compute<T> = {
@@ -51,18 +52,34 @@ export declare const OptionalProps: unique symbol;
51
52
  export declare const EagerProps: unique symbol;
52
53
  export declare const HiddenProps: unique symbol;
53
54
  export declare const Config: unique symbol;
54
- declare const __optional: unique symbol;
55
- declare const __hidden: unique symbol;
56
- declare const __config: unique symbol;
57
- export type Opt<T = unknown> = T & {
58
- [__optional]?: 1;
59
- };
60
- export type Hidden<T = unknown> = T & {
61
- [__hidden]?: 1;
62
- };
63
- export type DefineConfig<T extends TypeConfig> = T & {
64
- [__config]?: 1;
65
- };
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
+ }
66
83
  export type CleanTypeConfig<T> = Compute<Pick<T, Extract<keyof T, keyof TypeConfig>>>;
67
84
  export interface TypeConfig {
68
85
  forceObject?: boolean;
@@ -77,10 +94,11 @@ export type Primary<T> = IsAny<T> extends true ? any : T extends {
77
94
  } ? (PK extends keyof T ? ReadonlyPrimary<UnwrapPrimary<T[PK]>> : (PK extends (keyof T)[] ? ReadonlyPrimary<PrimaryPropToType<T, PK>> : PK)) : T extends {
78
95
  _id?: infer PK;
79
96
  } ? ReadonlyPrimary<PK> | string : T extends {
80
- uuid?: infer PK;
81
- } ? ReadonlyPrimary<PK> : T extends {
82
97
  id?: infer PK;
98
+ } ? ReadonlyPrimary<PK> : T extends {
99
+ uuid?: infer PK;
83
100
  } ? ReadonlyPrimary<PK> : T;
101
+ /** @internal */
84
102
  export type PrimaryProperty<T> = T extends {
85
103
  [PrimaryKeyProp]?: infer PK;
86
104
  } ? (PK extends keyof T ? PK : (PK extends any[] ? PK[number] : never)) : T extends {
@@ -88,10 +106,10 @@ export type PrimaryProperty<T> = T extends {
88
106
  } ? (T extends {
89
107
  id?: any;
90
108
  } ? 'id' | '_id' : '_id') : T extends {
91
- uuid?: any;
92
- } ? 'uuid' : T extends {
93
109
  id?: any;
94
- } ? 'id' : never;
110
+ } ? 'id' : T extends {
111
+ uuid?: any;
112
+ } ? 'uuid' : never;
95
113
  export type IPrimaryKeyValue = number | string | bigint | Date | {
96
114
  toHexString(): string;
97
115
  };
@@ -176,7 +194,7 @@ export interface IWrappedEntityInternal<Entity extends object> extends IWrappedE
176
194
  __touched: boolean;
177
195
  __originalEntityData?: EntityData<Entity>;
178
196
  __loadedProperties: Set<string>;
179
- __identifier?: EntityIdentifier;
197
+ __identifier?: EntityIdentifier | EntityIdentifier[];
180
198
  __managed: boolean;
181
199
  __processing: boolean;
182
200
  __schema?: string;
@@ -205,7 +223,7 @@ export type EntityName<T> = string | EntityClass<T> | EntitySchema<T, any> | {
205
223
  };
206
224
  export type GetRepository<Entity extends {
207
225
  [k: PropertyKey]: any;
208
- }, 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;
209
227
  export type EntityDataPropValue<T> = T | Primary<T>;
210
228
  type ExpandEntityProp<T, C extends boolean = false> = T extends Record<string, any> ? {
211
229
  [K in keyof T as CleanKeys<T, K>]?: EntityDataProp<ExpandProperty<T[K]>, C> | EntityDataPropValue<ExpandProperty<T[K]>> | null;
@@ -216,14 +234,17 @@ type ExpandRequiredEntityPropObject<T, I = never, C extends boolean = false> = {
216
234
  } & {
217
235
  [K in keyof T as OptionalKeys<T, K, I>]?: RequiredEntityDataProp<ExpandProperty<T[K]>, T, C> | EntityDataPropValue<ExpandProperty<T[K]>> | null | undefined;
218
236
  };
237
+ type NonArrayObject = object & {
238
+ [Symbol.iterator]?: never;
239
+ };
219
240
  export type EntityDataProp<T, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends {
220
241
  __runtime?: infer Runtime;
221
242
  __raw?: infer Raw;
222
- } ? (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>;
223
- 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 {
224
245
  __runtime?: infer Runtime;
225
246
  __raw?: infer Raw;
226
- } ? (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>;
227
248
  export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
228
249
  type EntityDataItem<T, C extends boolean> = C extends false ? T | EntityDataProp<T, C> | null : EntityDataProp<T, C> | null;
229
250
  export type RequiredEntityDataNested<T, O, C extends boolean> = T extends any[] ? Readonly<T> : RequiredEntityData<T, O> | ExpandRequiredEntityProp<T, O, C>;
@@ -235,12 +256,15 @@ type ExplicitlyOptionalProps<T> = (T extends {
235
256
  type NullableKeys<T, V = null> = {
236
257
  [K in keyof T]: V extends T[K] ? K : never;
237
258
  }[keyof T];
238
- 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>>;
239
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;
240
264
  type RequiredKeys<T, K extends keyof T, I> = IsOptional<T, K, I> extends false ? CleanKeys<T, K> : never;
241
265
  type OptionalKeys<T, K extends keyof T, I> = IsOptional<T, K, I> extends false ? never : CleanKeys<T, K>;
242
266
  export type EntityData<T, C extends boolean = false> = {
243
- [K in EntityKey<T>]?: EntityDataItem<T[K], C>;
267
+ [K in EntityKey<T>]?: EntityDataItem<T[K] & {}, C>;
244
268
  };
245
269
  export type RequiredEntityData<T, I = never, C extends boolean = false> = {
246
270
  [K in keyof T as RequiredKeys<T, K, I>]: T[K] | RequiredEntityDataProp<T[K], T, C> | Primary<T[K]>;
@@ -282,7 +306,7 @@ type PrimaryOrObject<T, U, C extends TypeConfig> = PreferExplicitConfig<C, Extra
282
306
  } : Primary<U>;
283
307
  export type EntityDTOProp<E, T, C extends TypeConfig = never> = T extends Scalar ? T : T extends {
284
308
  __serialized?: infer U;
285
- } ? 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;
286
310
  type DTOProbablyOptionalProps<T> = NonNullable<NullableKeys<T, undefined>>;
287
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;
288
312
  type DTORequiredKeys<T, K extends keyof T> = DTOIsOptional<T, K> extends false ? ExcludeHidden<T, K> & CleanKeys<T, K> : never;
@@ -292,7 +316,15 @@ export type EntityDTO<T, C extends TypeConfig = never> = {
292
316
  } & {
293
317
  [K in keyof T as DTOOptionalKeys<T, K>]?: EntityDTOProp<T, T[K], C> | AddOptional<T[K]>;
294
318
  };
295
- export type CheckCallback<T> = (columns: Record<keyof 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;
296
328
  export type GeneratedColumnCallback<T> = (columns: Record<keyof T, string>) => string;
297
329
  export interface CheckConstraint<T = any> {
298
330
  name?: string;
@@ -388,6 +420,8 @@ export interface EntityProperty<Owner = any, Target = any> {
388
420
  optional?: boolean;
389
421
  ignoreSchemaChanges?: ('type' | 'extra' | 'default')[];
390
422
  deferMode?: DeferMode;
423
+ createForeignKeyConstraint: boolean;
424
+ foreignKeyName?: string;
391
425
  }
392
426
  export declare class EntityMetadata<T = any> {
393
427
  private static counter;
@@ -396,8 +430,9 @@ export declare class EntityMetadata<T = any> {
396
430
  constructor(meta?: Partial<EntityMetadata>);
397
431
  addProperty(prop: Partial<EntityProperty<T>>, sync?: boolean): void;
398
432
  removeProperty(name: string, sync?: boolean): void;
399
- getPrimaryProps(): EntityProperty<T>[];
433
+ getPrimaryProps(flatten?: boolean): EntityProperty<T>[];
400
434
  getPrimaryProp(): EntityProperty<T>;
435
+ createColumnMappingObject(): Dictionary<any>;
401
436
  get tableName(): string;
402
437
  set tableName(name: string);
403
438
  sync(initIndexes?: boolean, config?: Configuration): void;
@@ -416,7 +451,7 @@ export interface EntityMetadata<T = any> {
416
451
  schema?: string;
417
452
  pivotTable?: boolean;
418
453
  virtual?: boolean;
419
- expression?: string | ((em: any, where: FilterQuery<T>, options: FindOptions<T, any, any, any>) => MaybePromise<RawQueryFragment | object | string>);
454
+ expression?: string | ((em: any, where: ObjectQuery<T>, options: FindOptions<T, any, any, any>) => MaybePromise<RawQueryFragment | object | string>);
420
455
  discriminatorColumn?: EntityKey<T> | AnyString;
421
456
  discriminatorValue?: number | string;
422
457
  discriminatorMap?: Dictionary<string>;
@@ -449,18 +484,18 @@ export interface EntityMetadata<T = any> {
449
484
  uniqueProps: EntityProperty<T>[];
450
485
  getterProps: EntityProperty<T>[];
451
486
  indexes: {
452
- properties: EntityKey<T> | EntityKey<T>[];
487
+ properties?: EntityKey<T> | EntityKey<T>[];
453
488
  name?: string;
454
489
  type?: string;
455
490
  options?: Dictionary;
456
- expression?: string;
491
+ expression?: string | IndexCallback<T>;
457
492
  }[];
458
493
  uniques: {
459
- properties: EntityKey<T> | EntityKey<T>[];
494
+ properties?: EntityKey<T> | EntityKey<T>[];
460
495
  name?: string;
461
496
  options?: Dictionary;
462
- expression?: string;
463
- deferMode?: DeferMode;
497
+ expression?: string | IndexCallback<T>;
498
+ deferMode?: DeferMode | `${DeferMode}`;
464
499
  }[];
465
500
  checks: CheckConstraint<T>[];
466
501
  repositoryClass?: string;
@@ -479,6 +514,7 @@ export interface EntityMetadata<T = any> {
479
514
  polymorphs?: EntityMetadata[];
480
515
  root: EntityMetadata<T>;
481
516
  definedProperties: Dictionary;
517
+ hasTriggers?: boolean;
482
518
  /** @internal can be used for computed numeric cache keys */
483
519
  readonly _id: number;
484
520
  }
@@ -681,7 +717,7 @@ export interface MigrationObject {
681
717
  }
682
718
  export type FilterDef = {
683
719
  name: string;
684
- cond: Dictionary | ((args: Dictionary, type: 'read' | 'update' | 'delete', em: any, options?: FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any>) => Dictionary | Promise<Dictionary>);
720
+ cond: Dictionary | ((args: Dictionary, type: 'read' | 'update' | 'delete', em: any, options?: FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any>, entityName?: EntityName<any>) => Dictionary | Promise<Dictionary>);
685
721
  default?: boolean;
686
722
  entity?: string[];
687
723
  args?: boolean;
@@ -692,6 +728,7 @@ export type PopulateOptions<T> = {
692
728
  strategy?: LoadStrategy;
693
729
  all?: boolean;
694
730
  filter?: boolean;
731
+ joinType?: 'inner join' | 'left join';
695
732
  children?: PopulateOptions<T[keyof T]>[];
696
733
  };
697
734
  type Loadable<T extends object> = Collection<T, any> | Reference<T> | Ref<T> | readonly T[];
@@ -726,7 +763,7 @@ export type MergeSelected<T, U, F extends string> = T extends Loaded<infer TT, i
726
763
  type MergeFields<F1 extends string, F2 extends string, P1, P2> = P1 | P2 extends '*' ? '*' : F1 | F2;
727
764
  type MergeExcludes<F extends string, E extends string> = F extends E ? never : Exclude<E, F>;
728
765
  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>;
729
- type AddOptional<T> = undefined | null extends T ? null | undefined : null extends T ? null : undefined extends T ? undefined : never;
766
+ export type AddOptional<T> = undefined | null extends T ? null | undefined : null extends T ? null : undefined extends T ? undefined : never;
730
767
  type LoadedProp<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedLoadable<T, Loaded<ExtractType<T>, L, F, E>>;
731
768
  export type AddEager<T> = ExtractEagerProps<T> & string;
732
769
  export type ExpandHint<T, L extends string> = L | AddEager<T>;
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;