@mikro-orm/core 7.1.9-dev.1 → 7.1.9-dev.11

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.
@@ -364,6 +364,9 @@ export class ObjectHydrator extends Hydrator {
364
364
  ret.push(` data${dataKey}.forEach((_, idx_${idx}) => {`);
365
365
  ret.push(...hydrateEmbedded(prop, [...path, `[idx_${idx}]`], `${dataKey}[idx_${idx}]`).map(l => ' ' + l));
366
366
  ret.push(` });`);
367
+ ret.push(` } else if (data${dataKey} === null) {`);
368
+ /* v8 ignore next */
369
+ ret.push(` entity${entityKey} = ${this.config.get('forceUndefined') ? 'undefined' : 'null'};`);
367
370
  ret.push(` }`);
368
371
  return ret;
369
372
  };
@@ -10,7 +10,8 @@ export class AbstractNamingStrategy {
10
10
  classToMigrationName(timestamp, customMigrationName) {
11
11
  let migrationName = `Migration${timestamp}`;
12
12
  if (customMigrationName) {
13
- migrationName += `_${customMigrationName}`;
13
+ // the name becomes part of a class identifier
14
+ migrationName += `_${customMigrationName.replace(/[^$\p{ID_Continue}]+/gu, '_')}`;
14
15
  }
15
16
  return migrationName;
16
17
  }
@@ -9,7 +9,8 @@ export interface NamingStrategy {
9
9
  */
10
10
  classToTableName(entityName: string, tableName?: string): string;
11
11
  /**
12
- * Return a migration name. This name should allow ordering.
12
+ * Return a migration name. This name should allow ordering, and has to be a valid class identifier,
13
+ * as it is used as the class name in the generated migration file.
13
14
  */
14
15
  classToMigrationName(timestamp: string, customMigrationName?: string): string;
15
16
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "7.1.9-dev.1",
3
+ "version": "7.1.9-dev.11",
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",
@@ -230,11 +230,15 @@ export class ChangeSetPersister {
230
230
  }
231
231
  const res = await this.#driver.nativeUpdateMany(meta.class, cond, payload, options);
232
232
  const map = new Map();
233
- res.rows?.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, true, this.#platform, true), item));
233
+ // returning rows are not mapped yet, so they are keyed by field names - we need to build the hash
234
+ // from those to be able to match them with `getSerializedPrimaryKey()` of the entity
235
+ const pkFields = meta.getPrimaryProps().flatMap(prop => prop.fieldNames);
236
+ res.rows?.forEach(item => map.set(Utils.getPrimaryKeyHash(pkFields.map(field => item[field])), item));
234
237
  for (const changeSet of changeSets) {
235
238
  if (res.rows) {
236
239
  const row = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
237
- this.mapReturnedValues(changeSet.entity, changeSet.payload, row, meta);
240
+ // STI batches can mix child types, so map through the change set's own metadata
241
+ this.mapReturnedValues(changeSet.entity, changeSet.payload, row, changeSet.meta);
238
242
  }
239
243
  changeSet.persisted = true;
240
244
  }
@@ -375,7 +379,8 @@ export class ChangeSetPersister {
375
379
  changeSets.forEach(cs => {
376
380
  Utils.keys(cs.payload).forEach(k => {
377
381
  if (isRaw(cs.payload[k]) && isRaw(cs.entity[k])) {
378
- returning.add(meta.properties[k]);
382
+ // STI batches can mix child types, so the property might not exist on `meta`
383
+ returning.add(cs.meta.properties[k]);
379
384
  }
380
385
  });
381
386
  });
@@ -400,12 +405,14 @@ export class ChangeSetPersister {
400
405
  options = this.prepareOptions(meta, options, {
401
406
  fields: Utils.unique(reloadProps.map(prop => prop.name)),
402
407
  });
403
- const data = await this.#driver.find(meta.class, { [pk]: { $in: pks } }, options);
408
+ // a mixed STI batch shares one table but the child discriminator would filter out the siblings
409
+ const target = changeSets.some(cs => cs.meta !== meta) && meta.root.discriminatorColumn ? meta.root : meta;
410
+ const data = await this.#driver.find(target.class, { [pk]: { $in: pks } }, options);
404
411
  const map = new Map();
405
412
  data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, false, this.#platform, true), item));
406
413
  for (const changeSet of changeSets) {
407
414
  const data = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
408
- this.#hydrator.hydrate(changeSet.entity, meta, data, this.#factory, 'full', false, true);
415
+ this.#hydrator.hydrate(changeSet.entity, changeSet.meta, data, this.#factory, 'full', false, true);
409
416
  Object.assign(changeSet.payload, data); // merge to the changeset payload, so it gets saved to the entity snapshot
410
417
  }
411
418
  }
@@ -85,7 +85,8 @@ const DEFAULTS = {
85
85
  safe: false,
86
86
  snapshot: true,
87
87
  emit: 'ts',
88
- fileName: (timestamp, name) => `Migration${timestamp}${name ? '_' + name : ''}`,
88
+ // mirrors `NamingStrategy.classToMigrationName`, so the file name matches the class it declares
89
+ fileName: (timestamp, name) => `Migration${timestamp}${name ? '_' + name.replace(/[^$\p{ID_Continue}]+/gu, '_') : ''}`,
89
90
  },
90
91
  schemaGenerator: {
91
92
  createForeignKeyConstraints: true,
@@ -447,6 +447,7 @@ export class EntityComparator {
447
447
  const ret = [];
448
448
  const padding = ' '.repeat(level * 2);
449
449
  const idx = this.#tmpIndex++;
450
+ ret.push(`${padding}if (entity${entityKey} === null) ret${dataKey} = null;`);
450
451
  ret.push(`${padding}if (Array.isArray(entity${entityKey})) {`);
451
452
  ret.push(`${padding} ret${dataKey} = [];`);
452
453
  ret.push(`${padding} entity${entityKey}.forEach((_, idx_${idx}) => {`);
package/utils/Utils.js CHANGED
@@ -153,7 +153,7 @@ export function parseJsonSafe(value) {
153
153
  /** Collection of general-purpose utility methods used throughout the ORM. */
154
154
  export class Utils {
155
155
  static PK_SEPARATOR = '~~~';
156
- static #ORM_VERSION = '7.1.9-dev.1';
156
+ static #ORM_VERSION = '7.1.9-dev.11';
157
157
  /**
158
158
  * Checks if the argument is instance of `Object`. Returns false for arrays.
159
159
  */