@mikro-orm/core 7.1.0-dev.9 → 7.1.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 (53) hide show
  1. package/EntityManager.d.ts +47 -3
  2. package/EntityManager.js +150 -23
  3. package/README.md +2 -1
  4. package/connections/Connection.d.ts +67 -1
  5. package/connections/Connection.js +64 -0
  6. package/drivers/IDatabaseDriver.d.ts +20 -6
  7. package/entity/BaseEntity.d.ts +68 -1
  8. package/entity/BaseEntity.js +18 -0
  9. package/entity/Collection.d.ts +1 -1
  10. package/entity/Collection.js +4 -1
  11. package/entity/EntityAssigner.js +8 -0
  12. package/entity/EntityFactory.js +5 -3
  13. package/entity/EntityLoader.d.ts +8 -1
  14. package/entity/EntityLoader.js +97 -29
  15. package/entity/Reference.d.ts +42 -1
  16. package/entity/Reference.js +9 -0
  17. package/entity/defineEntity.d.ts +69 -16
  18. package/entity/defineEntity.js +17 -0
  19. package/entity/utils.js +4 -5
  20. package/enums.d.ts +8 -1
  21. package/index.d.ts +1 -1
  22. package/metadata/EntitySchema.js +18 -0
  23. package/metadata/MetadataDiscovery.d.ts +1 -0
  24. package/metadata/MetadataDiscovery.js +79 -15
  25. package/metadata/MetadataValidator.d.ts +26 -0
  26. package/metadata/MetadataValidator.js +228 -1
  27. package/metadata/Routine.d.ts +74 -0
  28. package/metadata/Routine.js +140 -0
  29. package/metadata/index.d.ts +1 -0
  30. package/metadata/index.js +1 -0
  31. package/metadata/types.d.ts +75 -8
  32. package/package.json +1 -1
  33. package/platforms/Platform.d.ts +13 -3
  34. package/platforms/Platform.js +51 -6
  35. package/serialization/EntitySerializer.js +4 -3
  36. package/typings.d.ts +323 -21
  37. package/typings.js +32 -12
  38. package/unit-of-work/UnitOfWork.js +43 -5
  39. package/utils/AbstractMigrator.d.ts +9 -4
  40. package/utils/AbstractMigrator.js +60 -28
  41. package/utils/AbstractSchemaGenerator.d.ts +1 -1
  42. package/utils/AbstractSchemaGenerator.js +4 -1
  43. package/utils/Configuration.d.ts +30 -0
  44. package/utils/Configuration.js +45 -0
  45. package/utils/EntityComparator.js +1 -1
  46. package/utils/TransactionManager.js +2 -0
  47. package/utils/Utils.js +1 -1
  48. package/utils/index.d.ts +1 -0
  49. package/utils/index.js +1 -0
  50. package/utils/partition-utils.d.ts +17 -0
  51. package/utils/partition-utils.js +79 -0
  52. package/utils/upsert-utils.d.ts +2 -0
  53. package/utils/upsert-utils.js +26 -1
