@mikro-orm/core 7.0.0-dev.5 → 7.0.0-dev.50

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 (115) hide show
  1. package/EntityManager.d.ts +81 -27
  2. package/EntityManager.js +287 -175
  3. package/MikroORM.d.ts +6 -6
  4. package/MikroORM.js +31 -74
  5. package/README.md +3 -2
  6. package/cache/FileCacheAdapter.d.ts +2 -1
  7. package/cache/FileCacheAdapter.js +6 -4
  8. package/connections/Connection.d.ts +9 -5
  9. package/connections/Connection.js +16 -13
  10. package/decorators/Embedded.d.ts +5 -11
  11. package/decorators/Entity.d.ts +18 -3
  12. package/decorators/Indexed.d.ts +2 -2
  13. package/decorators/ManyToMany.d.ts +2 -0
  14. package/decorators/ManyToOne.d.ts +4 -0
  15. package/decorators/OneToOne.d.ts +4 -0
  16. package/decorators/Property.d.ts +53 -9
  17. package/decorators/Transactional.d.ts +1 -0
  18. package/decorators/Transactional.js +3 -3
  19. package/decorators/index.d.ts +1 -1
  20. package/drivers/DatabaseDriver.d.ts +10 -5
  21. package/drivers/DatabaseDriver.js +4 -4
  22. package/drivers/IDatabaseDriver.d.ts +28 -4
  23. package/entity/ArrayCollection.d.ts +6 -4
  24. package/entity/ArrayCollection.js +26 -9
  25. package/entity/BaseEntity.d.ts +0 -1
  26. package/entity/BaseEntity.js +0 -3
  27. package/entity/Collection.d.ts +3 -4
  28. package/entity/Collection.js +37 -17
  29. package/entity/EntityAssigner.d.ts +1 -1
  30. package/entity/EntityAssigner.js +9 -1
  31. package/entity/EntityFactory.d.ts +7 -0
  32. package/entity/EntityFactory.js +29 -11
  33. package/entity/EntityHelper.js +25 -8
  34. package/entity/EntityLoader.d.ts +5 -4
  35. package/entity/EntityLoader.js +69 -36
  36. package/entity/EntityRepository.d.ts +1 -1
  37. package/entity/EntityValidator.js +1 -1
  38. package/entity/Reference.d.ts +9 -7
  39. package/entity/Reference.js +30 -3
  40. package/entity/WrappedEntity.d.ts +0 -2
  41. package/entity/WrappedEntity.js +1 -5
  42. package/entity/defineEntity.d.ts +555 -0
  43. package/entity/defineEntity.js +529 -0
  44. package/entity/index.d.ts +2 -0
  45. package/entity/index.js +2 -0
  46. package/entity/utils.d.ts +7 -0
  47. package/entity/utils.js +15 -3
  48. package/enums.d.ts +16 -3
  49. package/enums.js +13 -0
  50. package/errors.d.ts +6 -1
  51. package/errors.js +14 -4
  52. package/events/EventSubscriber.d.ts +3 -1
  53. package/hydration/ObjectHydrator.d.ts +4 -4
  54. package/hydration/ObjectHydrator.js +35 -24
  55. package/index.d.ts +2 -1
  56. package/index.js +1 -1
  57. package/logging/DefaultLogger.d.ts +1 -1
  58. package/logging/SimpleLogger.d.ts +1 -1
  59. package/metadata/EntitySchema.d.ts +8 -4
  60. package/metadata/EntitySchema.js +39 -19
  61. package/metadata/MetadataDiscovery.d.ts +4 -4
  62. package/metadata/MetadataDiscovery.js +139 -122
  63. package/metadata/MetadataStorage.js +1 -1
  64. package/metadata/MetadataValidator.js +4 -3
  65. package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
  66. package/naming-strategy/AbstractNamingStrategy.js +7 -1
  67. package/naming-strategy/NamingStrategy.d.ts +11 -1
  68. package/package.json +5 -5
  69. package/platforms/Platform.d.ts +5 -3
  70. package/platforms/Platform.js +4 -8
  71. package/serialization/EntitySerializer.d.ts +2 -0
  72. package/serialization/EntitySerializer.js +23 -5
  73. package/serialization/EntityTransformer.js +16 -6
  74. package/serialization/SerializationContext.js +14 -11
  75. package/types/BigIntType.d.ts +9 -6
  76. package/types/BigIntType.js +3 -0
  77. package/types/BooleanType.d.ts +1 -1
  78. package/types/DecimalType.d.ts +6 -4
  79. package/types/DecimalType.js +1 -1
  80. package/types/DoubleType.js +1 -1
  81. package/types/JsonType.d.ts +1 -1
  82. package/types/JsonType.js +7 -2
  83. package/types/Type.d.ts +2 -1
  84. package/types/Type.js +1 -1
  85. package/types/index.d.ts +1 -1
  86. package/typings.d.ts +89 -49
  87. package/typings.js +31 -31
  88. package/unit-of-work/ChangeSetComputer.js +8 -3
  89. package/unit-of-work/ChangeSetPersister.d.ts +4 -2
  90. package/unit-of-work/ChangeSetPersister.js +37 -16
  91. package/unit-of-work/UnitOfWork.d.ts +8 -1
  92. package/unit-of-work/UnitOfWork.js +110 -53
  93. package/utils/AbstractSchemaGenerator.js +3 -1
  94. package/utils/Configuration.d.ts +29 -16
  95. package/utils/Configuration.js +17 -18
  96. package/utils/ConfigurationLoader.d.ts +9 -22
  97. package/utils/ConfigurationLoader.js +49 -72
  98. package/utils/Cursor.d.ts +3 -3
  99. package/utils/Cursor.js +3 -0
  100. package/utils/DataloaderUtils.d.ts +7 -2
  101. package/utils/DataloaderUtils.js +38 -7
  102. package/utils/EntityComparator.d.ts +6 -2
  103. package/utils/EntityComparator.js +104 -58
  104. package/utils/QueryHelper.d.ts +9 -1
  105. package/utils/QueryHelper.js +66 -5
  106. package/utils/RawQueryFragment.d.ts +36 -4
  107. package/utils/RawQueryFragment.js +34 -13
  108. package/utils/TransactionManager.d.ts +65 -0
  109. package/utils/TransactionManager.js +223 -0
  110. package/utils/Utils.d.ts +13 -11
  111. package/utils/Utils.js +82 -55
  112. package/utils/index.d.ts +1 -0
  113. package/utils/index.js +1 -0
  114. package/utils/upsert-utils.d.ts +7 -2
  115. package/utils/upsert-utils.js +52 -1
