@mikro-orm/core 7.0.0-dev.99 → 7.0.0-rc.1

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 (107) hide show
  1. package/EntityManager.d.ts +34 -17
  2. package/EntityManager.js +95 -103
  3. package/MikroORM.d.ts +5 -5
  4. package/MikroORM.js +25 -20
  5. package/cache/FileCacheAdapter.js +11 -3
  6. package/connections/Connection.d.ts +3 -2
  7. package/connections/Connection.js +4 -3
  8. package/drivers/DatabaseDriver.d.ts +11 -11
  9. package/drivers/DatabaseDriver.js +91 -25
  10. package/drivers/IDatabaseDriver.d.ts +50 -20
  11. package/entity/BaseEntity.d.ts +61 -1
  12. package/entity/Collection.d.ts +8 -1
  13. package/entity/Collection.js +12 -13
  14. package/entity/EntityAssigner.js +9 -9
  15. package/entity/EntityFactory.d.ts +6 -1
  16. package/entity/EntityFactory.js +40 -22
  17. package/entity/EntityHelper.d.ts +2 -2
  18. package/entity/EntityHelper.js +27 -4
  19. package/entity/EntityLoader.d.ts +5 -4
  20. package/entity/EntityLoader.js +193 -80
  21. package/entity/EntityRepository.d.ts +27 -7
  22. package/entity/EntityRepository.js +8 -2
  23. package/entity/PolymorphicRef.d.ts +12 -0
  24. package/entity/PolymorphicRef.js +18 -0
  25. package/entity/WrappedEntity.d.ts +2 -2
  26. package/entity/WrappedEntity.js +1 -1
  27. package/entity/defineEntity.d.ts +89 -50
  28. package/entity/defineEntity.js +12 -0
  29. package/entity/index.d.ts +1 -0
  30. package/entity/index.js +1 -0
  31. package/entity/utils.d.ts +6 -1
  32. package/entity/utils.js +33 -0
  33. package/entity/validators.js +2 -2
  34. package/enums.d.ts +2 -2
  35. package/enums.js +1 -0
  36. package/errors.d.ts +16 -8
  37. package/errors.js +40 -13
  38. package/hydration/ObjectHydrator.js +63 -21
  39. package/index.d.ts +1 -1
  40. package/logging/colors.d.ts +1 -1
  41. package/logging/colors.js +7 -6
  42. package/logging/inspect.js +1 -6
  43. package/metadata/EntitySchema.d.ts +43 -13
  44. package/metadata/EntitySchema.js +82 -27
  45. package/metadata/MetadataDiscovery.d.ts +60 -3
  46. package/metadata/MetadataDiscovery.js +665 -154
  47. package/metadata/MetadataProvider.js +3 -1
  48. package/metadata/MetadataStorage.d.ts +13 -6
  49. package/metadata/MetadataStorage.js +64 -19
  50. package/metadata/MetadataValidator.d.ts +32 -2
  51. package/metadata/MetadataValidator.js +196 -31
  52. package/metadata/discover-entities.js +5 -5
  53. package/metadata/types.d.ts +111 -14
  54. package/naming-strategy/AbstractNamingStrategy.d.ts +11 -3
  55. package/naming-strategy/AbstractNamingStrategy.js +12 -0
  56. package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
  57. package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
  58. package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
  59. package/naming-strategy/MongoNamingStrategy.js +6 -6
  60. package/naming-strategy/NamingStrategy.d.ts +17 -3
  61. package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
  62. package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
  63. package/package.json +2 -2
  64. package/platforms/Platform.d.ts +4 -2
  65. package/platforms/Platform.js +5 -2
  66. package/serialization/EntitySerializer.d.ts +3 -0
  67. package/serialization/EntitySerializer.js +15 -13
  68. package/serialization/EntityTransformer.js +6 -6
  69. package/serialization/SerializationContext.d.ts +6 -6
  70. package/typings.d.ts +325 -110
  71. package/typings.js +84 -17
  72. package/unit-of-work/ChangeSet.d.ts +4 -3
  73. package/unit-of-work/ChangeSet.js +2 -3
  74. package/unit-of-work/ChangeSetComputer.d.ts +3 -6
  75. package/unit-of-work/ChangeSetComputer.js +34 -13
  76. package/unit-of-work/ChangeSetPersister.d.ts +12 -10
  77. package/unit-of-work/ChangeSetPersister.js +55 -25
  78. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  79. package/unit-of-work/CommitOrderCalculator.js +13 -13
  80. package/unit-of-work/IdentityMap.d.ts +12 -0
  81. package/unit-of-work/IdentityMap.js +39 -1
  82. package/unit-of-work/UnitOfWork.d.ts +21 -3
  83. package/unit-of-work/UnitOfWork.js +203 -56
  84. package/utils/AbstractSchemaGenerator.js +17 -8
  85. package/utils/AsyncContext.d.ts +6 -0
  86. package/utils/AsyncContext.js +42 -0
  87. package/utils/Configuration.d.ts +52 -11
  88. package/utils/Configuration.js +12 -8
  89. package/utils/Cursor.js +21 -8
  90. package/utils/DataloaderUtils.js +13 -11
  91. package/utils/EntityComparator.d.ts +14 -7
  92. package/utils/EntityComparator.js +132 -46
  93. package/utils/QueryHelper.d.ts +16 -6
  94. package/utils/QueryHelper.js +53 -18
  95. package/utils/RawQueryFragment.d.ts +28 -23
  96. package/utils/RawQueryFragment.js +34 -56
  97. package/utils/RequestContext.js +2 -2
  98. package/utils/TransactionContext.js +2 -2
  99. package/utils/TransactionManager.js +1 -1
  100. package/utils/Utils.d.ts +7 -26
  101. package/utils/Utils.js +25 -79
  102. package/utils/clone.js +7 -21
  103. package/utils/env-vars.d.ts +4 -0
  104. package/utils/env-vars.js +13 -3
  105. package/utils/fs-utils.d.ts +21 -0
  106. package/utils/fs-utils.js +106 -11
  107. package/utils/upsert-utils.d.ts +4 -4
