Skip to content

Commit

Permalink
fix(chore): add #122 changes in mixin and transaction repository
Browse files Browse the repository at this point in the history
add development note to ensure future modifications universal
add changes made in PR #122 in
soft-crud mixin and transaction-soft-crud repository

GH-129
  • Loading branch information
shubhamp-sf committed Feb 22, 2023
1 parent 72b213d commit c4d90af
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 38 deletions.
62 changes: 58 additions & 4 deletions src/__tests__/unit/mixin/soft-crud.mixin.unit.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/repository
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// DEVELOPMENT NOTE:
// Please ensure that any modifications made to this file are also applied to the following locations:
// 1) src/__tests_/unit/repository/default-transaction-soft-crud.repository.base.ts
// 2) src/__tests_/unit/repository/soft-crud.repository.unit.ts

import {expect} from '@loopback/testlab';

Expand Down Expand Up @@ -368,6 +368,60 @@ describe('SoftCrudRepositoryMixin', () => {
expect(e.message).to.be.equal('EntityNotFound');
}
});
it('should not return soft deleted entry by id, without using deleted in fields filter', async () => {
try {
await repo.findById(3, {
fields: {
id: true,
email: true,
},
});
fail();
} catch (e) {
expect(e.message).to.be.equal('EntityNotFound');
}
});
it('should not return soft deleted entry by id, without using deleted in fields filter(fields fileter is passed as array)', async () => {
try {
await repo.findById(3, {
fields: ['id', 'email'],
});
fail();
} catch (e) {
expect(e.message).to.be.equal('EntityNotFound');
}
});
it('should return requested fields only when not using deleted in fields filter', async () => {
const customer = await repo.findById(4, {
fields: {
id: true,
email: true,
},
});
expect(customer).to.not.have.property('deleted');
});
it('should return requested fields matched with fields filter', async () => {
const customer = await repo.findById(4, {
fields: {
id: true,
email: true,
deleted: true,
},
});
expect(customer).to.have.property('deleted');
});
it('should return requested fields only when not using deleted in fields filter array', async () => {
const customer = await repo.findById(4, {
fields: ['id', 'email'],
});
expect(customer).to.not.have.property('deleted');
});
it('should return requested fields matched with fields filter array', async () => {
const customer = await repo.findById(4, {
fields: ['id', 'email', 'deleted'],
});
expect(customer).to.have.property('deleted');
});
});

describe('findByIdIncludeSoftDelete', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/repository
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// DEVELOPMENT NOTE:
// Please ensure that any modifications made to this file are also applied to the following locations:
// 1) src/__tests__/unit/mixin/soft-crud.mixin.unit.ts
// 2) src/__tests__/unit/repository/soft-crud.repository.unit.ts

import {expect} from '@loopback/testlab';

Expand Down Expand Up @@ -358,6 +358,60 @@ describe('DefaultTransactionSoftCrudRepository', () => {
expect(e.message).to.be.equal('EntityNotFound');
}
});
it('should not return soft deleted entry by id, without using deleted in fields filter', async () => {
try {
await repo.findById(3, {
fields: {
id: true,
email: true,
},
});
fail();
} catch (e) {
expect(e.message).to.be.equal('EntityNotFound');
}
});
it('should not return soft deleted entry by id, without using deleted in fields filter(fields fileter is passed as array)', async () => {
try {
await repo.findById(3, {
fields: ['id', 'email'],
});
fail();
} catch (e) {
expect(e.message).to.be.equal('EntityNotFound');
}
});
it('should return requested fields only when not using deleted in fields filter', async () => {
const customer = await repo.findById(4, {
fields: {
id: true,
email: true,
},
});
expect(customer).to.not.have.property('deleted');
});
it('should return requested fields matched with fields filter', async () => {
const customer = await repo.findById(4, {
fields: {
id: true,
email: true,
deleted: true,
},
});
expect(customer).to.have.property('deleted');
});
it('should return requested fields only when not using deleted in fields filter array', async () => {
const customer = await repo.findById(4, {
fields: ['id', 'email'],
});
expect(customer).to.not.have.property('deleted');
});
it('should return requested fields matched with fields filter array', async () => {
const customer = await repo.findById(4, {
fields: ['id', 'email', 'deleted'],
});
expect(customer).to.have.property('deleted');
});
});

