@mikro-orm/core 7.0.0-rc.3 → 7.0.1-dev.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 (94) hide show
  1. package/EntityManager.d.ts +2 -15
  2. package/EntityManager.js +155 -152
  3. package/MikroORM.d.ts +4 -6
  4. package/MikroORM.js +20 -20
  5. package/README.md +5 -4
  6. package/cache/FileCacheAdapter.d.ts +1 -5
  7. package/cache/FileCacheAdapter.js +22 -22
  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 +27 -11
  16. package/drivers/DatabaseDriver.d.ts +0 -2
  17. package/drivers/DatabaseDriver.js +2 -4
  18. package/entity/Collection.d.ts +1 -9
  19. package/entity/Collection.js +95 -105
  20. package/entity/EntityFactory.d.ts +1 -8
  21. package/entity/EntityFactory.js +48 -48
  22. package/entity/EntityLoader.d.ts +1 -3
  23. package/entity/EntityLoader.js +36 -39
  24. package/entity/Reference.d.ts +1 -2
  25. package/entity/Reference.js +11 -11
  26. package/entity/WrappedEntity.d.ts +4 -2
  27. package/entity/defineEntity.d.ts +18 -73
  28. package/enums.d.ts +2 -1
  29. package/enums.js +1 -0
  30. package/errors.d.ts +11 -11
  31. package/errors.js +3 -13
  32. package/events/EventManager.d.ts +1 -4
  33. package/events/EventManager.js +25 -22
  34. package/events/index.d.ts +1 -1
  35. package/events/index.js +0 -1
  36. package/exceptions.js +8 -6
  37. package/hydration/ObjectHydrator.d.ts +1 -2
  38. package/hydration/ObjectHydrator.js +16 -16
  39. package/logging/DefaultLogger.js +3 -2
  40. package/logging/Logger.d.ts +2 -1
  41. package/logging/colors.js +1 -1
  42. package/logging/index.d.ts +1 -1
  43. package/logging/index.js +0 -1
  44. package/metadata/EntitySchema.d.ts +1 -1
  45. package/metadata/MetadataDiscovery.d.ts +1 -9
  46. package/metadata/MetadataDiscovery.js +162 -149
  47. package/metadata/MetadataStorage.d.ts +1 -5
  48. package/metadata/MetadataStorage.js +36 -36
  49. package/metadata/discover-entities.js +1 -1
  50. package/metadata/index.d.ts +1 -1
  51. package/metadata/index.js +0 -1
  52. package/naming-strategy/AbstractNamingStrategy.js +1 -1
  53. package/naming-strategy/EntityCaseNamingStrategy.js +1 -1
  54. package/naming-strategy/index.d.ts +1 -1
  55. package/naming-strategy/index.js +0 -1
  56. package/package.json +1 -1
  57. package/platforms/Platform.d.ts +23 -1
  58. package/platforms/Platform.js +57 -4
  59. package/serialization/EntitySerializer.js +1 -1
  60. package/serialization/EntityTransformer.js +4 -1
  61. package/serialization/SerializationContext.d.ts +4 -8
  62. package/serialization/SerializationContext.js +20 -15
  63. package/types/UuidType.d.ts +2 -0
  64. package/types/UuidType.js +14 -2
  65. package/types/index.d.ts +2 -1
  66. package/typings.d.ts +12 -1
  67. package/unit-of-work/ChangeSetComputer.d.ts +1 -6
  68. package/unit-of-work/ChangeSetComputer.js +21 -21
  69. package/unit-of-work/ChangeSetPersister.d.ts +1 -9
  70. package/unit-of-work/ChangeSetPersister.js +52 -52
  71. package/unit-of-work/CommitOrderCalculator.d.ts +1 -4
  72. package/unit-of-work/CommitOrderCalculator.js +13 -13
  73. package/unit-of-work/IdentityMap.d.ts +2 -5
  74. package/unit-of-work/IdentityMap.js +18 -18
  75. package/unit-of-work/UnitOfWork.d.ts +5 -19
  76. package/unit-of-work/UnitOfWork.js +182 -174
  77. package/utils/AbstractMigrator.d.ts +1 -1
  78. package/utils/AbstractMigrator.js +7 -7
  79. package/utils/Configuration.d.ts +90 -189
  80. package/utils/Configuration.js +94 -78
  81. package/utils/Cursor.d.ts +3 -3
  82. package/utils/Cursor.js +4 -4
  83. package/utils/EntityComparator.d.ts +8 -15
  84. package/utils/EntityComparator.js +49 -49
  85. package/utils/QueryHelper.d.ts +16 -1
  86. package/utils/QueryHelper.js +70 -24
  87. package/utils/RawQueryFragment.d.ts +4 -4
  88. package/utils/TransactionManager.js +1 -2
  89. package/utils/Utils.d.ts +1 -1
  90. package/utils/Utils.js +5 -4
  91. package/utils/clone.js +5 -0
  92. package/utils/fs-utils.d.ts +3 -17
  93. package/utils/fs-utils.js +1 -1
  94. package/utils/upsert-utils.js +1 -1
