@mikro-orm/core 7.0.0-dev.6 → 7.0.0-dev.61

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 (123) hide show
  1. package/EntityManager.d.ts +85 -32
  2. package/EntityManager.js +281 -178
  3. package/MikroORM.d.ts +8 -8
  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 +5 -4
  8. package/connections/Connection.d.ts +11 -7
  9. package/connections/Connection.js +16 -13
  10. package/decorators/Embeddable.d.ts +2 -0
  11. package/decorators/Embedded.d.ts +5 -11
  12. package/decorators/Entity.d.ts +20 -3
  13. package/decorators/Indexed.d.ts +2 -2
  14. package/decorators/ManyToMany.d.ts +2 -0
  15. package/decorators/ManyToOne.d.ts +4 -0
  16. package/decorators/OneToOne.d.ts +4 -0
  17. package/decorators/Property.d.ts +53 -9
  18. package/decorators/Transactional.d.ts +3 -1
  19. package/decorators/Transactional.js +6 -3
  20. package/decorators/index.d.ts +1 -1
  21. package/drivers/DatabaseDriver.d.ts +11 -5
  22. package/drivers/DatabaseDriver.js +13 -4
  23. package/drivers/IDatabaseDriver.d.ts +29 -5
  24. package/entity/ArrayCollection.d.ts +6 -4
  25. package/entity/ArrayCollection.js +27 -12
  26. package/entity/BaseEntity.d.ts +0 -1
  27. package/entity/BaseEntity.js +0 -3
  28. package/entity/Collection.d.ts +3 -4
  29. package/entity/Collection.js +34 -17
  30. package/entity/EntityAssigner.d.ts +1 -1
  31. package/entity/EntityAssigner.js +9 -1
  32. package/entity/EntityFactory.d.ts +7 -0
  33. package/entity/EntityFactory.js +63 -40
  34. package/entity/EntityHelper.js +26 -9
  35. package/entity/EntityLoader.d.ts +5 -4
  36. package/entity/EntityLoader.js +69 -36
  37. package/entity/EntityRepository.d.ts +1 -1
  38. package/entity/EntityValidator.js +2 -2
  39. package/entity/Reference.d.ts +9 -7
  40. package/entity/Reference.js +32 -5
  41. package/entity/WrappedEntity.d.ts +0 -2
  42. package/entity/WrappedEntity.js +1 -5
  43. package/entity/defineEntity.d.ts +555 -0
  44. package/entity/defineEntity.js +529 -0
  45. package/entity/index.d.ts +2 -0
  46. package/entity/index.js +2 -0
  47. package/entity/utils.d.ts +7 -0
  48. package/entity/utils.js +15 -3
  49. package/enums.d.ts +18 -5
  50. package/enums.js +13 -0
  51. package/errors.d.ts +6 -1
  52. package/errors.js +14 -4
  53. package/events/EventSubscriber.d.ts +3 -1
  54. package/hydration/ObjectHydrator.d.ts +4 -4
  55. package/hydration/ObjectHydrator.js +35 -24
  56. package/index.d.ts +2 -1
  57. package/index.js +1 -1
  58. package/logging/DefaultLogger.d.ts +1 -1
  59. package/logging/SimpleLogger.d.ts +1 -1
  60. package/metadata/EntitySchema.d.ts +8 -4
  61. package/metadata/EntitySchema.js +41 -23
  62. package/metadata/MetadataDiscovery.d.ts +5 -7
  63. package/metadata/MetadataDiscovery.js +151 -159
  64. package/metadata/MetadataStorage.js +1 -1
  65. package/metadata/MetadataValidator.js +4 -3
  66. package/metadata/discover-entities.d.ts +5 -0
  67. package/metadata/discover-entities.js +39 -0
  68. package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
  69. package/naming-strategy/AbstractNamingStrategy.js +7 -1
  70. package/naming-strategy/NamingStrategy.d.ts +11 -1
  71. package/package.json +14 -8
  72. package/platforms/Platform.d.ts +5 -8
  73. package/platforms/Platform.js +4 -17
  74. package/serialization/EntitySerializer.d.ts +2 -0
  75. package/serialization/EntitySerializer.js +29 -11
  76. package/serialization/EntityTransformer.js +22 -12
  77. package/serialization/SerializationContext.js +14 -11
  78. package/types/BigIntType.d.ts +9 -6
  79. package/types/BigIntType.js +3 -0
  80. package/types/BlobType.d.ts +0 -1
  81. package/types/BlobType.js +0 -3
  82. package/types/BooleanType.d.ts +2 -1
  83. package/types/BooleanType.js +3 -0
  84. package/types/DecimalType.d.ts +6 -4
  85. package/types/DecimalType.js +1 -1
  86. package/types/DoubleType.js +1 -1
  87. package/types/JsonType.d.ts +1 -1
  88. package/types/JsonType.js +7 -2
  89. package/types/Type.d.ts +2 -1
  90. package/types/Type.js +1 -1
  91. package/types/Uint8ArrayType.d.ts +0 -1
  92. package/types/Uint8ArrayType.js +0 -3
  93. package/types/index.d.ts +1 -1
  94. package/typings.d.ts +95 -52
  95. package/typings.js +31 -31
  96. package/unit-of-work/ChangeSetComputer.js +8 -3
  97. package/unit-of-work/ChangeSetPersister.d.ts +4 -2
  98. package/unit-of-work/ChangeSetPersister.js +37 -16
  99. package/unit-of-work/UnitOfWork.d.ts +8 -1
  100. package/unit-of-work/UnitOfWork.js +110 -53
  101. package/utils/AbstractSchemaGenerator.js +3 -1
  102. package/utils/Configuration.d.ts +201 -184
  103. package/utils/Configuration.js +143 -151
  104. package/utils/ConfigurationLoader.d.ts +9 -22
  105. package/utils/ConfigurationLoader.js +53 -76
  106. package/utils/Cursor.d.ts +3 -3
  107. package/utils/Cursor.js +3 -0
  108. package/utils/DataloaderUtils.d.ts +15 -5
  109. package/utils/DataloaderUtils.js +53 -7
  110. package/utils/EntityComparator.d.ts +8 -4
  111. package/utils/EntityComparator.js +105 -58
  112. package/utils/QueryHelper.d.ts +9 -1
  113. package/utils/QueryHelper.js +66 -5
  114. package/utils/RawQueryFragment.d.ts +36 -4
  115. package/utils/RawQueryFragment.js +34 -13
  116. package/utils/TransactionManager.d.ts +65 -0
  117. package/utils/TransactionManager.js +223 -0
  118. package/utils/Utils.d.ts +16 -31
  119. package/utils/Utils.js +129 -107
  120. package/utils/index.d.ts +1 -0
  121. package/utils/index.js +1 -0
  122. package/utils/upsert-utils.d.ts +7 -2
  123. package/utils/upsert-utils.js +52 -1