@@ -1,4 +1,4 @@
1
- import type { AnyEntity, Constructor, EntityName, AnyString, CheckCallback, GeneratedColumnCallback, FilterQuery, Dictionary, AutoPath, EntityClass, IndexCallback, ObjectQuery } from '../typings.js';
1
+ import type { AnyEntity, Constructor, EntityName, AnyString, CheckCallback, GeneratedColumnCallback, FormulaCallback, FilterQuery, Dictionary, AutoPath, EntityClass, IndexCallback, ObjectQuery, Raw } from '../typings.js';
2
2
  import type { Cascade, LoadStrategy, DeferMode, QueryOrderMap, EmbeddedPrefixMode } from '../enums.js';
3
3
  import type { Type, types } from '../types/index.js';
4
4
  import type { EntityManager } from '../EntityManager.js';
@@ -11,12 +11,25 @@ export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
11
11
  schema?: string;
12
12
  /** Override default collection/table name. Alias for `tableName`. */
13
13
  collection?: string;
14
+ /**
15
+ * Set default ordering for this entity. This ordering is applied when:
16
+ * - Querying the entity directly via `em.find()`, `em.findAll()`, etc.
17
+ * - Populating the entity as a relation
18
+ *
19
+ * All orderings are combined together. Precedence (highest to lowest):
20
+ * 1. Runtime `FindOptions.orderBy`
21
+ * 2. Relation-level `@OneToMany({ orderBy })` / `@ManyToMany({ orderBy })`
22
+ * 3. Entity-level `@Entity({ orderBy })`
23
+ */
24
+ orderBy?: QueryOrderMap<E> | QueryOrderMap<E>[];
14
25
  /** For {@doclink inheritance-mapping#single-table-inheritance | Single Table Inheritance}. */
15
26
  discriminatorColumn?: (T extends EntityClass<infer P> ? keyof P : string) | AnyString;
16
27
  /** For {@doclink inheritance-mapping#single-table-inheritance | Single Table Inheritance}. */
17
28
  discriminatorMap?: Dictionary<string>;
18
29
  /** For {@doclink inheritance-mapping#single-table-inheritance | Single Table Inheritance}. */
19
30
  discriminatorValue?: number | string;
31
+ /** Set inheritance strategy: 'tpt' for {@doclink inheritance-mapping#table-per-type-inheritance-tpt | Table-Per-Type} inheritance. When set on the root entity, each entity in the hierarchy gets its own table with a FK from child PK to parent PK. */
32
+ inheritance?: 'tpt';
20
33
  /** Enforce use of constructor when creating managed entity instances. */
21
34
  forceConstructor?: boolean;
22
35
  /** Specify constructor parameters to be used in `em.create` or when `forceConstructor` is enabled. Those should be names of declared entity properties in the same order as your constructor uses them. The ORM tries to infer those automatically, use this option in case the inference fails. */
@@ -27,11 +40,24 @@ export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
27
40
  abstract?: boolean;
28
41
  /** Disables change tracking - such entities are ignored during flush. */
29
42
  readonly?: boolean;
30
- /** Marks entity as {@doclink virtual-entities | virtual}. This is set automatically when you use `expression` option. */
43
+ /** Marks entity as {@doclink virtual-entities | virtual}. This is set automatically when you use `expression` option (unless `view` is set). */
31
44
  virtual?: boolean;
45
+ /**
46
+ * Marks entity as a database view. Unlike virtual entities which evaluate expressions at query time,
47
+ * view entities create actual database views. The `expression` option must be provided when `view` is true.
48
+ * View entities are read-only by default.
49
+ *
50
+ * Use `view: true` for regular views, or `view: { materialized: true }` for materialized views (PostgreSQL only).
51
+ * Materialized views store the query results and must be refreshed to update data.
52
+ * Use `view: { materialized: true, withData: false }` to create an unpopulated materialized view.
53
+ */
54
+ view?: boolean | {
55
+ materialized?: boolean;
56
+ withData?: boolean;
57
+ };
32
58
  /** Used to make ORM aware of externally defined triggers. This is needed for MS SQL Server multi inserts, ignored in other dialects. */
33
59
  hasTriggers?: boolean;
34
- /** SQL query that maps to a {@doclink virtual-entities | virtual entity}. */
60
+ /** SQL query that maps to a {@doclink virtual-entities | virtual entity}, or for view entities, the view definition. */
35
61
  expression?: string | ((em: any, where: ObjectQuery<E>, options: FindOptions<E, any, any, any>, stream?: boolean) => object);