describe('findByIdIncludeSoftDelete', () => {
Expand Down Expand Up @@ -741,22 +795,13 @@ describe('DefaultTransactionSoftCrudRepository', () => {
await repo.create({id: 4, email: 'bob@example.com'});
await repo.deleteById(3);

await repoWithCustomDeletedByKey.create({
id: 1,
email: 'john@example.com',
});
await repoWithCustomDeletedByKey.create({
id: 2,
email: 'mary@example.com',
});
await repoWithCustomDeletedByKey.create({id: 1, email: 'john@example.com'});
await repoWithCustomDeletedByKey.create({id: 2, email: 'mary@example.com'});
await repoWithCustomDeletedByKey.create({
id: 3,
email: 'alice@example.com',
});
await repoWithCustomDeletedByKey.create({
id: 4,
email: 'bob@example.com',
});
await repoWithCustomDeletedByKey.create({id: 4, email: 'bob@example.com'});
await repoWithCustomDeletedByKey.deleteById(3);
}

Expand Down
8 changes: 4 additions & 4 deletions src/__tests__/unit/repository/soft-crud.repository.unit.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/repository
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// DEVELOPMENT NOTE:
// Please ensure that any modifications made to this file are also applied to the following locations:
// 1) src/__tests__/unit/mixin/soft-crud.mixin.unit.ts
// 2) src/__tests__/unit/repository/default-transaction-soft-crud.repository.base.ts

import {expect} from '@loopback/testlab';

Expand Down
54 changes: 48 additions & 6 deletions src/mixins/soft-crud.repository.mixin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// DEVELOPMENT NOTE:
// Please ensure that any modifications made to this file are also applied to the following locations:
// 1) src/repositories/soft-crud.repository.base.ts
// 2) src/repositories/default-transaction-soft-crud.repository.base.ts

import {Constructor, Getter} from '@loopback/core';
import {
AndClause,
AnyObject,
Condition,
DataObject,
DefaultCrudRepository,
Expand Down Expand Up @@ -157,13 +163,49 @@ export function SoftCrudRepositoryMixin<
} as Condition<E>;
}

//As parent method findById have filter: FilterExcludingWhere<E>
//so we need add check here.
const entityToRemove = await super.findOne(filter, options);
let finalFilter: Filter<E> = {};

if (entityToRemove) {
// Now call super
return super.findById(id, filter, options);
// In case of array of fields, we need to copy the array
// by value and not by reference
finalFilter = {
...filter,
fields:
filter?.fields && Array.isArray(filter.fields)
? [...filter.fields]
: filter.fields,
};
if (finalFilter.fields) {
if (Array.isArray(finalFilter.fields)) {
const fields = finalFilter.fields as Extract<
keyof SoftDeleteEntity,
string
>[];
if (!fields.includes('deleted')) {
fields.push('deleted');
}
} else {
finalFilter.fields = {
...finalFilter.fields,
deleted: true,
};
}
}
const entity = await super.findById(id, finalFilter, options);
if (entity && !entity.deleted) {
if (filter.fields) {
if (Array.isArray(filter.fields)) {
const temp = filter.fields as Extract<
keyof SoftDeleteEntity,
string
>[];
if (!temp.includes('deleted')) {
delete entity.deleted;
}
} else if (!(filter.fields as AnyObject).deleted) {
delete entity.deleted;
}
}
return entity;
} else {
throw new HttpErrors.NotFound(ErrorKeys.EntityNotFound);
}
Expand Down
56 changes: 48 additions & 8 deletions src/repositories/default-transaction-soft-crud.repository.base.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
// DEVELOPMENT NOTE:
// Please ensure that any modifications made to this file are also applied to the following locations:
// 1) src/repositories/soft-crud.repository.base.ts
// 2) src/mixins/soft-crud.repository.mixin.ts

import {
AndClause,
AnyObject,
Condition,
DataObject,
DefaultTransactionalRepository,
Expand Down Expand Up @@ -121,7 +127,6 @@ export abstract class DefaultTransactionSoftCrudRepository<
filter?: Filter<T>,
options?: Options,
): Promise<T & Relations> {
// Filter out soft deleted entries
// Filter out soft deleted entries
if (
filter?.where &&
Expand Down Expand Up @@ -155,13 +160,48 @@ export abstract class DefaultTransactionSoftCrudRepository<
id: id,
} as Condition<T>;
}

//As parent method findById have filter: FilterExcludingWhere<T>
//so we need add check here.
const entityToRemove = await super.findOne(filter, options);
if (entityToRemove) {
// Now call super
return super.findById(id, filter, options);
let finalFilter: Filter<T> = {};
//In case of array of fields, we need to copy the array
// by value and not by reference
finalFilter = {
...filter,
fields:
filter?.fields && Array.isArray(filter.fields)
? [...filter.fields]
: filter.fields,
};
if (finalFilter.fields) {
if (Array.isArray(finalFilter.fields)) {
const fields = finalFilter.fields as Extract<
keyof SoftDeleteEntity,
string
>[];
if (!fields.includes('deleted')) {
fields.push('deleted');
}
} else {
finalFilter.fields = {
...finalFilter.fields,
deleted: true,
};
}
}
const entity = await super.findById(id, finalFilter, options);
if (entity && !entity.deleted) {
if (filter.fields) {
if (Array.isArray(filter.fields)) {
const temp = filter.fields as Extract<
keyof SoftDeleteEntity,
string
>[];
if (!temp.includes('deleted')) {
delete entity.deleted;
}
} else if (!(filter.fields as AnyObject).deleted) {
delete entity.deleted;
}
}
return entity;
} else {
throw new HttpErrors.NotFound(ErrorKeys.EntityNotFound);
}
Expand Down
5 changes: 5 additions & 0 deletions src/repositories/soft-crud.repository.base.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// DEVELOPMENT NOTE:
// Please ensure that any modifications made to this file are also applied to the following locations:
// 1) src/repositories/default-transaction-soft-crud.repository.base.ts
// 2) src/mixins/soft-crud.repository.mixin.ts

import {Getter} from '@loopback/core';
import {
AndClause,
Expand Down

0 comments on commit c4d90af

Please sign in to comment.