@mikro-orm/core 6.3.8-dev.6 → 6.3.8-dev.7

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.
@@ -227,7 +227,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
227
227
  *
228
228
  * If the entity is already present in current context, there won't be any queries - instead, the entity data will be assigned and an explicit `flush` will be required for those changes to be persisted.
229
229
  */
230
- upsert<Entity extends object>(entityNameOrEntity: EntityName<Entity> | Entity, data?: EntityData<Entity> | NoInfer<Entity>, options?: UpsertOptions<Entity>): Promise<Entity>;
230
+ upsert<Entity extends object, Fields extends string = any>(entityNameOrEntity: EntityName<Entity> | Entity, data?: EntityData<Entity> | NoInfer<Entity>, options?: UpsertOptions<Entity, Fields>): Promise<Entity>;
231
231
  /**
232
232
  * Creates or updates the entity, based on whether it is already present in the database.
233
233
  * This method performs an `insert on conflict merge` query ensuring the database is in sync, returning a managed
@@ -253,7 +253,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
253
253
  *
254
254
  * If the entity is already present in current context, there won't be any queries - instead, the entity data will be assigned and an explicit `flush` will be required for those changes to be persisted.
255
255
  */
256
- upsertMany<Entity extends object>(entityNameOrEntity: EntityName<Entity> | Entity[], data?: (EntityData<Entity> | NoInfer<Entity>)[], options?: UpsertManyOptions<Entity>): Promise<Entity[]>;
256
+ upsertMany<Entity extends object, Fields extends string = any>(entityNameOrEntity: EntityName<Entity> | Entity[], data?: (EntityData<Entity> | NoInfer<Entity>)[], options?: UpsertManyOptions<Entity, Fields>): Promise<Entity[]>;
257
257
  /**
258
258
  * Runs your callback wrapped inside a database transaction.
259
259
  */
