@mikro-orm/core 7.0.0-rc.2 → 7.0.0

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 (114) hide show
  1. package/EntityManager.d.ts +4 -16
  2. package/EntityManager.js +248 -181
  3. package/MikroORM.d.ts +4 -6
  4. package/MikroORM.js +24 -24
  5. package/README.md +5 -4
  6. package/cache/FileCacheAdapter.d.ts +1 -5
  7. package/cache/FileCacheAdapter.js +22 -24
  8. package/cache/GeneratedCacheAdapter.d.ts +1 -1
  9. package/cache/GeneratedCacheAdapter.js +6 -6
  10. package/cache/MemoryCacheAdapter.d.ts +1 -2
  11. package/cache/MemoryCacheAdapter.js +8 -8
  12. package/cache/index.d.ts +1 -1
  13. package/cache/index.js +0 -1
  14. package/connections/Connection.d.ts +1 -0
  15. package/connections/Connection.js +43 -14
  16. package/drivers/DatabaseDriver.d.ts +0 -2
  17. package/drivers/DatabaseDriver.js +28 -12
  18. package/drivers/IDatabaseDriver.d.ts +43 -0
  19. package/entity/Collection.d.ts +1 -9
  20. package/entity/Collection.js +124 -108
  21. package/entity/EntityAssigner.js +23 -11
  22. package/entity/EntityFactory.d.ts +1 -8
  23. package/entity/EntityFactory.js +79 -59
  24. package/entity/EntityHelper.js +25 -16
  25. package/entity/EntityLoader.d.ts +1 -3
  26. package/entity/EntityLoader.js +90 -60
  27. package/entity/Reference.d.ts +2 -3
  28. package/entity/Reference.js +48 -19
  29. package/entity/WrappedEntity.d.ts +4 -2
  30. package/entity/WrappedEntity.js +5 -1
  31. package/entity/defineEntity.d.ts +42 -85
  32. package/entity/utils.js +28 -26
  33. package/entity/validators.js +2 -1
  34. package/enums.d.ts +2 -1
  35. package/enums.js +13 -17
  36. package/errors.d.ts +11 -11
  37. package/errors.js +8 -8
  38. package/events/EventManager.d.ts +1 -4
  39. package/events/EventManager.js +26 -23
  40. package/events/index.d.ts +1 -1
  41. package/events/index.js +0 -1
  42. package/exceptions.js +9 -2
  43. package/hydration/ObjectHydrator.d.ts +1 -2
  44. package/hydration/ObjectHydrator.js +41 -27
  45. package/index.d.ts +1 -1
  46. package/index.js +1 -1
  47. package/logging/DefaultLogger.js +6 -7
  48. package/logging/Logger.d.ts +2 -1
  49. package/logging/colors.js +2 -5
  50. package/logging/index.d.ts +1 -1
  51. package/logging/index.js +0 -1
  52. package/metadata/EntitySchema.d.ts +3 -3
  53. package/metadata/EntitySchema.js +12 -2
  54. package/metadata/MetadataDiscovery.d.ts +1 -9
  55. package/metadata/MetadataDiscovery.js +251 -179
  56. package/metadata/MetadataProvider.js +26 -1
  57. package/metadata/MetadataStorage.d.ts +1 -5
  58. package/metadata/MetadataStorage.js +37 -39
  59. package/metadata/MetadataValidator.js +20 -5
  60. package/metadata/discover-entities.js +1 -1
  61. package/metadata/index.d.ts +1 -1
  62. package/metadata/index.js +0 -1
  63. package/metadata/types.d.ts +2 -2
  64. package/naming-strategy/AbstractNamingStrategy.js +6 -3
  65. package/naming-strategy/EntityCaseNamingStrategy.js +1 -1
  66. package/naming-strategy/index.d.ts +1 -1
  67. package/naming-strategy/index.js +0 -1
  68. package/not-supported.js +5 -1
  69. package/package.json +38 -38
  70. package/platforms/Platform.d.ts +24 -1
  71. package/platforms/Platform.js +106 -27
  72. package/serialization/EntitySerializer.js +8 -4
  73. package/serialization/EntityTransformer.js +4 -1
  74. package/serialization/SerializationContext.d.ts +4 -8
  75. package/serialization/SerializationContext.js +21 -16
  76. package/types/UuidType.d.ts +2 -0
  77. package/types/UuidType.js +14 -2
  78. package/types/index.d.ts +2 -1
  79. package/typings.d.ts +35 -24
  80. package/typings.js +9 -9
  81. package/unit-of-work/ChangeSet.js +4 -4
  82. package/unit-of-work/ChangeSetComputer.d.ts +1 -6
  83. package/unit-of-work/ChangeSetComputer.js +29 -27
  84. package/unit-of-work/ChangeSetPersister.d.ts +1 -9
  85. package/unit-of-work/ChangeSetPersister.js +63 -58
  86. package/unit-of-work/CommitOrderCalculator.d.ts +1 -4
  87. package/unit-of-work/CommitOrderCalculator.js +17 -15
  88. package/unit-of-work/IdentityMap.d.ts +2 -5
  89. package/unit-of-work/IdentityMap.js +18 -18
  90. package/unit-of-work/UnitOfWork.d.ts +12 -20
  91. package/unit-of-work/UnitOfWork.js +228 -191
  92. package/utils/AbstractMigrator.d.ts +2 -2
  93. package/utils/AbstractMigrator.js +10 -12
  94. package/utils/AbstractSchemaGenerator.js +2 -1
  95. package/utils/AsyncContext.js +1 -1
  96. package/utils/Configuration.d.ts +90 -189
  97. package/utils/Configuration.js +97 -77
  98. package/utils/Cursor.d.ts +3 -3
  99. package/utils/Cursor.js +8 -6
  100. package/utils/DataloaderUtils.js +15 -12
  101. package/utils/EntityComparator.d.ts +8 -15
  102. package/utils/EntityComparator.js +100 -92
  103. package/utils/QueryHelper.d.ts +16 -1
  104. package/utils/QueryHelper.js +108 -50
  105. package/utils/RawQueryFragment.d.ts +4 -4
  106. package/utils/RawQueryFragment.js +3 -2
  107. package/utils/TransactionManager.js +3 -3
  108. package/utils/Utils.d.ts +2 -2
  109. package/utils/Utils.js +39 -32
  110. package/utils/clone.js +5 -0
  111. package/utils/env-vars.js +6 -5
  112. package/utils/fs-utils.d.ts +3 -17
  113. package/utils/fs-utils.js +2 -5
  114. package/utils/upsert-utils.js +7 -4
