@mikro-orm/core 7.2.0-dev.2 → 7.2.0-dev.20

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 (86) hide show
  1. package/EntityManager.d.ts +42 -8
  2. package/EntityManager.js +256 -70
  3. package/MikroORM.d.ts +4 -0
  4. package/MikroORM.js +9 -0
  5. package/cache/CacheAdapter.d.ts +6 -4
  6. package/cache/FileCacheAdapter.d.ts +1 -1
  7. package/cache/FileCacheAdapter.js +7 -2
  8. package/connections/Connection.d.ts +10 -1
  9. package/connections/Connection.js +9 -0
  10. package/drivers/DatabaseDriver.d.ts +17 -1
  11. package/drivers/DatabaseDriver.js +203 -41
  12. package/drivers/IDatabaseDriver.d.ts +1 -0
  13. package/entity/Collection.js +4 -2
  14. package/entity/EntityFactory.js +6 -0
  15. package/entity/EntityLoader.d.ts +7 -1
  16. package/entity/EntityLoader.js +46 -11
  17. package/entity/EntityRepository.d.ts +4 -5
  18. package/entity/EntityRepository.js +7 -2
  19. package/entity/defineEntity.d.ts +48 -14
  20. package/entity/defineEntity.js +32 -1
  21. package/enums.d.ts +5 -1
  22. package/enums.js +2 -0
  23. package/errors.d.ts +36 -0
  24. package/errors.js +90 -0
  25. package/events/EventManager.js +6 -3
  26. package/exceptions.d.ts +5 -0
  27. package/exceptions.js +5 -0
  28. package/hydration/ObjectHydrator.d.ts +2 -0
  29. package/hydration/ObjectHydrator.js +15 -8
  30. package/index.d.ts +1 -1
  31. package/metadata/EntitySchema.js +5 -2
  32. package/metadata/MetadataDiscovery.d.ts +3 -0
  33. package/metadata/MetadataDiscovery.js +161 -28
  34. package/metadata/MetadataProvider.js +1 -1
  35. package/metadata/MetadataStorage.d.ts +4 -3
  36. package/metadata/MetadataStorage.js +32 -2
  37. package/metadata/Routine.js +4 -1
  38. package/metadata/types.d.ts +19 -3
  39. package/naming-strategy/AbstractNamingStrategy.js +2 -1
  40. package/naming-strategy/NamingStrategy.d.ts +2 -1
  41. package/package.json +1 -1
  42. package/platforms/Platform.d.ts +24 -3
  43. package/platforms/Platform.js +63 -1
  44. package/types/BigIntType.d.ts +1 -0
  45. package/types/BigIntType.js +23 -0
  46. package/types/DateTimeType.d.ts +1 -0
  47. package/types/DateTimeType.js +8 -0
  48. package/types/StringType.d.ts +14 -3
  49. package/types/StringType.js +34 -4
  50. package/types/TextType.d.ts +2 -4
  51. package/types/TextType.js +2 -8
  52. package/types/Type.d.ts +11 -0
  53. package/types/Type.js +4 -4
  54. package/types/index.d.ts +2 -2
  55. package/typings.d.ts +58 -2
  56. package/typings.js +24 -1
  57. package/unit-of-work/ChangeSet.js +10 -7
  58. package/unit-of-work/ChangeSetPersister.js +32 -20
  59. package/unit-of-work/UnitOfWork.js +11 -4
  60. package/utils/AbstractMigrator.d.ts +1 -1
  61. package/utils/AbstractMigrator.js +3 -2
  62. package/utils/Configuration.d.ts +15 -1
  63. package/utils/Configuration.js +13 -2
  64. package/utils/Cursor.d.ts +2 -0
  65. package/utils/Cursor.js +44 -39
  66. package/utils/DataloaderUtils.js +2 -1
  67. package/utils/EntityComparator.d.ts +2 -0
  68. package/utils/EntityComparator.js +11 -4
  69. package/utils/QueryHelper.d.ts +17 -0
  70. package/utils/QueryHelper.js +100 -4
  71. package/utils/RawQueryFragment.d.ts +6 -0
  72. package/utils/RawQueryFragment.js +15 -6
  73. package/utils/RequestContext.d.ts +2 -2
  74. package/utils/RequestContext.js +11 -2
  75. package/utils/TransactionManager.d.ts +6 -0
  76. package/utils/TransactionManager.js +36 -3
  77. package/utils/Utils.d.ts +14 -2
  78. package/utils/Utils.js +34 -5
  79. package/utils/clone.js +6 -0
  80. package/utils/env-vars.js +1 -0
  81. package/utils/index.d.ts +1 -0
  82. package/utils/index.js +1 -0
  83. package/utils/rls-utils.d.ts +35 -0
  84. package/utils/rls-utils.js +97 -0
  85. package/utils/upsert-utils.d.ts +9 -1
  86. package/utils/upsert-utils.js +26 -3