@@ -141,13 +141,13 @@ export interface NativeInsertUpdateOptions<T> {
141
141
  export interface NativeInsertUpdateManyOptions<T> extends NativeInsertUpdateOptions<T> {
142
142
  processCollections?: boolean;
143
143
  }
144
- export interface UpsertOptions<Entity> extends Omit<NativeInsertUpdateOptions<Entity>, 'upsert'> {
144
+ export interface UpsertOptions<Entity, Fields extends string = never> extends Omit<NativeInsertUpdateOptions<Entity>, 'upsert'> {
145
145
  onConflictFields?: (keyof Entity)[] | RawQueryFragment;
146
146
  onConflictAction?: 'ignore' | 'merge';
147
- onConflictMergeFields?: (keyof Entity)[];
148
- onConflictExcludeFields?: (keyof Entity)[];
147
+ onConflictMergeFields?: AutoPath<Entity, Fields, `${PopulatePath.ALL}`>[];
148
+ onConflictExcludeFields?: AutoPath<Entity, Fields, `${PopulatePath.ALL}`>[];
149
149
  }
150
- export interface UpsertManyOptions<Entity> extends UpsertOptions<Entity> {
150
+ export interface UpsertManyOptions<Entity, Fields extends string = never> extends UpsertOptions<Entity, Fields> {
151
151
  batchSize?: number;
152
152
  }
153
153
  export interface CountOptions<T extends object, P extends string = never> {
@@ -41,7 +41,7 @@ export declare class EntityRepository<Entity extends object> {
41
41
  *
42
42
  * If the entity is already present in current context, there won't be any queries - instead, the entity data will be assigned and an explicit `flush` will be required for those changes to be persisted.
43
43
  */
44
- upsert(entityOrData?: EntityData<Entity> | Entity, options?: UpsertOptions<Entity>): Promise<Entity>;
44
+ upsert<Fields extends string = any>(entityOrData?: EntityData<Entity> | Entity, options?: UpsertOptions<Entity, Fields>): Promise<Entity>;
45
45
  /**
46
46
  * Creates or updates the entity, based on whether it is already present in the database.
47
47
  * This method performs an `insert on conflict merge` query ensuring the database is in sync, returning a managed
@@ -67,7 +67,7 @@ export declare class EntityRepository<Entity extends object> {
67
67
  *
68
68
  * If the entity is already present in current context, there won't be any queries - instead, the entity data will be assigned and an explicit `flush` will be required for those changes to be persisted.
69
69
  */
70
- upsertMany(entitiesOrData?: EntityData<Entity>[] | Entity[], options?: UpsertManyOptions<Entity>): Promise<Entity[]>;
70
+ upsertMany<Fields extends string = any>(entitiesOrData?: EntityData<Entity>[] | Entity[], options?: UpsertManyOptions<Entity, Fields>): Promise<Entity[]>;
71
71
  /**
72
72
  * Finds all entities matching your `where` query. You can pass additional options via the `options` parameter.
73
73
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "6.3.8-dev.6",
3
+ "version": "6.3.8-dev.7",
4
4
  "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.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -64,7 +64,7 @@
64
64
  "esprima": "4.0.1",
65
65
  "fs-extra": "11.2.0",
66
66
  "globby": "11.1.0",
67
- "mikro-orm": "6.3.8-dev.6",
67
+ "mikro-orm": "6.3.8-dev.7",
68
68
  "reflect-metadata": "0.2.2"
69
69
  }
70
70
  }
@@ -4,4 +4,4 @@ import type { RawQueryFragment } from '../utils/RawQueryFragment';
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
- export declare function getOnConflictReturningFields<T>(meta: EntityMetadata<T> | undefined, data: EntityData<T>, uniqueFields: (keyof T)[] | RawQueryFragment, options: UpsertOptions<T>): (keyof T)[] | '*';
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)[] | '*';
@@ -2,21 +2,76 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getOnConflictFields = getOnConflictFields;
4
4
  exports.getOnConflictReturningFields = getOnConflictReturningFields;
5
+ function expandEmbeddedProperties(prop, key) {
6
+ if (prop.object) {
7
+ return [prop.name];
8
+ }
9
+ return Object.values(prop.embeddedProps).flatMap(p => {
10
+ /* istanbul ignore next */
11
+ if (p.embeddable && !p.object) {
12
+ return expandEmbeddedProperties(p);
13
+ }
14
+ return [p.name];
15
+ });
16
+ }
17
+ /**
18
+ * Expands dot paths and stars
19
+ */
20
+ function expandFields(meta, fields) {
21
+ return fields.flatMap(f => {
22
+ if (f === '*' && meta) {
23
+ return meta.comparableProps.filter(p => !p.lazy && !p.embeddable).map(p => p.name);
24
+ }
25
+ if (f.includes('.')) {
26
+ const [k, ...tmp] = f.split('.');
27
+ const rest = tmp.join('.');
28
+ const prop = meta?.properties[k];
29
+ if (prop?.embeddable) {
30
+ if (rest === '*') {
31
+ return expandEmbeddedProperties(prop);
32
+ }
33
+ return expandEmbeddedProperties(prop, rest);
34
+ }
35
+ }
36
+ const prop = meta?.properties[f];
37
+ if (prop?.embeddable) {
38
+ return expandEmbeddedProperties(prop);
39
+ }
40
+ return [f];
41
+ });
42
+ }
5
43
  /** @internal */
6
44
  function getOnConflictFields(meta, data, uniqueFields, options) {
7
45
  if (options.onConflictMergeFields) {
8
- return options.onConflictMergeFields;
46
+ const onConflictMergeFields = expandFields(meta, options.onConflictMergeFields);
47
+ return onConflictMergeFields.flatMap(f => {
48
+ const prop = meta?.properties[f];
49
+ /* istanbul ignore next */
50
+ if (prop?.embeddable && !prop.object) {
51
+ return Object.values(prop.embeddedProps).map(p => p.name);
52
+ }
53
+ return f;
54
+ });
9
55
  }
10
- const keys = Object.keys(data).filter(f => {
11
- return Array.isArray(uniqueFields) && !uniqueFields.includes(f) && !meta?.properties[f]?.embeddable;
56
+ const keys = Object.keys(data).flatMap(f => {
57
+ if (!(Array.isArray(uniqueFields) && !uniqueFields.includes(f))) {
58
+ return [];
59
+ }
60
+ const prop = meta?.properties[f];
61
+ if (prop?.embeddable && !prop.object) {
62
+ return expandEmbeddedProperties(prop);
63
+ }
64
+ return [f];
12
65
  });
13
66
  if (options.onConflictExcludeFields) {
14
- return keys.filter(f => !options.onConflictExcludeFields.includes(f));
67
+ const onConflictExcludeFields = expandFields(meta, options.onConflictExcludeFields);
68
+ return keys.filter(f => !onConflictExcludeFields.includes(f));
15
69
  }
16
70
  return keys;
17
71
  }
18
72
  /** @internal */
19
73
  function getOnConflictReturningFields(meta, data, uniqueFields, options) {
74
+ /* istanbul ignore next */
20
75
  if (!meta) {
21
76
  return '*';
22
77
  }
@@ -28,10 +83,12 @@ function getOnConflictReturningFields(meta, data, uniqueFields, options) {
28
83
  return keys;
29
84
  }
30
85
  if (options.onConflictMergeFields) {
31
- return keys.filter(key => !options.onConflictMergeFields.includes(key));
86
+ const onConflictMergeFields = expandFields(meta, options.onConflictMergeFields);
87
+ return keys.filter(key => !onConflictMergeFields.includes(key));
32
88
  }
33
89
  if (options.onConflictExcludeFields) {
34
- return [...new Set(keys.concat(...options.onConflictExcludeFields))];
90
+ const onConflictExcludeFields = expandFields(meta, options.onConflictExcludeFields);
91
+ return [...new Set(keys.concat(...onConflictExcludeFields))];
35
92
  }
36
93
  return keys.filter(key => !(key in data));
37
94
  }