GithubHelp home page GithubHelp logo

thenightmarex / mikro-orm-soft-delete Goto Github PK

View Code? Open in Web Editor NEW
29.0 3.0 10.0 738 KB

Generic soft delete solution for MikroORM.

License: Apache License 2.0

JavaScript 11.89% TypeScript 88.11%
typescript mikroorm soft-delete

mikro-orm-soft-delete's Introduction

Mikro ORM Soft Delete

The declarative soft-delete solution for MikroORM.

npm i mikro-orm-soft-delete

Inspired by: mikro-orm/mikro-orm#1492 (comment)

Compatibilities

Library Version ORM Version
v1.x.x v6.x.x
v0.x.x v5.x.x

Migrating to v1

  • It is now mandatory to register SoftDeleteHandler as an extension for this library to work. See Initialization for details.
  • Base entities no longer accept any generic type parameters.

Tutorial

Initialization

To enable soft-delete for your MikroORM instance, register SoftDeleteHandler as an extension in the initialization config:

import { SoftDeleteHandler } from "mikro-orm-soft-delete";

await MikroORM.init({
  // ...
  extensions: [SoftDeleteHandler],
  // ...
});

Basics

Put a SoftDeletable decorator on your entity definition to make it soft-deletable:

import { SoftDeletable } from "mikro-orm-soft-delete";

@SoftDeletable(() => User, "deletedAt", () => new Date())
@Entity()
export class User extends BaseEntity {
  @PrimaryKey()
  id: number;

  @Property({ nullable: true })
  deletedAt?: Date;
}

The above code snippet means that:

  • A filter with conditions { deletedAt: null } is applied to User and enabled by default, so that those soft-deleted entities will be excluded from your queries. This filter could be disabled by:
    import { SOFT_DELETABLE_FILTER } from "mikro-orm-soft-delete";
    repo.find({ ... }, { filters: { [SOFT_DELETABLE_FILTER]: false } });
    repo.find({ ... }, { filters: false }); // if you are sure that there are no other filters enabled
  • When an deletion command is executed on a User entity, its deletedAt field will be set to a newly instantiated Date. You could find all delete statements replaced with update ones under MikroORM's debugging mode:
    repo.remove(user);
    await repo.flush();
    user.id !== undefined; // true
    user.deletedAt instanceof Date; // true
  • cascade: [Cascade.Remove] and orphanRemoval: true still work with repo.remove(). But you would have to avoid removing items from collections when using orphanRemoval as it's currently not possible to intercept deletions caused by these operations.

Config API

Aside from passing the parameters by positions, there is also an object-based API that accepts a config object instead:

@SoftDeletable({
  type: () => User,
  field: 'deletedAt',
  value: () => new Date(),
})

Default Field Value

By default, a null value is used in the filter to exclude soft-deleted entities: { deletedAt: null }. However, if the default value of the field is not null, the query would not work as we expected.

For example, when the field is isDeleted and the default value is false, the query { isDeleted: null } would not match any entities.

In this case, an additional option valueInitial needs to be specified:

@SoftDeletable({
  type: () => User,
  field: 'isDeleted',
  value: () => true,
  valueInitial: false, // indicating that the default value of `isDeleted` is `false`.
})

...which would make the query look like { isDeleted: false } to find all the entities that is not soft-deleted.

This option could also be specified through the 4th argument:

@SoftDeletable(() => User, 'isDeleted', () => true, false)

Inheritance

Inheritance is supported for the SoftDeletable decorator, thus it is possible to create a SoftDeletableBaseEntity to make all the sub entity classes soft-deletable:

@SoftDeletable(() => SoftDeletableBaseEntity, "deletedAt", () => new Date())
export abstract class SoftDeletableBaseEntity extends BaseEntity {
  @Property({ nullable: true })
  deletedAt?: Date;
}

Hard Deletions

Currently it's impossible to hard-delete an entity marked as soft-deletable. As a workaround, the native API could be used for hard-deletions:

em.nativeDelete(...);

mikro-orm-soft-delete's People

Contributors

adrivanhoudt avatar char2sgu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mikro-orm-soft-delete's Issues

Throw Error If Subscriber Not Registered

@TheNightmareX The one thing I wish I could of done but couldn't see a path to implement was get the @SoftDeletable decorator to throw an error if the subscriber wasn't registered. If you're able to see a path forward/point me in the right direction, I could open a follow up PR.

Originally posted by @Tucker-Eric in #6 (comment)

