Skip to content

Commit

Permalink
feat(repository): implement undo soft delete feature (#185)
Browse files Browse the repository at this point in the history
GH-182

## Description

Add 2 functionalities to undo the soft delete of a record
1. undoSoftDeleteById() -> This will just undo soft delete entity by
specified id
2. undoSoftDeleteAll() -> This will undo soft delete entities depending
on where clause or all.
Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

## How Has This Been Tested ?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration

- [x] Test A
- [x] Test B

## Checklist:

- [x] Performed a self-review of my own code
- [x] npm test passes on your machine
  • Loading branch information
sf-sahil-jassal authored Jan 1, 2024
1 parent bc202f4 commit 8622d8e
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 2 deletions.
75 changes: 75 additions & 0 deletions src/__tests__/unit/repository/soft-crud.repository.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ describe('SoftCrudRepository', () => {
const customers = await repo.find();
expect(customers).to.have.length(3);
});

it('should find non soft deleted entries with and operator', async () => {
const customers = await repo.find({
where: {
Expand Down Expand Up @@ -793,6 +794,80 @@ describe('SoftCrudRepository', () => {
});
});

describe('undoSoftDelete', () => {
beforeEach(setupTestData);
afterEach(clearTestData);

it('should undo soft deleted entry by id', async () => {
await repo.undoSoftDeleteById(3);
const customer = await repo.findById(3);
const customers = await repo.find();
expect(customer.deleted).to.false();
expect(customers).to.have.length(4);
});

it('should check deletedOn flag is undefined after undo', async () => {
const softDeletedCustomer = await repo.findByIdIncludeSoftDelete(3);
expect(softDeletedCustomer.deletedOn).to.Date();
await repo.undoSoftDeleteById(3);
const customer = await repo.findById(3);
expect(customer.deletedOn).to.undefined();
});

it('should undo all soft deleted entries', async () => {
await repo.deleteAll();
await repo.undoSoftDeleteAll();
const customers = await repo.find();
expect(customers).to.have.length(4);
});

it('should undo soft deleted entries with and operator', async () => {
await repo.undoSoftDeleteAll({
and: [{email: '[email protected]'}, {id: 3}],
});
const customers = await repo.find({
where: {
and: [
{
email: '[email protected]',
},
{
id: 3,
},
],
},
});
expect(customers).to.have.length(1);
});

it('should undo soft deleted entries with or operator', async () => {
await repo.deleteAll({email: '[email protected]'});
await repo.undoSoftDeleteAll({
or: [
{
email: '[email protected]',
},
{
email: '[email protected]',
},
],
});
const customers = await repo.find({
where: {
or: [
{
email: '[email protected]',
},
{
email: '[email protected]',
},
],
},
});
expect(customers).to.have.length(2);
});
});

describe('deleteAll', () => {
beforeEach(setupTestData);
afterEach(clearTestData);
Expand Down
31 changes: 29 additions & 2 deletions src/repositories/soft-crud.repository.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

import {Getter} from '@loopback/core';
import {
Condition,
DataObject,
DefaultCrudRepository,
Entity,
Filter,
juggler,
Where,
Condition,
juggler,
} from '@loopback/repository';
import {Count} from '@loopback/repository/src/common-types';
import {HttpErrors} from '@loopback/rest';
Expand Down Expand Up @@ -168,6 +168,33 @@ export abstract class SoftCrudRepository<
);
}

/**
* Method to perform undo the soft delete by Id.
* @param id
* @param options
*/
async undoSoftDeleteById(id: ID, options?: Options): Promise<void> {
await this.undoSoftDeleteAll({id} as Where<E>, options);
}

/**
* Method to perform undo all the soft deletes
* @param where
* @param options
*/
async undoSoftDeleteAll(where?: Where<E>, options?: Options): Promise<Count> {
const filter = new SoftFilterBuilder({where})
.imposeCondition({
deleted: true,
} as Condition<E>)
.build();
return super.updateAll(
{deleted: false, deletedOn: undefined},
filter.where,
options,
);
}

/**
* Method to perform hard delete of entries. Take caution.
* @param entity
Expand Down

0 comments on commit 8622d8e

Please sign in to comment.