@mikro-orm/core 7.0.0-dev.335 → 7.0.0-dev.337

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.
@@ -346,8 +346,8 @@ export class DatabaseDriver {
346
346
  const props = prop.embeddedProps;
347
347
  let unknownProp = false;
348
348
  Object.keys(data[prop.name]).forEach(kk => {
349
- // explicitly allow `$exists`, `$eq` and `$ne` operators here as they can't be misused this way
350
- const operator = Object.keys(data[prop.name]).some(f => Utils.isOperator(f) && !['$exists', '$ne', '$eq'].includes(f));
349
+ // explicitly allow `$exists`, `$eq`, `$ne` and `$elemMatch` operators here as they can't be misused this way
350
+ const operator = Object.keys(data[prop.name]).some(f => Utils.isOperator(f) && !['$exists', '$ne', '$eq', '$elemMatch'].includes(f));
351
351
  if (operator) {
352
352
  throw ValidationError.cannotUseOperatorsInsideEmbeddables(meta.class, prop.name, data);
353
353
  }
package/enums.d.ts CHANGED
@@ -45,7 +45,8 @@ export declare enum QueryOperator {
45
45
  $size = "size",// collection operators, sql only
46
46
  $hasKey = "?",// postgres only, json
47
47
  $hasKeys = "?&",// postgres only, json
48
- $hasSomeKeys = "?|"
48
+ $hasSomeKeys = "?|",// postgres only, json
49
+ $elemMatch = "elemMatch"
49
50
  }
50
51
  export declare const ARRAY_OPERATORS: string[];
51
52
  export declare const JSON_KEY_OPERATORS: string[];
package/enums.js CHANGED
@@ -48,6 +48,7 @@ export var QueryOperator;
48
48
  QueryOperator["$hasKey"] = "?";
49
49
  QueryOperator["$hasKeys"] = "?&";
50
50
  QueryOperator["$hasSomeKeys"] = "?|";
51
+ QueryOperator["$elemMatch"] = "elemMatch";
51
52
  })(QueryOperator || (QueryOperator = {}));
52
53
  export const ARRAY_OPERATORS = ['$eq', '$gt', '$gte', '$lt', '$lte', '$ne', '$overlap', '$contains', '$contained'];
53
54
  export const JSON_KEY_OPERATORS = ['$hasKey', '$hasKeys', '$hasSomeKeys'];
@@ -990,9 +990,13 @@ export class MetadataDiscovery {
990
990
  if (properties[prop.name] && properties[prop.name].type !== prop.type) {
991
991
  properties[prop.name].type = `${properties[prop.name].type} | ${prop.type}`;
992
992
  properties[prop.name].runtimeType = 'any';
993
+ properties[prop.name].stiMerged = true;
993
994
  return properties[prop.name];
994
995
  }
995
- return (properties[prop.name] = prop);
996
+ // Deep copy to prevent mutating the original entity's property —
997
+ // both from the merge path above (GH #6522/#6523) and from
998
+ // downstream code that mutates nested arrays like fieldNames.
999
+ return (properties[prop.name] = Utils.copy(prop));
996
1000
  });
997
1001
  };