36
62
  /** Set {@doclink repositories#custom-repository | custom repository class}. */
37
63
  repository?: () => Constructor;
@@ -108,22 +134,22 @@ export interface PropertyOptions<Owner> {
108
134
  * Specify default column value for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}.
109
135
  * This is a runtime value, assignable to the entity property. (SQL only)
110
136
  */
111
- default?: string | string[] | number | number[] | boolean | null;
137
+ default?: string | string[] | number | number[] | boolean | null | Date | Raw;
112
138
  /**
113
139
  * Specify SQL functions for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
114
140
  * Since v4 you should use defaultRaw for SQL functions. e.g. now()
115
141
  */
116
- defaultRaw?: string;
142
+ defaultRaw?: string | Raw;
117
143
  /**
118
144
  * Set to map some SQL snippet for the entity.
119
145
  *
120
146
  * @see https://mikro-orm.io/docs/defining-entities#formulas Formulas
121
147
  */
122
- formula?: string | ((alias: string) => string);
148
+ formula?: string | FormulaCallback<Owner>;
123
149
  /**
124
150
  * For generated columns. This will be appended to the column type after the `generated always` clause.
125
151
  */
126
- generated?: string | GeneratedColumnCallback<Owner>;
152
+ generated?: string | Raw | GeneratedColumnCallback<Owner>;
127
153
  /**
128
154
  * Set column as nullable for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}.
129
155
  */
@@ -307,8 +333,8 @@ export interface PropertyOptions<Owner> {
307
333
  ignoreSchemaChanges?: ('type' | 'extra' | 'default')[];
308
334
  }
