Refactor: merge find findPage - findAndPopulate findPageAndPopulate

This commit is contained in:
yassinedorbozgithub 2024-12-03 17:16:57 +01:00
parent acf3663bd5
commit cde4a36294
29 changed files with 82 additions and 163 deletions

View File

@ -80,14 +80,9 @@ export class BlockController extends BaseController<
filters: TFilterQuery<Block>,
@Query(PageQueryPipe) pageQuery?: PageQueryDto<Block>,
): Promise<Block[] | BlockFull[]> {
if (pageQuery?.limit) {
return this.canPopulate(populate)
? await this.blockService.findPageAndPopulate(filters, pageQuery)
: await this.blockService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.blockService.findAndPopulate(filters, pageQuery?.sort)
: await this.blockService.find(filters, pageQuery?.sort);
? await this.blockService.findAndPopulate(filters, pageQuery)
: await this.blockService.find(filters, pageQuery);
}
/**

View File

@ -57,11 +57,7 @@ export class CategoryController extends BaseController<Category> {
@Query(new SearchFilterPipe<Category>({ allowedFields: ['label'] }))
filters: TFilterQuery<Category>,
) {
if (pageQuery.limit) {
return await this.categoryService.findPage(filters, pageQuery);
}
return await this.categoryService.find(filters, pageQuery.sort);
return await this.categoryService.find(filters, pageQuery);
}
/**

View File

@ -28,7 +28,7 @@ import {
ContextVarUpdateDto,
} from '../dto/context-var.dto';
import { ContextVarRepository } from '../repositories/context-var.repository';
import { ContextVarModel, ContextVar } from '../schemas/context-var.schema';
import { ContextVar, ContextVarModel } from '../schemas/context-var.schema';
import { ContextVarService } from '../services/context-var.service';
import { ContextVarController } from './context-var.controller';
@ -80,10 +80,10 @@ describe('ContextVarController', () => {
describe('findPage', () => {
it('should return an array of contextVars', async () => {
const pageQuery = getPageQuery<ContextVar>();
jest.spyOn(contextVarService, 'findPage');
jest.spyOn(contextVarService, 'find');
const result = await contextVarController.findPage(pageQuery, {});
expect(contextVarService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(contextVarService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(contextVarFixtures.sort(sortRowsBy));
});
});

View File

@ -60,11 +60,7 @@ export class ContextVarController extends BaseController<ContextVar> {
@Query(new SearchFilterPipe<ContextVar>({ allowedFields: ['label'] }))
filters: TFilterQuery<ContextVar>,
): Promise<ContextVar[]> {
if (pageQuery.limit) {
return await this.contextVarService.findPage(filters, pageQuery);
}
return await this.contextVarService.find(filters, pageQuery.sort);
return await this.contextVarService.find(filters, pageQuery);
}
/**

View File

@ -104,13 +104,13 @@ describe('LabelController', () => {
describe('findPage', () => {
const pageQuery = getPageQuery<Label>();
it('should find labels', async () => {
jest.spyOn(labelService, 'findPage');
jest.spyOn(labelService, 'find');
const result = await labelController.findPage(pageQuery, [], {});
const labelsWithBuiltin = labelFixtures.map((labelFixture) => ({
...labelFixture,
}));
expect(labelService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(labelService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(labelsWithBuiltin.sort(sortRowsBy), [
...IGNORED_TEST_FIELDS,
'nextBlocks',
@ -118,7 +118,7 @@ describe('LabelController', () => {
});
it('should find labels, and foreach label populate its corresponding users', async () => {
jest.spyOn(labelService, 'findPageAndPopulate');
jest.spyOn(labelService, 'findAndPopulate');
const result = await labelController.findPage(pageQuery, ['users'], {});
const allLabels = await labelService.findAll();
const allSubscribers = await subscriberService.findAll();
@ -127,10 +127,7 @@ describe('LabelController', () => {
users: allSubscribers,
}));
expect(labelService.findPageAndPopulate).toHaveBeenCalledWith(
{},
pageQuery,
);
expect(labelService.findAndPopulate).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(labelsWithUsers.sort(sortRowsBy));
});
});

View File

@ -62,15 +62,9 @@ export class LabelController extends BaseController<
@Query(new SearchFilterPipe<Label>({ allowedFields: ['name', 'title'] }))
filters: TFilterQuery<Label>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.labelService.findPageAndPopulate(filters, pageQuery)
: await this.labelService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.labelService.findAndPopulate(filters, pageQuery.sort)
: await this.labelService.find(filters, pageQuery.sort);
? await this.labelService.findAndPopulate(filters, pageQuery)
: await this.labelService.find(filters, pageQuery);
}
/**

View File

@ -185,7 +185,7 @@ describe('MessageController', () => {
describe('findPage', () => {
const pageQuery = getPageQuery<Message>();
it('should find messages', async () => {
jest.spyOn(messageService, 'findPage');
jest.spyOn(messageService, 'find');
const result = await messageController.findPage(pageQuery, [], {});
const messagesWithSenderAndRecipient = allMessages.map((message) => ({
...message,
@ -195,12 +195,12 @@ describe('MessageController', () => {
sentBy: allUsers.find(({ id }) => id === message['sentBy']).id,
}));
expect(messageService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(messageService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(messagesWithSenderAndRecipient);
});
it('should find messages, and foreach message populate the corresponding sender and recipient', async () => {
jest.spyOn(messageService, 'findPageAndPopulate');
jest.spyOn(messageService, 'findAndPopulate');
const result = await messageController.findPage(
pageQuery,
['sender', 'recipient'],
@ -213,7 +213,7 @@ describe('MessageController', () => {
sentBy: allUsers.find(({ id }) => id === message['sentBy']).id,
}));
expect(messageService.findPageAndPopulate).toHaveBeenCalledWith(
expect(messageService.findAndPopulate).toHaveBeenCalledWith(
{},
pageQuery,
);

View File

@ -80,15 +80,9 @@ export class MessageController extends BaseController<
)
filters: TFilterQuery<Message>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.messageService.findPageAndPopulate(filters, pageQuery)
: await this.messageService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.messageService.findAndPopulate(filters, pageQuery.sort)
: await this.messageService.find(filters, pageQuery.sort);
? await this.messageService.findAndPopulate(filters, pageQuery)
: await this.messageService.find(filters, pageQuery);
}
/**

View File

@ -18,7 +18,7 @@ import { RoleRepository } from '@/user/repositories/role.repository';
import { UserRepository } from '@/user/repositories/user.repository';
import { PermissionModel } from '@/user/schemas/permission.schema';
import { RoleModel } from '@/user/schemas/role.schema';
import { UserModel, User } from '@/user/schemas/user.schema';
import { User, UserModel } from '@/user/schemas/user.schema';
import { RoleService } from '@/user/services/role.service';
import {
installSubscriberFixtures,
@ -35,8 +35,8 @@ import { WebsocketGateway } from '@/websocket/websocket.gateway';
import { LabelRepository } from '../repositories/label.repository';
import { SubscriberRepository } from '../repositories/subscriber.repository';
import { LabelModel, Label } from '../schemas/label.schema';
import { SubscriberModel, Subscriber } from '../schemas/subscriber.schema';
import { Label, LabelModel } from '../schemas/label.schema';
import { Subscriber, SubscriberModel } from '../schemas/subscriber.schema';
import { SubscriberService } from '../services/subscriber.service';
import { UserService } from './../../user/services/user.service';
@ -153,7 +153,7 @@ describe('SubscriberController', () => {
describe('findPage', () => {
const pageQuery = getPageQuery<Subscriber>();
it('should find subscribers', async () => {
jest.spyOn(subscriberService, 'findPage');
jest.spyOn(subscriberService, 'find');
const result = await subscriberController.findPage(pageQuery, [], {});
const subscribersWithIds = allSubscribers.map(({ labels, ...rest }) => ({
...rest,
@ -162,12 +162,12 @@ describe('SubscriberController', () => {
.map(({ id }) => id),
}));
expect(subscriberService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(subscriberService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(subscribersWithIds.sort(sortRowsBy));
});
it('should find subscribers, and foreach subscriber populate the corresponding labels', async () => {
jest.spyOn(subscriberService, 'findPageAndPopulate');
jest.spyOn(subscriberService, 'findAndPopulate');
const result = await subscriberController.findPage(
pageQuery,
['labels'],
@ -181,7 +181,7 @@ describe('SubscriberController', () => {
}),
);
expect(subscriberService.findPageAndPopulate).toHaveBeenCalledWith(
expect(subscriberService.findAndPopulate).toHaveBeenCalledWith(
{},
pageQuery,
);

View File

@ -73,15 +73,9 @@ export class SubscriberController extends BaseController<
)
filters: TFilterQuery<Subscriber>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.subscriberService.findPageAndPopulate(filters, pageQuery)
: await this.subscriberService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.subscriberService.findAndPopulate(filters, pageQuery.sort)
: await this.subscriberService.find(filters, pageQuery.sort);
? await this.subscriberService.findAndPopulate(filters, pageQuery)
: await this.subscriberService.find(filters, pageQuery);
}
/**

View File

@ -88,9 +88,9 @@ describe('ContentTypeController', () => {
describe('findPage', () => {
it('should return all contentTypes', async () => {
const pageQuery = getPageQuery<ContentType>({ sort: ['_id', 'asc'] });
jest.spyOn(contentTypeService, 'findPage');
jest.spyOn(contentTypeService, 'find');
const result = await contentTypeController.findPage(pageQuery, {});
expect(contentTypeService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(contentTypeService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toHaveLength(contentTypeFixtures.length);
expect(result).toEqualPayload(contentTypeFixtures);
});

View File

@ -75,11 +75,7 @@ export class ContentTypeController extends BaseController<ContentType> {
@Query(new SearchFilterPipe<ContentType>({ allowedFields: ['name'] }))
filters: TFilterQuery<ContentType>,
) {
if (pageQuery.limit) {
return await this.contentTypeService.findPage(filters, pageQuery);
}
return await this.contentTypeService.find(filters, pageQuery.sort);
return await this.contentTypeService.find(filters, pageQuery);
}
/**

View File

@ -194,14 +194,9 @@ export class ContentController extends BaseController<
)
filters: TFilterQuery<Content>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.contentService.findPageAndPopulate(filters, pageQuery)
: await this.contentService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.contentService.findAndPopulate(filters, pageQuery.sort)
: await this.contentService.find(filters, pageQuery.sort);
? await this.contentService.findAndPopulate(filters, pageQuery)
: await this.contentService.find(filters, pageQuery);
}
/**

View File

@ -76,11 +76,7 @@ export class MenuController extends BaseController<
@Query(new SearchFilterPipe<Menu>({ allowedFields: ['parent'] }))
filters: TFilterQuery<Menu>,
) {
if (pageQuery.limit) {
return await this.menuService.findPage(filters, pageQuery);
}
return await this.menuService.find(filters, pageQuery.sort);
return await this.menuService.find(filters, pageQuery);
}
/**

View File

@ -100,10 +100,10 @@ describe('LanguageController', () => {
describe('findPage', () => {
const pageQuery = getPageQuery<Language>({ sort: ['code', 'asc'] });
it('should find languages', async () => {
jest.spyOn(languageService, 'findPage');
jest.spyOn(languageService, 'find');
const result = await languageController.findPage(pageQuery, {});
expect(languageService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(languageService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(
languageFixtures.sort(({ code: codeA }, { code: codeB }) => {
if (codeA < codeB) {

View File

@ -57,11 +57,7 @@ export class LanguageController extends BaseController<Language> {
@Query(new SearchFilterPipe<Language>({ allowedFields: ['title', 'code'] }))
filters: TFilterQuery<Language>,
) {
if (pageQuery.limit) {
return await this.languageService.findPage(filters, pageQuery);
}
return await this.languageService.find(filters, pageQuery.sort);
return await this.languageService.find(filters, pageQuery);
}
/**

View File

@ -172,10 +172,10 @@ describe('TranslationController', () => {
describe('findPage', () => {
const pageQuery = getPageQuery<Translation>();
it('should find translations', async () => {
jest.spyOn(translationService, 'findPage');
jest.spyOn(translationService, 'find');
const result = await translationController.findPage(pageQuery, {});
expect(translationService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(translationService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(translationFixtures);
});
});

View File

@ -55,10 +55,7 @@ export class TranslationController extends BaseController<Translation> {
@Query(new SearchFilterPipe<Translation>({ allowedFields: ['str'] }))
filters: TFilterQuery<Translation>,
) {
if (pageQuery.limit) {
return await this.translationService.findPage(filters, pageQuery);
}
return await this.translationService.find(filters, pageQuery.sort);
return await this.translationService.find(filters, pageQuery);
}
/**

View File

@ -135,15 +135,9 @@ export class NlpEntityController extends BaseController<
@Query(new SearchFilterPipe<NlpEntity>({ allowedFields: ['name', 'doc'] }))
filters: TFilterQuery<NlpEntity>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.nlpEntityService.findPageAndPopulate(filters, pageQuery)
: await this.nlpEntityService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.nlpEntityService.findAndPopulate(filters)
: await this.nlpEntityService.find(filters, pageQuery.sort);
? await this.nlpEntityService.findAndPopulate(filters, pageQuery)
: await this.nlpEntityService.find(filters, pageQuery);
}
/**

View File

@ -280,15 +280,9 @@ export class NlpSampleController extends BaseController<
)
filters: TFilterQuery<NlpSample>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.nlpSampleService.findPageAndPopulate(filters, pageQuery)
: await this.nlpSampleService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.nlpSampleService.findAndPopulate(filters, pageQuery.sort)
: await this.nlpSampleService.find(filters, pageQuery.sort);
? await this.nlpSampleService.findAndPopulate(filters, pageQuery)
: await this.nlpSampleService.find(filters, pageQuery);
}
/**

View File

@ -146,15 +146,9 @@ export class NlpValueController extends BaseController<
)
filters: TFilterQuery<NlpValue>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.nlpValueService.findPageAndPopulate(filters, pageQuery)
: await this.nlpValueService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.nlpValueService.findAndPopulate(filters, pageQuery.sort)
: await this.nlpValueService.find(filters, pageQuery.sort);
? await this.nlpValueService.findAndPopulate(filters, pageQuery)
: await this.nlpValueService.find(filters, pageQuery);
}
/**

View File

@ -78,6 +78,8 @@ describe('SettingController', () => {
{},
{
sort: ['weight', 'asc'],
limit: undefined,
skip: undefined,
},
);

View File

@ -20,7 +20,7 @@ import { CsrfCheck } from '@tekuconcept/nestjs-csrf';
import { CsrfInterceptor } from '@/interceptors/csrf.interceptor';
import { LoggerService } from '@/logger/logger.service';
import { QuerySortDto } from '@/utils/pagination/pagination-query.dto';
import { PageQueryDto } from '@/utils/pagination/pagination-query.dto';
import { PageQueryPipe } from '@/utils/pagination/pagination-query.pipe';
import { SearchFilterPipe } from '@/utils/pipes/search-filter.pipe';
import { TFilterQuery } from '@/utils/types/filter.types';
@ -52,9 +52,9 @@ export class SettingController {
}),
)
filters: TFilterQuery<Setting>,
@Query(PageQueryPipe) { sort }: { sort: QuerySortDto<Setting> },
@Query(PageQueryPipe) pageQuery: PageQueryDto<Setting>,
) {
return await this.settingService.find(filters, sort);
return await this.settingService.find(filters, pageQuery);
}
/**

View File

@ -23,9 +23,9 @@ import { PermissionCreateDto } from '../dto/permission.dto';
import { ModelRepository } from '../repositories/model.repository';
import { PermissionRepository } from '../repositories/permission.repository';
import { RoleRepository } from '../repositories/role.repository';
import { ModelModel, Model } from '../schemas/model.schema';
import { PermissionModel, Permission } from '../schemas/permission.schema';
import { RoleModel, Role } from '../schemas/role.schema';
import { Model, ModelModel } from '../schemas/model.schema';
import { Permission, PermissionModel } from '../schemas/permission.schema';
import { Role, RoleModel } from '../schemas/role.schema';
import { ModelService } from '../services/model.service';
import { PermissionService } from '../services/permission.service';
import { RoleService } from '../services/role.service';

View File

@ -30,7 +30,7 @@ import { PermissionRepository } from '../repositories/permission.repository';
import { RoleRepository } from '../repositories/role.repository';
import { UserRepository } from '../repositories/user.repository';
import { PermissionModel } from '../schemas/permission.schema';
import { RoleModel, Role } from '../schemas/role.schema';
import { Role, RoleModel } from '../schemas/role.schema';
import { UserModel } from '../schemas/user.schema';
import { PermissionService } from '../services/permission.service';
import { RoleService } from '../services/role.service';
@ -96,14 +96,14 @@ describe('RoleController', () => {
describe('findPage', () => {
const pageQuery = getPageQuery<Role>({ sort: ['_id', 'asc'] });
it('should find roles', async () => {
jest.spyOn(roleService, 'findPage');
jest.spyOn(roleService, 'find');
const result = await roleController.findPage(pageQuery, [], {});
expect(roleService.findPage).toHaveBeenCalledWith({}, pageQuery);
expect(roleService.find).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(roleFixtures);
});
it('should find roles, and for each role populate the corresponding users and permissions', async () => {
jest.spyOn(roleService, 'findPageAndPopulate');
jest.spyOn(roleService, 'findAndPopulate');
const allRoles = await roleService.findAll();
const allPermissions = await permissionService.findAll();
const allUsers = await userService.findAll();
@ -128,10 +128,7 @@ describe('RoleController', () => {
return acc;
}, []);
expect(roleService.findPageAndPopulate).toHaveBeenCalledWith(
{},
pageQuery,
);
expect(roleService.findAndPopulate).toHaveBeenCalledWith({}, pageQuery);
expect(result).toEqualPayload(rolesWithPermissionsAndUsers);
});
});

View File

@ -68,15 +68,9 @@ export class RoleController extends BaseController<
@Query(new SearchFilterPipe<Role>({ allowedFields: ['name'] }))
filters: TFilterQuery<Role>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.roleService.findPageAndPopulate(filters, pageQuery)
: await this.roleService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.roleService.findAndPopulate(filters, pageQuery.sort)
: await this.roleService.find(filters, pageQuery.sort);
? await this.roleService.findAndPopulate(filters, pageQuery)
: await this.roleService.find(filters, pageQuery);
}
/**

View File

@ -168,15 +168,9 @@ export class ReadOnlyUserController extends BaseController<
)
filters: TFilterQuery<User>,
) {
if (pageQuery.limit) {
return this.canPopulate(populate)
? await this.userService.findPageAndPopulate(filters, pageQuery)
: await this.userService.findPage(filters, pageQuery);
}
return this.canPopulate(populate)
? await this.userService.findAndPopulate(filters, pageQuery.sort)
: await this.userService.find(filters, pageQuery.sort);
? await this.userService.findAndPopulate(filters, pageQuery)
: await this.userService.find(filters, pageQuery);
}
/**

View File

@ -247,16 +247,17 @@ export abstract class BaseRepository<
return await this.executeOne(query, this.clsPopulate);
}
protected findQuery(filter: TFilterQuery<T>, sort?: QuerySortDto<T>) {
protected findQuery(filter: TFilterQuery<T>, pageQuery?: PageQueryDto<T>) {
const { skip = 0, limit, sort = ['createdAt', 'asc'] } = pageQuery || {};
const query = this.model.find<T>(filter);
if (sort) {
return query.sort([sort] as [string, SortOrder][]);
}
return query;
return query
.skip(skip)
.limit(limit)
.sort([sort] as [string, SortOrder][]);
}
async find(filter: TFilterQuery<T>, sort?: QuerySortDto<T>) {
const query = this.findQuery(filter, sort);
async find(filter: TFilterQuery<T>, pageQuery?: PageQueryDto<T>) {
const query = this.findQuery(filter, pageQuery);
return await this.execute(query, this.cls);
}
@ -266,18 +267,18 @@ export abstract class BaseRepository<
}
}
async findAndPopulate(filters: TFilterQuery<T>, sort?: QuerySortDto<T>) {
async findAndPopulate(filters: TFilterQuery<T>, pageQuery?: PageQueryDto<T>) {
this.ensureCanPopulate();
const query = this.findQuery(filters, sort).populate(this.populate);
const query = this.findQuery(filters, pageQuery).populate(this.populate);
return await this.execute(query, this.clsPopulate);
}
protected findAllQuery(sort?: QuerySortDto<T>) {
return this.findQuery({}, sort);
return this.findQuery({}, { limit: undefined, skip: undefined, sort });
}
async findAll(sort?: QuerySortDto<T>) {
return await this.find({}, sort);
return await this.find({}, { limit: undefined, skip: undefined, sort });
}
async findAllAndPopulate(sort?: QuerySortDto<T>) {

View File

@ -39,12 +39,15 @@ export abstract class BaseService<
return await this.repository.findOneAndPopulate(criteria);
}
async find(filter: TFilterQuery<T>, sort?: QuerySortDto<T>): Promise<T[]> {
return await this.repository.find(filter, sort);
async find(
filter: TFilterQuery<T>,
pageQuery?: PageQueryDto<T>,
): Promise<T[]> {
return await this.repository.find(filter, pageQuery);
}
async findAndPopulate(filters: TFilterQuery<T>, sort?: QuerySortDto<T>) {
return await this.repository.findAndPopulate(filters, sort);
async findAndPopulate(filters: TFilterQuery<T>, pageQuery?: PageQueryDto<T>) {
return await this.repository.findAndPopulate(filters, pageQuery);
}
async findAll(sort?: QuerySortDto<T>): Promise<T[]> {