@@ -3,7 +3,7 @@ import { EntityRepository } from '../entity/EntityRepository.js';
3
3
  import { UnderscoreNamingStrategy } from '../naming-strategy/UnderscoreNamingStrategy.js';
4
4
  import { ExceptionConverter } from './ExceptionConverter.js';
5
5
  import { ArrayType, BigIntType, BlobType, BooleanType, CharacterType, DateTimeType, DateType, DecimalType, DoubleType, EnumType, FloatType, IntegerType, IntervalType, JsonType, MediumIntType, SmallIntType, StringType, TextType, TimeType, TinyIntType, Type, Uint8ArrayType, UnknownType, UuidType, } from '../types/index.js';
6
- import { parseJsonSafe } from '../utils/Utils.js';
6
+ import { parseJsonSafe, Utils } from '../utils/Utils.js';
7
7
  import { ReferenceKind } from '../enums.js';
8
8
  import { Raw } from '../utils/RawQueryFragment.js';
9
9
  export const JsonProperty = Symbol('JsonProperty');
@@ -104,6 +104,11 @@ export class Platform {
104
104
  getRegExpOperator(val, flags) {
105
105
  return 'regexp';
106
106
  }
107
+ mapRegExpCondition(mappedKey, value) {
108
+ const operator = this.getRegExpOperator(value.$re, value.$flags);
109
+ const quotedKey = this.quoteIdentifier(mappedKey);
110
+ return { sql: `${quotedKey} ${operator} ?`, params: [value.$re] };
111
+ }
107
112
  getRegExpValue(val) {
108
113
  if (val.flags.includes('i')) {
109
114
  return { $re: `(?i)${val.source}` };
@@ -156,7 +161,7 @@ export class Platform {
156
161
  return 'interval' + (column.length ? `(${column.length})` : '');
157
162
  }
158
163
  getTextTypeDeclarationSQL(_column) {
159
- return `text`;
164
+ return 'text';
160
165
  }
161
166
  getEnumTypeDeclarationSQL(column) {
162
167
  if (column.items?.every(item => typeof item === 'string')) {
@@ -180,7 +185,7 @@ export class Platform {
180
185
  return this.getVarcharTypeDeclarationSQL(column);
181
186
  }
182
187
  extractSimpleType(type) {
183
- return type.toLowerCase().match(/[^(), ]+/)[0];
188
+ return /[^(), ]+/.exec(type.toLowerCase())[0];
184
189
  }
185
190
  /**
186
191
  * This should be used only to compare types, it can strip some information like the length.
@@ -198,43 +203,76 @@ export class Platform {
198
203
  }
199
204
  switch (this.extractSimpleType(type)) {
200
205
  case 'character':
201
- case 'char': return Type.getType(CharacterType);
206
+ case 'char':
207
+ return Type.getType(CharacterType);
202
208
  case 'string':
203
- case 'varchar': return Type.getType(StringType);
204
- case 'interval': return Type.getType(IntervalType);
205
- case 'text': return Type.getType(TextType);
209
+ case 'varchar':
210
+ return Type.getType(StringType);
211
+ case 'interval':
212
+ return Type.getType(IntervalType);
213
+ case 'text':
214
+ return Type.getType(TextType);
206
215
  case 'int':
207
- case 'number': return Type.getType(IntegerType);
208
- case 'bigint': return Type.getType(BigIntType);
209
- case 'smallint': return Type.getType(SmallIntType);
210
- case 'tinyint': return Type.getType(TinyIntType);
211
- case 'mediumint': return Type.getType(MediumIntType);
212
- case 'float': return Type.getType(FloatType);
213
- case 'double': return Type.getType(DoubleType);
214
- case 'integer': return Type.getType(IntegerType);
216
+ case 'number':
217
+ return Type.getType(IntegerType);
218
+ case 'bigint':
219
+ return Type.getType(BigIntType);
220
+ case 'smallint':
221
+ return Type.getType(SmallIntType);
222
+ case 'tinyint':
223
+ return Type.getType(TinyIntType);
224
+ case 'mediumint':
225
+ return Type.getType(MediumIntType);
226
+ case 'float':
227
+ return Type.getType(FloatType);
228
+ case 'double':
229
+ return Type.getType(DoubleType);
230
+ case 'integer':
231
+ return Type.getType(IntegerType);
215
232
  case 'decimal':
216
- case 'numeric': return Type.getType(DecimalType);
217
- case 'boolean': return Type.getType(BooleanType);
233
+ case 'numeric':
234
+ return Type.getType(DecimalType);
235
+ case 'boolean':
236
+ return Type.getType(BooleanType);
218
237
  case 'blob':
219
- case 'buffer': return Type.getType(BlobType);
220
- case 'uint8array': return Type.getType(Uint8ArrayType);
221
- case 'uuid': return Type.getType(UuidType);
222
- case 'date': return Type.getType(DateType);
238
+ case 'buffer':
239
+ return Type.getType(BlobType);
240
+ case 'uint8array':
241
+ return Type.getType(Uint8ArrayType);
242
+ case 'uuid':
243
+ return Type.getType(UuidType);
244
+ case 'date':
245
+ return Type.getType(DateType);
223
246
  case 'datetime':
224
- case 'timestamp': return Type.getType(DateTimeType);
225
- case 'time': return Type.getType(TimeType);
247
+ case 'timestamp':
248
+ return Type.getType(DateTimeType);
249
+ case 'time':
250
+ return Type.getType(TimeType);
226
251
  case 'object':
227
- case 'json': return Type.getType(JsonType);
228
- case 'enum': return Type.getType(EnumType);
229
- default: return Type.getType(UnknownType);
252
+ case 'json':
253
+ return Type.getType(JsonType);
254
+ case 'enum':
255
+ return Type.getType(EnumType);
256
+ default:
257
+ return Type.getType(UnknownType);
230
258
  }
231
259
  }
232
260
  supportsMultipleCascadePaths() {
233
261
  return true;
234
262
  }
263
+ /**
264
+ * Returns true if the platform supports ON UPDATE foreign key rules.
265
+ * Oracle doesn't support ON UPDATE rules.
266
+ */
267
+ supportsOnUpdate() {
268
+ return true;
269
+ }
235
270
  supportsMultipleStatements() {
236
271
  return this.config.get('multipleStatements');
237
272
  }
273
+ supportsUnionWhere() {
274
+ return false;
275
+ }
238
276
  getArrayDeclarationSQL() {
239
277
  return 'text';
240
278
  }
@@ -259,6 +297,31 @@ export class Platform {
259
297
  getSearchJsonPropertyKey(path, type, aliased, value) {
260
298
  return path.join('.');
261
299
  }
300
+ processJsonCondition(o, value, path, alias) {
301
+ if (Utils.isPlainObject(value) && !Object.keys(value).some(k => Utils.isOperator(k))) {
302
+ Utils.keys(value).forEach(k => {
303
+ this.processJsonCondition(o, value[k], [...path, k], alias);
304
+ });
305
+ return o;
306
+ }
307
+ if (path.length === 1) {
308
+ o[path[0]] = value;
309
+ return o;
310
+ }
311
+ const type = this.getJsonValueType(value);
312
+ const k = this.getSearchJsonPropertyKey(path, type, alias, value);
313
+ o[k] = value;
314
+ return o;
315
+ }
316
+ getJsonValueType(value) {
317
+ if (Array.isArray(value)) {
318
+ return typeof value[0];
319
+ }
320
+ if (Utils.isPlainObject(value) && Object.keys(value).every(k => Utils.isOperator(k))) {
321
+ return this.getJsonValueType(Object.values(value)[0]);
322
+ }
323
+ return typeof value;
324
+ }
262
325
  /* v8 ignore next */
263
326
  getJsonIndexDefinition(index) {
264
327
  return index.columnNames;
@@ -290,6 +353,22 @@ export class Platform {
290
353
  convertIntervalToDatabaseValue(value) {
291
354
  return value;
292
355
  }
356
+ usesAsKeyword() {
357
+ return true;
358
+ }
359
+ /**
360
+ * Determines how UUID values are compared in the change set tracking.
361
+ * Return `'string'` for inline string comparison (fast), or `'any'` for deep comparison via type methods.
362
+ */
363
+ compareUuids() {
364
+ return 'string';
365
+ }
366
+ convertUuidToJSValue(value) {
367
+ return value;
368
+ }
369
+ convertUuidToDatabaseValue(value) {
370
+ return value;
371
+ }
293
372
  parseDate(value) {
294
373
  const date = new Date(value);
295
374
  /* v8 ignore next */
@@ -354,7 +433,7 @@ export class Platform {
354
433
  let j = 0;
355
434
  let pos = 0;
356
435
  let ret = '';
357
- if (sql[0] === '?') {
436
+ if (sql.startsWith('?')) {
358
437
  if (sql[1] === '?') {
359
438
  ret += this.quoteIdentifier(params[j++]);
360
439
  pos = 2;
@@ -9,7 +9,8 @@ function isVisible(meta, propName, options) {
9
9
  if (options.groups && prop?.groups) {
10
10
  return prop.groups.some(g => options.groups.includes(g));
11
11
  }
12
- if (Array.isArray(options.populate) && options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
12
+ if (Array.isArray(options.populate) &&
13
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
13
14
  return true;
14
15
  }
15
16
  if (options.exclude?.find(item => item === propName)) {
@@ -20,7 +21,8 @@ function isVisible(meta, propName, options) {
20
21
  return visible && !prefixed;
21
22
  }
22
23
  function isPopulated(propName, options) {
23
- if (typeof options.populate !== 'boolean' && options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
24
+ if (typeof options.populate !== 'boolean' &&
25
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
24
26
  return true;
25
27
  }
26
28
  if (typeof options.populate === 'boolean') {
@@ -34,7 +36,7 @@ export class EntitySerializer {
34
36
  const meta = wrapped.__meta;
35
37
  let contextCreated = false;
36
38
  if (!wrapped.__serializationContext.root) {
37
- const root = new SerializationContext(wrapped.__config);
39
+ const root = new SerializationContext();
38
40
  SerializationContext.propagate(root, entity, (meta, prop) => meta.properties[prop]?.kind !== ReferenceKind.SCALAR);
39
41
  options.populate = (options.populate ? Utils.asArray(options.populate) : options.populate);
40
42
  contextCreated = true;
@@ -176,7 +178,9 @@ export class EntitySerializer {
176
178
  static extractChildOptions(options, prop) {
177
179
  return {
178
180
  ...options,
179
- populate: Array.isArray(options.populate) ? Utils.extractChildElements(options.populate, prop, '*') : options.populate,
181
+ populate: Array.isArray(options.populate)
182
+ ? Utils.extractChildElements(options.populate, prop, '*')
183
+ : options.populate,
180
184
  exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop) : options.exclude,
181
185
  };
182
186
  }
@@ -20,7 +20,7 @@ export class EntityTransformer {
20
20
  return entity;
21
21
  }
22
22
  if (!wrapped.__serializationContext.root) {
23
- const root = new SerializationContext(wrapped.__config, wrapped.__serializationContext.populate, wrapped.__serializationContext.fields, wrapped.__serializationContext.exclude);
23
+ const root = new SerializationContext(wrapped.__serializationContext.populate, wrapped.__serializationContext.fields, wrapped.__serializationContext.exclude);
24
24
  SerializationContext.propagate(root, entity, isVisible);
25
25
  contextCreated = true;
26
26
  }
@@ -64,6 +64,9 @@ export class EntityTransformer {
64
64
  if (!partiallyLoaded && !populated && !isPrimary) {
65
65
  continue;
66
66
  }
67
+ if (root.isExcluded(meta.class, prop) && !populated) {
68
+ continue;
69
+ }
67
70
  }
68
71
  const cycle = root.visit(meta.class, prop);
69
72
  if (cycle && visited) {
@@ -1,19 +1,14 @@
1
1
  import type { AnyEntity, EntityMetadata, EntityName, PopulateOptions } from '../typings.js';
2
- import type { Configuration } from '../utils/Configuration.js';
3
2
  /**
4
3
  * Helper that allows to keep track of where we are currently at when serializing complex entity graph with cycles.
5
4
  * Before we process a property, we call `visit` that checks if it is not a cycle path (but allows to pass cycles that
6
5
  * are defined in populate hint). If not, we proceed and call `leave` afterwards.
7
6
  */
8
7
  export declare class SerializationContext<T extends object> {
9
- private readonly config;
10
- private readonly populate;
11
- private readonly fields?;
12
- private readonly exclude?;
8
+ #private;
13
9
  readonly path: [EntityName, string][];
14
- readonly visited: Set<Partial<any>>;
15
- private entities;
16
- constructor(config: Configuration, populate?: PopulateOptions<T>[], fields?: Set<string> | undefined, exclude?: string[] | undefined);
10
+ readonly visited: Set<AnyEntity>;
11
+ constructor(populate?: PopulateOptions<T>[], fields?: Set<string>, exclude?: readonly string[]);
17
12
  /**
18
13
  * Returns true when there is a cycle detected.
19
14
  */
@@ -25,6 +20,7 @@ export declare class SerializationContext<T extends object> {
25
20
  */
26
21
  static propagate(root: SerializationContext<any>, entity: AnyEntity, isVisible: (meta: EntityMetadata, prop: string) => boolean): void;
27
22
  isMarkedAsPopulated(entityName: EntityName, prop: string): boolean;
23
+ isExcluded(entityName: EntityName, prop: string): boolean;
28
24
  isPartiallyLoaded(entityName: EntityName, prop: string): boolean;
29
25
  private register;
30
26
  }
@@ -6,18 +6,16 @@ import { helper } from '../entity/wrap.js';
6
6
  * are defined in populate hint). If not, we proceed and call `leave` afterwards.
7
7
  */
8
8
  export class SerializationContext {
9
- config;
10
- populate;
11
- fields;
12
- exclude;
13
9
  path = [];
14
10
  visited = new Set();
15
- entities = new Set();
16
- constructor(config, populate = [], fields, exclude) {
17
- this.config = config;
18
- this.populate = populate;
19
- this.fields = fields;
20
- this.exclude = exclude;
11
+ #entities = new Set();
12
+ #populate;
13
+ #fields;
14
+ #exclude;
15
+ constructor(populate = [], fields, exclude) {
16
+ this.#populate = populate;
17
+ this.#fields = fields;
18
+ this.#exclude = exclude;
21
19
  }
22
20
  /**
23
21
  * Returns true when there is a cycle detected.
@@ -42,7 +40,7 @@ export class SerializationContext {
42
40
  }
43
41
  }
44
42
  close() {
45
- for (const entity of this.entities) {
43
+ for (const entity of this.#entities) {
46
44
  delete helper(entity).__serializationContext.root;
47
45
  }
48
46
  }
@@ -73,7 +71,7 @@ export class SerializationContext {
73
71
  }
74
72
  }
75
73
  isMarkedAsPopulated(entityName, prop) {
76
- let populate = this.populate ?? [];
74
+ let populate = this.#populate ?? [];
77
75
  for (const segment of this.path) {
78
76
  const hints = populate.filter(p => p.field === segment[1]);
79
77
  if (hints.length > 0) {
@@ -92,11 +90,18 @@ export class SerializationContext {
92
90
  }
93
91
  return !!populate?.some(p => p.field === prop);
94
92
  }
93
+ isExcluded(entityName, prop) {
94
+ if (!this.#exclude || this.#exclude.length === 0) {
95
+ return false;
96
+ }
97
+ const fullPath = this.path.map(segment => segment[1] + '.').join('') + prop;
98
+ return this.#exclude.includes(fullPath);
99
+ }
95
100
  isPartiallyLoaded(entityName, prop) {
96
- if (!this.fields) {
101
+ if (!this.#fields) {
97
102
  return true;
98
103
  }
99
- let fields = [...this.fields];
104
+ let fields = [...this.#fields];
100
105
  for (const segment of this.path) {
101
106
  /* v8 ignore next */
102
107
  if (fields.length === 0) {
@@ -104,12 +109,12 @@ export class SerializationContext {
104
109
  }
105
110
  fields = fields
106
111
  .filter(field => field.startsWith(`${segment[1]}.`) || field === '*')
107
- .map(field => field === '*' ? field : field.substring(segment[1].length + 1));
112
+ .map(field => (field === '*' ? field : field.substring(segment[1].length + 1)));
108
113
  }
109
114
  return fields.some(p => p === prop || p === '*');
110
115
  }
111
116
  register(entity) {
112
117
  helper(entity).__serializationContext.root = this;
113
- this.entities.add(entity);
118
+ this.#entities.add(entity);
114
119
  }
115
120
  }
@@ -4,5 +4,7 @@ import type { EntityProperty } from '../typings.js';
4
4
  export declare class UuidType extends Type<string | null | undefined> {
5
5
  getColumnType(prop: EntityProperty, platform: Platform): string;
6
6
  compareAsType(): string;
7
+ convertToDatabaseValue(value: string | null | undefined, platform: Platform): string | null;
8
+ convertToJSValue(value: string | null | undefined, platform: Platform): string | null | undefined;
7
9
  ensureComparable(): boolean;
8
10
  }
package/types/UuidType.js CHANGED
@@ -4,9 +4,21 @@ export class UuidType extends Type {
4
4
  return platform.getUuidTypeDeclarationSQL(prop);
5
5
  }
6
6
  compareAsType() {
7
- return 'string';
7
+ return this.platform?.compareUuids() ?? 'string';
8
+ }
9
+ convertToDatabaseValue(value, platform) {
10
+ if (value == null) {
11
+ return value;
12
+ }
13
+ return platform.convertUuidToDatabaseValue(value);
14
+ }
15
+ convertToJSValue(value, platform) {
16
+ if (value == null) {
17
+ return value;
18
+ }
19
+ return platform.convertUuidToJSValue(value);
8
20
  }
9
21
  ensureComparable() {
10
- return false;
22
+ return this.platform?.compareUuids() !== 'string';
11
23
  }
12
24
  }
package/types/index.d.ts CHANGED
@@ -23,7 +23,8 @@ 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';
26
- export { Type, DateType, TimeType, DateTimeType, BigIntType, BlobType, Uint8ArrayType, ArrayType, EnumArrayType, EnumType, JsonType, IntegerType, SmallIntType, TinyIntType, MediumIntType, FloatType, DoubleType, BooleanType, DecimalType, StringType, UuidType, TextType, UnknownType, TransformContext, IntervalType, IType, CharacterType, };
26
+ export type { TransformContext, IType };
27
+ export { Type, DateType, TimeType, DateTimeType, BigIntType, BlobType, Uint8ArrayType, ArrayType, EnumArrayType, EnumType, JsonType, IntegerType, SmallIntType, TinyIntType, MediumIntType, FloatType, DoubleType, BooleanType, DecimalType, StringType, UuidType, TextType, UnknownType, IntervalType, CharacterType, };
27
28
  export declare const types: {
28
29
  readonly date: typeof DateType;
29
30
  readonly time: typeof TimeType;
package/typings.d.ts CHANGED
@@ -36,11 +36,11 @@ export type Compute<T> = {
36
36
  [K in keyof T]: T[K];
37
37
  } & {};
38
38
  type InternalKeys = 'EntityRepositoryType' | 'PrimaryKeyProp' | 'OptionalProps' | 'EagerProps' | 'HiddenProps' | '__selectedType' | '__loadedType';
39
- export type CleanKeys<T, K extends keyof T, B extends boolean = false> = (T[K] & {}) extends Function ? never : K extends symbol | InternalKeys ? never : B extends true ? (T[K] & {}) extends Scalar ? never : K : K;
39
+ export type CleanKeys<T, K extends keyof T, B extends boolean = false> = T[K] & {} extends Function ? never : K extends symbol | InternalKeys ? never : B extends true ? T[K] & {} extends Scalar ? never : K : K;
40
40
  export type FunctionKeys<T, K extends keyof T> = T[K] extends Function ? K : never;
41
41
  export type Cast<T, R> = T extends R ? T : R;
42
- export type IsUnknown<T> = T extends unknown ? unknown extends T ? true : never : never;
43
- export type IsAny<T> = 0 extends (1 & T) ? true : false;
42
+ export type IsUnknown<T> = T extends unknown ? (unknown extends T ? true : never) : never;
43
+ export type IsAny<T> = 0 extends 1 & T ? true : false;
44
44
  export type IsNever<T, True = true, False = false> = [T] extends [never] ? True : False;
45
45
  export type MaybePromise<T> = T | Promise<T>;
46
46
  /**
@@ -98,9 +98,9 @@ type LoadableShape = CollectionShape | ReferenceShape | readonly any[];
98
98
  export type UnionKeys<T> = T extends any ? keyof T : never;
99
99
  export type UnionPropertyType<T, K extends PropertyKey> = T extends any ? (K extends keyof T ? T[K] : never) : never;
100
100
  type IsUnion<T, U = T> = T extends any ? ([U] extends [T] ? false : true) : false;
101
- export type MergeUnion<T> = [T] extends [object] ? (T extends Scalar ? T : IsUnion<T> extends true ? {
101
+ export type MergeUnion<T> = [T] extends [object] ? T extends Scalar ? T : IsUnion<T> extends true ? {
102
102
  [K in UnionKeys<T>]: UnionPropertyType<T, K>;
103
- } : T) : T;
103
+ } : T : T;
104
104
  export type DeepPartial<T> = T & {
105
105
  [P in keyof T]?: T[P] extends (infer U)[] ? DeepPartial<U>[] : T[P] extends Readonly<infer U>[] ? Readonly<DeepPartial<U>>[] : DeepPartial<T[P]>;
106
106
  };
@@ -113,7 +113,7 @@ export declare const Config: unique symbol;
113
113
  export declare const EntityName: unique symbol;
114
114
  export type InferEntityName<T> = T extends {
115
115
  [EntityName]?: infer Name;
116
- } ? Name extends string ? Name : never : never;
116
+ } ? (Name extends string ? Name : never) : never;
117
117
  export type Opt<T = unknown> = T & Opt.Brand;
118
118
  export declare namespace Opt {
119
119
  const __optional: unique symbol;
@@ -173,11 +173,11 @@ export type Primary<T> = IsAny<T> extends true ? any : T extends {
173
173
  /** @internal */
174
174
  export type PrimaryProperty<T> = T extends {
175
175
  [PrimaryKeyProp]?: infer PK;
176
- } ? (PK extends keyof T ? PK : (PK extends any[] ? PK[number] : never)) : T extends {
176
+ } ? PK extends keyof T ? PK : PK extends any[] ? PK[number] : never : T extends {
177
177
  _id?: any;
178
- } ? (T extends {
178
+ } ? T extends {
179
179
  id?: any;
180
- } ? 'id' | '_id' : '_id') : T extends {
180
+ } ? 'id' | '_id' : '_id' : T extends {
181
181
  id?: any;
182
182
  } ? 'id' : T extends {
183
183
  uuid?: any;
@@ -234,10 +234,20 @@ export type FilterItemValue<T> = T | ExpandScalar<T> | Primary<T> | Raw;
234
234
  export type FilterValue<T> = OperatorMap<FilterItemValue<T>> | FilterItemValue<T> | FilterItemValue<T>[] | null;
235
235
  type FilterObjectProp<T, K extends PropertyKey> = K extends keyof MergeUnion<T> ? MergeUnion<T>[K] : K extends keyof T ? T[K] : never;
236
236
  type ExpandQueryMerged<T> = [T] extends [object] ? [T] extends [Scalar] ? never : FilterQuery<MergeUnion<T>> : FilterValue<T>;
237
+ type ElemMatchCondition<T extends Record<string, any>> = {
238
+ [K in keyof T]?: T[K] | OperatorMap<T[K]>;
239
+ } & {
240
+ $or?: ElemMatchCondition<T>[];
241
+ $and?: ElemMatchCondition<T>[];
242
+ $not?: ElemMatchCondition<T>;
243
+ };
244
+ type ElemMatchFilter<T> = T extends readonly (infer E)[] ? E extends Record<string, any> ? {
245
+ $elemMatch: ElemMatchCondition<E>;
246
+ } : never : never;
237
247
  export type FilterObject<T> = {
238
- -readonly [K in EntityKey<T>]?: ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>> | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>> | FilterValue<ExpandProperty<FilterObjectProp<T, K>>> | null;
248
+ -readonly [K in EntityKey<T>]?: ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>> | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>> | FilterValue<ExpandProperty<FilterObjectProp<T, K>>> | ElemMatchFilter<FilterObjectProp<T, K>> | null;
239
249
  };
240
- export type ExpandQuery<T> = T extends object ? T extends Scalar ? never : FilterQuery<T> : FilterValue<T>;
250
+ export type ExpandQuery<T> = T extends object ? (T extends Scalar ? never : FilterQuery<T>) : FilterValue<T>;
241
251
  export type EntityProps<T> = {
242
252
  -readonly [K in EntityKey<T>]?: T[K];
243
253
  };
@@ -324,11 +334,11 @@ type NonArrayObject = object & {
324
334
  export type EntityDataProp<T, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends ScalarReference<infer U> ? EntityDataProp<U, C> : T extends {
325
335
  __runtime?: infer Runtime;
326
336
  __raw?: infer Raw;
327
- } ? (C extends true ? Raw : Runtime) : T extends ReferenceShape<infer U> ? EntityDataNested<U, C> : T extends CollectionShape<infer U> ? U | U[] | EntityDataNested<U & object, C> | EntityDataNested<U & object, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : U[] | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
337
+ } ? C extends true ? Raw : Runtime : T extends ReferenceShape<infer U> ? EntityDataNested<U, C> : T extends CollectionShape<infer U> ? U | U[] | EntityDataNested<U & object, C> | EntityDataNested<U & object, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : U[] | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
328
338
  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 ScalarReference<infer U> ? RequiredEntityDataProp<U, O, C> : T extends {
329
339
  __runtime?: infer Runtime;
330
340
  __raw?: infer Raw;
331
- } ? (C extends true ? Raw : Runtime) : T extends ReferenceShape<infer U> ? RequiredEntityDataNested<U, O, C> : T extends CollectionShape<infer U> ? U | U[] | RequiredEntityDataNested<U & object, O, C> | RequiredEntityDataNested<U & object, 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>;
341
+ } ? C extends true ? Raw : Runtime : T extends ReferenceShape<infer U> ? RequiredEntityDataNested<U, O, C> : T extends CollectionShape<infer U> ? U | U[] | RequiredEntityDataNested<U & object, O, C> | RequiredEntityDataNested<U & object, 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>;
332
342
  export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
333
343
  type UnwrapScalarRef<T> = T extends ScalarReference<infer U> ? U : T;
334
344
  type EntityDataItem<T, C extends boolean> = C extends false ? UnwrapScalarRef<T> | EntityDataProp<T, C> | Raw | null : EntityDataProp<T, C> | Raw | null;
@@ -368,9 +378,9 @@ export type Rel<T> = T;
368
378
  /** Alias for `ScalarReference` (see {@apilink Ref}). */
369
379
  export type ScalarRef<T> = ScalarReference<T>;
370
380
  /** Alias for `Reference<T> & { id: number }` (see {@apilink Ref}). */
371
- export type EntityRef<T extends object> = true extends IsUnknown<PrimaryProperty<T>> ? Reference<T> : IsAny<T> extends true ? Reference<T> : ({
381
+ export type EntityRef<T extends object> = true extends IsUnknown<PrimaryProperty<T>> ? Reference<T> : IsAny<T> extends true ? Reference<T> : {
372
382
  [K in PrimaryProperty<T> & keyof T]: T[K];
373
- } & Reference<T>);
383
+ } & Reference<T>;
374
384
  /**
375
385
  * Ref type represents a `Reference` instance, and adds the primary keys to its prototype automatically, so you can do
376
386
  * `ref.id` instead of `ref.unwrap().id`. It resolves to either `ScalarRef` or `EntityRef`, based on the type argument.
@@ -384,7 +394,7 @@ type ExtractHiddenProps<T> = (T extends {
384
394
  type ExcludeHidden<T, K extends keyof T> = K extends ExtractHiddenProps<T> ? never : K;
385
395
  type ExtractConfig<T> = T extends {
386
396
  [Config]?: infer K;
387
- } ? (K & TypeConfig) : TypeConfig;
397
+ } ? K & TypeConfig : TypeConfig;
388
398
  type PreferExplicitConfig<E, I> = IsNever<E, I, E>;
389
399
  type PrimaryOrObject<T, U, C extends TypeConfig> = PreferExplicitConfig<C, ExtractConfig<T>>['forceObject'] extends true ? {
390
400
  [K in PrimaryProperty<U> & keyof U]: U[K];
@@ -392,7 +402,7 @@ type PrimaryOrObject<T, U, C extends TypeConfig> = PreferExplicitConfig<C, Extra
392
402
  type DTOWrapper<T, C extends TypeConfig, Flat extends boolean> = Flat extends true ? EntityDTOFlat<T, C> : EntityDTO<T, C>;
393
403
  export type EntityDTOProp<E, T, C extends TypeConfig = never, Flat extends boolean = false> = T extends Scalar ? T : T extends ScalarReference<infer U> ? U : T extends {
394
404
  __serialized?: infer U;
395
- } ? (IsUnknown<U> extends false ? U : T) : T extends LoadedReferenceShape<infer U> ? DTOWrapper<U, C, Flat> : T extends ReferenceShape<infer U> ? PrimaryOrObject<E, U, C> : T extends LoadedCollectionShape<infer U> ? DTOWrapper<U & object, C, Flat>[] : T extends CollectionShape<infer U> ? PrimaryOrObject<E, U & object, C>[] : T extends readonly (infer U)[] ? U extends Scalar ? T : EntityDTOProp<E, U, C, Flat>[] : T extends Relation<T> ? DTOWrapper<T, C, Flat> : T;
405
+ } ? IsUnknown<U> extends false ? U : T : T extends LoadedReferenceShape<infer U> ? DTOWrapper<U, C, Flat> : T extends ReferenceShape<infer U> ? PrimaryOrObject<E, U, C> : T extends LoadedCollectionShape<infer U> ? DTOWrapper<U & object, C, Flat>[] : T extends CollectionShape<infer U> ? PrimaryOrObject<E, U & object, C>[] : T extends readonly (infer U)[] ? U extends Scalar ? T : EntityDTOProp<E, U, C, Flat>[] : T extends Relation<T> ? DTOWrapper<T, C, Flat> : T;
396
406
  type UnwrapLoadedEntity<T> = T extends {
397
407
  [__loadedType]?: infer U;
398
408
  } ? NonNullable<U> : T;
@@ -422,7 +432,7 @@ export type EntityDTOFlat<T, C extends TypeConfig = never> = {
422
432
  */
423
433
  type SerializeTopHints<H extends string> = H extends `${infer Top}.${string}` ? Top : H;
424
434
  type SerializeSubHints<K extends string, H extends string> = H extends `${K}.${infer Rest}` ? Rest : never;
425
- type SerializePropValue<T, K extends keyof T, H extends string, C extends TypeConfig = never> = (K & string) extends SerializeTopHints<H> ? NonNullable<T[K]> extends CollectionShape<infer U> ? SerializeDTO<U & object, SerializeSubHints<K & string, H>, never, C>[] : SerializeDTO<ExpandProperty<T[K]>, SerializeSubHints<K & string, H>, never, C> | Extract<T[K], null | undefined> : EntityDTOProp<T, T[K], C>;
435
+ type SerializePropValue<T, K extends keyof T, H extends string, C extends TypeConfig = never> = K & string extends SerializeTopHints<H> ? NonNullable<T[K]> extends CollectionShape<infer U> ? SerializeDTO<U & object, SerializeSubHints<K & string, H>, never, C>[] : SerializeDTO<ExpandProperty<T[K]>, SerializeSubHints<K & string, H>, never, C> | Extract<T[K], null | undefined> : EntityDTOProp<T, T[K], C>;
426
436
  export type SerializeDTO<T, H extends string = never, E extends string = never, C extends TypeConfig = never> = string extends H ? EntityDTOFlat<T, C> : {
427
437
  [K in keyof T as ExcludeHidden<T, K> & CleanKeys<T, K> & (IsNever<E> extends true ? K : Exclude<K, E>)]: SerializePropValue<T, K, H, C> | Extract<T[K], null | undefined>;
428
438
  };
@@ -523,6 +533,7 @@ export interface EntityProperty<Owner = any, Target = any> {
523
533
  nullable?: boolean;
524
534
  inherited?: boolean;
525
535
  renamedFrom?: string;
536
+ stiMerged?: boolean;
526
537
  stiFieldNames?: string[];
527
538
  stiFieldNameMap?: Dictionary<string>;
528
539
  unsigned?: boolean;
@@ -975,7 +986,7 @@ type ExtractStringKeys<T> = {
975
986
  * Simplified to just check `T extends object` since ExtractType handles the unwrapping.
976
987
  */
977
988
  type StringKeys<T, E extends string = never> = T extends object ? ExtractStringKeys<ExtractType<T>> | E : never;
978
- type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractType<T[K]> : (K extends E ? keyof T : never);
989
+ type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractType<T[K]> : K extends E ? keyof T : never;
979
990
  type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
980
991
  type RelationKeys<T> = T extends object ? {
981
992
  [K in keyof T]-?: CleanKeys<T, K, true>;
@@ -985,12 +996,12 @@ export type UnboxArray<T> = T extends any[] ? ArrayElement<T> : T;
985
996
  export type ArrayElement<ArrayType extends unknown[]> = ArrayType extends (infer ElementType)[] ? ElementType : never;
986
997
  export type ExpandProperty<T> = T extends ReferenceShape<infer U> ? NonNullable<U> : T extends CollectionShape<infer U> ? NonNullable<U> : T extends (infer U)[] ? NonNullable<U> : NonNullable<T>;
987
998
  type LoadedLoadable<T, E extends object> = T extends CollectionShape ? LoadedCollection<E> : T extends ScalarReference<infer U> ? LoadedScalarReference<U> : T extends ReferenceShape ? T & LoadedReference<E> : T extends Scalar ? T : T extends (infer U)[] ? U extends Scalar ? T : E[] : E;
988
- type IsTrue<T> = IsNever<T> extends true ? false : T extends boolean ? T extends true ? true : false : false;
989
- type StringLiteral<T> = T extends string ? string extends T ? never : T : never;
990
- type Prefix<T, K> = K extends `${infer S}.${string}` ? S : (K extends '*' ? keyof T : K);
999
+ type IsTrue<T> = IsNever<T> extends true ? false : T extends boolean ? (T extends true ? true : false) : false;
1000
+ type StringLiteral<T> = T extends string ? (string extends T ? never : T) : never;
1001
+ type Prefix<T, K> = K extends `${infer S}.${string}` ? S : K extends '*' ? keyof T : K;
991
1002
  type IsPrefixedExclude<T, K extends keyof T, E extends string> = K extends E ? never : K;
992
- export type IsPrefixed<T, K extends keyof T, L extends string, E extends string = never> = IsNever<E> extends false ? IsPrefixedExclude<T, K, E> : K extends symbol ? never : IsTrue<L> extends true ? (T[K] & {} extends LoadableShape ? K : never) : IsNever<StringLiteral<L>> extends true ? never : '*' extends L ? K : K extends Prefix<T, L> ? K : K extends PrimaryProperty<T> ? K : never;
993
- type Suffix<Key, Hint extends string, All = true | '*'> = Hint extends `${infer Pref}.${infer Suf}` ? (Pref extends Key ? Suf : never) : Hint extends All ? Hint : never;
1003
+ export type IsPrefixed<T, K extends keyof T, L extends string, E extends string = never> = IsNever<E> extends false ? IsPrefixedExclude<T, K, E> : K extends symbol ? never : IsTrue<L> extends true ? T[K] & {} extends LoadableShape ? K : never : IsNever<StringLiteral<L>> extends true ? never : '*' extends L ? K : K extends Prefix<T, L> ? K : K extends PrimaryProperty<T> ? K : never;
1004
+ type Suffix<Key, Hint extends string, All = true | '*'> = Hint extends `${infer Pref}.${infer Suf}` ? Pref extends Key ? Suf : never : Hint extends All ? Hint : never;
994
1005
  export type IsSubset<T, U> = keyof U extends keyof T ? {} : string extends keyof U ? {} : {
995
1006
  [K in keyof U as K extends keyof T ? never : CleanKeys<U, K>]: never;
996
1007
  };
package/typings.js CHANGED
@@ -31,11 +31,9 @@ export class EntityMetadata {
31
31
  Object.assign(this, meta);
32
32
  const name = meta.className ?? meta.name;
33
33
  if (!this.class && name) {
34
- const Class = this.extends === BaseEntity
35
- ? ({ [name]: class extends BaseEntity {
36
- } })[name]
37
- : ({ [name]: class {
38
- } })[name];
34
+ const Class = this.extends === BaseEntity ? { [name]: class extends BaseEntity {
35
+ } }[name] : { [name]: class {
36
+ } }[name];
39
37
  this.class = Class;
40
38
  }
41
39
  }
@@ -108,9 +106,7 @@ export class EntityMetadata {
108
106
  */
109
107
  createSchemaColumnMappingObject() {
110
108
  // For TPT entities, only include properties that belong to this entity's table
111
- const props = this.inheritanceType === 'tpt' && this.ownProps
112
- ? this.ownProps
113
- : Object.values(this.properties);
109
+ const props = this.inheritanceType === 'tpt' && this.ownProps ? this.ownProps : Object.values(this.properties);
114
110
  return props.reduce((o, prop) => {
115
111
  if (prop.fieldNames) {
116
112
  o[prop.name] = prop.fieldNames[0];
@@ -208,7 +204,11 @@ export class EntityMetadata {
208
204
  const hydrator = wrapped.hydrator;
209
205
  const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
210
206
  const old = Reference.unwrapReference(wrapped.__data[prop.name]);
211
- if (old && old !== entity && prop.kind === ReferenceKind.MANY_TO_ONE && prop.inversedBy && old[prop.inversedBy]) {
207
+ if (old &&
208
+ old !== entity &&
209
+ prop.kind === ReferenceKind.MANY_TO_ONE &&
210
+ prop.inversedBy &&
211
+ old[prop.inversedBy]) {
212
212
  old[prop.inversedBy].removeWithoutPropagation(this);
213
213
  }
214
214
  wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
@@ -27,10 +27,10 @@ export class ChangeSet {
27
27
  else {
28
28
  this.primaryKey = this.originalEntity[this.meta.primaryKeys[0]];
29
29
  }
30
- if (!this.meta.compositePK
31
- && this.meta.getPrimaryProp().targetMeta?.compositePK
32
- && typeof this.primaryKey === 'object'
33
- && this.primaryKey !== null) {
30
+ if (!this.meta.compositePK &&
31
+ this.meta.getPrimaryProp().targetMeta?.compositePK &&
32
+ typeof this.primaryKey === 'object' &&
33
+ this.primaryKey !== null) {
34
34
  this.primaryKey = this.meta.getPrimaryProp().targetMeta.primaryKeys.map(childPK => {
35
35
  return this.primaryKey[childPK];
36
36
  });