package/utils/Utils.js CHANGED
@@ -1,15 +1,11 @@
1
1
  import { createRequire } from 'node:module';
2
- import globby from 'globby';
3
2
  import { extname, isAbsolute, join, normalize, relative, resolve } from 'node:path';
4
- import { platform } from 'node:os';
5
3
  import { fileURLToPath, pathToFileURL } from 'node:url';
6
- import { existsSync, mkdirSync, readFileSync } from 'node:fs';
4
+ import { existsSync, globSync, statSync, mkdirSync, readFileSync } from 'node:fs';
7
5
  import { createHash } from 'node:crypto';
8
- import { tokenize } from 'esprima';
9
6
  import { clone } from './clone.js';
10
- import { ARRAY_OPERATORS, JSON_KEY_OPERATORS, GroupOperator, PlainObject, QueryOperator, ReferenceKind } from '../enums.js';
7
+ import { ARRAY_OPERATORS, GroupOperator, JSON_KEY_OPERATORS, PlainObject, QueryOperator, ReferenceKind, } from '../enums.js';
11
8
  import { helper } from '../entity/wrap.js';
12
- export const ObjectBindingPattern = Symbol('ObjectBindingPattern');
13
9
  function compareConstructors(a, b) {
14
10
  if (a.constructor === b.constructor) {
15
11
  return true;
@@ -359,53 +355,37 @@ export class Utils {
359
355
  }
360
356
  }
361
357
  /**
362
- * Returns array of functions argument names. Uses `esprima` for source code analysis.
358
+ * Returns array of functions argument names. Uses basic regex for source code analysis, might not work with advanced syntax.
363
359
  */
364
- static tokenize(func) {
365
- if (Array.isArray(func)) {
366
- return func;
367
- }
368
- /* v8 ignore next 5 */
369
- try {
370
- return tokenize(func.toString(), { tolerant: true });
360
+ static getConstructorParams(func) {
361
+ const source = func.toString();
362
+ const i = source.indexOf('constructor');
363
+ if (i === -1) {
364
+ return undefined;
371
365
  }
372
- catch {
373
- return [];
366
+ const start = source.indexOf('(', i);
367
+ if (start === -1) {
368
+ return undefined;
374
369
  }
375
- }
376
- /**
377
- * Returns array of functions argument names. Uses `esprima` for source code analysis.
378
- */
379
- static getParamNames(func, methodName) {
380
- const ret = [];
381
- const tokens = this.tokenize(func);
382
- let inside = 0;
383
- let currentBlockStart = 0;
384
- for (let i = 0; i < tokens.length; i++) {
385
- const token = tokens[i];
386
- if (token.type === 'Identifier' && token.value === methodName) {
387
- inside = 1;
388
- currentBlockStart = i;
389
- continue;
370
+ let depth = 0;
371
+ let end = start;
372
+ for (; end < source.length; end++) {
373
+ if (source[end] === '(') {
374
+ depth++;
390
375
  }
391
- if (inside === 1 && token.type === 'Punctuator' && token.value === '(') {
392
- inside = 2;
393
- currentBlockStart = i;
394
- continue;
376
+ if (source[end] === ')') {
377
+ depth--;
395
378
  }
396
- if (inside === 2 && token.type === 'Punctuator' && token.value === ')') {
379
+ if (depth === 0) {
397
380
  break;
398
381
  }
399
- if (inside === 2 && token.type === 'Punctuator' && token.value === '{' && i === currentBlockStart + 1) {
400
- ret.push(ObjectBindingPattern);
401
- i = tokens.findIndex((t, idx) => idx > i + 2 && t.type === 'Punctuator' && t.value === '}');
402
- continue;
403
- }
404
- if (inside === 2 && token.type === 'Identifier') {
405
- ret.push(token.value);
406
- }
407
382
  }
408
- return ret;
383
+ const raw = source.slice(start + 1, end);
384
+ return raw
385
+ .split(',')
386
+ .map(s => s.trim().replace(/=.*$/, '').trim())
387
+ .filter(Boolean)
388
+ .map(raw => raw.startsWith('{') && raw.endsWith('}') ? '' : raw);
409
389
  }
410
390
  /**
411
391
  * Checks whether the argument looks like primary key (string, number or ObjectId).
@@ -435,7 +415,11 @@ export class Utils {
435
415
  return data;
436
416
  }
437
417
  if (Utils.isEntity(data, true)) {
438
- return helper(data).getPrimaryKey();
418
+ const wrapped = helper(data);
419
+ if (wrapped.__meta.compositePK) {
420
+ return wrapped.getPrimaryKeys();
421
+ }
422
+ return wrapped.getPrimaryKey();
439
423
  }
440
424
  if (strict && meta && Utils.getObjectKeysSize(data) !== meta.primaryKeys.length) {
441
425
  return null;
@@ -444,7 +428,7 @@ export class Utils {
444
428
  if (meta.compositePK) {
445
429
  return this.getCompositeKeyValue(data, meta);
446
430
  }
447
- return data[meta.primaryKeys[0]] || data[meta.serializedPrimaryKey] || null;
431
+ return data[meta.primaryKeys[0]] ?? data[meta.serializedPrimaryKey] ?? null;
448
432
  }
449
433
  return null;
450
434
  }
@@ -483,7 +467,7 @@ export class Utils {
483
467
  static splitPrimaryKeys(key) {
484
468
  return key.split(this.PK_SEPARATOR);
485
469
  }
486
- static getPrimaryKeyValues(entity, primaryKeys, allowScalar = false, convertCustomTypes = false) {
470
+ static getPrimaryKeyValues(entity, meta, allowScalar = false, convertCustomTypes = false) {
487
471
  /* v8 ignore next 3 */
488
472
  if (entity == null) {
489
473
  return entity;
@@ -494,15 +478,28 @@ export class Utils {
494
478
  }
495
479
  return val;
496
480
  }
497
- const pk = Utils.isEntity(entity, true)
498
- ? helper(entity).getPrimaryKey(convertCustomTypes)
499
- : primaryKeys.reduce((o, pk) => { o[pk] = entity[pk]; return o; }, {});
500
- if (primaryKeys.length > 1) {
481
+ let pk;
482
+ if (Utils.isEntity(entity, true)) {
483
+ pk = helper(entity).getPrimaryKey(convertCustomTypes);
484
+ }
485
+ else {
486
+ pk = meta.primaryKeys.reduce((o, pk) => {
487
+ const targetMeta = meta.properties[pk].targetMeta;
488
+ if (targetMeta && Utils.isPlainObject(entity[pk])) {
489
+ o[pk] = Utils.getPrimaryKeyValues(entity[pk], targetMeta, allowScalar, convertCustomTypes);
490
+ }
491
+ else {
492
+ o[pk] = entity[pk];
493
+ }
494
+ return o;
495
+ }, {});
496
+ }
497
+ if (meta.primaryKeys.length > 1) {
501
498
  return toArray(pk);
502
499
  }
503
500
  if (allowScalar) {
504
501
  if (Utils.isPlainObject(pk)) {
505
- return pk[primaryKeys[0]];
502
+ return pk[(meta.primaryKeys)[0]];
506
503
  }
507
504
  return pk;
508
505
  }
@@ -546,7 +543,7 @@ export class Utils {
546
543
  return o;
547
544
  }, {});
548
545
  }
549
- static getOrderedPrimaryKeys(id, meta, platform, convertCustomTypes = false) {
546
+ static getOrderedPrimaryKeys(id, meta, platform, convertCustomTypes = false, allowScalar = false) {
550
547
  const data = (Utils.isPrimaryKey(id) ? { [meta.primaryKeys[0]]: id } : id);
551
548
  const pks = meta.primaryKeys.map((pk, idx) => {
552
549
  const prop = meta.properties[pk];
@@ -556,11 +553,14 @@ export class Utils {
556
553
  value = prop.customType.convertToJSValue(value, platform);
557
554
  }
558
555
  if (prop.kind !== ReferenceKind.SCALAR && prop.targetMeta) {
559
- const value2 = this.getOrderedPrimaryKeys(value, prop.targetMeta, platform, convertCustomTypes);
556
+ const value2 = this.getOrderedPrimaryKeys(value, prop.targetMeta, platform, convertCustomTypes, allowScalar);
560
557
  value = value2.length > 1 ? value2 : value2[0];
561
558
  }
562
559
  return value;
563
560
  });
561
+ if (allowScalar && pks.length === 1) {
562
+ return pks[0];
563
+ }
564
564
  // we need to flatten the PKs as composite PKs can be build from another composite PKs
565
565
  // and this method is used to get the PK hash in identity map, that expects flat array
566
566
  return Utils.flatten(pks);
@@ -625,8 +625,12 @@ export class Utils {
625
625
  || !!process.env.TS_JEST // check if ts-jest is used (works only with v27.0.4+)
626
626
  || !!process.env.VITEST // check if vitest is used
627
627
  || !!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
628
+ || process.argv.slice(1).some(arg => arg.match(/\.([mc]?ts|tsx)$/)) // executing `.ts` file
629
+ || process.execArgv.some(arg => {
630
+ return arg.includes('ts-node') // check for ts-node loader
631
+ || arg.includes('@swc-node/register') // check for swc-node/register loader
632
+ || arg.includes('node_modules/tsx/'); // check for tsx loader
633
+ });
630
634
  }
631
635
  /**
632
636
  * Uses some dark magic to get source path to caller where decorator is used.
@@ -644,7 +648,8 @@ export class Utils {
644
648
  // but those are also present in node, so we need to check this only if they weren't found.
645
649
  if (line === -1) {
646
650
  // 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'));
651
+ // Different bun versions might have different stack traces. The "last index" works for both 1.2.6 and 1.2.7.
652
+ const reflectLine = stack.findLastIndex(line => Utils.normalizePath(line).includes('node_modules/reflect-metadata/Reflect.js'));
648
653
  if (reflectLine === -1 || reflectLine + 2 >= stack.length || !stack[reflectLine + 1].includes('bun:wrap')) {
649
654
  return name;
650
655
  }
@@ -673,11 +678,11 @@ export class Utils {
673
678
  return simple;
674
679
  }
675
680
  const objectType = Object.prototype.toString.call(value);
676
- const type = objectType.match(/\[object (\w+)]/)[1];
681
+ const type = objectType.match(/^\[object (.+)]$/)[1];
677
682
  if (type === 'Uint8Array') {
678
683
  return 'Buffer';
679
684
  }
680
- return ['Date', 'Buffer', 'RegExp'].includes(type) ? type : type.toLowerCase();
685
+ return type;
681
686
  }
682
687
  /**
683
688
  * Checks whether the value is POJO (e.g. `{ foo: 'bar' }`, and not instance of `Foo`)
@@ -761,8 +766,9 @@ export class Utils {
761
766
  }
762
767
  return Utils.normalizePath(path);
763
768
  }
764
- static hash(data, length) {
765
- const hash = createHash('md5').update(data).digest('hex');
769
+ static hash(data, length, algorithm) {
770
+ const hashAlgorithm = algorithm || 'sha256';
771
+ const hash = createHash(hashAlgorithm).update(data).digest('hex');
766
772
  if (length) {
767
773
  return hash.substring(0, length);
768
774
  }
@@ -794,12 +800,32 @@ export class Utils {
794
800
  static randomInt(min, max) {
795
801
  return Math.round(Math.random() * (max - min)) + min;
796
802
  }
797
- static async pathExists(path, options = {}) {
798
- if (globby.hasMagic(path)) {
799
- const found = await globby(path, options);
803
+ static glob(input, cwd) {
804
+ if (Array.isArray(input)) {
805
+ return input.flatMap(paths => this.glob(paths, cwd));
806
+ }
807
+ const hasGlobChars = /[*?[\]]/.test(input);
808
+ if (!hasGlobChars) {
809
+ try {
810
+ const s = statSync(cwd ? Utils.normalizePath(cwd, input) : input);
811
+ if (s.isDirectory()) {
812
+ const files = globSync(join(input, '**'), { cwd, withFileTypes: true });
813
+ return files.filter(f => f.isFile()).map(f => join(f.parentPath, f.name));
814
+ }
815
+ }
816
+ catch {
817
+ // ignore
818
+ }
819
+ }
820
+ const files = globSync(input, { cwd, withFileTypes: true });
821
+ return files.filter(f => f.isFile()).map(f => join(f.parentPath, f.name));
822
+ }
823
+ static pathExists(path) {
824
+ if (/[*?[\]]/.test(path)) {
825
+ const found = globSync(path);
800
826
  return found.length > 0;
801
827
  }
802
- return this.pathExistsSync(path);
828
+ return existsSync(path);
803
829
  }
804
830
  /**
805
831
  * Extracts all possible values of a TS enum. Works with both string and numeric enums.
@@ -863,18 +889,25 @@ export class Utils {
863
889
  }
864
890
  return createRequire(resolve(from))(id);
865
891
  }
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
- }
892
+ /**
893
+ * Resolve path to a module.
894
+ * @param id The module to require
895
+ * @param [from] Location to start the node resolution
896
+ */
897
+ static resolveModulePath(id, from = process.cwd()) {
898
+ if (!extname(from)) {
899
+ from = join(from, '__fake.js');
875
900
  }
901
+ const path = Utils.normalizePath(createRequire(resolve(from)).resolve(id));
902
+ const parts = path.split('/');
903
+ const idx = parts.lastIndexOf(id) + 1;
904
+ parts.splice(idx, parts.length - idx);
905
+ return parts.join('/');
906
+ }
907
+ static async dynamicImport(id) {
876
908
  /* v8 ignore next */
877
- return this.dynamicImportProvider(id);
909
+ const specifier = id.startsWith('file://') ? id : pathToFileURL(id).href;
910
+ return this.dynamicImportProvider(specifier);
878
911
  }
879
912
  /* v8 ignore next 3 */
880
913
  static setDynamicImportProvider(provider) {
@@ -885,9 +918,6 @@ export class Utils {
885
918
  mkdirSync(path, { recursive: true });
886
919
  }
887
920
  }
888
- static pathExistsSync(path) {
889
- return existsSync(path);
890
- }
891
921
  static readJSONSync(path) {
892
922
  const file = readFileSync(path);
893
923
  return JSON.parse(file.toString());
@@ -899,8 +929,13 @@ export class Utils {
899
929
  /* v8 ignore next 5 */
900
930
  }
901
931
  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;
932
+ try {
933
+ // this works in production build where we do not have the `src` folder
934
+ return this.requireFrom('../package.json', import.meta.dirname).version;
935
+ }
936
+ catch {
937
+ return 'N/A';
938
+ }
904
939
  }
905
940
  }
906
941
  static createFunction(context, code) {
@@ -1035,8 +1070,10 @@ export class Utils {
1035
1070
  }
1036
1071
  catch (err) {
1037
1072
  if (err.message.includes(allowError)) {
1038
- // eslint-disable-next-line no-console
1039
- console.warn(warning);
1073
+ if (warning) {
1074
+ // eslint-disable-next-line no-console
1075
+ console.warn(warning);
1076
+ }
1040
1077
  return undefined;
1041
1078
  }
1042
1079
  throw err;
@@ -1044,37 +1081,22 @@ export class Utils {
1044
1081
  }
1045
1082
  static async tryImport({ module, warning }) {
1046
1083
  try {
1047
- return await this.dynamicImport(module);
1084
+ return await import(module);
1048
1085
  }
1049
1086
  catch (err) {
1050
- // eslint-disable-next-line no-console
1051
- console.warn(warning);
1052
- return undefined;
1087
+ if (err.code === 'ERR_MODULE_NOT_FOUND') {
1088
+ if (warning) {
1089
+ // eslint-disable-next-line no-console
1090
+ console.warn(warning);
1091
+ }
1092
+ return undefined;
1093
+ }
1094
+ throw err;
1053
1095
  }
1054
1096
  }
1055
1097
  static stripRelativePath(str) {
1056
1098
  return str.replace(/^(?:\.\.\/|\.\/)+/, '/');
1057
1099
  }
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
1100
  static xor(a, b) {
1079
1101
  return (a || b) && !(a && b);
1080
1102
  }
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
+ }