Relationships not updated correctly

I have a Foo entity with a OneToOne relation to a Bar entity.
When hard-deleting Foo, Bar is deleted due to having deleteRule: 'cascade'.
When soft-deleting Foo, Bar is not deleted and it's deletedAt property is not updated, only Foo's deletedAt.

HOWEVER: If I attempt to fetch Bar, the orm doesn't find it, even when its deletedAt property is still undefined. If I disable filters, it's fetched correctly.

So it seems it's working half way. Am I missing something? Is there a standardized way I should be cascading soft deletions? I'm only using deleteRule: 'cascade'. No orphan removal.

Add "recover" option to support recovery after soft deletion

Description:
It would be helpful to have an option to recover entities that have been soft-deleted. This feature would enable users to restore entities to their original state, rather than permanently losing them due to soft deletion.

Feature Request:

  • Implement a method to recover soft-deleted entities.
  • Ensure that the method updates the appropriate flags/fields to mark the entity as active.
  • Include documentation and examples for using this feature.

Benefits:

  • Provides users with the ability to recover entities that may have been accidentally soft-deleted.
  • Increases flexibility in managing soft-deleted data.
  • Reduces risk of permanent data loss.

soft-delete affect lazy-loading

Lazy-loading will not work properly if you use this library.

below code is sample

import {  Entity, BaseEntity, PrimaryKey, Property, sql, Ref, ManyToOne, OneToMany } from '@mikro-orm/core';

@SoftDeletable(
  () => {
    return CustomBaseEntity;
  },
  'deletedAt',
  () => new Date(),
)
class CustomBaseEntity extends BaseEntity {
  @PrimaryKey()
  id: number; 

   @Property({ nullable: true })
  deletedAt?: Date;
}

@Entity()
class  A extends CustomBaseEntity {
   @Property({
    length: 128,
  })
  name: string;
 
 @OneToMany(() => B, (b) => b.a)
 blist = new Collection<B>(this);
}

@Entity()
class  B extends CustomBaseEntity {
   @Property({
    length: 128,
  })
  name: string;

  @ManyToOne(() => A, {ref: true})
  a: Ref<A>;
}

when i run code

const list = await entityManager.findAll(B, {});

then output sql has 'inner join' like this.

select `c0`.*, `a1`.`id` as `app_id`
 from `B` as `c0` 
 inner join `A` as `a1` on `c0`.`a_id` = `a1`.`id` and `a1`.`deleted_at` is null 
 where `c0`.`deleted_at` is null"

I don't think there should be an inner-join as it should be.

https://github.com/mikro-orm/mikro-orm/blob/38344faa928fd312a4a03bf7e578b2750bf2d64a/packages/core/src/EntityManager.ts#L481 this line attach populated condition because of cond is { deletedAt: null }

is this support Inheritance?

I think this is not support inheritance. is it right?

 @SoftDeletable(() => SoftDeletableBaseEntity, "deletedAt", () => new Date())
 export abstract class SoftDeletableBaseEntity extends BaseEntity {
   @Property({ nullable: true })
   deletedAt?: Date;
 }

 @Entity()
 class DeleteEntity extends SoftDeletableBaseEntity {
     @Property()
     name: string;
 }

Above code, We can see errors like this.

error TS1238: Unable to resolve signature of class decorator when called as an expression.
      Argument of type 'typeof SoftDeletableBaseEntity' is not assignable to parameter of type 'Type<SoftDeletableBaseEntity>'.

    48 @SoftDeletable(() => SoftDeletableBaseEntity, "deletedAt", () => new Date())
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2322: Type 'typeof SoftDeletableBaseEntity' is not assignable to type 'Type<SoftDeletableBaseEntity>'.
      Cannot assign an abstract constructor type to a non-abstract constructor type.

    48 @SoftDeletable(() => SoftDeletableBaseEntity, "deletedAt", () => new Date())

https://github.com/TheNightmareX/mikro-orm-soft-delete/blob/main/src/decorator.ts#L12 this line use 'new' keyword of T.
But If T is abstract class, then it can not use 'new' keyword.

So I think @SoftDeletable decorator can not used on abstract class.
'm assuming you don't use this decorator for abstract classes?

docs: force hard delete

i think would be great to add on README, instructions to user when they want to "force" a hard delete and skip the soft delete logic.

I accomplished with nativeDelete. i.e:

trx.nativeDelete (Entity, {
            id: entity.id,
          });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.