Soft Delete & Auditing

nest-extended records who changed a record and never destroys data on delete — rows are flagged instead of removed, so they can be excluded from queries and restored later.

Audit fields

When auditing is enabled, the service maintains these fields for you:

FieldSet onValue
createdBycreateauthenticated user id
updatedBypatchauthenticated user id
deletedByremoveauthenticated user id
deletedremovetrue
deletedAtremovetimestamp

_remove performs a soft delete: it sets the flags above and returns the record as it was before deletion, while _find and _get automatically exclude soft-deleted rows.

Capturing the current user

The audit values come from the request-scoped user stored in nestjs-cls. Use the @ModifyBody decorator with the built-in setCreatedBy modifier to stamp the user id onto the body before it reaches the service:

cats.controller.ts
import { Controller, Post, Patch, Param } from '@nestjs/common';
import { ModifyBody, setCreatedBy } from '@nest-extended/decorators';
 
@Controller('cats')
export class CatsController {
  @Post()
  create(@ModifyBody(setCreatedBy()) body: CreateCatDto) {
    // body.createdBy === current user id
  }
 
  @Patch(':id')
  update(@Param('id') id: string, @ModifyBody(setCreatedBy('updatedBy')) body: UpdateCatDto) {
    // body.updatedBy === current user id
  }
}

Read the current user anywhere with the CLS helper:

import { getCurrentUser } from '@nest-extended/core';
 
const user = getCurrentUser();

Configuration

Soft-delete behaviour is configured on NestExtendedModule.forRoot(). Provide getQuery to control how deleted rows are filtered out and getData to control what is written on delete:

app.module.ts
NestExtendedModule.forRoot({
  softDelete: {
    getQuery: () => ({ deleted: { $ne: true } }),
    getData: (user) => ({ deleted: true, deletedAt: new Date(), deletedBy: user?._id }),
  },
});

Auditing relies on the ClsModule being mounted as middleware so the user is available for the whole request. See Getting Started.

Next steps