@@ -1,12 +1,8 @@
1
1
  import { type Dictionary, EntityMetadata, type EntityName } from '../typings.js';
2
2
  import type { EntityManager } from '../EntityManager.js';
3
3
  export declare class MetadataStorage {
4
+ #private;
4
5
  static readonly PATH_SYMBOL: unique symbol;
5
- private static readonly metadata;
6
- private readonly metadata;
7
- private readonly idMap;
8
- private readonly classNameMap;
9
- private readonly uniqueNameMap;
10
6
  constructor(metadata?: Dictionary<EntityMetadata>);
11
7
  static getMetadata(): Dictionary<EntityMetadata>;
12
8
  static getMetadata<T = any>(entity: string, path: string): EntityMetadata<T>;
@@ -10,39 +10,39 @@ function getGlobalStorage(namespace) {
10
10
  }
11
11
  export class MetadataStorage {
12
12
  static PATH_SYMBOL = Symbol.for('@mikro-orm/core/MetadataStorage.PATH_SYMBOL');
13
- static metadata = getGlobalStorage('metadata');
14
- metadata = new Map();
15
- idMap;
16
- classNameMap;
17
- uniqueNameMap;
13
+ static #metadata = getGlobalStorage('metadata');
14
+ #metadataMap = new Map();
15
+ #idMap;
16
+ #classNameMap;
17
+ #uniqueNameMap;
18
18
  constructor(metadata = {}) {
19
- this.idMap = {};
20
- this.uniqueNameMap = {};
21
- this.classNameMap = Utils.copy(metadata, false);
22
- for (const meta of Object.values(this.classNameMap)) {
23
- this.idMap[meta._id] = meta;
24
- this.uniqueNameMap[meta.uniqueName] = meta;
25
- this.metadata.set(meta.class, meta);
19
+ this.#idMap = {};
20
+ this.#uniqueNameMap = {};
21
+ this.#classNameMap = Utils.copy(metadata, false);
22
+ for (const meta of Object.values(this.#classNameMap)) {
23
+ this.#idMap[meta._id] = meta;
24
+ this.#uniqueNameMap[meta.uniqueName] = meta;
25
+ this.#metadataMap.set(meta.class, meta);
26
26
  }
27
27
  }
28
28
  static getMetadata(entity, path) {
29
29
  const key = entity && path ? entity + '-' + Utils.hash(path) : null;
30
- if (key && !MetadataStorage.metadata[key]) {
31
- MetadataStorage.metadata[key] = new EntityMetadata({ className: entity, path });
30
+ if (key && !MetadataStorage.#metadata[key]) {
31
+ MetadataStorage.#metadata[key] = new EntityMetadata({ className: entity, path });
32
32
  }
33
33
  if (key) {
34
- return MetadataStorage.metadata[key];
34
+ return MetadataStorage.#metadata[key];
35
35
  }
36
- return MetadataStorage.metadata;
36
+ return MetadataStorage.#metadata;
37
37
  }
38
38
  static isKnownEntity(name) {
39
- return !!Object.values(this.metadata).find(meta => meta.className === name);
39
+ return !!Object.values(this.#metadata).find(meta => meta.className === name);
40
40
  }
41
41
  static clear() {
42
- Object.keys(this.metadata).forEach(k => delete this.metadata[k]);
42
+ Object.keys(this.#metadata).forEach(k => delete this.#metadata[k]);
43
43
  }
44
44
  getAll() {
45
- return this.metadata;
45
+ return this.#metadataMap;
46
46
  }
47
47
  get(entityName, init = false) {
48
48
  const exists = this.find(entityName);
@@ -61,50 +61,50 @@ export class MetadataStorage {
61
61
  if (!entityName) {
62
62
  return;
63
63
  }
64
- const meta = this.metadata.get(entityName);
64
+ const meta = this.#metadataMap.get(entityName);
65
65
  if (meta) {
66
66
  return meta;
67
67
  }
68
68
  if (entityName instanceof EntitySchema) {
69
- return this.metadata.get(entityName.meta.class) ?? entityName.meta;
69
+ return this.#metadataMap.get(entityName.meta.class) ?? entityName.meta;
70
70
  }
71
- return this.classNameMap[Utils.className(entityName)];
71
+ return this.#classNameMap[Utils.className(entityName)];
72
72
  }
73
73
  has(entityName) {
74
- return this.metadata.has(entityName);
74
+ return this.#metadataMap.has(entityName);
75
75
  }
76
76
  set(entityName, meta) {
77
- this.metadata.set(entityName, meta);
78
- this.idMap[meta._id] = meta;
79
- this.uniqueNameMap[meta.uniqueName] = meta;
80
- this.classNameMap[Utils.className(entityName)] = meta;
77
+ this.#metadataMap.set(entityName, meta);
78
+ this.#idMap[meta._id] = meta;
79
+ this.#uniqueNameMap[meta.uniqueName] = meta;
80
+ this.#classNameMap[Utils.className(entityName)] = meta;
81
81
  return meta;
82
82
  }
83
83
  reset(entityName) {
84
84
  const meta = this.find(entityName);
85
85
  if (meta) {
86
- this.metadata.delete(meta.class);
87
- delete this.idMap[meta._id];
88
- delete this.uniqueNameMap[meta.uniqueName];
89
- delete this.classNameMap[meta.className];
86
+ this.#metadataMap.delete(meta.class);
87
+ delete this.#idMap[meta._id];
88
+ delete this.#uniqueNameMap[meta.uniqueName];
89
+ delete this.#classNameMap[meta.className];
90
90
  }
91
91
  }
92
92
  decorate(em) {
93
- [...this.metadata.values()].filter(meta => meta.prototype).forEach(meta => EntityHelper.decorate(meta, em));
93
+ [...this.#metadataMap.values()].filter(meta => meta.prototype).forEach(meta => EntityHelper.decorate(meta, em));
94
94
  }
95
95
  *[Symbol.iterator]() {
96
- for (const meta of this.metadata.values()) {
96
+ for (const meta of this.#metadataMap.values()) {
97
97
  yield meta;
98
98
  }
99
99
  }
100
100
  getById(id) {
101
- return this.idMap[id];
101
+ return this.#idMap[id];
102
102
  }
103
103
  getByClassName(className, validate = true) {
104
- return this.validate(this.classNameMap[className], className, validate);
104
+ return this.validate(this.#classNameMap[className], className, validate);
105
105
  }
106
106
  getByUniqueName(uniqueName, validate = true) {
107
- return this.validate(this.uniqueNameMap[uniqueName], uniqueName, validate);
107
+ return this.validate(this.#uniqueNameMap[uniqueName], uniqueName, validate);
108
108
  }
109
109
  validate(meta, id, validate) {
110
110
  if (!meta && validate) {
@@ -31,7 +31,7 @@ export async function discoverEntities(paths, options) {
31
31
  const found = new Map();
32
32
  for (const filepath of files) {
33
33
  const filename = basename(filepath);
34
- if (!filename.match(/\.[cm]?[jt]s$/) || filename.match(/\.d\.[cm]?ts/)) {
34
+ if (!/\.[cm]?[jt]s$/.exec(filename) || /\.d\.[cm]?ts/.exec(filename)) {
35
35
  continue;
36
36
  }
37
37
  await getEntityClassOrSchema(filepath, found, baseDir);
@@ -1,4 +1,4 @@
1
- export * from './types.js';
1
+ export type * from './types.js';
2
2
  export * from './EntitySchema.js';
3
3
  export * from './MetadataDiscovery.js';
4
4
  export * from './MetadataStorage.js';
package/metadata/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from './types.js';
2
1
  export * from './EntitySchema.js';
3
2
  export * from './MetadataDiscovery.js';
4
3
  export * from './MetadataStorage.js';
@@ -34,7 +34,7 @@ export class AbstractNamingStrategy {
34
34
  * @inheritDoc
35
35
  */
36
36
  getEntityName(tableName, schemaName) {
37
- const name = tableName.match(/^[^$_\p{ID_Start}]/u) ? `E_${tableName}` : tableName;
37
+ const name = /^[^$_\p{ID_Start}]/u.exec(tableName) ? `E_${tableName}` : tableName;
38
38
  return this.getClassName(name.replaceAll(/[^\u200C\u200D\p{ID_Continue}]+/gu, r => r
39
39
  .split('')
40
40
  .map(c => `$${c.codePointAt(0)}`)
@@ -11,7 +11,7 @@ export class EntityCaseNamingStrategy extends AbstractNamingStrategy {
11
11
  }
12
12
  joinKeyColumnName(entityName, referencedColumnName, composite, tableName) {
13
13
  entityName = this.classToTableName(entityName, tableName);
14
- const name = entityName.substr(0, 1).toLowerCase() + entityName.substr(1);
14
+ const name = entityName.substring(0, 1).toLowerCase() + entityName.substring(1);
15
15
  if (composite && referencedColumnName) {
16
16
  return name + '_' + referencedColumnName;
17
17
  }
@@ -1,4 +1,4 @@
1
- export * from './NamingStrategy.js';
1
+ export type * from './NamingStrategy.js';
2
2
  export * from './AbstractNamingStrategy.js';
3
3
  export * from './MongoNamingStrategy.js';
4
4
  export * from './UnderscoreNamingStrategy.js';
@@ -1,4 +1,3 @@
1
- export * from './NamingStrategy.js';
2
1
  export * from './AbstractNamingStrategy.js';
3
2
  export * from './MongoNamingStrategy.js';
4
3
  export * from './UnderscoreNamingStrategy.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "7.0.0-rc.3",
3
+ "version": "7.0.1-dev.0",
4
4
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
5
5
  "keywords": [
6
6
  "data-mapper",
@@ -1,6 +1,6 @@
1
1
  import { EntityRepository } from '../entity/EntityRepository.js';
2
2
  import { type NamingStrategy } from '../naming-strategy/NamingStrategy.js';
3
- import type { Constructor, EntityMetadata, EntityProperty, IPrimaryKey, ISchemaGenerator, PopulateOptions, Primary, SimpleColumnMeta } from '../typings.js';
3
+ import type { Constructor, EntityMetadata, EntityProperty, IPrimaryKey, ISchemaGenerator, PopulateOptions, Primary, SimpleColumnMeta, FilterQuery, EntityValue, EntityKey } from '../typings.js';
4
4
  import { ExceptionConverter } from './ExceptionConverter.js';
5
5
  import type { EntityManager } from '../EntityManager.js';
6
6
  import type { Configuration } from '../utils/Configuration.js';
@@ -61,6 +61,13 @@ export declare abstract class Platform {
61
61
  getDateTypeDeclarationSQL(length?: number): string;
62
62
  getTimeTypeDeclarationSQL(length?: number): string;
63
63
  getRegExpOperator(val?: unknown, flags?: string): string;
64
+ mapRegExpCondition(mappedKey: string, value: {
65
+ $re: string;
66
+ $flags?: string;
67
+ }): {
68
+ sql: string;
69
+ params: unknown[];
70
+ };
64
71
  getRegExpValue(val: RegExp): {
65
72
  $re: string;
66
73
  $flags?: string;
@@ -139,6 +146,11 @@ export declare abstract class Platform {
139
146
  getMappedType(type: string): Type<unknown>;
140
147
  getDefaultMappedType(type: string): Type<unknown>;
141
148
  supportsMultipleCascadePaths(): boolean;
149
+ /**
150
+ * Returns true if the platform supports ON UPDATE foreign key rules.
151
+ * Oracle doesn't support ON UPDATE rules.
152
+ */
153
+ supportsOnUpdate(): boolean;
142
154
  supportsMultipleStatements(): boolean;
143
155
  supportsUnionWhere(): boolean;
144
156
  getArrayDeclarationSQL(): string;
@@ -148,6 +160,8 @@ export declare abstract class Platform {
148
160
  getJsonDeclarationSQL(): string;
149
161
  getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string | Raw;
150
162
  getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string | Raw;
163
+ processJsonCondition<T extends object>(o: FilterQuery<T>, value: EntityValue<T>, path: EntityKey<T>[], alias: boolean): FilterQuery<T>;
164
+ protected getJsonValueType(value: unknown): string;
151
165
  getJsonIndexDefinition(index: {
152
166
  columnNames: string[];
153
167
  }): string[];
@@ -160,6 +174,14 @@ export declare abstract class Platform {
160
174
  convertDateToJSValue(value: string | Date): string;
161
175
  convertIntervalToJSValue(value: string): unknown;
162
176
  convertIntervalToDatabaseValue(value: unknown): unknown;
177
+ usesAsKeyword(): boolean;
178
+ /**
179
+ * Determines how UUID values are compared in the change set tracking.
180
+ * Return `'string'` for inline string comparison (fast), or `'any'` for deep comparison via type methods.
181
+ */
182
+ compareUuids(): string;
183
+ convertUuidToJSValue(value: unknown): unknown;
184
+ convertUuidToDatabaseValue(value: unknown): unknown;
163
185
  parseDate(value: string | number): Date;
164
186
  getRepositoryClass<T extends object>(): Constructor<EntityRepository<T>>;
165
187
  getDefaultCharset(): string;
@@ -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.
@@ -255,6 +260,13 @@ export class Platform {
255
260
  supportsMultipleCascadePaths() {
256
261
  return true;
257
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
+ }
258
270
  supportsMultipleStatements() {
259
271
  return this.config.get('multipleStatements');
260
272
  }
@@ -285,6 +297,31 @@ export class Platform {
285
297
  getSearchJsonPropertyKey(path, type, aliased, value) {
286
298
  return path.join('.');
287
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
+ }
288
325
  /* v8 ignore next */
289
326
  getJsonIndexDefinition(index) {
290
327
  return index.columnNames;
@@ -316,6 +353,22 @@ export class Platform {
316
353
  convertIntervalToDatabaseValue(value) {
317
354
  return value;
318
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
+ }
319
372
  parseDate(value) {
320
373
  const date = new Date(value);
321
374
  /* v8 ignore next */
@@ -380,7 +433,7 @@ export class Platform {
380
433
  let j = 0;
381
434
  let pos = 0;
382
435
  let ret = '';
383
- if (sql[0] === '?') {
436
+ if (sql.startsWith('?')) {
384
437
  if (sql[1] === '?') {
385
438
  ret += this.quoteIdentifier(params[j++]);
386
439
  pos = 2;
@@ -36,7 +36,7 @@ export class EntitySerializer {
36
36
  const meta = wrapped.__meta;
37
37
  let contextCreated = false;
38
38
  if (!wrapped.__serializationContext.root) {
39
- const root = new SerializationContext(wrapped.__config);
39
+ const root = new SerializationContext();
40
40
  SerializationContext.propagate(root, entity, (meta, prop) => meta.properties[prop]?.kind !== ReferenceKind.SCALAR);
41
41
  options.populate = (options.populate ? Utils.asArray(options.populate) : options.populate);
42
42
  contextCreated = true;
@@ -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) {
@@ -110,6 +115,6 @@ export class SerializationContext {
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
@@ -234,8 +234,18 @@ 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
250
  export type ExpandQuery<T> = T extends object ? (T extends Scalar ? never : FilterQuery<T>) : FilterValue<T>;
241
251
  export type EntityProps<T> = {
@@ -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;
@@ -3,12 +3,7 @@ import { ChangeSet } from './ChangeSet.js';
3
3
  import { type Collection } from '../entity/Collection.js';
4
4
  import type { EntityManager } from '../EntityManager.js';
5
5
  export declare class ChangeSetComputer {
6
- private readonly em;
7
- private readonly collectionUpdates;
8
- private readonly comparator;
9
- private readonly metadata;
10
- private readonly platform;
11
- private readonly config;
6
+ #private;
12
7
  constructor(em: EntityManager, collectionUpdates: Set<Collection<AnyEntity>>);
13
8
  computeChangeSet<T extends object>(entity: T): ChangeSet<T> | null;
14
9
  /**