npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mikro-orm-recycle-bin

v1.0.0

Published

A MikroORM-based soft delete library for TypeScript that moves soft-deleted entities into a recycle bin table using decorators.

Readme

MikroORM Recycle Bin ♻️

A MikroORM-based soft-delete library for TypeScript that automatically moves soft-deleted (or hard-deleted) entities into a dedicated recycle bin table.

Unlike traditional soft-delete implementations that simply hide records with a deleted_at flag, this library physically moves the data to a separate table. This keeps your main tables lean and optimized while ensuring that deleted data is safely archived and recoverable.

✨ Features

  • Automatic Archiving: Moves entities to a recycle bin table upon deletion or soft-delete.
  • Auto Table Creation: Automatically creates the recycle bin table with the correct schema if it doesn't exist, mirroring the entity's structure.
  • Flexible Triggers: Supports both hard deletes (em.remove()) and soft-delete updates (e.g., setting a deleted_at timestamp).
  • Schema Support: Supports custom database schemas for the recycle bin tables (e.g., archive.user_history).
  • MikroORM Integration: Plugs directly into the MikroORM lifecycle using an EventSubscriber.
  • Lightweight: Zero external dependencies (besides MikroORM and its Knex-based drivers).

📋 Requirements

  • MikroORM v6+ (may work with v5, but tested on v6)
  • Knex-based driver (primarily PostgreSQL, also supports MySQL/MariaDB)
  • TypeScript

🚀 Installation

npm install mikro-orm-recycle-bin

🛠️ Usage

1. Define your Entity

Use the @RecycleBin() decorator to mark an entity for the recycle bin.

import { Entity, PrimaryKey, Property } from "@mikro-orm/core";
import { RecycleBin } from "mikro-orm-recycle-bin";

@Entity()
@RecycleBin({
  tableName: "user_recycle_bin", // Target table for deleted records
  columnName: "deleted_at", // The property/column that triggers soft-delete move
  schema: "recycle_bin", // Optional: separate schema for the bin
})
export class User {
  @PrimaryKey()
  id!: number;

  @Property()
  username!: string;

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

2. Register the Subscriber

Register the RecycleBinSubscriber in your MikroORM configuration.

import { MikroORM } from "@mikro-orm/postgresql";
import { RecycleBinSubscriber } from "mikro-orm-recycle-bin";

const orm = await MikroORM.init({
  entities: [User],
  dbName: "my_db",
  subscribers: [new RecycleBinSubscriber()], // Add it here
});

💡 How it works

The RecycleBinSubscriber listens to the onFlush event. When an entity with the @RecycleBin decorator is encountered during a flush:

  1. Detection:
    • Hard Delete: If the entity is being deleted via em.remove(entity).
    • Soft Delete: If the entity is being updated and the property specified in columnName (e.g., deletedAt) has a truthy value in the changeset payload.
  2. Archiving:
    • It checks if the target recycle bin table exists; if not, it automatically creates it based on the entity's metadata (columns, types, etc.).
    • It inserts the current entity data (all mapped fields) into the recycle bin table.
    • If it was a soft-delete update, it removes the record from the original table to complete the "move" operation.

🏗️ Examples

Simple Deletion (Hard Delete)

When you use em.remove(), the subscriber intercepts the deletion and moves the data to the recycle bin before it's gone forever.

const user = await em.findOneOrFail(User, 1);
await em.removeAndFlush(user);
// User is now in 'user_recycle_bin' table and removed from 'user' table.

Soft-Delete Move

If you prefer to trigger the move by setting a timestamp:

const user = await em.findOneOrFail(User, 1);
user.deletedAt = new Date();
await em.flush();
// User is now in 'user_recycle_bin' table and removed from 'user' table.

NestJS Integration

Integrating with @mikro-orm/nestjs is straightforward:

// app.module.ts
import { MikroOrmModule } from "@mikro-orm/nestjs";
import { RecycleBinSubscriber } from "mikro-orm-recycle-bin";

@Module({
  imports: [
    MikroOrmModule.forRoot({
      // … your config
      subscribers: [new RecycleBinSubscriber()],
    }),
  ],
})
export class AppModule {}

⚙️ Configuration Options

The @RecycleBin() decorator accepts the following options:

| Option | Type | Description | |:-------------|:---------|:--------------------------------------------------------------------------------------------------------------| | tableName | string | Required. The name of the table where deleted records will be stored. | | columnName | string | Required. The entity property name (or database column name) that triggers a soft-delete move when set. | | schema | string | Optional. The database schema where the recycle bin table resides. If it doesn't exist, it will be created. |

📄 License

MIT