From 295b94a53cbce732076650d341a729e7ac8e0bac Mon Sep 17 00:00:00 2001 From: KHLIFI <hicham.khlifi.externe@swisslife.fr> Date: Fri, 13 May 2022 18:15:27 +0200 Subject: [PATCH] develop(todoService): methods --- .eslintrc.js | 3 +- .prettierrc | 6 ++-- package-lock.json | 24 +++++++++++++++ package.json | 2 ++ src/_dto/todo.dto.ts | 40 +++++++++++++++++++++++++ src/_enum/errors.enum.ts | 5 ++++ src/_enum/states.enum.ts | 8 +++++ src/main.ts | 11 ++++++- src/todo/todo.controller.ts | 26 ++++++++++++++++ src/todo/todo.service.ts | 60 +++++++++++++++++++++++++++++++++++++ 10 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 src/_dto/todo.dto.ts create mode 100644 src/_enum/errors.enum.ts create mode 100644 src/_enum/states.enum.ts create mode 100644 src/todo/todo.controller.ts create mode 100644 src/todo/todo.service.ts diff --git a/.eslintrc.js b/.eslintrc.js index 8f5aedb..12eef49 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { project: 'tsconfig.json', - tsconfigRootDir : __dirname, + tsconfigRootDir : __dirname, sourceType: 'module', }, plugins: ['@typescript-eslint/eslint-plugin'], @@ -21,5 +21,6 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/rule-empty-line-before': 'off', }, }; diff --git a/.prettierrc b/.prettierrc index dcb7279..79caa54 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,6 @@ { "singleQuote": true, - "trailingComma": "all" -} \ No newline at end of file + "trailingComma": "all", + "bracketSpacing": true, + rule-empty-line-before +} diff --git a/package-lock.json b/package-lock.json index 7911006..7680970 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2327,6 +2327,20 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "class-transformer": { + "version": "0.5.1", + "resolved": "https://nexus.swisslife.lan/repository/npm-group/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "class-validator": { + "version": "0.13.2", + "resolved": "https://nexus.swisslife.lan/repository/npm-group/class-validator/-/class-validator-0.13.2.tgz", + "integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==", + "requires": { + "libphonenumber-js": "^1.9.43", + "validator": "^13.7.0" + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://nexus.swisslife.lan/repository/npm-group/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -4629,6 +4643,11 @@ "type-check": "~0.4.0" } }, + "libphonenumber-js": { + "version": "1.9.53", + "resolved": "https://nexus.swisslife.lan/repository/npm-group/libphonenumber-js/-/libphonenumber-js-1.9.53.tgz", + "integrity": "sha512-3cuMrA2CY3TbKVC0wKye5dXYgxmVVi4g13gzotprQSguFHMqf0pIrMM2Z6ZtMsSWqvtIqi5TuQhGjMhxz0O9Mw==" + }, "light-my-request": { "version": "4.10.1", "resolved": "https://nexus.swisslife.lan/repository/npm-group/light-my-request/-/light-my-request-4.10.1.tgz", @@ -6095,6 +6114,11 @@ "convert-source-map": "^1.6.0" } }, + "validator": { + "version": "13.7.0", + "resolved": "https://nexus.swisslife.lan/repository/npm-group/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + }, "vary": { "version": "1.1.2", "resolved": "https://nexus.swisslife.lan/repository/npm-group/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index f346975..e02b141 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "@nestjs/common": "^8.0.0", "@nestjs/core": "^8.0.0", "@nestjs/platform-fastify": "^8.0.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.13.2", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0" diff --git a/src/_dto/todo.dto.ts b/src/_dto/todo.dto.ts new file mode 100644 index 0000000..f714a71 --- /dev/null +++ b/src/_dto/todo.dto.ts @@ -0,0 +1,40 @@ +import { + IsDate, + IsEnum, + IsNumber, + IsOptional, + IsString, +} from 'class-validator'; +import { StatesEnum } from '../_enum/states.enum'; + +export class TodoDto { + @IsString() + id: string; + + @IsString() + title: string; + + @IsString() + author: string; + + @IsDate() + createdAt: Date = new Date(); + + @IsDate() + @IsOptional() + expiredAt: Date; + + @IsString() + @IsOptional() + content: string; + + @IsNumber() + @IsOptional() + priority: number; + + @IsEnum(StatesEnum) + state: StatesEnum = StatesEnum.CREATED; + + @IsNumber() + index: number; +} diff --git a/src/_enum/errors.enum.ts b/src/_enum/errors.enum.ts new file mode 100644 index 0000000..1023626 --- /dev/null +++ b/src/_enum/errors.enum.ts @@ -0,0 +1,5 @@ +export enum ErrorsEnum { + SAVE = 'SAVE', + FETCH_ALL = 'FETCH_ALL', + DELETE = 'DELETE', +} diff --git a/src/_enum/states.enum.ts b/src/_enum/states.enum.ts new file mode 100644 index 0000000..4089848 --- /dev/null +++ b/src/_enum/states.enum.ts @@ -0,0 +1,8 @@ +export enum StatesEnum { + CREATED = 'CREATED', + READY = 'READY', + IN_PROGRESS = 'IN_PROGRESS', + BLOCKED = 'BLOCKED', + DONE = 'DONE', + CANCELED = 'CANCELED', +} diff --git a/src/main.ts b/src/main.ts index 13cad38..fc98c8e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,17 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; +import { + FastifyAdapter, + NestFastifyApplication, +} from '@nestjs/platform-fastify'; +import { ValidationPipe } from '@nestjs/common'; async function bootstrap() { - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create<NestFastifyApplication>( + AppModule, + new FastifyAdapter({ logger: true }), + ); + app.useGlobalPipes(new ValidationPipe()); await app.listen(3000); } bootstrap(); diff --git a/src/todo/todo.controller.ts b/src/todo/todo.controller.ts new file mode 100644 index 0000000..53c42f6 --- /dev/null +++ b/src/todo/todo.controller.ts @@ -0,0 +1,26 @@ +import { Controller, Delete, Get, Param, Post } from '@nestjs/common'; +import { TodoDto } from '../_dto/todo.dto'; +import { Type } from 'class-transformer'; +import { TodoService } from './todo.service'; +import { Observable } from 'rxjs'; + +@Controller('Todo') +export class TodoController { + constructor(private readonly _todoService: TodoService) {} + + @Get() + getAllTodos(): Observable<TodoDto[]> { + return this._todoService.getAllTodos(); + } + + @Post() + @Type(() => TodoDto) + saveTodo(td: TodoDto): Observable<void> { + return this._todoService.saveTodo(td); + } + + @Delete('/:id') + deleteTodo(@Param('id') id: string): void { + this._todoService.deleteTodo(id); + } +} diff --git a/src/todo/todo.service.ts b/src/todo/todo.service.ts new file mode 100644 index 0000000..b8b8e88 --- /dev/null +++ b/src/todo/todo.service.ts @@ -0,0 +1,60 @@ +import { Injectable, InternalServerErrorException, Logger } from '@nestjs/common'; +import { TodoDto } from '../_dto/todo.dto'; +import { catchError, Observable, tap, Observer } from 'rxjs'; +import { ErrorsEnum } from '../_enum/errors.enum'; + +@Injectable() +export class TodoService { + private _logger = new Logger('TodoService'); + + /** + * Méthode permettant la sauvegarde d'un todo + * @param {TodoDto} td La todo à sauvegarder + * @returns {Observable<void>} + */ + saveTodo(td: TodoDto): Observable<void> { + this._logger.log(`[APPEL] Initialisation de la sauvegarde de la todo ${td.id}`); + return new Observable<void>().pipe( + tap(() => this._logger.log(`[SUCCESS] La todo ${td.id} est sauvegardé`)), + catchError((err) => { + const error = err; + error.name = ErrorsEnum.SAVE; + this._logger.error('[ERROR] La sauvegarde a échoué'); + throw new InternalServerErrorException(error, 'La sauvegarde a échoué'); + }), + ); + } + + /** + * Méthode qui retourne tous les todos + * @returns {Observable<TodoDto[]>} Tableau de todo + */ + getAllTodos(): Observable<TodoDto[]> { + this._logger.log(`[APPEL] Initialisation du fetch de tous les todos`); + return new Observable<TodoDto[]>().pipe( + tap(() => { + this._logger.log('[SUCCESS] Tous les todos ont été retournés'); + return []; + }), + catchError((err) => { + const error = err; + error.name = ErrorsEnum.FETCH_ALL; + this._logger.error('[ERROR] Le fetch a échoué'); + throw new InternalServerErrorException(error, 'Le fetch a échoué') + }) + ) + } + + deleteTodo(id: string): Observable<void> { + this._logger.log(`[APPEL] Initialisation de la délétion d'un todo`); + return new Observable<void>().pipe( + tap(() => this._logger.log('[SUCCESS] Le todo a été supprimé')), + catchError((err) => { + const error = err; + error.name = ErrorsEnum.DELETE; + this._logger.error('[ERROR] La suppression a échoué'); + throw new InternalServerErrorException(error, 'La suppression a échoué') + }) + ); + } +} -- GitLab