@mikro-orm/core 7.1.0-dev.2 → 7.1.0-dev.3

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.
@@ -307,6 +307,25 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
307
307
  * Fires native insert query. Calling this has no side effects on the context (identity map).
308
308
  */
309
309
  insert<Entity extends object>(entityNameOrEntity: EntityName<Entity> | Entity, data?: RequiredEntityData<Entity> | Entity, options?: NativeInsertUpdateOptions<Entity>): Promise<Primary<Entity>>;
310
+ /**
311
+ * Clones rows matching the condition at the database level via INSERT...SELECT.
312
+ * Automatically excludes auto-increment PKs, generated columns, and resets version properties.
313
+ * Returns the cloned entity, registered in the identity map.
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * // Clone by entity class + where + overrides
318
+ * const cloned = await em.clone(Author, { id: 1 }, { email: 'new@email.com' });
319
+ *
320
+ * // Pure clone (all non-PK fields copied)
321
+ * const cloned = await em.clone(Author, { id: 1 });
322
+ *
323
+ * // Clone a loaded entity
324
+ * const author = await em.findOneOrFail(Author, 1);
325
+ * const cloned = await em.clone(author, { email: 'new@email.com' });
326
+ * ```
327
+ */
328
+ clone<Entity extends object>(entityNameOrEntity: EntityName<Entity> | Entity, whereOrOverrides?: FilterQuery<NoInfer<Entity>> | EntityData<Entity>, overridesOrOptions?: EntityData<Entity> | NativeInsertUpdateOptions<Entity>, options?: NativeInsertUpdateOptions<Entity>): Promise<Entity>;
310
329
  /**
311
330
  * Fires native multi-insert query. Calling this has no side effects on the context (identity map).
312
331
  */
package/EntityManager.js CHANGED
@@ -1211,6 +1211,54 @@ export class EntityManager {
1211
1211
  });
1212
1212
  return res.insertId;
1213
1213
  }
1214
+ /**
1215
+ * Clones rows matching the condition at the database level via INSERT...SELECT.
1216
+ * Automatically excludes auto-increment PKs, generated columns, and resets version properties.
1217
+ * Returns the cloned entity, registered in the identity map.
1218
+ *
1219
+ * @example
1220
+ * ```ts
1221
+ * // Clone by entity class + where + overrides
1222
+ * const cloned = await em.clone(Author, { id: 1 }, { email: 'new@email.com' });
1223
+ *
1224
+ * // Pure clone (all non-PK fields copied)
1225
+ * const cloned = await em.clone(Author, { id: 1 });
1226
+ *
1227
+ * // Clone a loaded entity
1228
+ * const author = await em.findOneOrFail(Author, 1);
1229
+ * const cloned = await em.clone(author, { email: 'new@email.com' });
1230
+ * ```
1231
+ */
1232
+ async clone(entityNameOrEntity, whereOrOverrides, overridesOrOptions, options) {
1233
+ const em = this.getContext(false);
1234
+ let entityName;
1235
+ let where;
1236
+ let overrides;
1237
+ if (Utils.isEntity(entityNameOrEntity)) {
1238
+ // clone(entity, overrides?, options?)
1239
+ entityName = entityNameOrEntity.constructor;
1240
+ where = helper(entityNameOrEntity).getPrimaryKey();
1241
+ overrides = whereOrOverrides;
1242
+ options = overridesOrOptions;
1243
+ }
1244
+ else {
1245
+ // clone(EntityClass, where, overrides?, options?)
1246
+ entityName = entityNameOrEntity;
1247
+ where = whereOrOverrides;
1248
+ overrides = overridesOrOptions;
1249
+ }
1250
+ options ??= {};
1251
+ em.prepareOptions(options);
1252
+ const meta = em.metadata.get(entityName);
1253
+ const res = await em.driver.nativeClone(entityName, where, overrides, {
1254
+ ctx: em.#transactionContext,
1255
+ ...options,
1256
+ });
1257
+ const pk = res.insertId ?? res.row?.[meta.primaryKeys[0]];
1258
+ return em.findOneOrFail(entityName, pk, {
1259
+ schema: options.schema,
1260
+ });
1261
+ }
1214
1262
  /**
1215
1263
  * Fires native multi-insert query. Calling this has no side effects on the context (identity map).
1216
1264
  */
@@ -28,6 +28,7 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
28
28
  abstract nativeUpdate<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
29
29
  nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
30
30
  abstract nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
31
+ nativeClone<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, overrides?: EntityData<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
31
32
  abstract count<T extends object, P extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
32
33
  /** Creates a new EntityManager instance bound to this driver. */
33
34
  createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
@@ -27,6 +27,9 @@ export class DatabaseDriver {
27
27
  async nativeUpdateMany(entityName, where, data, options) {
28
28
  throw new Error(`Batch updates are not supported by ${this.constructor.name} driver`);
29
29
  }
30
+ async nativeClone(entityName, where, overrides, options) {
31
+ throw new Error(`${this.constructor.name} does not support nativeClone`);
32
+ }
30
33
  /** Creates a new EntityManager instance bound to this driver. */
31
34
  createEntityManager(useContext) {
32
35
  const EntityManagerClass = this.config.get('entityManager', EntityManager);
@@ -52,6 +52,11 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
52
52
  nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
53
53
  /** Deletes rows matching the given condition. */
54
54
  nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: NativeDeleteOptions<T>): Promise<QueryResult<T>>;
55
+ /**
56
+ * Clones rows matching the condition at the database level via INSERT...SELECT.
57
+ * Automatically excludes auto-increment PKs, generated columns, and resets version properties.
58
+ */
59
+ nativeClone<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, overrides?: EntityData<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
55
60
  /** Persists changes to M:N collections (inserts/deletes pivot table rows). */
56
61
  syncCollections<T extends object, O extends object>(collections: Iterable<Collection<T, O>>, options?: DriverMethodOptions): Promise<void>;
57
62
  /** Counts entities matching the given condition. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "7.1.0-dev.2",
3
+ "version": "7.1.0-dev.3",
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/utils/Utils.js CHANGED
@@ -141,7 +141,7 @@ export function parseJsonSafe(value) {
141
141
  /** Collection of general-purpose utility methods used throughout the ORM. */
142
142
  export class Utils {
143
143
  static PK_SEPARATOR = '~~~';
144
- static #ORM_VERSION = '7.1.0-dev.2';
144
+ static #ORM_VERSION = '7.1.0-dev.3';
145
145
  /**
146
146
  * Checks if the argument is instance of `Object`. Returns false for arrays.
147
147
  */