309
335
  export interface ReferenceOptions<Owner, Target> extends PropertyOptions<Owner> {
310
- /** Set target entity type. */
311
- entity?: string | (() => EntityName<Target>);
336
+ /** Set target entity type. For polymorphic relations, pass an array of entity types. */
337
+ entity?: () => EntityName<Target> | EntityName<Target>[];
312
338
  /** Set what actions on owning entity should be cascaded to the relationship. Defaults to [Cascade.PERSIST, Cascade.MERGE] (see {@doclink cascading}). */
313
339
  cascade?: Cascade[];
314
340
  /** Always load the relationship. Discouraged for use with to-many relations for performance reasons. */
@@ -323,7 +349,20 @@ export interface ReferenceOptions<Owner, Target> extends PropertyOptions<Owner>
323
349
  * @ignore
324
350
  */
325
351
  export type ColumnType = 'int' | 'int4' | 'integer' | 'bigint' | 'int8' | 'int2' | 'tinyint' | 'smallint' | 'mediumint' | 'double' | 'double precision' | 'real' | 'float8' | 'decimal' | 'numeric' | 'float' | 'float4' | 'datetime' | 'time' | 'time with time zone' | 'timestamp' | 'timestamp with time zone' | 'timetz' | 'timestamptz' | 'date' | 'interval' | 'character varying' | 'varchar' | 'char' | 'character' | 'uuid' | 'text' | 'tinytext' | 'mediumtext' | 'longtext' | 'boolean' | 'bool' | 'bit' | 'enum' | 'blob' | 'tinyblob' | 'mediumblob' | 'longblob' | 'bytea' | 'point' | 'line' | 'lseg' | 'box' | 'circle' | 'path' | 'polygon' | 'geometry' | 'tsvector' | 'tsquery' | 'json' | 'jsonb';
326
- export interface ManyToOneOptions<Owner, Target> extends ReferenceOptions<Owner, Target> {
352
+ interface PolymorphicOptions {
353
+ /**
354
+ * For polymorphic relations. Specifies the property name that stores the entity type discriminator.
355
+ * Defaults to the property name. Only used when `entity` returns an array of types.
356
+ * For M:N relations, this is the column name in the pivot table.
357
+ */
358
+ discriminator?: string;
359
+ /**
360
+ * For polymorphic relations. Custom mapping of discriminator values to entity class names.
361
+ * If not provided, table names are used as discriminator values.
362
+ */
363
+ discriminatorMap?: Dictionary<string>;
364
+ }
365
+ export interface ManyToOneOptions<Owner, Target> extends ReferenceOptions<Owner, Target>, PolymorphicOptions {
327
366
  /** Point to the inverse side property name. */
328
367
  inversedBy?: (string & keyof Target) | ((e: Target) => any);
329
368
  /** Wrap the entity in {@apilink Reference} wrapper. */
@@ -342,6 +381,8 @@ export interface ManyToOneOptions<Owner, Target> extends ReferenceOptions<Owner,
342
381
  referenceColumnName?: string;
343
382
  /** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
344
383
  referencedColumnNames?: string[];
384
+ /** Specify the property name on the target entity that this FK references instead of the primary key. */
385
+ targetKey?: string & keyof Target;
345
386
  /** What to do when the target entity gets deleted. */
346
387
  deleteRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
347
388
  /** What to do when the reference to the target entity gets updated. */
@@ -375,7 +416,7 @@ export interface OneToManyOptions<Owner, Target> extends ReferenceOptions<Owner,
375
416
  /** Point to the owning side property name. */
376
417
  mappedBy: (string & keyof Target) | ((e: Target) => any);
377
418
  }
378
- export interface OneToOneOptions<Owner, Target> extends Partial<Omit<OneToManyOptions<Owner, Target>, 'orderBy'>> {
419
+ export interface OneToOneOptions<Owner, Target> extends Partial<Omit<OneToManyOptions<Owner, Target>, 'orderBy'>>, PolymorphicOptions {
379
420
  /** Set this side as owning. Owning side is where the foreign key is defined. This option is not required if you use `inversedBy` or `mappedBy` to distinguish owning and inverse side. */
380
421
  owner?: boolean;
381
422
  /** Point to the inverse side property name. */
@@ -388,6 +429,8 @@ export interface OneToOneOptions<Owner, Target> extends Partial<Omit<OneToManyOp
388
429
  mapToPk?: boolean;
389
430
  /** When a part of a composite column is shared in other properties, use this option to specify what columns are considered as owned by this property. This is useful when your composite property is nullable, but parts of it are not. */
390
431
  ownColumns?: string[];
432
+ /** Specify the property name on the target entity that this FK references instead of the primary key. */
433
+ targetKey?: string & keyof Target;
391
434
  /** What to do when the target entity gets deleted. */
392
435
  deleteRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
393
436
  /** What to do when the reference to the target entity gets updated. */
@@ -399,7 +442,7 @@ export interface OneToOneOptions<Owner, Target> extends Partial<Omit<OneToManyOp
399
442
  /** Enable/disable foreign key constraint creation on this relation */
400
443
  createForeignKeyConstraint?: boolean;
401
444
  }
402
- export interface ManyToManyOptions<Owner, Target> extends ReferenceOptions<Owner, Target> {
445
+ export interface ManyToManyOptions<Owner, Target> extends ReferenceOptions<Owner, Target>, PolymorphicOptions {
403
446
  /** Set this side as owning. Owning side is where the foreign key is defined. This option is not required if you use `inversedBy` or `mappedBy` to distinguish owning and inverse side. */
404
447
  owner?: boolean;
405
448
  /** Point to the inverse side property name. */
@@ -417,7 +460,7 @@ export interface ManyToManyOptions<Owner, Target> extends ReferenceOptions<Owner
417
460
  /** Override default name for pivot table (see {@doclink naming-strategy | Naming Strategy}). */
418
461
  pivotTable?: string;
419
462
  /** Set pivot entity for this relation (see {@doclink collections#custom-pivot-table-entity | Custom pivot table entity}). */
420
- pivotEntity?: string | (() => EntityName<any>);
463
+ pivotEntity?: () => EntityName;
421
464
  /** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
422
465
  joinColumn?: string;
423
466
  /** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
@@ -438,7 +481,7 @@ export interface ManyToManyOptions<Owner, Target> extends ReferenceOptions<Owner
438
481
  createForeignKeyConstraint?: boolean;
439
482
  }
440
483
  export interface EmbeddedOptions<Owner, Target> extends PropertyOptions<Owner> {
441
- entity?: string | (() => EntityName<Target> | EntityName<Target>[]);
484
+ entity?: () => EntityName<Target> | EntityName[];
442
485
  prefix?: string | boolean;
443
486
  prefixMode?: EmbeddedPrefixMode;
444
487
  object?: boolean;
@@ -447,6 +490,9 @@ export interface EmbeddedOptions<Owner, Target> extends PropertyOptions<Owner> {
447
490
  export interface EmbeddableOptions<Owner> {
448
491
  /** Specify constructor parameters to be used in `em.create` or when `forceConstructor` is enabled. Those should be names of declared entity properties in the same order as your constructor uses them. The ORM tries to infer those automatically, use this option in case the inference fails. */
449
492
  constructorParams?: (Owner extends EntityClass<infer P> ? keyof P : string)[];
493
+ /** For polymorphic embeddables. Specify the property name that stores the discriminator value. Alias for `discriminatorColumn`. */
494
+ discriminator?: (Owner extends EntityClass<infer P> ? keyof P : string) | AnyString;
495
+ /** For polymorphic embeddables. @deprecated Use `discriminator` instead. */
450
496
  discriminatorColumn?: (Owner extends EntityClass<infer P> ? keyof P : string) | AnyString;
451
497
  discriminatorMap?: Dictionary<string>;
452
498
  discriminatorValue?: number | string;
@@ -465,16 +511,67 @@ export interface SerializedPrimaryKeyOptions<T> extends PropertyOptions<T> {
465
511
  }
466
512
  type MaybeArray<T> = T | T[];
467
513
  type Properties<T, H extends string> = MaybeArray<AutoPath<T, H>>;
514
+ /** Options for column within an index, supporting advanced index features like prefix length and collation. */
515
+ export interface IndexColumnOptions {
516
+ /** Column name or property path. */
517
+ name: string;
518
+ /** Sort order for the column (default: ASC). */
519
+ sort?: 'ASC' | 'DESC' | 'asc' | 'desc';
520
+ /** NULLS ordering for the column (PostgreSQL). */
521
+ nulls?: 'FIRST' | 'LAST' | 'first' | 'last';
522
+ /** Prefix length for the column (MySQL, MariaDB). */
523
+ length?: number;
524
+ /** Collation for the column (PostgreSQL, SQLite, or MySQL/MariaDB via expression). */
525
+ collation?: string;
526
+ }
468
527
  interface BaseOptions<T, H extends string> {
469
528
  name?: string;
470
529
  properties?: (T extends EntityClass<infer P> ? Properties<P, H> : Properties<T, H>);
471
530
  options?: Dictionary;
472
531
  expression?: string | (T extends EntityClass<infer P> ? IndexCallback<P> : IndexCallback<T>);
532
+ /**
533
+ * Advanced column options for the index.
534
+ * When specified, allows fine-grained control over each column in the index including
535
+ * sort order, nulls ordering, prefix length, and collation.
536
+ * If both `columns` and `properties` are specified, `columns` takes precedence for index creation.
537
+ */
538
+ columns?: IndexColumnOptions[];
539
+ /**
540
+ * Columns to include in the index but not as part of the key (PostgreSQL, MSSQL).
541
+ * These columns are stored in the leaf level of the index but not used for searching.
542
+ */
543
+ include?: (T extends EntityClass<infer P> ? Properties<P, H> : Properties<T, H>);
544
+ /** Fill factor for the index as a percentage 0-100 (PostgreSQL, MSSQL). */
545
+ fillFactor?: number;
473
546
  }
474
547
  export interface UniqueOptions<T, H extends string = string> extends BaseOptions<T, H> {
475
548
  deferMode?: DeferMode | `${DeferMode}`;
549
+ /**
550
+ * Whether the index is disabled (MSSQL only).
551
+ * A disabled index is not used for query planning and is not maintained on writes.
552
+ * It can be re-enabled later using `ALTER INDEX ... REBUILD`.
553
+ */
554
+ disabled?: boolean;
476
555
  }
477
556
  export interface IndexOptions<T, H extends string = string> extends BaseOptions<T, H> {
478
557
  type?: string;
558
+ /**
559
+ * Whether the index is invisible/hidden from the query optimizer (MySQL 8+, MariaDB 10.6+, MongoDB).
560
+ * An invisible index is still maintained on writes but not used for query planning.
561
+ * Useful for testing the impact of removing an index before actually dropping it.
562
+ */
563
+ invisible?: boolean;
564
+ /**
565
+ * Whether the index is disabled (MSSQL only).
566
+ * A disabled index is not used for query planning and is not maintained on writes.
567
+ * It can be re-enabled later using `ALTER INDEX ... REBUILD`.
568
+ */
569
+ disabled?: boolean;
570
+ /**
571
+ * Whether the index should be clustered (MariaDB, MSSQL).
572
+ * A clustered index determines the physical order of data in the table.
573
+ * Only one clustered index can exist per table.
574
+ */
575
+ clustered?: boolean;
479
576
  }
480
577
  export {};
@@ -26,10 +26,18 @@ export declare abstract class AbstractNamingStrategy implements NamingStrategy {
26
26
  * @inheritDoc
27
27
  */
28
28
  inverseSideName(entityName: string, propertyName: string, kind: ReferenceKind): string;
29
- abstract classToTableName(entityName: string): string;
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ manyToManyPropertyName(ownerEntityName: string, targetEntityName: string, pivotTableName: string, ownerTableName: string, schemaName?: string): string;
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ discriminatorColumnName(baseName: string): string;
37
+ abstract classToTableName(entityName: string, tableName?: string): string;
30
38
  abstract joinColumnName(propertyName: string): string;
31
- abstract joinKeyColumnName(entityName: string, referencedColumnName?: string): string;
32
- abstract joinTableName(sourceEntity: string, targetEntity: string, propertyName?: string): string;
39
+ abstract joinKeyColumnName(entityName: string, referencedColumnName?: string, composite?: boolean, tableName?: string): string;
40
+ abstract joinTableName(sourceEntity: string, targetEntity: string, propertyName?: string, tableName?: string): string;
33
41
  abstract propertyToColumnName(propertyName: string, object?: boolean): string;
34
42
  abstract referenceColumnName(): string;
35
43
  }
@@ -79,4 +79,16 @@ export class AbstractNamingStrategy {
79
79
  }
80
80
  return entityName[0].toLowerCase() + entityName.substring(1) + suffix;
81
81
  }
82
+ /**
83
+ * @inheritDoc
84
+ */
85
+ manyToManyPropertyName(ownerEntityName, targetEntityName, pivotTableName, ownerTableName, schemaName) {
86
+ return this.columnNameToProperty(pivotTableName.replace(new RegExp('^' + ownerTableName + '_'), ''));
87
+ }
88
+ /**
89
+ * @inheritDoc
90
+ */
91
+ discriminatorColumnName(baseName) {
92
+ return this.propertyToColumnName(baseName + 'Type');
93
+ }
82
94
  }
@@ -3,10 +3,10 @@ import { AbstractNamingStrategy } from './AbstractNamingStrategy.js';
3
3
  * This strategy keeps original entity/property names for table/column.
4
4
  */
5
5
  export declare class EntityCaseNamingStrategy extends AbstractNamingStrategy {
6
- classToTableName(entityName: string): string;
6
+ classToTableName(entityName: string, tableName?: string): string;
7
7
  joinColumnName(propertyName: string): string;
8
- joinKeyColumnName(entityName: string, referencedColumnName?: string, composite?: boolean): string;
9
- joinTableName(sourceEntity: string, targetEntity: string, propertyName: string): string;
8
+ joinKeyColumnName(entityName: string, referencedColumnName?: string, composite?: boolean, tableName?: string): string;
9
+ joinTableName(sourceEntity: string, targetEntity: string, propertyName: string, tableName?: string): string;
10
10
  propertyToColumnName(propertyName: string): string;
11
11
  referenceColumnName(): string;
12
12
  }
@@ -3,21 +3,22 @@ import { AbstractNamingStrategy } from './AbstractNamingStrategy.js';
3
3
  * This strategy keeps original entity/property names for table/column.
4
4
  */
5
5
  export class EntityCaseNamingStrategy extends AbstractNamingStrategy {
6
- classToTableName(entityName) {
7
- return entityName;
6
+ classToTableName(entityName, tableName) {
7
+ return tableName ?? entityName;
8
8
  }
9
9
  joinColumnName(propertyName) {
10
10
  return propertyName;
11
11
  }
12
- joinKeyColumnName(entityName, referencedColumnName, composite = false) {
12
+ joinKeyColumnName(entityName, referencedColumnName, composite, tableName) {
13
+ entityName = this.classToTableName(entityName, tableName);
13
14
  const name = entityName.substr(0, 1).toLowerCase() + entityName.substr(1);
14
15
  if (composite && referencedColumnName) {
15
16
  return name + '_' + referencedColumnName;
16
17
  }
17
18
  return name;
18
19
  }
19
- joinTableName(sourceEntity, targetEntity, propertyName) {
20
- return this.classToTableName(sourceEntity) + '_' + this.propertyToColumnName(propertyName);
20
+ joinTableName(sourceEntity, targetEntity, propertyName, tableName) {
21
+ return this.classToTableName(sourceEntity, tableName) + '_' + this.propertyToColumnName(propertyName);
21
22
  }
22
23
  propertyToColumnName(propertyName) {
23
24
  return propertyName;
@@ -1,9 +1,9 @@
1
1
  import { AbstractNamingStrategy } from './AbstractNamingStrategy.js';
2
2
  export declare class MongoNamingStrategy extends AbstractNamingStrategy {
3
- classToTableName(entityName: string): string;
3
+ classToTableName(entityName: string, tableName?: string): string;
4
4
  joinColumnName(propertyName: string): string;
5
- joinKeyColumnName(entityName: string, referencedColumnName?: string): string;
6
- joinTableName(sourceEntity: string, targetEntity: string, propertyName: string): string;
5
+ joinKeyColumnName(entityName: string, referencedColumnName?: string, composite?: boolean, tableName?: string): string;
6
+ joinTableName(sourceEntity: string, targetEntity: string, propertyName: string, tableName?: string): string;
7
7
  propertyToColumnName(propertyName: string): string;
8
8
  referenceColumnName(): string;
9
9
  }
@@ -1,16 +1,16 @@
1
1
  import { AbstractNamingStrategy } from './AbstractNamingStrategy.js';
2
2
  export class MongoNamingStrategy extends AbstractNamingStrategy {
3
- classToTableName(entityName) {
4
- return entityName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
3
+ classToTableName(entityName, tableName) {
4
+ return tableName ?? entityName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
5
5
  }
6
6
  joinColumnName(propertyName) {
7
7
  return propertyName;
8
8
  }
9
- joinKeyColumnName(entityName, referencedColumnName) {
10
- return entityName;
9
+ joinKeyColumnName(entityName, referencedColumnName, composite, tableName) {
10
+ return tableName ?? entityName;
11
11
  }
12
- joinTableName(sourceEntity, targetEntity, propertyName) {
13
- return this.classToTableName(sourceEntity) + '_' + this.propertyToColumnName(propertyName);
12
+ joinTableName(sourceEntity, targetEntity, propertyName, tableName) {
13
+ return this.classToTableName(sourceEntity, tableName) + '_' + this.propertyToColumnName(propertyName);
14
14
  }
15
15
  propertyToColumnName(propertyName) {
16
16
  return propertyName;
@@ -7,7 +7,7 @@ export interface NamingStrategy {
7
7
  /**
8
8
  * Return a table name for an entity class
9
9
  */
10
- classToTableName(entityName: string): string;
10
+ classToTableName(entityName: string, tableName?: string): string;
11
11
  /**
12
12
  * Return a migration name. This name should allow ordering.
13
13
  */
@@ -67,11 +67,11 @@ export interface NamingStrategy {
67
67
  /**
68
68
  * Return a join table name
69
69
  */
70
- joinTableName(sourceEntity: string, targetEntity: string, propertyName: string): string;
70
+ joinTableName(sourceEntity: string, targetEntity: string, propertyName: string, tableName?: string): string;
71
71
  /**
72
72
  * Return the foreign key column name for the given parameters
73
73
  */
74
- joinKeyColumnName(entityName: string, referencedColumnName?: string, composite?: boolean): string;
74
+ joinKeyColumnName(entityName: string, referencedColumnName?: string, composite?: boolean, tableName?: string): string;
75
75
  /**
76
76
  * Returns key/constraint name for the given type. Some drivers might not support all the types (e.g. mysql and sqlite enforce the PK name).
77
77
  */
@@ -85,4 +85,18 @@ export interface NamingStrategy {
85
85
  * Returns the name of the inverse side property. Used in the `EntityGenerator` with `bidirectionalRelations` option.
86
86
  */
87
87
  inverseSideName(entityName: string, propertyName: string, kind: ReferenceKind): string;
88
+ /**
89
+ * Return a property name for a many-to-many relation (used in `EntityGenerator`).
90
+ *
91
+ * @param ownerEntityName - The owner entity class name
92
+ * @param targetEntityName - The target entity class name
93
+ * @param pivotTableName - The pivot table name
94
+ * @param ownerTableName - The owner table name
95
+ * @param schemaName - The schema name (if any)
96
+ */
97
+ manyToManyPropertyName(ownerEntityName: string, targetEntityName: string, pivotTableName: string, ownerTableName: string, schemaName?: string): string;
98
+ /**
99
+ * Returns the discriminator column name for polymorphic relations.
100
+ */
101
+ discriminatorColumnName(baseName: string): string;
88
102
  }
@@ -1,9 +1,9 @@
1
1
  import { AbstractNamingStrategy } from './AbstractNamingStrategy.js';
2
2
  export declare class UnderscoreNamingStrategy extends AbstractNamingStrategy {
3
- classToTableName(entityName: string): string;
3
+ classToTableName(entityName: string, tableName?: string): string;
4
4
  joinColumnName(propertyName: string): string;
5
- joinKeyColumnName(entityName: string, referencedColumnName?: string): string;
6
- joinTableName(sourceEntity: string, targetEntity: string, propertyName: string): string;
5
+ joinKeyColumnName(entityName: string, referencedColumnName?: string, composite?: boolean, tableName?: string): string;
6
+ joinTableName(sourceEntity: string, targetEntity: string, propertyName: string, tableName?: string): string;
7
7
  propertyToColumnName(propertyName: string, object?: boolean): string;
8
8
  referenceColumnName(): string;
9
9
  private underscore;
@@ -1,16 +1,16 @@
1
1
  import { AbstractNamingStrategy } from './AbstractNamingStrategy.js';
2
2
  export class UnderscoreNamingStrategy extends AbstractNamingStrategy {
3
- classToTableName(entityName) {
4
- return this.underscore(entityName);
3
+ classToTableName(entityName, tableName) {
4
+ return tableName ?? this.underscore(entityName);
5
5
  }
6
6
  joinColumnName(propertyName) {
7
7
  return this.underscore(propertyName) + '_' + this.referenceColumnName();
8
8
  }
9
- joinKeyColumnName(entityName, referencedColumnName) {
10
- return this.classToTableName(entityName) + '_' + (referencedColumnName || this.referenceColumnName());
9
+ joinKeyColumnName(entityName, referencedColumnName, composite, tableName) {
10
+ return this.classToTableName(entityName, tableName) + '_' + (referencedColumnName || this.referenceColumnName());
11
11
  }
12
- joinTableName(sourceEntity, targetEntity, propertyName) {
13
- return this.classToTableName(sourceEntity) + '_' + this.classToTableName(propertyName);
12
+ joinTableName(sourceEntity, targetEntity, propertyName, tableName) {
13
+ return this.classToTableName(sourceEntity, tableName) + '_' + this.classToTableName(propertyName);
14
14
  }
15
15
  propertyToColumnName(propertyName, object) {
16
16
  return this.underscore(propertyName);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
3
  "type": "module",
4
- "version": "7.0.0-dev.99",
4
+ "version": "7.0.0-rc.1",
5
5
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
6
6
  "exports": {
7
7
  "./package.json": "./package.json",
@@ -50,7 +50,7 @@
50
50
  "node": ">= 22.17.0"
51
51
  },
52
52
  "scripts": {
53
- "build": "yarn clean && yarn compile && yarn copy",
53
+ "build": "yarn compile && yarn copy",
54
54
  "clean": "yarn run -T rimraf ./dist",
55
55
  "compile": "yarn run -T tsc -p tsconfig.build.json",
56
56
  "copy": "node ../../scripts/copy.mjs"
@@ -8,6 +8,7 @@ import type { IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
8
8
  import { Type } from '../types/index.js';
9
9
  import type { MikroORM } from '../MikroORM.js';
10
10
  import type { TransformContext } from '../types/Type.js';
11
+ import { Raw } from '../utils/RawQueryFragment.js';
11
12
  export declare const JsonProperty: unique symbol;
12
13
  export declare abstract class Platform {
13
14
  protected readonly exceptionConverter: ExceptionConverter;
@@ -27,6 +28,7 @@ export declare abstract class Platform {
27
28
  supportsNativeEnums(): boolean;
28
29
  /** for postgres text enums (default) */
29
30
  usesEnumCheckConstraints(): boolean;
31
+ supportsMaterializedViews(): boolean;
30
32
  getSchemaHelper(): unknown;
31
33
  indexForeignKeys(): boolean;
32
34
  /**
@@ -141,8 +143,8 @@ export declare abstract class Platform {
141
143
  unmarshallArray(value: string): string[];
142
144
  getBlobDeclarationSQL(): string;
143
145
  getJsonDeclarationSQL(): string;
144
- getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string;
145
- getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string;
146
+ getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string | Raw;
147
+ getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string | Raw;
146
148
  getJsonIndexDefinition(index: {
147
149
  columnNames: string[];
148
150
  }): string[];
@@ -5,7 +5,7 @@ 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
6
  import { parseJsonSafe } from '../utils/Utils.js';
7
7
  import { ReferenceKind } from '../enums.js';
8
- import { RawQueryFragment } from '../utils/RawQueryFragment.js';
8
+ import { Raw } from '../utils/RawQueryFragment.js';
9
9
  export const JsonProperty = Symbol('JsonProperty');
10
10
  export class Platform {
11
11
  exceptionConverter = new ExceptionConverter();
@@ -41,6 +41,9 @@ export class Platform {
41
41
  usesEnumCheckConstraints() {
42
42
  return false;
43
43
  }
44
+ supportsMaterializedViews() {
45
+ return false;
46
+ }
44
47
  getSchemaHelper() {
45
48
  return undefined;
46
49
  }
@@ -330,7 +333,7 @@ export class Platform {
330
333
  return value;
331
334
  }
332
335
  quoteIdentifier(id, quote = '`') {
333
- const raw = RawQueryFragment.getKnownFragment(id);
336
+ const raw = Raw.getKnownFragment(id);
334
337
  if (raw) {
335
338
  return this.formatQuery(raw.sql, raw.params);
336
339
  }
@@ -4,6 +4,7 @@ export declare class EntitySerializer {
4
4
  static serialize<T extends object, P extends string = never, E extends string = never>(entity: T, options?: SerializeOptions<T, P, E>): EntityDTO<Loaded<T, P>>;
5
5
  private static propertyName;
6
6
  private static processProperty;
7
+ private static processCustomType;
7
8
  private static extractChildOptions;
8
9
  private static processEntity;
9
10
  private static processCollection;
@@ -23,6 +24,8 @@ export interface SerializeOptions<T, P extends string = never, E extends string
23
24
  skipNull?: boolean;
24
25
  /** Only include properties for a specific group. If a property does not specify any group, it will be included, otherwise only properties with a matching group are included. */
25
26
  groups?: string[];
27
+ /** Convert custom types to their database representation. By default, the `Type.toJSON` method is invoked instead. */
28
+ convertCustomTypes?: boolean;
26
29
  }
27
30
  /**
28
31
  * Converts entity instance to POJO, converting the `Collection`s to arrays and unwrapping the `Reference` wrapper, while respecting the serialization options.
@@ -69,13 +69,13 @@ export class EntitySerializer {
69
69
  if (!isVisible(meta, prop, options)) {
70
70
  continue;
71
71
  }
72
- const cycle = root.visit(meta.className, prop);
72
+ const cycle = root.visit(meta.class, prop);
73
73
  if (cycle && visited) {
74
74
  continue;
75
75
  }
76
76
  const val = this.processProperty(prop, entity, options);
77
77
  if (!cycle) {
78
- root.leave(meta.className, prop);
78
+ root.leave(meta.class, prop);
79
79
  }
80
80
  if (options.skipNull && Utils.isPlainObject(val)) {
81
81
  Utils.dropUndefinedProperties(val, null);
@@ -159,12 +159,20 @@ export class EntitySerializer {
159
159
  return helper(value).toJSON();
160
160
  }
161
161
  }
162
- const customType = property?.customType;
163
- if (customType) {
164
- return customType.toJSON(value, wrapped.__platform);
162
+ if (property.customType) {
163
+ return this.processCustomType(value, property, wrapped.__platform, options.convertCustomTypes);
165
164
  }
166
165
  return wrapped.__platform.normalizePrimaryKey(value);
167
166
  }
167
+ static processCustomType(value, prop, platform, convertCustomTypes) {
168
+ if (!prop.customType) {
169
+ return value;
170
+ }
171
+ if (convertCustomTypes) {
172
+ return prop.customType.convertToDatabaseValue(value, platform, { mode: 'serialization' });
173
+ }
174
+ return prop.customType.toJSON(value, platform);
175
+ }
168
176
  static extractChildOptions(options, prop) {
169
177
  return {
170
178
  ...options,
@@ -183,10 +191,7 @@ export class EntitySerializer {
183
191
  if (expand) {
184
192
  return this.serialize(child, childOptions);
185
193
  }
186
- let pk = wrapped.getPrimaryKey();
187
- if (prop.customType) {
188
- pk = prop.customType.toJSON(pk, wrapped.__platform);
189
- }
194
+ const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
190
195
  if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
191
196
  return Utils.primaryKeyToObject(meta, pk, visible);
192
197
  }
@@ -210,10 +215,7 @@ export class EntitySerializer {
210
215
  if (populated || !wrapped.__managed) {
211
216
  return this.serialize(item, this.extractChildOptions(options, prop.name));
212
217
  }
213
- let pk = wrapped.getPrimaryKey();
214
- if (prop.customType) {
215
- pk = prop.customType.toJSON(pk, wrapped.__platform);
216
- }
218
+ const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
217
219
  if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
218
220
  return Utils.primaryKeyToObject(wrapped.__meta, pk);
219
221
  }