package/utils/Utils.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { createRequire } from 'node:module';
2
- import globby from 'globby';
2
+ import { glob, isDynamicPattern } from 'tinyglobby';
3
3
  import { extname, isAbsolute, join, normalize, relative, resolve } from 'node:path';
4
- import { platform } from 'node:os';
5
4
  import { fileURLToPath, pathToFileURL } from 'node:url';
6
5
  import { existsSync, mkdirSync, readFileSync } from 'node:fs';
7
6
  import { createHash } from 'node:crypto';
@@ -435,7 +434,11 @@ export class Utils {
435
434
  return data;
436
435
  }
437
436
  if (Utils.isEntity(data, true)) {
438
- return helper(data).getPrimaryKey();
437
+ const wrapped = helper(data);
438
+ if (wrapped.__meta.compositePK) {
439
+ return wrapped.getPrimaryKeys();
440
+ }
441
+ return wrapped.getPrimaryKey();
439
442
  }
440
443
  if (strict && meta && Utils.getObjectKeysSize(data) !== meta.primaryKeys.length) {
441
444
  return null;
@@ -483,6 +486,7 @@ export class Utils {
483
486
  static splitPrimaryKeys(key) {
484
487
  return key.split(this.PK_SEPARATOR);
485
488
  }
489
+ // TODO v7: remove support for `primaryKeys: string[]`
486
490
  static getPrimaryKeyValues(entity, primaryKeys, allowScalar = false, convertCustomTypes = false) {
487
491
  /* v8 ignore next 3 */
488
492
  if (entity == null) {
@@ -494,9 +498,24 @@ export class Utils {
494
498
  }
495
499
  return val;
496
500
  }
497
- const pk = Utils.isEntity(entity, true)
498
- ? helper(entity).getPrimaryKey(convertCustomTypes)
499
- : primaryKeys.reduce((o, pk) => { o[pk] = entity[pk]; return o; }, {});
501
+ const meta = Array.isArray(primaryKeys) ? undefined : primaryKeys;
502
+ primaryKeys = Array.isArray(primaryKeys) ? primaryKeys : meta.primaryKeys;
503
+ let pk;
504
+ if (Utils.isEntity(entity, true)) {
505
+ pk = helper(entity).getPrimaryKey(convertCustomTypes);
506
+ }
507
+ else {
508
+ pk = primaryKeys.reduce((o, pk) => {
509
+ const targetMeta = meta?.properties[pk].targetMeta;
510
+ if (targetMeta && Utils.isPlainObject(entity[pk])) {
511
+ o[pk] = Utils.getPrimaryKeyValues(entity[pk], targetMeta, allowScalar, convertCustomTypes);
512
+ }
513
+ else {
514
+ o[pk] = entity[pk];
515
+ }
516
+ return o;
517
+ }, {});
518
+ }
500
519
  if (primaryKeys.length > 1) {
501
520
  return toArray(pk);
502
521
  }
@@ -546,7 +565,7 @@ export class Utils {
546
565
  return o;
547
566
  }, {});
548
567
  }
549
- static getOrderedPrimaryKeys(id, meta, platform, convertCustomTypes = false) {
568
+ static getOrderedPrimaryKeys(id, meta, platform, convertCustomTypes = false, allowScalar = false) {
550
569
  const data = (Utils.isPrimaryKey(id) ? { [meta.primaryKeys[0]]: id } : id);
551
570
  const pks = meta.primaryKeys.map((pk, idx) => {
552
571
  const prop = meta.properties[pk];
@@ -556,11 +575,14 @@ export class Utils {
556
575
  value = prop.customType.convertToJSValue(value, platform);
557
576
  }
558
577
  if (prop.kind !== ReferenceKind.SCALAR && prop.targetMeta) {
559
- const value2 = this.getOrderedPrimaryKeys(value, prop.targetMeta, platform, convertCustomTypes);
578
+ const value2 = this.getOrderedPrimaryKeys(value, prop.targetMeta, platform, convertCustomTypes, allowScalar);
560
579
  value = value2.length > 1 ? value2 : value2[0];
561
580
  }
562
581
  return value;
563
582
  });
583
+ if (allowScalar && pks.length === 1) {
584
+ return pks[0];
585
+ }
564
586
  // we need to flatten the PKs as composite PKs can be build from another composite PKs
565
587
  // and this method is used to get the PK hash in identity map, that expects flat array
566
588
  return Utils.flatten(pks);
@@ -625,8 +647,12 @@ export class Utils {
625
647
  || !!process.env.TS_JEST // check if ts-jest is used (works only with v27.0.4+)
626
648
  || !!process.env.VITEST // check if vitest is used
627
649
  || !!process.versions.bun // check if bun is used
628
- || process.argv.slice(1).some(arg => arg.includes('ts-node')) // registering ts-node runner
629
- || process.execArgv.some(arg => arg === 'ts-node/esm'); // check for ts-node/esm module loader
650
+ || process.argv.slice(1).some(arg => arg.match(/\.([mc]?ts|tsx)$/)) // executing `.ts` file
651
+ || process.execArgv.some(arg => {
652
+ return arg.includes('ts-node') // check for ts-node loader
653
+ || arg.includes('@swc-node/register') // check for swc-node/register loader
654
+ || arg.includes('node_modules/tsx/'); // check for tsx loader
655
+ });
630
656
  }
631
657
  /**
632
658
  * Uses some dark magic to get source path to caller where decorator is used.
@@ -644,7 +670,8 @@ export class Utils {
644
670
  // but those are also present in node, so we need to check this only if they weren't found.
645
671
  if (line === -1) {
646
672
  // here we handle bun which stack is different from nodejs so we search for reflect-metadata
647
- const reflectLine = stack.findIndex(line => Utils.normalizePath(line).includes('node_modules/reflect-metadata/Reflect.js'));
673
+ // Different bun versions might have different stack traces. The "last index" works for both 1.2.6 and 1.2.7.
674
+ const reflectLine = stack.findLastIndex(line => Utils.normalizePath(line).includes('node_modules/reflect-metadata/Reflect.js'));
648
675
  if (reflectLine === -1 || reflectLine + 2 >= stack.length || !stack[reflectLine + 1].includes('bun:wrap')) {
649
676
  return name;
650
677
  }
@@ -673,11 +700,11 @@ export class Utils {
673
700
  return simple;
674
701
  }
675
702
  const objectType = Object.prototype.toString.call(value);
676
- const type = objectType.match(/\[object (\w+)]/)[1];
703
+ const type = objectType.match(/^\[object (.+)]$/)[1];
677
704
  if (type === 'Uint8Array') {
678
705
  return 'Buffer';
679
706
  }
680
- return ['Date', 'Buffer', 'RegExp'].includes(type) ? type : type.toLowerCase();
707
+ return type;
681
708
  }
682
709
  /**
683
710
  * Checks whether the value is POJO (e.g. `{ foo: 'bar' }`, and not instance of `Foo`)
@@ -761,8 +788,9 @@ export class Utils {
761
788
  }
762
789
  return Utils.normalizePath(path);
763
790
  }
764
- static hash(data, length) {
765
- const hash = createHash('md5').update(data).digest('hex');
791
+ static hash(data, length, algorithm) {
792
+ const hashAlgorithm = algorithm || 'sha256';
793
+ const hash = createHash(hashAlgorithm).update(data).digest('hex');
766
794
  if (length) {
767
795
  return hash.substring(0, length);
768
796
  }
@@ -795,8 +823,8 @@ export class Utils {
795
823
  return Math.round(Math.random() * (max - min)) + min;
796
824
  }
797
825
  static async pathExists(path, options = {}) {
798
- if (globby.hasMagic(path)) {
799
- const found = await globby(path, options);
826
+ if (isDynamicPattern(path)) {
827
+ const found = await glob(path, options);
800
828
  return found.length > 0;
801
829
  }
802
830
  return this.pathExistsSync(path);
@@ -863,18 +891,25 @@ export class Utils {
863
891
  }
864
892
  return createRequire(resolve(from))(id);
865
893
  }
866
- static async dynamicImport(id) {
867
- /* v8 ignore next 7 */
868
- if (platform() === 'win32') {
869
- try {
870
- id = pathToFileURL(id).toString();
871
- }
872
- catch {
873
- // ignore
874
- }
894
+ /**
895
+ * Resolve path to a module.
896
+ * @param id The module to require
897
+ * @param [from] Location to start the node resolution
898
+ */
899
+ static resolveModulePath(id, from = process.cwd()) {
900
+ if (!extname(from)) {
901
+ from = join(from, '__fake.js');
875
902
  }
903
+ const path = Utils.normalizePath(createRequire(resolve(from)).resolve(id));
904
+ const parts = path.split('/');
905
+ const idx = parts.lastIndexOf(id) + 1;
906
+ parts.splice(idx, parts.length - idx);
907
+ return parts.join('/');
908
+ }
909
+ static async dynamicImport(id) {
876
910
  /* v8 ignore next */
877
- return this.dynamicImportProvider(id);
911
+ const specifier = id.startsWith('file://') ? id : pathToFileURL(id).href;
912
+ return this.dynamicImportProvider(specifier);
878
913
  }
879
914
  /* v8 ignore next 3 */
880
915
  static setDynamicImportProvider(provider) {
@@ -899,8 +934,13 @@ export class Utils {
899
934
  /* v8 ignore next 5 */
900
935
  }
901
936
  catch {
902
- // this works in production build where we do not have the `src` folder
903
- return this.requireFrom('../package.json', import.meta.dirname).version;
937
+ try {
938
+ // this works in production build where we do not have the `src` folder
939
+ return this.requireFrom('../package.json', import.meta.dirname).version;
940
+ }
941
+ catch {
942
+ return 'N/A';
943
+ }
904
944
  }
905
945
  }
906
946
  static createFunction(context, code) {
@@ -1035,8 +1075,10 @@ export class Utils {
1035
1075
  }
1036
1076
  catch (err) {
1037
1077
  if (err.message.includes(allowError)) {
1038
- // eslint-disable-next-line no-console
1039
- console.warn(warning);
1078
+ if (warning) {
1079
+ // eslint-disable-next-line no-console
1080
+ console.warn(warning);
1081
+ }
1040
1082
  return undefined;
1041
1083
  }
1042
1084
  throw err;
@@ -1044,37 +1086,22 @@ export class Utils {
1044
1086
  }
1045
1087
  static async tryImport({ module, warning }) {
1046
1088
  try {
1047
- return await this.dynamicImport(module);
1089
+ return await import(module);
1048
1090
  }
1049
1091
  catch (err) {
1050
- // eslint-disable-next-line no-console
1051
- console.warn(warning);
1052
- return undefined;
1092
+ if (err.code === 'ERR_MODULE_NOT_FOUND') {
1093
+ if (warning) {
1094
+ // eslint-disable-next-line no-console
1095
+ console.warn(warning);
1096
+ }
1097
+ return undefined;
1098
+ }
1099
+ throw err;
1053
1100
  }
1054
1101
  }
1055
1102
  static stripRelativePath(str) {
1056
1103
  return str.replace(/^(?:\.\.\/|\.\/)+/, '/');
1057
1104
  }
1058
- /**
1059
- * simple process.argv parser, supports only properties with long names, prefixed with `--`
1060
- */
1061
- static parseArgs() {
1062
- let lastKey;
1063
- return process.argv.slice(2).reduce((args, arg) => {
1064
- if (arg.includes('=')) {
1065
- const [key, value] = arg.split('=');
1066
- args[key.substring(2)] = value;
1067
- }
1068
- else if (lastKey) {
1069
- args[lastKey] = arg;
1070
- lastKey = undefined;
1071
- }
1072
- else if (arg.startsWith('--')) {
1073
- lastKey = arg.substring(2);
1074
- }
1075
- return args;
1076
- }, {});
1077
- }
1078
1105
  static xor(a, b) {
1079
1106
  return (a || b) && !(a && b);
1080
1107
  }
package/utils/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export * from './DataloaderUtils.js';
5
5
  export * from './Utils.js';
6
6
  export * from './RequestContext.js';
7
7
  export * from './TransactionContext.js';
8
+ export * from './TransactionManager.js';
8
9
  export * from './QueryHelper.js';
9
10
  export * from './NullHighlighter.js';
10
11
  export * from './EntityComparator.js';
package/utils/index.js CHANGED
@@ -5,6 +5,7 @@ export * from './DataloaderUtils.js';
5
5
  export * from './Utils.js';
6
6
  export * from './RequestContext.js';
7
7
  export * from './TransactionContext.js';
8
+ export * from './TransactionManager.js';
8
9
  export * from './QueryHelper.js';
9
10
  export * from './NullHighlighter.js';
10
11
  export * from './EntityComparator.js';
@@ -1,7 +1,12 @@
1
- import type { EntityData, EntityMetadata } from '../typings.js';
1
+ import type { EntityData, EntityMetadata, FilterQuery } from '../typings.js';
2
2
  import type { UpsertOptions } from '../drivers/IDatabaseDriver.js';
3
- import type { RawQueryFragment } from '../utils/RawQueryFragment.js';
3
+ import { type RawQueryFragment } from '../utils/RawQueryFragment.js';
4
4
  /** @internal */
5
5
  export declare function getOnConflictFields<T>(meta: EntityMetadata<T> | undefined, data: EntityData<T>, uniqueFields: (keyof T)[] | RawQueryFragment, options: UpsertOptions<T>): (keyof T)[];
6
6
  /** @internal */
7
7
  export declare function getOnConflictReturningFields<T, P extends string>(meta: EntityMetadata<T> | undefined, data: EntityData<T>, uniqueFields: (keyof T)[] | RawQueryFragment, options: UpsertOptions<T, P>): (keyof T)[] | '*';
8
+ /** @internal */
9
+ export declare function getWhereCondition<T extends object>(meta: EntityMetadata<T>, onConflictFields: (keyof T)[] | RawQueryFragment | undefined, data: EntityData<T>, where: FilterQuery<T>): {
10
+ where: FilterQuery<T>;
11
+ propIndex: number | false;
12
+ };
@@ -1,3 +1,5 @@
1
+ import { isRaw } from '../utils/RawQueryFragment.js';
2
+ import { Utils } from './Utils.js';
1
3
  function expandEmbeddedProperties(prop, key) {
2
4
  if (prop.object) {
3
5
  return [prop.name];
@@ -71,7 +73,15 @@ export function getOnConflictReturningFields(meta, data, uniqueFields, options)
71
73
  if (!meta) {
72
74
  return '*';
73
75
  }
74
- const keys = meta.comparableProps.filter(p => !p.lazy && !p.embeddable && Array.isArray(uniqueFields) && !uniqueFields.includes(p.name)).map(p => p.name);
76
+ const keys = meta.comparableProps.filter(p => {
77
+ if (p.lazy || p.embeddable) {
78
+ return false;
79
+ }
80
+ if (p.autoincrement) {
81
+ return true;
82
+ }
83
+ return Array.isArray(uniqueFields) && !uniqueFields.includes(p.name);
84
+ }).map(p => p.name);
75
85
  if (meta.versionProperty) {
76
86
  keys.push(meta.versionProperty);
77
87
  }
@@ -88,3 +98,44 @@ export function getOnConflictReturningFields(meta, data, uniqueFields, options)
88
98
  }
89
99
  return keys.filter(key => !(key in data));
90
100
  }
101
+ function getPropertyValue(obj, key) {
102
+ if (key.indexOf('.') === -1) {
103
+ return obj[key];
104
+ }
105
+ const parts = key.split('.');
106
+ let curr = obj;
107
+ for (let i = 0; i < parts.length - 1; i++) {
108
+ curr[parts[i]] ??= {};
109
+ curr = curr[parts[i]];
110
+ }
111
+ return curr[parts[parts.length - 1]];
112
+ }
113
+ /** @internal */
114
+ export function getWhereCondition(meta, onConflictFields, data, where) {
115
+ const unique = onConflictFields ?? meta.props.filter(p => p.unique).map(p => p.name);
116
+ const propIndex = !isRaw(unique) && unique.findIndex(p => data[p] ?? data[p.substring(0, p.indexOf('.'))] != null);
117
+ if (onConflictFields || where == null) {
118
+ if (propIndex !== false && propIndex >= 0) {
119
+ let key = unique[propIndex];
120
+ if (key.includes('.')) {
121
+ const prop = meta.properties[key.substring(0, key.indexOf('.'))];
122
+ if (prop) {
123
+ key = `${prop.fieldNames[0]}${key.substring(key.indexOf('.'))}`;
124
+ }
125
+ }
126
+ where = { [key]: getPropertyValue(data, unique[propIndex]) };
127
+ }
128
+ else if (meta.uniques.length > 0) {
129
+ for (const u of meta.uniques) {
130
+ if (Utils.asArray(u.properties).every(p => data[p] != null)) {
131
+ where = Utils.asArray(u.properties).reduce((o, key) => {
132
+ o[key] = data[key];
133
+ return o;
134
+ }, {});
135
+ break;
136
+ }
137
+ }
138
+ }
139
+ }
140
+ return { where, propIndex };
141
+ }