package/errors.js CHANGED
@@ -94,6 +94,30 @@ export class ValidationError extends Error {
94
94
  static cannotUseGlobalContext() {
95
95
  return new ValidationError("Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instance's identity map, use `allowGlobalContext` configuration option or `fork()` instead.");
96
96
  }
97
+ static sessionContextNotSupported() {
98
+ return new ValidationError('Database session context (row level security) is only supported by the PostgreSQL driver. To test a PostgreSQL app without a server, use the `@mikro-orm/pglite` driver instead of sqlite.');
99
+ }
100
+ static sessionContextRequiresImplicitTransactions() {
101
+ return new ValidationError("Cannot set a database session context (row level security) with the 'transaction' strategy while 'implicitTransactions' is disabled. The context is applied on transaction begin, but writes would run without a transaction and silently bypass the policies. Enable 'implicitTransactions', wrap the work in 'em.transactional()', or use the 'connection' session context strategy.");
102
+ }
103
+ static sessionContextWithDisabledTransactions() {
104
+ return new ValidationError("Cannot set a database session context (row level security) with the 'transaction' strategy while transactions are disabled via 'disableTransactions'. The context is applied on transaction begin, so flushes would run without it and silently bypass the policies. Enable transactions, or use the 'connection' session context strategy.");
105
+ }
106
+ static sessionContextInsideTransaction(action = 'set') {
107
+ const advice = action === 'set'
108
+ ? "Set the session context before starting the transaction (e.g. via 'em.fork({ session })')."
109
+ : 'Clear the session context outside the transaction.';
110
+ return new ValidationError(`Cannot ${action} a database session context (row level security) inside an active transaction. The context is applied when the transaction begins or the connection is reserved, so the change would never reach an already-open transaction (with the 'connection' strategy the pinned connection was reserved with the previous context). ${advice}`);
111
+ }
112
+ static cannotStageNonScalarSessionVariable(filterName, argName) {
113
+ return new ValidationError(`Cannot stage the '${argName}' argument of filter '${filterName}' as a session variable (row level security) — only scalar values (string, number, boolean, Date) can be mirrored to the database policy backing the filter.`);
114
+ }
115
+ static sessionContextStreamRequiresTransaction() {
116
+ return new ValidationError("Cannot stream under a database session context (row level security) with the 'transaction' strategy outside a transaction. Streaming never opens the implicit transaction that applies the context, so the streamed rows would not be scoped by it (other tenants' rows would leak). Wrap the stream in 'em.transactional()', or use the 'connection' session context strategy.");
117
+ }
118
+ static connectionSessionContextNotSupported() {
119
+ return new ValidationError("The 'connection' session context strategy requires a driver that supports per-acquire connection hooks (the `postgresql` driver). Use the default 'transaction' strategy instead.");
120
+ }
97
121
  static cannotUseOperatorsInsideEmbeddables(entityName, propName, payload) {
98
122
  return new ValidationError(`Using operators inside embeddables is not allowed, move the operator above. (property: ${Utils.className(entityName)}.${propName}, payload: ${inspect(payload)})`);
99
123
  }
@@ -116,6 +140,11 @@ export class CursorError extends ValidationError {
116
140
  static missingValue(entityName, prop) {
117
141
  return new CursorError(`Invalid cursor condition, value for '${entityName}.${prop}' is missing.`);
118
142
  }
143
+ static invalidCursor(entityName, cause) {
144
+ const error = new CursorError(`Invalid cursor for entity ${entityName}: ${cause.message}`);
145
+ error.cause = cause;
146
+ return error;
147
+ }
119
148
  }
120
149
  /** Error thrown when an optimistic lock conflict is detected during entity persistence. */
121
150
  export class OptimisticLockError extends ValidationError {
@@ -195,6 +224,9 @@ export class MetadataError extends ValidationError {
195
224
  static missingMetadata(entity) {
196
225
  return new MetadataError(`Metadata for entity ${entity} not found`);
197
226
  }
227
+ static ambiguousEntityName(className) {
228
+ return new MetadataError(`Entity name '${className}' is ambiguous, multiple discovered entity classes share it (possibly due to a minifier mangling class names). Use a class reference instead of a string name.`);
229
+ }
198
230
  static invalidPrimaryKey(meta, prop, requiredName) {
199
231
  return this.fromMessage(meta, prop, `has wrong field name, '${requiredName}' is required in current driver`);
200
232
  }
@@ -214,6 +246,16 @@ export class MetadataError extends ValidationError {
214
246
  const suggestion = target.embeddable ? 'Embedded' : 'ManyToOne';
215
247
  return this.fromMessage(meta, prop, `is defined as scalar @Property(), but its type is a discovered entity ${target.className}. Maybe you want to use @${suggestion}() decorator instead?`);
216
248
  }
249
+ static throughRelationMissingProperty(meta, prop, through, side) {
250
+ const target = side === 'owner' ? meta.className : prop.targetMeta.className;
251
+ return this.fromMessage(meta, prop, `uses 'through' entity ${through.className} which has no ManyToOne property pointing to ${target}`);
252
+ }
253
+ static throughRelationCompositeTarget(meta, prop) {
254
+ return this.fromMessage(meta, prop, `uses 'through' option which is not supported for targets with composite primary key`);
255
+ }
256
+ static throughRelationInvalidKind(meta, prop) {
257
+ return this.fromMessage(meta, prop, `uses 'through' option which is only supported for ManyToOne and OneToOne relations`);
258
+ }
217
259
  static fromMissingOption(meta, prop, option) {
218
260
  return this.fromMessage(meta, prop, `is missing '${option}' option`);
219
261
  }
@@ -247,6 +289,54 @@ export class MetadataError extends ValidationError {
247
289
  static triggersNotSupportedByDriver(meta) {
248
290
  return new MetadataError(`Entity ${meta.className} defines database triggers which are not supported by the current driver. Triggers are only available with SQL drivers.`);
249
291
  }
292
+ /** Thrown when row level security is declared on an entity using a driver that does not support it. */
293
+ static rowLevelSecurityNotSupportedByDriver(meta) {
294
+ return new MetadataError(`Entity ${meta.className} declares row level security which is not supported by the current driver. Row level security is only available with the PostgreSQL driver. To test a PostgreSQL app without a server, use the \`@mikro-orm/pglite\` driver instead of sqlite.`);
295
+ }
296
+ /** Thrown when row level security is declared on a non-root entity of an STI hierarchy. */
297
+ static rowLevelSecurityOnNonRootStiEntity(meta) {
298
+ return new MetadataError(`Entity ${meta.className} declares row level security, but it is part of a single table inheritance hierarchy. Declare policies on the root entity ${meta.root.className} instead, as the whole hierarchy shares a single table.`);
299
+ }
300
+ /** Thrown when two policies on the same entity are given the same explicit name. */
301
+ static duplicatePolicyName(meta, name) {
302
+ return new MetadataError(`Entity ${meta.className} declares multiple row level security policies named '${name}'. Policy names must be unique per table; rename one of them or omit the name to use an auto-generated one.`);
303
+ }
304
+ /** Thrown when a filter flagged with `rls` is declared on a driver that does not support row level security. */
305
+ static rlsFilterNotSupportedByDriver(meta, filterName) {
306
+ return new MetadataError(`Filter '${filterName}' on entity ${meta.className} is flagged with 'rls', which is only supported by the PostgreSQL driver. To test a PostgreSQL app without a server, use the \`@mikro-orm/pglite\` driver instead of sqlite.`);
307
+ }
308
+ /** Thrown when a filter flagged with `rls` is declared on a non-root entity of an STI hierarchy. */
309
+ static rlsFilterOnNonRootStiEntity(meta, filterName) {
310
+ return new MetadataError(`Filter '${filterName}' on entity ${meta.className} is flagged with 'rls', but the entity is part of a single table inheritance hierarchy. Declare the filter on the root entity ${meta.root.className} instead, as the whole hierarchy shares a single table and the policy would never be created otherwise.`);
311
+ }
312
+ /** Thrown when a global (config or EM registered) filter is flagged with `rls`; RLS filters must be entity scoped. */
313
+ static rlsFilterMustBeEntityScoped(filterName) {
314
+ return new MetadataError(`Filter '${filterName}' is a global filter and cannot be flagged with 'rls'. RLS filters must be declared on an entity via @Filter() so a policy can be attached to its table.`);
315
+ }
316
+ /** Thrown when an entity-scoped `rls` filter is registered at runtime via `em.addFilter()` instead of in metadata. */
317
+ static rlsFilterCannotBeRegisteredAtRuntime(filterName) {
318
+ return new MetadataError(`Filter '${filterName}' cannot be flagged with 'rls' when registered at runtime via 'em.addFilter()'. RLS filters must be declared in entity metadata via the @Filter() decorator (or the entity 'filters' option) so a policy can be attached to the table.`);
319
+ }
320
+ /** Thrown when a filter's custom `setting` is used with more than one argument. */
321
+ static rlsFilterMultiArgSetting(filterName, args) {
322
+ return new MetadataError(`Filter '${filterName}' sets a custom 'setting' but references multiple arguments (${args.join(', ')}). A custom 'setting' is only allowed for single-argument RLS filters; remove it to use the default 'mikro.${filterName}.<arg>' names.`);
323
+ }
324
+ /** Thrown when an `rls` filter's condition depends on runtime state and cannot be compiled to a static policy. */
325
+ static rlsFilterDependsOnRuntimeState(filterName) {
326
+ return new MetadataError(`Filter '${filterName}' cannot be compiled to an RLS policy because its condition depends on runtime state (it accesses 'em', 'type', 'options' or 'entityName', or resolves asynchronously). Declare an explicit policy instead.`);
327
+ }
328
+ /** Thrown when an `rls` filter compares against a column whose type has no automatic session-variable cast. */
329
+ static rlsFilterUncastableType(filterName, columnType) {
330
+ return new MetadataError(`Filter '${filterName}' cannot be compiled to an RLS policy because the column type '${columnType}' has no automatic session-variable cast. Declare an explicit policy instead.`);
331
+ }
332
+ /** Thrown when an `rls` filter references an argument outside of a direct comparison, which cannot be compiled. */
333
+ static rlsFilterUnsupportedCond(filterName) {
334
+ return new MetadataError(`Filter '${filterName}' cannot be compiled to an RLS policy because it references an argument outside of a direct comparison (only expressions like { prop: args.x } are supported). Declare an explicit policy instead.`);
335
+ }
336
+ /** Thrown when an `rls` filter compares against a column the schema generator does not manage. */
337
+ static rlsFilterUnmanagedColumn(filterName, column) {
338
+ return new MetadataError(`Filter '${filterName}' cannot be compiled to an RLS policy because column '${column}' is not part of the managed schema (e.g. the property is marked 'persist: false' or the column is excluded via 'skipColumns'). Declare an explicit policy instead.`);
339
+ }
250
340
  static fromMessage(meta, prop, message) {
251
341
  return new MetadataError(`${meta.className}.${prop.name} ${message}`);
252
342
  }
@@ -43,7 +43,10 @@ export class EventManager {
43
43
  }));
44
44
  for (const listener of this.#listeners[event] ?? new Set()) {
45
45
  const entities = this.#entities.get(listener);
46
- if (entities.size === 0 || !entity || entities.has(entity.constructor.name)) {
46
+ if (entities.size === 0 ||
47
+ !entity ||
48
+ entities.has(entity.constructor) ||
49
+ entities.has(entity.constructor.name)) {
47
50
  listeners.push(listener[event].bind(listener));
48
51
  }
49
52
  }
@@ -68,7 +71,7 @@ export class EventManager {
68
71
  }
69
72
  for (const listener of this.#listeners[event] ?? new Set()) {
70
73
  const entities = this.#entities.get(listener);
71
- if (entities.size === 0 || entities.has(meta.className)) {
74
+ if (entities.size === 0 || entities.has(meta.class) || entities.has(meta.className)) {
72
75
  this.#cache.set(cacheKey, true);
73
76
  return true;
74
77
  }
@@ -84,6 +87,6 @@ export class EventManager {
84
87
  if (!listener.getSubscribedEntities) {
85
88
  return new Set();
86
89
  }
87
- return new Set(listener.getSubscribedEntities().map(name => Utils.className(name)));
90
+ return new Set(listener.getSubscribedEntities().map(name => Utils.classOrName(name)));
88
91
  }
89
92
  }
package/exceptions.d.ts CHANGED
@@ -102,3 +102,8 @@ export declare class TableNotFoundException extends DatabaseObjectNotFoundExcept
102
102
  */
103
103
  export declare class UniqueConstraintViolationException extends ConstraintViolationException {
104
104
  }
105
+ /**
106
+ * Exception for a row-level security policy violation (failed `WITH CHECK`) detected in the driver.
107
+ */
108
+ export declare class RowLevelSecurityViolationException extends ConstraintViolationException {
109
+ }
package/exceptions.js CHANGED
@@ -115,3 +115,8 @@ export class TableNotFoundException extends DatabaseObjectNotFoundException {
115
115
  */
116
116
  export class UniqueConstraintViolationException extends ConstraintViolationException {
117
117
  }
118
+ /**
119
+ * Exception for a row-level security policy violation (failed `WITH CHECK`) detected in the driver.
120
+ */
121
+ export class RowLevelSecurityViolationException extends ConstraintViolationException {
122
+ }
@@ -19,6 +19,8 @@ export declare class ObjectHydrator extends Hydrator {
19
19
  getEntityHydrator<T extends object>(meta: EntityMetadata<T>, type: 'full' | 'reference', normalizeAccessors?: boolean): EntityHydrator<T>;
20
20
  private createCollectionItemMapper;
21
21
  private wrap;
22
+ /** Renders a key as a single-quoted JS string literal, safe to embed in generated code. */
23
+ private quote;
22
24
  private safeKey;
23
25
  }
24
26
  export {};
@@ -87,7 +87,7 @@ export class ObjectHydrator extends Hydrator {
87
87
  ret.push(` if (data${dataKey} === null) {`);
88
88
  if (prop.ref) {
89
89
  ret.push(` entity${entityKey} = new ScalarReference();`);
90
- ret.push(` entity${entityKey}.bind(entity, '${prop.name}');`);
90
+ ret.push(` entity${entityKey}.bind(entity, ${this.quote(prop.name)});`);
91
91
  ret.push(` entity${entityKey}.set(${nullVal});`);
92
92
  }
93
93
  else {
@@ -127,14 +127,14 @@ export class ObjectHydrator extends Hydrator {
127
127
  if (prop.ref) {
128
128
  ret.push(` const value = isScalarReference(entity${entityKey}) ? entity${entityKey}.unwrap() : entity${entityKey};`);
129
129
  ret.push(` entity${entityKey} = oldValue_${idx} ?? new ScalarReference(value);`);
130
- ret.push(` entity${entityKey}.bind(entity, '${prop.name}');`);
130
+ ret.push(` entity${entityKey}.bind(entity, ${this.quote(prop.name)});`);
131
131
  ret.push(` entity${entityKey}.set(value);`);
132
132
  }
133
133
  ret.push(` }`);
134
134
  if (prop.ref) {
135
135
  ret.push(` if (!entity${entityKey}) {`);
136
136
  ret.push(` entity${entityKey} = new ScalarReference();`);
137
- ret.push(` entity${entityKey}.bind(entity, '${prop.name}');`);
137
+ ret.push(` entity${entityKey}.bind(entity, ${this.quote(prop.name)});`);
138
138
  ret.push(` }`);
139
139
  }
140
140
  return ret;
@@ -220,7 +220,7 @@ export class ObjectHydrator extends Hydrator {
220
220
  ret.push(` }`);
221
221
  ret.push(` if (Array.isArray(data${dataKey})) {`);
222
222
  ret.push(` const items = data${dataKey}.map(value => createCollectionItem_${this.safeKey(prop.name)}(value, entity));`);
223
- ret.push(` const coll = Collection.create(entity, '${prop.name}', items, newEntity);`);
223
+ ret.push(` const coll = Collection.create(entity, ${this.quote(prop.name)}, items, newEntity);`);
224
224
  ret.push(` if (newEntity) {`);
225
225
  ret.push(` coll.setDirty();`);
226
226
  ret.push(` } else {`);
@@ -231,11 +231,11 @@ export class ObjectHydrator extends Hydrator {
231
231
  if (!this.platform.usesPivotTable() && prop.owner && prop.kind === ReferenceKind.MANY_TO_MANY) {
232
232
  ret.push(` } else if (!entity${entityKey} && Array.isArray(data${dataKey})) {`);
233
233
  const items = this.platform.usesPivotTable() || !prop.owner ? 'undefined' : '[]';
234
- ret.push(` const coll = Collection.create(entity, '${prop.name}', ${items}, !!data${dataKey} || newEntity);`);
234
+ ret.push(` const coll = Collection.create(entity, ${this.quote(prop.name)}, ${items}, !!data${dataKey} || newEntity);`);
235
235
  ret.push(` coll.setDirty(false);`);
236
236
  }
237
237
  ret.push(` } else if (!entity${entityKey}) {`);
238
- ret.push(` const coll = Collection.create(entity, '${prop.name}', undefined, newEntity);`);
238
+ ret.push(` const coll = Collection.create(entity, ${this.quote(prop.name)}, undefined, newEntity);`);
239
239
  ret.push(` coll.setDirty(false);`);
240
240
  ret.push(` }`);
241
241
  return ret;
@@ -364,6 +364,9 @@ export class ObjectHydrator extends Hydrator {
364
364
  ret.push(` data${dataKey}.forEach((_, idx_${idx}) => {`);
365
365
  ret.push(...hydrateEmbedded(prop, [...path, `[idx_${idx}]`], `${dataKey}[idx_${idx}]`).map(l => ' ' + l));
366
366
  ret.push(` });`);
367
+ ret.push(` } else if (data${dataKey} === null) {`);
368
+ /* v8 ignore next */
369
+ ret.push(` entity${entityKey} = ${this.config.get('forceUndefined') ? 'undefined' : 'null'};`);
367
370
  ret.push(` }`);
368
371
  return ret;
369
372
  };
@@ -428,10 +431,14 @@ export class ObjectHydrator extends Hydrator {
428
431
  return lines;
429
432
  }
430
433
  wrap(key) {
431
- if (/^\[.*]$/.exec(key)) {
434
+ if (/^\[idx_\d+]$/.exec(key)) {
432
435
  return key;
433
436
  }
434
- return /^\w+$/.exec(key) ? `.${key}` : `['${key}']`;
437
+ return /^\w+$/.exec(key) ? `.${key}` : `[${this.quote(key)}]`;
438
+ }
439
+ /** Renders a key as a single-quoted JS string literal, safe to embed in generated code. */
440
+ quote(key) {
441
+ return `'${key.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
435
442
  }
436
443
  safeKey(key) {
437
444
  return key.replace(/\W/g, '_');
package/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * @module core
4
4
  */
5
5
  export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, EntityName, IndexHints, } from './typings.js';
6
- export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, InferEntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, EntityDTOFlat, EntityDTOProp, SerializeDTO, MigrationDiff, GenerateOptions, FilterObject, IndexFilterQuery, ExtractIndexHints, ExtractDefineEntityProperties, IndexName, IndexColumns, WithUsingOptions, IMigrationRunner, IEntityGenerator, ISeedManager, SeederObject, IMigratorStorage, RequiredEntityData, CheckCallback, TriggerCallback, IndexCallback, FormulaCallback, FormulaColumns, FormulaTable, SchemaTable, SchemaColumns, SchemaColumnRef, EntityDataPropValue, SimpleColumnMeta, Rel, Ref, LazyRef, ScalarRef, EntityRef, ISchemaGenerator, MigrationInfo, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, TriggerDef, RoutineReturns, RoutineBodyCallback, RoutineJsBody, RoutineIgnoreField, RoutineParamConfig, RoutineConfig, RoutineRuntimeType, RoutineArgs, RoutineReturn, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, PopulateHintOptions, Prefixes, } from './typings.js';
6
+ export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, InferEntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, EntityDTOFlat, EntityDTOProp, SerializeDTO, MigrationDiff, GenerateOptions, FilterObject, IndexFilterQuery, ExtractIndexHints, ExtractDefineEntityProperties, IndexName, IndexColumns, WithUsingOptions, IMigrationRunner, IEntityGenerator, ISeedManager, SeederObject, IMigratorStorage, RequiredEntityData, CheckCallback, TriggerCallback, IndexCallback, FormulaCallback, FormulaColumns, FormulaTable, SchemaTable, SchemaColumns, SchemaColumnRef, EntityDataPropValue, SimpleColumnMeta, Rel, Ref, LazyRef, ScalarRef, EntityRef, ISchemaGenerator, MigrationInfo, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, TriggerDef, PolicyDef, PolicyCallback, SessionContext, RoutineReturns, RoutineBodyCallback, RoutineJsBody, RoutineIgnoreField, RoutineParamConfig, RoutineConfig, RoutineRuntimeType, RoutineArgs, RoutineReturn, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, PopulateHintOptions, Prefixes, } from './typings.js';
7
7
  export * from './enums.js';
8
8
  export * from './errors.js';
9
9
  export * from './exceptions.js';
@@ -4,6 +4,8 @@ import { Cascade, ReferenceKind } from '../enums.js';
4
4
  import { Type } from '../types/Type.js';
5
5
  import { Utils } from '../utils/Utils.js';
6
6
  import { EnumArrayType } from '../types/EnumArrayType.js';
7
+ // mirrors `MetadataStorage.META_SYMBOL`, we can't import it here due to a module cycle
8
+ const META_SYMBOL = Symbol.for('@mikro-orm/core/MetadataStorage.META_SYMBOL');
7
9
  /** Class-less entity definition that provides a programmatic API for defining entities without decorators. */
8
10
  export class EntitySchema {
9
11
  /**
@@ -220,8 +222,9 @@ export class EntitySchema {
220
222
  // Only set extends if the parent is NOT the auto-generated class for this same entity.
221
223
  // When the user extends the auto-generated class (from defineEntity without a class option)
222
224
  // and registers their custom class via setClass, we don't want to discover the
223
- // auto-generated class as a separate parent entity.
224
- if (base !== BaseEntity && base.name !== this._meta.className) {
225
+ // auto-generated class as a separate parent entity. A parent carrying its own decorator
226
+ // metadata is a real base class even when a minifier mangles it to the same name as the child.
227
+ if (base !== BaseEntity && (base.name !== this._meta.className || Object.hasOwn(base, META_SYMBOL))) {
225
228
  this._meta.extends ??= base.name ? base : undefined;
226
229
  }
227
230
  }
@@ -117,6 +117,7 @@ export declare class MetadataDiscovery {
117
117
  private createSchemaTable;
118
118
  private initCheckConstraints;
119
119
  private initTriggers;
120
+ private initPolicies;
120
121
  private initGeneratedColumn;
121
122
  private getDefaultVersionValue;
122
123
  private inferDefaultValue;
@@ -125,6 +126,8 @@ export declare class MetadataDiscovery {
125
126
  private initVersionProperty;
126
127
  private initCustomType;
127
128
  private initRelation;
129
+ /** Resolves the `through` option of a virtual to-one relation into a read-only formula property. */
130
+ private initThroughRelation;
128
131
  private initColumnType;
129
132
  private getMappedType;
130
133
  private getPrefix;