feat: add pagination, sorting and filtering

This commit is contained in:
2026-06-07 12:58:38 +03:30
parent 28c1a4831e
commit d1fecf62ad
19 changed files with 389 additions and 176 deletions
+24
View File
@@ -0,0 +1,24 @@
import { Type } from 'class-transformer';
import { IsInt, IsOptional, IsString, Min } from 'class-validator';
export class PaginationQueryDTO {
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page?: number = 1;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
limit?: number = 20;
@IsOptional()
@IsString()
sortBy?: string;
@IsOptional()
@IsString()
order?: 'ASC' | 'DESC' = 'DESC';
}
@@ -0,0 +1,10 @@
import { RequestTimeoutException } from '@nestjs/common';
export class AppTimeoutException extends RequestTimeoutException {
constructor(cause?: unknown, description?: string) {
super('common.errors.requestTimeout', {
cause,
description: description ?? 'Error connecting to the database',
});
}
}
+2
View File
@@ -1,7 +1,9 @@
import * as StringUtils from './string-utils'; import * as StringUtils from './string-utils';
import * as PaginationUtils from './pagination-utils';
const Utils = { const Utils = {
StringUtils, StringUtils,
PaginationUtils,
}; };
export default Utils; export default Utils;
+13
View File
@@ -0,0 +1,13 @@
import { PaginationQueryDTO } from '../dtos/pagination-query.dto';
export const getPaginationOptions = (query: PaginationQueryDTO) => {
const page = query.page ?? 1;
const limit = query.limit ?? 20;
return {
skip: (page - 1) * limit,
take: limit,
page,
limit,
};
};
@@ -1,4 +1,4 @@
import { Body, Controller, HttpCode, Post } from '@nestjs/common'; import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common';
import { AdminAuthService } from './providers/admin-auth.service'; import { AdminAuthService } from './providers/admin-auth.service';
import { AdminLoginDTO } from './dtos/admin-login.dto'; import { AdminLoginDTO } from './dtos/admin-login.dto';
import { Public } from '@/modules/auth/decorators/public.decorator'; import { Public } from '@/modules/auth/decorators/public.decorator';
@@ -14,7 +14,7 @@ export class AdminAuthController {
@Public() @Public()
@Post('login') @Post('login')
@HttpCode(200) @HttpCode(HttpStatus.OK)
public async login(@Body() adminLoginDto: AdminLoginDTO) { public async login(@Body() adminLoginDto: AdminLoginDTO) {
return await this.adminAuthService.login(adminLoginDto); return await this.adminAuthService.login(adminLoginDto);
} }
@@ -1,16 +1,21 @@
import { Role } from '@/common/enums/roles.enum'; import { Role } from '@/common/enums/roles.enum';
import { Roles } from '@/modules/auth/decorators/roles.decorator'; import { Roles } from '@/modules/auth/decorators/roles.decorator';
import { CreateTestDTO } from '@/modules/tests/dtos/create-test.dto'; import { CreateTestDTO } from '@/modules/tests/dtos/create-test.dto';
import { FindTestsDTO } from '@/modules/tests/dtos/find-tests.dto';
import { UpdateTestDTO } from '@/modules/tests/dtos/update-test.dto'; import { UpdateTestDTO } from '@/modules/tests/dtos/update-test.dto';
import { TestsService } from '@/modules/tests/providers/tests.service'; import { TestsService } from '@/modules/tests/providers/tests.service';
import { import {
Body, Body,
Controller, Controller,
Delete,
Get, Get,
HttpCode,
HttpStatus,
Param, Param,
ParseIntPipe, ParseIntPipe,
Patch, Patch,
Post, Post,
Query,
} from '@nestjs/common'; } from '@nestjs/common';
@Controller('admin/tests') @Controller('admin/tests')
@@ -29,8 +34,8 @@ export class AdminTestsController {
} }
@Get() @Get()
public async getAllTests() { public async getAllTests(@Query() query: FindTestsDTO) {
return await this.testsService.adminGetAll(); return await this.testsService.adminGetAll(query);
} }
@Get(':id') @Get(':id')
@@ -45,4 +50,10 @@ export class AdminTestsController {
) { ) {
return await this.testsService.updateOne(id, updateTestDto); return await this.testsService.updateOne(id, updateTestDto);
} }
@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
public async deleteTestById(@Param('id', ParseIntPipe) id: number) {
return await this.testsService.deleteOne(id);
}
} }
@@ -0,0 +1,2 @@
DELETE http://localhost:3000/admin/tests/1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJwaG9uZSI6IjA5MzMzMDI2MzYzIiwiaWF0IjoxNzgwNzQ5MTcwLCJleHAiOjE3ODA3NTI3NzAsImF1ZCI6ImxvY2FsaG9zdCIsImlzcyI6ImxvY2FsaG9zdCJ9.apRhtVZgFMFcyutZGO7uzckscch9Jw42s0RCSZZv4K0
@@ -1,5 +1,5 @@
GET http://localhost:3000/admin/tests GET http://localhost:3000/admin/tests?title=test&isActive=true&accessType=paid&sortBy=title&order=DSC&page=2&limit=1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJwaG9uZSI6IjA5MzMzMDI2MzYzIiwiaWF0IjoxNzgwMzk4MzI0LCJleHAiOjE3ODA0MDE5MjQsImF1ZCI6ImxvY2FsaG9zdCIsImlzcyI6ImxvY2FsaG9zdCJ9.s3NAErSAjMTz2s27obas3TEi5Og2HPeLgWCoIyzmzII Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJwaG9uZSI6IjA5MzMzMDI2MzYzIiwiaWF0IjoxNzgwNzQ5MTcwLCJleHAiOjE3ODA3NTI3NzAsImF1ZCI6ImxvY2FsaG9zdCIsImlzcyI6ImxvY2FsaG9zdCJ9.apRhtVZgFMFcyutZGO7uzckscch9Jw42s0RCSZZv4K0
GET http://localhost:3000/admin/tests/4 GET http://localhost:3000/admin/tests/4
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJwaG9uZSI6IjA5MzMzMDI2MzYzIiwiaWF0IjoxNzgwMzk4MzI0LCJleHAiOjE3ODA0MDE5MjQsImF1ZCI6ImxvY2FsaG9zdCIsImlzcyI6ImxvY2FsaG9zdCJ9.s3NAErSAjMTz2s27obas3TEi5Og2HPeLgWCoIyzmzII Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJwaG9uZSI6IjA5MzMzMDI2MzYzIiwiaWF0IjoxNzgwNzQ5MTcwLCJleHAiOjE3ODA3NTI3NzAsImF1ZCI6ImxvY2FsaG9zdCIsImlzcyI6ImxvY2FsaG9zdCJ9.apRhtVZgFMFcyutZGO7uzckscch9Jw42s0RCSZZv4K0
+4 -4
View File
@@ -1,4 +1,4 @@
import { Body, Controller, HttpCode, Post } from '@nestjs/common'; import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common';
import { LoginDTO } from './dtos/login.dto'; import { LoginDTO } from './dtos/login.dto';
import { AuthService } from './providers/auth.service'; import { AuthService } from './providers/auth.service';
import { VerifyOtpDTO } from './dtos/verify-otp.dto'; import { VerifyOtpDTO } from './dtos/verify-otp.dto';
@@ -16,21 +16,21 @@ export class AuthController {
@Public() @Public()
@Post('login') @Post('login')
@HttpCode(200) @HttpCode(HttpStatus.OK)
public async logIn(@Body() loginDto: LoginDTO) { public async logIn(@Body() loginDto: LoginDTO) {
return await this.authService.logIn(loginDto); return await this.authService.logIn(loginDto);
} }
@Public() @Public()
@Post('verify-otp') @Post('verify-otp')
@HttpCode(200) @HttpCode(HttpStatus.OK)
public async verifyOTP(@Body() verifyOtpDto: VerifyOtpDTO) { public async verifyOTP(@Body() verifyOtpDto: VerifyOtpDTO) {
return await this.authService.verifyOTP(verifyOtpDto); return await this.authService.verifyOTP(verifyOtpDto);
} }
@Public() @Public()
@Post('refresh') @Post('refresh')
@HttpCode(200) @HttpCode(HttpStatus.OK)
public async refreshToken(@Body() refreshTokenDto: RefreshTokenDTO) { public async refreshToken(@Body() refreshTokenDto: RefreshTokenDTO) {
return await this.authService.refreshToken(refreshTokenDto); return await this.authService.refreshToken(refreshTokenDto);
} }
+3 -10
View File
@@ -1,15 +1,11 @@
import { import { HttpStatus, Injectable, UnauthorizedException } from '@nestjs/common';
HttpStatus,
Injectable,
RequestTimeoutException,
UnauthorizedException,
} from '@nestjs/common';
import { LessThan, MoreThanOrEqual, Repository } from 'typeorm'; import { LessThan, MoreThanOrEqual, Repository } from 'typeorm';
import { OTP } from '../entities/otp.entity'; import { OTP } from '../entities/otp.entity';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Cron } from '@nestjs/schedule'; import { Cron } from '@nestjs/schedule';
import { HashingProvider } from '@/common/modules/hashing/providers/hashing.provider'; import { HashingProvider } from '@/common/modules/hashing/providers/hashing.provider';
import { AppException } from '@/common/exceptions/app.exception'; import { AppException } from '@/common/exceptions/app.exception';
import { AppTimeoutException } from '@/common/exceptions/app-timeout.exception';
@Injectable() @Injectable()
export class OtpService { export class OtpService {
@@ -73,10 +69,7 @@ export class OtpService {
order: { createdAt: 'DESC' }, order: { createdAt: 'DESC' },
}); });
} catch (err) { } catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', { throw new AppTimeoutException(err);
cause: err,
description: 'Error connecting to the database',
});
} }
if (!otp) throw new UnauthorizedException('auth.errors.invalidOTP'); if (!otp) throw new UnauthorizedException('auth.errors.invalidOTP');
+41
View File
@@ -0,0 +1,41 @@
import { PaginationQueryDTO } from '@/common/dtos/pagination-query.dto';
import {
IsBoolean,
IsEnum,
IsNumber,
IsOptional,
IsString,
} from 'class-validator';
import { AccessType } from '../enums/access-types.enum';
import { PartialType } from '@nestjs/swagger';
import { TestSortField } from '../enums/test-sort-field.enum';
export class FindTestsDTO extends PartialType(PaginationQueryDTO) {
@IsNumber()
@IsOptional()
id?: number;
@IsString()
@IsOptional()
title?: string;
@IsString()
@IsOptional()
description?: string;
@IsString()
@IsOptional()
price?: string;
@IsEnum(AccessType)
@IsOptional()
accessType?: AccessType;
@IsBoolean()
@IsOptional()
isActive?: boolean;
@IsEnum(TestSortField)
@IsOptional()
sortBy?: TestSortField;
}
@@ -0,0 +1,9 @@
export enum TestSortField {
ID = 'id',
TITLE = 'title',
DESCRIPTION = 'description',
ACCESS_TYPE = 'accessType',
PRICE = 'price',
IS_ACTIVE = 'isActive',
CREATED_AT = 'createdAt',
}
@@ -0,0 +1,32 @@
import { FindOptionsWhere, ILike } from 'typeorm';
import { FindTestsDTO } from '../dtos/find-tests.dto';
export const filterTests = (query: FindTestsDTO) => {
const where: FindOptionsWhere<any> = {};
if (query.id) {
where.id = query.id;
}
if (query.title) {
where.title = ILike(`%${query.title}%`);
}
if (query.description) {
where.description = ILike(`%${query.description}%`);
}
if (query.accessType !== undefined) {
where.accessType = query.accessType;
}
if (query.price !== undefined) {
where.price = query.price;
}
if (query.isActive !== undefined) {
where.isActive = query.isActive;
}
return where;
};
@@ -0,0 +1,104 @@
import {
BadRequestException,
HttpStatus,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { CreateTestDTO } from '../dtos/create-test.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Test } from '../entities/test.entity';
import { Repository } from 'typeorm';
import { I18nService } from 'nestjs-i18n';
import { AppException } from '@/common/exceptions/app.exception';
import { AppResponse } from '@/common/responses';
import { AppTimeoutException } from '@/common/exceptions/app-timeout.exception';
import { UpdateTestDTO } from '../dtos/update-test.dto';
import { AccessType } from '../enums/access-types.enum';
@Injectable()
export class TestsCommandProvider {
constructor(
/**
* Inject Tests Repository
*/
@InjectRepository(Test)
private readonly testRepository: Repository<Test>,
/**
* Inject I18n Service
*/
private readonly i18nService: I18nService,
) {}
public async createOne(createTestDto: CreateTestDTO) {
const titleExists = await this.testRepository.findOne({
where: {
title: createTestDto.title,
},
});
if (titleExists) {
throw new AppException('validation.duplicateField', HttpStatus.CONFLICT, {
field: '$t(tests.fields.title)',
});
}
const newTest = this.testRepository.create(createTestDto);
try {
await this.testRepository.save(newTest);
return new AppResponse(
newTest,
this.i18nService.translate('tests.messages.createSuccess'),
);
} catch (err) {
throw new AppTimeoutException(err);
}
}
public async updateOne(id: number, updateTestDto: UpdateTestDTO) {
const test = await this.testRepository.findOneBy({ id });
if (!test) {
throw new NotFoundException('tests.errors.testNotFound');
}
const accessType = updateTestDto.accessType ?? test.accessType;
const price = updateTestDto.price ?? test.price;
if (
(accessType === AccessType.PAID && !price) ||
(accessType !== AccessType.PAID && price)
) {
throw new BadRequestException(
this.i18nService.translate('tests.errors.priceAccessConstraint'),
);
}
Object.assign(test, updateTestDto);
try {
return await this.testRepository.save(test);
} catch (err) {
throw new AppTimeoutException(err);
}
}
public async deleteOne(id: number) {
let test: Test | null = null;
try {
test = await this.testRepository.findOneBy({ id });
} catch (err) {
throw new AppTimeoutException(err);
}
if (!test) throw new NotFoundException('tests.errors.testNotFound');
try {
await this.testRepository.delete(test.id);
} catch (err) {
throw new AppTimeoutException(err);
}
}
}
@@ -0,0 +1,98 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { PaginatedResponse } from '@/common/responses';
import { AppTimeoutException } from '@/common/exceptions/app-timeout.exception';
import { FindTestsDTO } from '../dtos/find-tests.dto';
import { filterTests } from '../helpers/filter-tests.helper';
import Utils from '@/common/utils';
import { Test } from '../entities/test.entity';
@Injectable()
export class TestsQueryProvider {
constructor(
/**
* Inject Tests Repository
*/
@InjectRepository(Test)
private readonly testRepository: Repository<Test>,
) {}
public async findAllForAdmin(query: FindTestsDTO) {
const filterOptions = filterTests(query);
const { page, take, limit, skip } =
Utils.PaginationUtils.getPaginationOptions(query);
try {
const [tests, total] = await this.testRepository.findAndCount({
where: filterOptions,
skip,
take,
order: query.sortBy
? {
[query.sortBy]: query.order ?? 'ASC',
}
: { createdAt: 'DESC' },
});
return new PaginatedResponse(tests, {
page,
limit,
total,
});
} catch (err) {
throw new AppTimeoutException(err);
}
}
public async findAllForUser() {
try {
return await this.testRepository.find({
where: { isActive: true },
select: {
id: true,
accessType: true,
description: true,
price: true,
title: true,
},
order: { createdAt: 'DESC' },
});
} catch (err) {
throw new AppTimeoutException(err);
}
}
public async findOneForAdmin(id: number) {
try {
return await this.testRepository.findOneBy({ id });
} catch (err) {
throw new AppTimeoutException(err);
}
}
public async findOneForUser(id: number) {
let test: Test | null;
try {
test = await this.testRepository.findOne({
where: { id, isActive: true },
select: {
id: true,
accessType: true,
description: true,
price: true,
title: true,
},
});
} catch (err) {
throw new AppTimeoutException(err);
}
if (!test) {
throw new NotFoundException('tests.errors.testNotFound');
}
return test;
}
}
+18 -132
View File
@@ -1,163 +1,49 @@
import { import { Injectable } from '@nestjs/common';
BadRequestException,
HttpStatus,
Injectable,
NotFoundException,
RequestTimeoutException,
} from '@nestjs/common';
import { Repository } from 'typeorm';
import { Test } from '../entities/test.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateTestDTO } from '../dtos/create-test.dto'; import { CreateTestDTO } from '../dtos/create-test.dto';
import { AppException } from '@/common/exceptions/app.exception';
import { AppResponse } from '@/common/responses';
import { I18nService } from 'nestjs-i18n';
import { UpdateTestDTO } from '../dtos/update-test.dto'; import { UpdateTestDTO } from '../dtos/update-test.dto';
import { AccessType } from '../enums/access-types.enum'; import { FindTestsDTO } from '../dtos/find-tests.dto';
import { TestsQueryProvider } from './tests-query.provider';
import { TestsCommandProvider } from './tests-command.provider';
@Injectable() @Injectable()
export class TestsService { export class TestsService {
constructor( constructor(
/** /**
* Inject Tests Repository * Inject Tests Query Provider
*/ */
@InjectRepository(Test) private readonly testsQueryProvider: TestsQueryProvider,
private readonly testRepository: Repository<Test>,
/** /**
* Inject I18n Service * Inject Tests Command Provider
*/ */
private readonly i18nService: I18nService, private readonly testsCommandProvider: TestsCommandProvider,
) {} ) {}
public async createOne(createTestDto: CreateTestDTO) { public async createOne(createTestDto: CreateTestDTO) {
const titleExists = await this.testRepository.findOne({ return await this.testsCommandProvider.createOne(createTestDto);
where: {
title: createTestDto.title,
},
});
if (titleExists) {
throw new AppException('validation.duplicateField', HttpStatus.CONFLICT, {
field: '$t(tests.fields.title)',
});
}
const newTest = this.testRepository.create(createTestDto);
try {
await this.testRepository.save(newTest);
return new AppResponse(
newTest,
this.i18nService.translate('tests.messages.createSuccess'),
);
} catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', {
cause: err,
description: 'Error connecting to the database',
});
}
} }
public async adminGetAll() { public async adminGetAll(query: FindTestsDTO) {
try { return await this.testsQueryProvider.findAllForAdmin(query);
return await this.testRepository.find({ order: { createdAt: 'DESC' } });
} catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', {
cause: err,
description: 'Error connecting to the database',
});
}
} }
public async userGetAll() { public async userGetAll() {
try { return await this.testsQueryProvider.findAllForUser();
return await this.testRepository.find({
where: { isActive: true },
select: {
id: true,
accessType: true,
description: true,
price: true,
title: true,
},
order: { createdAt: 'DESC' },
});
} catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', {
cause: err,
description: 'Error connecting to the database',
});
}
} }
public async adminGetOne(id: number) { public async adminGetOne(id: number) {
try { return await this.testsQueryProvider.findOneForAdmin(id);
return await this.testRepository.findOneBy({ id });
} catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', {
cause: err,
description: 'Error connecting to the database',
});
}
} }
public async userGetOne(id: number) { public async userGetOne(id: number) {
let test: Test | null; return await this.testsQueryProvider.findOneForUser(id);
try {
test = await this.testRepository.findOne({
where: { id, isActive: true },
select: {
id: true,
accessType: true,
description: true,
price: true,
title: true,
},
});
} catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', {
cause: err,
description: 'Error connecting to the database',
});
}
if (!test) {
throw new NotFoundException('tests.errors.testNotFound');
}
return test;
} }
public async updateOne(id: number, updateTestDto: UpdateTestDTO) { public async updateOne(id: number, updateTestDto: UpdateTestDTO) {
const test = await this.testRepository.findOneBy({ id }); return await this.testsCommandProvider.updateOne(id, updateTestDto);
}
if (!test) { public async deleteOne(id: number) {
throw new NotFoundException('tests.errors.testNotFound'); return await this.testsCommandProvider.deleteOne(id);
}
const accessType = updateTestDto.accessType ?? test.accessType;
const price = updateTestDto.price ?? test.price;
if (
(accessType === AccessType.PAID && !price) ||
(accessType !== AccessType.PAID && price)
) {
throw new BadRequestException(
this.i18nService.translate('tests.errors.priceAccessConstraint'),
);
}
Object.assign(test, updateTestDto);
try {
return await this.testRepository.save(test);
} catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', {
cause: err,
description: 'Error connecting to the database',
});
}
} }
} }
+3 -1
View File
@@ -3,11 +3,13 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { Test } from './entities/test.entity'; import { Test } from './entities/test.entity';
import { TestsService } from './providers/tests.service'; import { TestsService } from './providers/tests.service';
import { TestsController } from './tests.controller'; import { TestsController } from './tests.controller';
import { TestsQueryProvider } from './providers/tests-query.provider';
import { TestsCommandProvider } from './providers/tests-command.provider';
@Module({ @Module({
imports: [TypeOrmModule.forFeature([Test])], imports: [TypeOrmModule.forFeature([Test])],
controllers: [TestsController], controllers: [TestsController],
providers: [TestsService], providers: [TestsService, TestsQueryProvider, TestsCommandProvider],
exports: [TestsService], exports: [TestsService],
}) })
export class TestsModule {} export class TestsModule {}
@@ -1,11 +1,12 @@
import { HashingProvider } from '@/common/modules/hashing/providers/hashing.provider'; import { HashingProvider } from '@/common/modules/hashing/providers/hashing.provider';
import { Injectable, RequestTimeoutException } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { I18nService } from 'nestjs-i18n'; import { I18nService } from 'nestjs-i18n';
import { User } from '../entities/user.entity'; import { User } from '../entities/user.entity';
import { UpdateProfileDTO } from '../dto/update-profile.dto'; import { UpdateProfileDTO } from '../dto/update-profile.dto';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { AppResponse } from '@/common/responses'; import { AppResponse } from '@/common/responses';
import { AppTimeoutException } from '@/common/exceptions/app-timeout.exception';
@Injectable() @Injectable()
export class UserProfileProvider { export class UserProfileProvider {
@@ -59,10 +60,7 @@ export class UserProfileProvider {
try { try {
await this.userRepository.update(user.id, updateData); await this.userRepository.update(user.id, updateData);
} catch (err) { } catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', { throw new AppTimeoutException(err);
cause: err,
description: 'Error connecting to the database',
});
} }
return { return {
+5 -17
View File
@@ -1,13 +1,10 @@
import { import { BadRequestException, Injectable } from '@nestjs/common';
BadRequestException,
Injectable,
RequestTimeoutException,
} from '@nestjs/common';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { User } from '../entities/user.entity'; import { User } from '../entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { UpdateProfileDTO } from '../dto/update-profile.dto'; import { UpdateProfileDTO } from '../dto/update-profile.dto';
import { UserProfileProvider } from './user-profile.provider'; import { UserProfileProvider } from './user-profile.provider';
import { AppTimeoutException } from '@/common/exceptions/app-timeout.exception';
@Injectable() @Injectable()
export class UsersService { export class UsersService {
@@ -29,10 +26,7 @@ export class UsersService {
try { try {
user = await this.userRepository.findOneById(id); user = await this.userRepository.findOneById(id);
} catch (err) { } catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', { throw new AppTimeoutException(err);
cause: err,
description: 'Error connecting to the database',
});
} }
if (!user) { if (!user) {
@@ -46,10 +40,7 @@ export class UsersService {
try { try {
return await this.userRepository.findOneBy({ phone }); return await this.userRepository.findOneBy({ phone });
} catch (err) { } catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', { throw new AppTimeoutException(err);
cause: err,
description: 'Error connecting to the database',
});
} }
} }
@@ -59,10 +50,7 @@ export class UsersService {
try { try {
await this.userRepository.save(newUser); await this.userRepository.save(newUser);
} catch (err) { } catch (err) {
throw new RequestTimeoutException('common.errors.requestTimeout', { throw new AppTimeoutException(err);
cause: err,
description: 'Error connecting to the database',
});
} }
return newUser; return newUser;