@@ -43,6 +43,8 @@ export declare abstract class Platform {
43
43
  getEnumArrayCheckConstraintExpression(column: string, items: string[]): string | null;
44
44
  /** Whether this platform supports materialized views. */
45
45
  supportsMaterializedViews(): boolean;
46
+ /** Whether this platform supports declarative table partitioning in schema generation. */
47
+ supportsPartitionedTables(): boolean;
46
48
  /** Returns the schema helper instance for this platform, or undefined if not supported. */
47
49
  getSchemaHelper(): unknown;
48
50
  /** Whether the platform automatically creates indexes on foreign key columns. */
@@ -168,7 +170,7 @@ export declare abstract class Platform {
168
170
  getUuidTypeDeclarationSQL(column: {
169
171
  length?: number;
170
172
  }): string;
171
- /** Extracts the base type name from a full SQL type declaration (e.g. "varchar(255)" -> "varchar"). */
173
+ /** Extracts the base type name from a full SQL type declaration (e.g. `varchar(255)` -> `varchar`). */
172
174
  extractSimpleType(type: string): string;
173
175
  /**
174
176
  * This should be used only to compare types, it can strip some information like the length.
@@ -276,9 +278,17 @@ export declare abstract class Platform {
276
278
  /** Whether the platform supports unsigned integer columns. */
277
279
  supportsUnsigned(): boolean;
278
280
  /**
279
- * Returns the default name of index for the given columns
281
+ * Maximum length of identifiers (table, column, index, constraint, …) the platform supports.
282
+ * Names produced by {@link getIndexName} above this limit are hash-truncated. Defaults to
283
+ * `Infinity` (no truncation); SQL platforms override with their engine's limit
284
+ * (PG 63, MySQL/MariaDB 64, MSSQL/Oracle 128).
280
285
  */
281
- getIndexName(tableName: string, columns: string[], type: 'index' | 'unique' | 'foreign' | 'primary' | 'sequence'): string;
286
+ getMaxIdentifierLength(): number;
287
+ /**
288
+ * Returns the default name of index for the given columns, hash-truncated if it would
289
+ * exceed {@link getMaxIdentifierLength}.
290
+ */
291
+ getIndexName(tableName: string, columns: string[], type: 'index' | 'unique' | 'foreign' | 'primary' | 'sequence' | 'check'): string;
282
292
  /** Returns the default primary key constraint name. */
283
293
  getDefaultPrimaryName(tableName: string, columns: string[]): string;
284
294
  /** Whether the platform supports custom names for primary key constraints. */
@@ -2,12 +2,22 @@ import { clone } from '../utils/clone.js';
2
2
  import { EntityRepository } from '../entity/EntityRepository.js';
3
3
  import { UnderscoreNamingStrategy } from '../naming-strategy/UnderscoreNamingStrategy.js';
4
4
  import { ExceptionConverter } from './ExceptionConverter.js';
5
+ import { MetadataError } from '../errors.js';
5
6
  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
7
  import { parseJsonSafe, Utils } from '../utils/Utils.js';
7
8
  import { ReferenceKind } from '../enums.js';
8
9
  import { Raw } from '../utils/RawQueryFragment.js';
9
10
  /** Symbol used to tag cloned embeddable data for JSON serialization handling. */
10
11
  export const JsonProperty = Symbol('JsonProperty');
12
+ const MULTI_WORD_SQL_TYPES = [
13
+ 'timestamp with time zone',
14
+ 'timestamp without time zone',
15
+ 'time with time zone',
16
+ 'time without time zone',
17
+ 'character varying',
18
+ 'double precision',
19
+ 'bit varying',
20
+ ];
11
21
  /** Abstract base class providing database-specific behavior and SQL dialect differences. */
12
22
  export class Platform {
13
23
  exceptionConverter = new ExceptionConverter();
@@ -62,6 +72,10 @@ export class Platform {
62
72
  supportsMaterializedViews() {
63
73
  return false;
64
74
  }
75
+ /** Whether this platform supports declarative table partitioning in schema generation. */
76
+ supportsPartitionedTables() {
77
+ return false;
78
+ }
65
79
  /** Returns the schema helper instance for this platform, or undefined if not supported. */
66
80
  getSchemaHelper() {
67
81
  return undefined;
@@ -222,9 +236,15 @@ export class Platform {
222
236
  column.length ??= 36;
223
237
  return this.getVarcharTypeDeclarationSQL(column);
224
238
  }
225
- /** Extracts the base type name from a full SQL type declaration (e.g. "varchar(255)" -> "varchar"). */
239
+ /** Extracts the base type name from a full SQL type declaration (e.g. `varchar(255)` -> `varchar`). */
226
240
  extractSimpleType(type) {
227
- return /[^(), ]+/.exec(type.toLowerCase())[0];
241
+ const lower = type.toLowerCase();
242
+ for (const multiWord of MULTI_WORD_SQL_TYPES) {
243
+ if (lower.startsWith(multiWord)) {
244
+ return multiWord;
245
+ }
246
+ }
247
+ return /[^(), ]+/.exec(lower)[0];
228
248
  }
229
249
  /**
230
250
  * This should be used only to compare types, it can strip some information like the length.
@@ -248,6 +268,7 @@ export class Platform {
248
268
  return Type.getType(CharacterType);
249
269
  case 'string':
250
270
  case 'varchar':
271
+ case 'character varying':
251
272
  return Type.getType(StringType);
252
273
  case 'interval':
253
274
  return Type.getType(IntervalType);
@@ -267,6 +288,7 @@ export class Platform {
267
288
  case 'float':
268
289
  return Type.getType(FloatType);
269
290
  case 'double':
291
+ case 'double precision':
270
292
  return Type.getType(DoubleType);
271
293
  case 'integer':
272
294
  return Type.getType(IntegerType);
@@ -286,8 +308,12 @@ export class Platform {
286
308
  return Type.getType(DateType);
287
309
  case 'datetime':
288
310
  case 'timestamp':
311
+ case 'timestamp with time zone':
312
+ case 'timestamp without time zone':
289
313
  return Type.getType(DateTimeType);
290
314
  case 'time':
315
+ case 'time with time zone':
316
+ case 'time without time zone':
291
317
  return Type.getType(TimeType);
292
318
  case 'object':
293
319
  case 'json':
@@ -513,7 +539,8 @@ export class Platform {
513
539
  if (raw) {
514
540
  return this.formatQuery(raw.sql, raw.params);
515
541
  }
516
- return `${quote}${id.toString().replace('.', `${quote}.${quote}`)}${quote}`;
542
+ const escaped = id.toString().replaceAll(quote, quote + quote);
543
+ return `${quote}${escaped.replace('.', `${quote}.${quote}`)}${quote}`;
517
544
  }
518
545
  /** Quotes a literal value for safe embedding in SQL. */
519
546
  quoteValue(value) {
@@ -603,10 +630,26 @@ export class Platform {
603
630
  return false;
604
631
  }
605
632
  /**
606
- * Returns the default name of index for the given columns
633
+ * Maximum length of identifiers (table, column, index, constraint, …) the platform supports.
634
+ * Names produced by {@link getIndexName} above this limit are hash-truncated. Defaults to
635
+ * `Infinity` (no truncation); SQL platforms override with their engine's limit
636
+ * (PG 63, MySQL/MariaDB 64, MSSQL/Oracle 128).
637
+ */
638
+ getMaxIdentifierLength() {
639
+ return Infinity;
640
+ }
641
+ /**
642
+ * Returns the default name of index for the given columns, hash-truncated if it would
643
+ * exceed {@link getMaxIdentifierLength}.
607
644
  */
608
645
  getIndexName(tableName, columns, type) {
609
- return this.namingStrategy.indexName(tableName, columns, type);
646
+ const indexName = this.namingStrategy.indexName(tableName, columns, type);
647
+ const max = this.getMaxIdentifierLength();
648
+ if (indexName.length > max) {
649
+ const suffix = type === 'primary' ? 'pkey' : type;
650
+ return `${indexName.substring(0, max - 8 - type.length)}_${Utils.hash(indexName, 5)}_${suffix}`;
651
+ }
652
+ return indexName;
610
653
  }
611
654
  /** Returns the default primary key constraint name. */
612
655
  getDefaultPrimaryName(tableName, columns) {
@@ -658,7 +701,9 @@ export class Platform {
658
701
  }
659
702
  /** Platform-specific validation of entity metadata. */
660
703
  validateMetadata(meta) {
661
- return;
704
+ if (meta.partitionBy && !this.supportsPartitionedTables()) {
705
+ throw new MetadataError(`Entity ${meta.className} uses partitionBy, but ${this.constructor.name} does not support partitioned tables`);
706
+ }
662
707
  }
663
708
  /**
664
709
  * Generates a custom order by statement given a set of in order values, eg.
@@ -16,7 +16,8 @@ function isVisible(meta, propName, options) {
16
16
  if (Array.isArray(options.fields) && options.fields.length > 0 && !matchesPath(options.fields, propName)) {
17
17
  return false;
18
18
  }
19
- if (Array.isArray(options.populate) && matchesPath(options.populate, propName)) {
19
+ if (Array.isArray(options.populate) &&
20
+ options.populate.find(item => item === propName || item.startsWith(propName + '.'))) {
20
21
  return true;
21
22
  }
22
23
  if (options.exclude?.find(item => item === propName)) {
@@ -224,7 +225,7 @@ export class EntitySerializer {
224
225
  return this.serialize(child, childOptions);
225
226
  }
226
227
  const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
227
- if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
228
+ if (options.forceObject ?? wrapped.__config.get('serialization').forceObject) {
228
229
  return Utils.primaryKeyToObject(meta, pk, visible);
229
230
  }
230
231
  if (Utils.isPlainObject(pk)) {
@@ -248,7 +249,7 @@ export class EntitySerializer {
248
249
  return this.serialize(item, this.extractChildOptions(options, prop.name));
249
250
  }
250
251
  const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
251
- if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
252
+ if (options.forceObject ?? wrapped.__config.get('serialization').forceObject) {
252
253
  return Utils.primaryKeyToObject(wrapped.__meta, pk);
253
254
  }
254
255
  return pk;