998
1002
  const processExtensions = (meta) => {
@@ -1219,8 +1223,13 @@ export class MetadataDiscovery {
1219
1223
  Object.values(meta.properties).forEach(prop => {
1220
1224
  const newProp = { ...prop };
1221
1225
  const rootProp = meta.root.properties[prop.name];
1226
+ // stiMerged is set during inlineProperties when a property was merged
1227
+ // from multiple polymorphic variants with different types. The flag is
1228
+ // cleared implicitly when the first child claims the root property via
1229
+ // addProperty below, so subsequent children correctly trigger renaming.
1230
+ const typesMatch = rootProp?.type === prop.type || rootProp?.stiMerged === true;
1222
1231
  if (rootProp &&
1223
- (rootProp.type !== prop.type ||
1232
+ (!typesMatch ||
1224
1233
  (rootProp.fieldNames && prop.fieldNames && !compareArrays(rootProp.fieldNames, prop.fieldNames)))) {
1225
1234
  const name = newProp.name;
1226
1235
  this.initFieldName(newProp, newProp.object);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "7.0.0-dev.335",
3
+ "version": "7.0.0-dev.337",
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
  "keywords": [
6
6
  "data-mapper",
package/typings.d.ts CHANGED
@@ -234,8 +234,18 @@ export type FilterItemValue<T> = T | ExpandScalar<T> | Primary<T> | Raw;
234
234
  export type FilterValue<T> = OperatorMap<FilterItemValue<T>> | FilterItemValue<T> | FilterItemValue<T>[] | null;
235
235
  type FilterObjectProp<T, K extends PropertyKey> = K extends keyof MergeUnion<T> ? MergeUnion<T>[K] : K extends keyof T ? T[K] : never;
236
236
  type ExpandQueryMerged<T> = [T] extends [object] ? [T] extends [Scalar] ? never : FilterQuery<MergeUnion<T>> : FilterValue<T>;
237
+ type ElemMatchCondition<T extends Record<string, any>> = {
238
+ [K in keyof T]?: T[K] | OperatorMap<T[K]>;
239
+ } & {
240
+ $or?: ElemMatchCondition<T>[];
241
+ $and?: ElemMatchCondition<T>[];
242
+ $not?: ElemMatchCondition<T>;
243
+ };
244
+ type ElemMatchFilter<T> = T extends readonly (infer E)[] ? E extends Record<string, any> ? {
245
+ $elemMatch: ElemMatchCondition<E>;
246
+ } : never : never;
237
247
  export type FilterObject<T> = {
238
- -readonly [K in EntityKey<T>]?: ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>> | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>> | FilterValue<ExpandProperty<FilterObjectProp<T, K>>> | null;
248
+ -readonly [K in EntityKey<T>]?: ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>> | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>> | FilterValue<ExpandProperty<FilterObjectProp<T, K>>> | ElemMatchFilter<FilterObjectProp<T, K>> | null;
239
249
  };
240
250
  export type ExpandQuery<T> = T extends object ? (T extends Scalar ? never : FilterQuery<T>) : FilterValue<T>;
241
251
  export type EntityProps<T> = {
@@ -523,6 +533,7 @@ export interface EntityProperty<Owner = any, Target = any> {
523
533
  nullable?: boolean;
524
534
  inherited?: boolean;
525
535
  renamedFrom?: string;
536
+ stiMerged?: boolean;
526
537
  stiFieldNames?: string[];
527
538
  stiFieldNameMap?: Dictionary<string>;
528
539
  unsigned?: boolean;
@@ -186,7 +186,7 @@ export class QueryHelper {
186
186
  value = QueryHelper.processCustomType(prop, value, platform, undefined, true);
187
187
  }
188
188
  // oxfmt-ignore
189
- const isJsonProperty = prop?.customType instanceof JsonType && !isRaw(value) && (Utils.isPlainObject(value) ? Object.keys(value)[0] !== '$eq' : !Array.isArray(value));
189
+ const isJsonProperty = prop?.customType instanceof JsonType && !isRaw(value) && (Utils.isPlainObject(value) ? !['$eq', '$elemMatch'].includes(Object.keys(value)[0]) : !Array.isArray(value));
190
190
  if (isJsonProperty && prop?.kind !== ReferenceKind.EMBEDDED) {
191
191
  return this.processJsonCondition(o, value, [prop.fieldNames[0]], platform, aliased);
192
192
  }
package/utils/Utils.js CHANGED
@@ -123,7 +123,7 @@ export function parseJsonSafe(value) {
123
123
  }
124
124
  export class Utils {
125
125
  static PK_SEPARATOR = '~~~';
126
- static #ORM_VERSION = '7.0.0-dev.335';
126
+ static #ORM_VERSION = '7.0.0-dev.337';
127
127
  /**
128
128
  * Checks if the argument is instance of `Object`. Returns false for arrays.
129
129
  */