From cb9e1f8485fc374fa17f79acc843f3960058d27d Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Fri, 23 Aug 2024 19:25:58 +0200 Subject: [PATCH 01/37] OV-59: + migration for creating videos table --- .../20240823170153_add_videos_table.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 backend/src/migrations/20240823170153_add_videos_table.ts diff --git a/backend/src/migrations/20240823170153_add_videos_table.ts b/backend/src/migrations/20240823170153_add_videos_table.ts new file mode 100644 index 000000000..c4518aae5 --- /dev/null +++ b/backend/src/migrations/20240823170153_add_videos_table.ts @@ -0,0 +1,44 @@ +import { type Knex } from 'knex'; + +const TABLE_NAME = 'videos'; + +const ColumnName = { + ID: 'id', + USER_ID: 'user_id', + NAME: 'name', + URL: 'url', + CREATED_AT: 'created_at', + UPDATED_AT: 'updated_at', +}; + +async function up(knex: Knex): Promise { + await knex.schema.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'); + await knex.schema.createTable(TABLE_NAME, (table) => { + table + .uuid(ColumnName.ID) + .notNullable() + .primary() + .defaultTo(knex.raw('uuid_generate_v4()')); + table.uuid(ColumnName.USER_ID).notNullable(); + table.string(ColumnName.NAME).notNullable(); + table.string(ColumnName.URL).notNullable(); + table + .dateTime(ColumnName.CREATED_AT) + .notNullable() + .defaultTo(knex.fn.now()); + table + .dateTime(ColumnName.UPDATED_AT) + .notNullable() + .defaultTo(knex.fn.now()); + table + .foreign(ColumnName.USER_ID) + .references('users.id') + .onDelete('CASCADE'); + }); +} + +async function down(knex: Knex): Promise { + return knex.schema.dropTableIfExists(TABLE_NAME); +} + +export { down, up }; From 331999639f595238ea2445000ec30efa9ef836e4 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Fri, 23 Aug 2024 22:00:03 +0200 Subject: [PATCH 02/37] OV-59: + video model --- backend/src/bundles/videos/video.model.ts | 18 ++++++++++++++++++ .../database/enums/database-table-name.enum.ts | 1 + 2 files changed, 19 insertions(+) create mode 100644 backend/src/bundles/videos/video.model.ts diff --git a/backend/src/bundles/videos/video.model.ts b/backend/src/bundles/videos/video.model.ts new file mode 100644 index 000000000..d84a9b459 --- /dev/null +++ b/backend/src/bundles/videos/video.model.ts @@ -0,0 +1,18 @@ +import { + AbstractModel, + DatabaseTableName, +} from '~/common/database/database.js'; + +class VideoModel extends AbstractModel { + public 'userId': string; + + public 'name': string; + + public 'url': string; + + public static override get tableName(): string { + return DatabaseTableName.VIDEOS; + } +} + +export { VideoModel }; diff --git a/backend/src/common/database/enums/database-table-name.enum.ts b/backend/src/common/database/enums/database-table-name.enum.ts index 610b737d5..dbb005bfd 100644 --- a/backend/src/common/database/enums/database-table-name.enum.ts +++ b/backend/src/common/database/enums/database-table-name.enum.ts @@ -1,6 +1,7 @@ const DatabaseTableName = { MIGRATIONS: 'migrations', USERS: 'users', + VIDEOS: 'videos', } as const; export { DatabaseTableName }; From 43e0122b5ed87ac0a7b1952b3ae503cf3caeb44a Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Fri, 23 Aug 2024 22:49:46 +0200 Subject: [PATCH 03/37] OV-59: * change id field from number to string --- backend/src/bundles/users/user.entity.ts | 10 +++++----- backend/src/common/database/abstract.model.ts | 2 +- .../users/types/user-get-all-item-response-dto.type.ts | 2 +- .../users/types/user-sign-in-response-dto.type.ts | 2 +- .../users/types/user-sign-up-response-dto.type.ts | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/src/bundles/users/user.entity.ts b/backend/src/bundles/users/user.entity.ts index 5a6f4a929..222aef70c 100644 --- a/backend/src/bundles/users/user.entity.ts +++ b/backend/src/bundles/users/user.entity.ts @@ -1,7 +1,7 @@ import { type Entity } from '~/common/types/types.js'; class UserEntity implements Entity { - private 'id': number | null; + private 'id': string | null; private 'email': string; @@ -15,7 +15,7 @@ class UserEntity implements Entity { passwordHash, passwordSalt, }: { - id: number | null; + id: string | null; email: string; passwordHash: string; passwordSalt: string; @@ -32,7 +32,7 @@ class UserEntity implements Entity { passwordHash, passwordSalt, }: { - id: number; + id: string; email: string; passwordHash: string; passwordSalt: string; @@ -63,11 +63,11 @@ class UserEntity implements Entity { } public toObject(): { - id: number; + id: string; email: string; } { return { - id: this.id as number, + id: this.id as string, email: this.email, }; } diff --git a/backend/src/common/database/abstract.model.ts b/backend/src/common/database/abstract.model.ts index 911aef949..20eb5374d 100644 --- a/backend/src/common/database/abstract.model.ts +++ b/backend/src/common/database/abstract.model.ts @@ -1,7 +1,7 @@ import { Model } from 'objection'; class Abstract extends Model { - public 'id': number; + public 'id': string; public 'createdAt': string; diff --git a/shared/src/bundles/users/types/user-get-all-item-response-dto.type.ts b/shared/src/bundles/users/types/user-get-all-item-response-dto.type.ts index 9c7d45f4c..6bc276a81 100644 --- a/shared/src/bundles/users/types/user-get-all-item-response-dto.type.ts +++ b/shared/src/bundles/users/types/user-get-all-item-response-dto.type.ts @@ -1,5 +1,5 @@ type UserGetAllItemResponseDto = { - id: number; + id: string; email: string; }; diff --git a/shared/src/bundles/users/types/user-sign-in-response-dto.type.ts b/shared/src/bundles/users/types/user-sign-in-response-dto.type.ts index afb72b351..c719c9f58 100644 --- a/shared/src/bundles/users/types/user-sign-in-response-dto.type.ts +++ b/shared/src/bundles/users/types/user-sign-in-response-dto.type.ts @@ -1,5 +1,5 @@ type UserSignInResponseDto = { - id: number; + id: string; email: string; }; diff --git a/shared/src/bundles/users/types/user-sign-up-response-dto.type.ts b/shared/src/bundles/users/types/user-sign-up-response-dto.type.ts index 624114d52..dcf2b6e70 100644 --- a/shared/src/bundles/users/types/user-sign-up-response-dto.type.ts +++ b/shared/src/bundles/users/types/user-sign-up-response-dto.type.ts @@ -1,5 +1,5 @@ type UserSignUpResponseDto = { - id: number; + id: string; email: string; }; From a68c8fd8e644d77ad31ce6b37f69e4df96e75083 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Fri, 23 Aug 2024 22:51:45 +0200 Subject: [PATCH 04/37] OV-59: + video entity --- backend/src/bundles/videos/video.entity.ts | 74 ++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 backend/src/bundles/videos/video.entity.ts diff --git a/backend/src/bundles/videos/video.entity.ts b/backend/src/bundles/videos/video.entity.ts new file mode 100644 index 000000000..0ebd257f7 --- /dev/null +++ b/backend/src/bundles/videos/video.entity.ts @@ -0,0 +1,74 @@ +import { type Entity } from '~/common/types/types.js'; + +class VideoEntity implements Entity { + private 'id': string | null; + + private 'userId': string; + + private 'name': string; + + private 'url': string; + + private constructor({ + id, + userId, + name, + url, + }: { + id: string | null; + userId: string; + name: string; + url: string; + }) { + this.id = id; + this.userId = userId; + this.name = name; + this.url = url; + } + + public static initialize({ + id, + userId, + name, + url, + }: { + id: string | null; + userId: string; + name: string; + url: string; + }): VideoEntity { + return new VideoEntity({ + id, + userId, + name, + url, + }); + } + + public static initializeNew({ + userId, + name, + url, + }: { + userId: string; + name: string; + url: string; + }): VideoEntity { + return new VideoEntity({ + id: null, + userId, + name, + url, + }); + } + + public toObject(): null { + return null; + } + + public toNewObject(): null { + return null; + } +} + +export { VideoEntity }; From 489fdf81ec3b4c2e1c50eefe13866292c000d58d Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 12:18:39 +0200 Subject: [PATCH 05/37] OV-59: * toObject and toNewObject methods for video entity --- backend/src/bundles/videos/video.entity.ts | 28 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/backend/src/bundles/videos/video.entity.ts b/backend/src/bundles/videos/video.entity.ts index 0ebd257f7..5d79732ad 100644 --- a/backend/src/bundles/videos/video.entity.ts +++ b/backend/src/bundles/videos/video.entity.ts @@ -32,7 +32,7 @@ class VideoEntity implements Entity { name, url, }: { - id: string | null; + id: string; userId: string; name: string; url: string; @@ -62,12 +62,30 @@ class VideoEntity implements Entity { }); } - public toObject(): null { - return null; + public toObject(): { + id: string; + userId: string; + name: string; + url: string; + } { + return { + id: this.id as string, + userId: this.userId, + name: this.name, + url: this.url, + }; } - public toNewObject(): null { - return null; + public toNewObject(): { + userId: string; + name: string; + url: string; + } { + return { + userId: this.userId, + name: this.name, + url: this.url, + }; } } From 10b30ecc76d2375a78db86976be265750e387afa Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 12:38:31 +0200 Subject: [PATCH 06/37] OV-59: + video repository with find methods --- .../src/bundles/videos/video.repository.ts | 37 +++++++++++++++++++ backend/src/common/types/repository.type.ts | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 backend/src/bundles/videos/video.repository.ts diff --git a/backend/src/bundles/videos/video.repository.ts b/backend/src/bundles/videos/video.repository.ts new file mode 100644 index 000000000..623c076bc --- /dev/null +++ b/backend/src/bundles/videos/video.repository.ts @@ -0,0 +1,37 @@ +import { VideoEntity } from '~/bundles/videos/video.entity.js'; +import { type VideoModel } from '~/bundles/videos/video.model.js'; +import { type Repository } from '~/common/types/types.js'; + +class VideoRepository implements Repository { + private videoModel: typeof VideoModel; + + public constructor(videoModel: typeof VideoModel) { + this.videoModel = videoModel; + } + + public async find(videoId: string): Promise { + const video = await this.videoModel.query().findById(videoId).execute(); + + return video ? VideoEntity.initialize(video) : null; + } + + public async findAll(): Promise { + const videos = await this.videoModel.query().execute(); + + return videos.map((it) => VideoEntity.initialize(it)); + } + + public create(entity: VideoEntity): Promise { + return Promise.resolve(entity); + } + + public update(): ReturnType { + return Promise.resolve(null); + } + + public delete(): ReturnType { + return Promise.resolve(true); + } +} + +export { VideoRepository }; diff --git a/backend/src/common/types/repository.type.ts b/backend/src/common/types/repository.type.ts index d69be849b..c1351f138 100644 --- a/backend/src/common/types/repository.type.ts +++ b/backend/src/common/types/repository.type.ts @@ -1,5 +1,5 @@ type Repository = { - find(): Promise; + find(id: string): Promise; findAll(): Promise; create(payload: unknown): Promise; update(): Promise; From 5ced750e044b13e5422e67a19b5545482b674720 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 12:56:08 +0200 Subject: [PATCH 07/37] OV-59: + types for get all videos --- shared/src/bundles/videos/types/types.ts | 2 ++ .../videos/types/video-get-all-item-response-dto.type.ts | 8 ++++++++ .../videos/types/video-get-all-response-dto.type.ts | 5 +++++ shared/src/bundles/videos/videos.ts | 4 ++++ shared/src/index.ts | 4 ++++ 5 files changed, 23 insertions(+) create mode 100644 shared/src/bundles/videos/types/types.ts create mode 100644 shared/src/bundles/videos/types/video-get-all-item-response-dto.type.ts create mode 100644 shared/src/bundles/videos/types/video-get-all-response-dto.type.ts create mode 100644 shared/src/bundles/videos/videos.ts diff --git a/shared/src/bundles/videos/types/types.ts b/shared/src/bundles/videos/types/types.ts new file mode 100644 index 000000000..93dc70cd8 --- /dev/null +++ b/shared/src/bundles/videos/types/types.ts @@ -0,0 +1,2 @@ +export { type VideoGetAllItemResponseDto } from './video-get-all-item-response-dto.type.js'; +export { type VideoGetAllResponseDto } from './video-get-all-response-dto.type.js'; diff --git a/shared/src/bundles/videos/types/video-get-all-item-response-dto.type.ts b/shared/src/bundles/videos/types/video-get-all-item-response-dto.type.ts new file mode 100644 index 000000000..a7eeaf45e --- /dev/null +++ b/shared/src/bundles/videos/types/video-get-all-item-response-dto.type.ts @@ -0,0 +1,8 @@ +type VideoGetAllItemResponseDto = { + id: string; + userId: string; + name: string; + url: string; +}; + +export { type VideoGetAllItemResponseDto }; diff --git a/shared/src/bundles/videos/types/video-get-all-response-dto.type.ts b/shared/src/bundles/videos/types/video-get-all-response-dto.type.ts new file mode 100644 index 000000000..9f62abc56 --- /dev/null +++ b/shared/src/bundles/videos/types/video-get-all-response-dto.type.ts @@ -0,0 +1,5 @@ +import { type VideoGetAllItemResponseDto } from './types.js'; + +type VideoGetAllResponseDto = VideoGetAllItemResponseDto[]; + +export { type VideoGetAllResponseDto }; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts new file mode 100644 index 000000000..38c1c7eb8 --- /dev/null +++ b/shared/src/bundles/videos/videos.ts @@ -0,0 +1,4 @@ +export { + type VideoGetAllItemResponseDto, + type VideoGetAllResponseDto, +} from './types/types.js'; diff --git a/shared/src/index.ts b/shared/src/index.ts index d4b77ee0e..a601ff55e 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -11,6 +11,10 @@ export { userSignUpValidationSchema, UserValidationMessage, } from './bundles/users/users.js'; +export { + type VideoGetAllItemResponseDto, + type VideoGetAllResponseDto, +} from './bundles/videos/videos.js'; export { ApiPath, AppEnvironment, From aa3565ce8f06b49e6fb7b2d5834b86a06bf9ee61 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 13:20:25 +0200 Subject: [PATCH 08/37] OV-59: + video service with find methods --- backend/src/bundles/videos/types/types.ts | 4 ++ backend/src/bundles/videos/video.service.ts | 51 +++++++++++++++++++ backend/src/common/types/service.type.ts | 2 +- .../types/video-get-all-response-dto.type.ts | 2 +- 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 backend/src/bundles/videos/types/types.ts create mode 100644 backend/src/bundles/videos/video.service.ts diff --git a/backend/src/bundles/videos/types/types.ts b/backend/src/bundles/videos/types/types.ts new file mode 100644 index 000000000..e79c0f579 --- /dev/null +++ b/backend/src/bundles/videos/types/types.ts @@ -0,0 +1,4 @@ +export { + type VideoGetAllItemResponseDto, + type VideoGetAllResponseDto, +} from 'shared'; diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts new file mode 100644 index 000000000..61cf17f32 --- /dev/null +++ b/backend/src/bundles/videos/video.service.ts @@ -0,0 +1,51 @@ +import { type VideoRepository } from '~/bundles/videos/video.repository.js'; +import { HttpCode, HttpError } from '~/common/http/http.js'; +import { type Service } from '~/common/types/types.js'; + +import { + type VideoGetAllItemResponseDto, + type VideoGetAllResponseDto, +} from './types/types.js'; + +class VideoService implements Service { + private videoRepository: VideoRepository; + + public constructor(videoRepository: VideoRepository) { + this.videoRepository = videoRepository; + } + + public async find(videoId: string): Promise { + const video = await this.videoRepository.find(videoId); + + if (!video) { + throw new HttpError({ + message: 'Video with this id does not exist', + status: HttpCode.BAD_REQUEST, + }); + } + + return video.toObject(); + } + + public async findAll(): Promise { + const items = await this.videoRepository.findAll(); + + return { + items: items.map((it) => it.toObject()), + }; + } + + public create(payload: null): ReturnType { + return Promise.resolve(payload); + } + + public update(): ReturnType { + return Promise.resolve(null); + } + + public delete(): ReturnType { + return Promise.resolve(true); + } +} + +export { VideoService }; diff --git a/backend/src/common/types/service.type.ts b/backend/src/common/types/service.type.ts index 7b1a64ebb..ca4232685 100644 --- a/backend/src/common/types/service.type.ts +++ b/backend/src/common/types/service.type.ts @@ -1,5 +1,5 @@ type Service = { - find(): Promise; + find(id: string): Promise; findAll(): Promise<{ items: T[]; }>; diff --git a/shared/src/bundles/videos/types/video-get-all-response-dto.type.ts b/shared/src/bundles/videos/types/video-get-all-response-dto.type.ts index 9f62abc56..de20025e3 100644 --- a/shared/src/bundles/videos/types/video-get-all-response-dto.type.ts +++ b/shared/src/bundles/videos/types/video-get-all-response-dto.type.ts @@ -1,5 +1,5 @@ import { type VideoGetAllItemResponseDto } from './types.js'; -type VideoGetAllResponseDto = VideoGetAllItemResponseDto[]; +type VideoGetAllResponseDto = { items: VideoGetAllItemResponseDto[] }; export { type VideoGetAllResponseDto }; From 268ad656b77f9e7691de64b19a276ba876fb6066 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 13:27:20 +0200 Subject: [PATCH 09/37] OV-59: + video validation message enum --- backend/src/bundles/videos/enums/enums.ts | 1 + backend/src/bundles/videos/video.service.ts | 3 ++- shared/src/bundles/videos/enums/enums.ts | 1 + .../bundles/videos/enums/video-validation-message.enum.ts | 5 +++++ shared/src/bundles/videos/videos.ts | 1 + shared/src/index.ts | 1 + 6 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 backend/src/bundles/videos/enums/enums.ts create mode 100644 shared/src/bundles/videos/enums/enums.ts create mode 100644 shared/src/bundles/videos/enums/video-validation-message.enum.ts diff --git a/backend/src/bundles/videos/enums/enums.ts b/backend/src/bundles/videos/enums/enums.ts new file mode 100644 index 000000000..97a49c62a --- /dev/null +++ b/backend/src/bundles/videos/enums/enums.ts @@ -0,0 +1 @@ +export { VideoValidationMessage } from 'shared'; diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index 61cf17f32..0fed82f35 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -2,6 +2,7 @@ import { type VideoRepository } from '~/bundles/videos/video.repository.js'; import { HttpCode, HttpError } from '~/common/http/http.js'; import { type Service } from '~/common/types/types.js'; +import { VideoValidationMessage } from './enums/enums.js'; import { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, @@ -19,7 +20,7 @@ class VideoService implements Service { if (!video) { throw new HttpError({ - message: 'Video with this id does not exist', + message: VideoValidationMessage.VIDEO_DOESNT_EXIST, status: HttpCode.BAD_REQUEST, }); } diff --git a/shared/src/bundles/videos/enums/enums.ts b/shared/src/bundles/videos/enums/enums.ts new file mode 100644 index 000000000..f56735482 --- /dev/null +++ b/shared/src/bundles/videos/enums/enums.ts @@ -0,0 +1 @@ +export { VideoValidationMessage } from './video-validation-message.enum.js'; diff --git a/shared/src/bundles/videos/enums/video-validation-message.enum.ts b/shared/src/bundles/videos/enums/video-validation-message.enum.ts new file mode 100644 index 000000000..7c450a1e6 --- /dev/null +++ b/shared/src/bundles/videos/enums/video-validation-message.enum.ts @@ -0,0 +1,5 @@ +const VideoValidationMessage = { + VIDEO_DOESNT_EXIST: 'Video with this id does not exist', +} as const; + +export { VideoValidationMessage }; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts index 38c1c7eb8..cae693b83 100644 --- a/shared/src/bundles/videos/videos.ts +++ b/shared/src/bundles/videos/videos.ts @@ -1,3 +1,4 @@ +export { VideoValidationMessage } from './enums/enums.js'; export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, diff --git a/shared/src/index.ts b/shared/src/index.ts index a601ff55e..fe44b0d1a 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -14,6 +14,7 @@ export { export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, + VideoValidationMessage, } from './bundles/videos/videos.js'; export { ApiPath, From 03875a8ba1716ff7250411e8c204941d6698a1fb Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 13:41:08 +0200 Subject: [PATCH 10/37] OV-59: + video controller with get all videos route --- backend/src/bundles/videos/enums/enums.ts | 2 +- .../src/bundles/videos/video.controller.ts | 35 +++++++++++++++++++ shared/src/bundles/videos/enums/enums.ts | 1 + .../videos/enums/videos-api-path.enum.ts | 5 +++ shared/src/bundles/videos/videos.ts | 2 +- shared/src/enums/api-path.enum.ts | 1 + shared/src/index.ts | 1 + 7 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 backend/src/bundles/videos/video.controller.ts create mode 100644 shared/src/bundles/videos/enums/videos-api-path.enum.ts diff --git a/backend/src/bundles/videos/enums/enums.ts b/backend/src/bundles/videos/enums/enums.ts index 97a49c62a..2f314a44f 100644 --- a/backend/src/bundles/videos/enums/enums.ts +++ b/backend/src/bundles/videos/enums/enums.ts @@ -1 +1 @@ -export { VideoValidationMessage } from 'shared'; +export { VideosApiPath, VideoValidationMessage } from 'shared'; diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts new file mode 100644 index 000000000..cbacfdee2 --- /dev/null +++ b/backend/src/bundles/videos/video.controller.ts @@ -0,0 +1,35 @@ +import { type VideoService } from '~/bundles/videos/video.service.js'; +import { + type ApiHandlerResponse, + BaseController, +} from '~/common/controller/controller.js'; +import { ApiPath } from '~/common/enums/enums.js'; +import { HttpCode } from '~/common/http/http.js'; +import { type Logger } from '~/common/logger/logger.js'; + +import { VideosApiPath } from './enums/enums.js'; + +class VideoController extends BaseController { + private videoService: VideoService; + + public constructor(logger: Logger, videoService: VideoService) { + super(logger, ApiPath.VIDEOS); + + this.videoService = videoService; + + this.addRoute({ + path: VideosApiPath.ROOT, + method: 'GET', + handler: () => this.findAll(), + }); + } + + private async findAll(): Promise { + return { + status: HttpCode.OK, + payload: await this.videoService.findAll(), + }; + } +} + +export { VideoController }; diff --git a/shared/src/bundles/videos/enums/enums.ts b/shared/src/bundles/videos/enums/enums.ts index f56735482..db6fd0548 100644 --- a/shared/src/bundles/videos/enums/enums.ts +++ b/shared/src/bundles/videos/enums/enums.ts @@ -1 +1,2 @@ export { VideoValidationMessage } from './video-validation-message.enum.js'; +export { VideosApiPath } from './videos-api-path.enum.js'; diff --git a/shared/src/bundles/videos/enums/videos-api-path.enum.ts b/shared/src/bundles/videos/enums/videos-api-path.enum.ts new file mode 100644 index 000000000..84529646b --- /dev/null +++ b/shared/src/bundles/videos/enums/videos-api-path.enum.ts @@ -0,0 +1,5 @@ +const VideosApiPath = { + ROOT: '/', +} as const; + +export { VideosApiPath }; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts index cae693b83..ed0d94e14 100644 --- a/shared/src/bundles/videos/videos.ts +++ b/shared/src/bundles/videos/videos.ts @@ -1,4 +1,4 @@ -export { VideoValidationMessage } from './enums/enums.js'; +export { VideosApiPath, VideoValidationMessage } from './enums/enums.js'; export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, diff --git a/shared/src/enums/api-path.enum.ts b/shared/src/enums/api-path.enum.ts index de8fc7b8d..262230bfe 100644 --- a/shared/src/enums/api-path.enum.ts +++ b/shared/src/enums/api-path.enum.ts @@ -1,6 +1,7 @@ const ApiPath = { USERS: '/users', AUTH: '/auth', + VIDEOS: '/videos', } as const; export { ApiPath }; diff --git a/shared/src/index.ts b/shared/src/index.ts index fe44b0d1a..daac4e486 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -14,6 +14,7 @@ export { export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, + VideosApiPath, VideoValidationMessage, } from './bundles/videos/videos.js'; export { From 9bcdfddcfc8176bee0a037d7c1b43b7f37b5f948 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 13:51:21 +0200 Subject: [PATCH 11/37] OV-59: + create instance of video controller --- backend/src/bundles/videos/videos.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 backend/src/bundles/videos/videos.ts diff --git a/backend/src/bundles/videos/videos.ts b/backend/src/bundles/videos/videos.ts new file mode 100644 index 000000000..aa892cca4 --- /dev/null +++ b/backend/src/bundles/videos/videos.ts @@ -0,0 +1,12 @@ +import { logger } from '~/common/logger/logger.js'; + +import { VideoController } from './video.controller.js'; +import { VideoModel } from './video.model.js'; +import { VideoRepository } from './video.repository.js'; +import { VideoService } from './video.service.js'; + +const videoRepository = new VideoRepository(VideoModel); +const videoService = new VideoService(videoRepository); +const videoController = new VideoController(logger, videoService); + +export { videoController }; From 9c7807ad797f1c8aff283c29af511ac644a89325 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 13:52:08 +0200 Subject: [PATCH 12/37] OV-59: * add video routes to server app --- backend/src/common/server-application/server-application.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/common/server-application/server-application.ts b/backend/src/common/server-application/server-application.ts index c8c4a88f9..7adc8b597 100644 --- a/backend/src/common/server-application/server-application.ts +++ b/backend/src/common/server-application/server-application.ts @@ -1,5 +1,6 @@ import { authController } from '~/bundles/auth/auth.js'; import { userController } from '~/bundles/users/users.js'; +import { videoController } from '~/bundles/videos/videos.js'; import { config } from '~/common/config/config.js'; import { database } from '~/common/database/database.js'; import { logger } from '~/common/logger/logger.js'; @@ -12,6 +13,7 @@ const apiV1 = new BaseServerAppApi( config, ...authController.routes, ...userController.routes, + ...videoController.routes, ); const serverApp = new BaseServerApp({ config, From 58d0ab214076b844c84955abc3c801b8c0521a61 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 14:29:45 +0200 Subject: [PATCH 13/37] OV-59: + route for finding one video --- .../src/bundles/videos/video.controller.ts | 23 +++++++++++++++++++ .../videos/enums/videos-api-path.enum.ts | 1 + 2 files changed, 24 insertions(+) diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index cbacfdee2..ef2f85c68 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -1,5 +1,6 @@ import { type VideoService } from '~/bundles/videos/video.service.js'; import { + type ApiHandlerOptions, type ApiHandlerResponse, BaseController, } from '~/common/controller/controller.js'; @@ -22,6 +23,17 @@ class VideoController extends BaseController { method: 'GET', handler: () => this.findAll(), }); + + this.addRoute({ + path: VideosApiPath.VIDEO, + method: 'GET', + handler: (options) => + this.find( + options as ApiHandlerOptions<{ + params: { videoId: string }; + }>, + ), + }); } private async findAll(): Promise { @@ -30,6 +42,17 @@ class VideoController extends BaseController { payload: await this.videoService.findAll(), }; } + + private async find( + options: ApiHandlerOptions<{ + params: { videoId: string }; + }>, + ): Promise { + return { + status: HttpCode.OK, + payload: await this.videoService.find(options.params.videoId), + }; + } } export { VideoController }; diff --git a/shared/src/bundles/videos/enums/videos-api-path.enum.ts b/shared/src/bundles/videos/enums/videos-api-path.enum.ts index 84529646b..b6c24855a 100644 --- a/shared/src/bundles/videos/enums/videos-api-path.enum.ts +++ b/shared/src/bundles/videos/enums/videos-api-path.enum.ts @@ -1,5 +1,6 @@ const VideosApiPath = { ROOT: '/', + VIDEO: '/:videoId', } as const; export { VideosApiPath }; From d0f48b51322f9f2fe635393764eb677b32c6c623 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 14:50:10 +0200 Subject: [PATCH 14/37] OV-59: + get one video request type --- backend/src/bundles/videos/types/types.ts | 1 + backend/src/bundles/videos/video.controller.ts | 5 +++-- shared/src/bundles/videos/types/types.ts | 1 + .../bundles/videos/types/video-get-one-request-dto.type.ts | 5 +++++ shared/src/bundles/videos/videos.ts | 1 + shared/src/index.ts | 1 + 6 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 shared/src/bundles/videos/types/video-get-one-request-dto.type.ts diff --git a/backend/src/bundles/videos/types/types.ts b/backend/src/bundles/videos/types/types.ts index e79c0f579..36dcaf689 100644 --- a/backend/src/bundles/videos/types/types.ts +++ b/backend/src/bundles/videos/types/types.ts @@ -1,4 +1,5 @@ export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, + type VideoGetOneRequestDto, } from 'shared'; diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index ef2f85c68..e682eaab0 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -9,6 +9,7 @@ import { HttpCode } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; import { VideosApiPath } from './enums/enums.js'; +import { type VideoGetOneRequestDto } from './types/types.js'; class VideoController extends BaseController { private videoService: VideoService; @@ -30,7 +31,7 @@ class VideoController extends BaseController { handler: (options) => this.find( options as ApiHandlerOptions<{ - params: { videoId: string }; + params: VideoGetOneRequestDto; }>, ), }); @@ -45,7 +46,7 @@ class VideoController extends BaseController { private async find( options: ApiHandlerOptions<{ - params: { videoId: string }; + params: VideoGetOneRequestDto; }>, ): Promise { return { diff --git a/shared/src/bundles/videos/types/types.ts b/shared/src/bundles/videos/types/types.ts index 93dc70cd8..67ec2facc 100644 --- a/shared/src/bundles/videos/types/types.ts +++ b/shared/src/bundles/videos/types/types.ts @@ -1,2 +1,3 @@ export { type VideoGetAllItemResponseDto } from './video-get-all-item-response-dto.type.js'; export { type VideoGetAllResponseDto } from './video-get-all-response-dto.type.js'; +export { type VideoGetOneRequestDto } from './video-get-one-request-dto.type.js'; diff --git a/shared/src/bundles/videos/types/video-get-one-request-dto.type.ts b/shared/src/bundles/videos/types/video-get-one-request-dto.type.ts new file mode 100644 index 000000000..ffe4d1b85 --- /dev/null +++ b/shared/src/bundles/videos/types/video-get-one-request-dto.type.ts @@ -0,0 +1,5 @@ +type VideoGetOneRequestDto = { + videoId: string; +}; + +export { type VideoGetOneRequestDto }; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts index ed0d94e14..97b15539a 100644 --- a/shared/src/bundles/videos/videos.ts +++ b/shared/src/bundles/videos/videos.ts @@ -2,4 +2,5 @@ export { VideosApiPath, VideoValidationMessage } from './enums/enums.js'; export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, + type VideoGetOneRequestDto, } from './types/types.js'; diff --git a/shared/src/index.ts b/shared/src/index.ts index daac4e486..2135f1253 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -14,6 +14,7 @@ export { export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, + type VideoGetOneRequestDto, VideosApiPath, VideoValidationMessage, } from './bundles/videos/videos.js'; From d0fef8352a98c9544df7311b41436ded7dcb22ee Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 19:36:54 +0200 Subject: [PATCH 15/37] OV-59: + implement create video method in repository --- backend/src/bundles/videos/video.repository.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/src/bundles/videos/video.repository.ts b/backend/src/bundles/videos/video.repository.ts index 623c076bc..895322794 100644 --- a/backend/src/bundles/videos/video.repository.ts +++ b/backend/src/bundles/videos/video.repository.ts @@ -21,8 +21,19 @@ class VideoRepository implements Repository { return videos.map((it) => VideoEntity.initialize(it)); } - public create(entity: VideoEntity): Promise { - return Promise.resolve(entity); + public async create(entity: VideoEntity): Promise { + const { userId, name, url } = entity.toNewObject(); + const item = await this.videoModel + .query() + .insert({ + userId, + name, + url, + }) + .returning('*') + .execute(); + + return VideoEntity.initialize(item); } public update(): ReturnType { From 31cf4ea88f33b8adcf8ce65a4f9bc2e733757ede Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 19:38:18 +0200 Subject: [PATCH 16/37] OV-59: + implement create video method in service --- backend/src/bundles/videos/types/types.ts | 1 + backend/src/bundles/videos/video.service.ts | 12 ++++++++++-- .../videos/types/create-video-request-dto.type.ts | 7 +++++++ shared/src/bundles/videos/types/types.ts | 1 + shared/src/bundles/videos/videos.ts | 1 + shared/src/index.ts | 1 + 6 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 shared/src/bundles/videos/types/create-video-request-dto.type.ts diff --git a/backend/src/bundles/videos/types/types.ts b/backend/src/bundles/videos/types/types.ts index 36dcaf689..af7c6cb05 100644 --- a/backend/src/bundles/videos/types/types.ts +++ b/backend/src/bundles/videos/types/types.ts @@ -1,4 +1,5 @@ export { + type CreateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, type VideoGetOneRequestDto, diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index 0fed82f35..939cb9847 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -1,9 +1,11 @@ +import { VideoEntity } from '~/bundles/videos/video.entity.js'; import { type VideoRepository } from '~/bundles/videos/video.repository.js'; import { HttpCode, HttpError } from '~/common/http/http.js'; import { type Service } from '~/common/types/types.js'; import { VideoValidationMessage } from './enums/enums.js'; import { + type CreateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, } from './types/types.js'; @@ -36,8 +38,14 @@ class VideoService implements Service { }; } - public create(payload: null): ReturnType { - return Promise.resolve(payload); + public async create( + payload: CreateVideoRequestDto, + ): Promise { + const video = await this.videoRepository.create( + VideoEntity.initializeNew(payload), + ); + + return video.toObject(); } public update(): ReturnType { diff --git a/shared/src/bundles/videos/types/create-video-request-dto.type.ts b/shared/src/bundles/videos/types/create-video-request-dto.type.ts new file mode 100644 index 000000000..40d9b309f --- /dev/null +++ b/shared/src/bundles/videos/types/create-video-request-dto.type.ts @@ -0,0 +1,7 @@ +type CreateVideoRequestDto = { + userId: string; + name: string; + url: string; +}; + +export { type CreateVideoRequestDto }; diff --git a/shared/src/bundles/videos/types/types.ts b/shared/src/bundles/videos/types/types.ts index 67ec2facc..cb3c5c4da 100644 --- a/shared/src/bundles/videos/types/types.ts +++ b/shared/src/bundles/videos/types/types.ts @@ -1,3 +1,4 @@ +export { type CreateVideoRequestDto } from './create-video-request-dto.type.js'; export { type VideoGetAllItemResponseDto } from './video-get-all-item-response-dto.type.js'; export { type VideoGetAllResponseDto } from './video-get-all-response-dto.type.js'; export { type VideoGetOneRequestDto } from './video-get-one-request-dto.type.js'; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts index 97b15539a..b3bb23447 100644 --- a/shared/src/bundles/videos/videos.ts +++ b/shared/src/bundles/videos/videos.ts @@ -1,5 +1,6 @@ export { VideosApiPath, VideoValidationMessage } from './enums/enums.js'; export { + type CreateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, type VideoGetOneRequestDto, diff --git a/shared/src/index.ts b/shared/src/index.ts index 2135f1253..cbf5a1344 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -12,6 +12,7 @@ export { UserValidationMessage, } from './bundles/users/users.js'; export { + type CreateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, type VideoGetOneRequestDto, From 546a5b933412cbe7f37eead85c4e3fc34a189ae9 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 20:02:56 +0200 Subject: [PATCH 17/37] OV-59: + validation schema for creating video --- .../create-video.validation-schema.ts | 28 +++++++++++++++++++ .../validation-schemas/validation-schemas.ts | 1 + shared/src/bundles/videos/videos.ts | 1 + shared/src/index.ts | 1 + 4 files changed, 31 insertions(+) create mode 100644 shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts create mode 100644 shared/src/bundles/videos/validation-schemas/validation-schemas.ts diff --git a/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts new file mode 100644 index 000000000..c7762ed74 --- /dev/null +++ b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts @@ -0,0 +1,28 @@ +import { z } from 'zod'; + +type CreateVideoValidationDto = { + userId: z.ZodString; + name: z.ZodString; + url: z.ZodString; +}; + +const createVideo = z + .object({ + userId: z + .string({ required_error: 'User id is required' }) + .trim() + .uuid({ message: 'Invalid UUID' }), + name: z + .string({ required_error: 'The video name is required' }) + .trim() + .min(1, { + message: 'The video name should have at least 1 character', + }), + url: z + .string({ required_error: 'The video url is required' }) + .trim() + .url({ message: 'Invalid url' }), + }) + .required(); + +export { createVideo }; diff --git a/shared/src/bundles/videos/validation-schemas/validation-schemas.ts b/shared/src/bundles/videos/validation-schemas/validation-schemas.ts new file mode 100644 index 000000000..f36f1d09e --- /dev/null +++ b/shared/src/bundles/videos/validation-schemas/validation-schemas.ts @@ -0,0 +1 @@ +export { createVideo } from './create-video.validation-schema.js'; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts index b3bb23447..b0ad14a66 100644 --- a/shared/src/bundles/videos/videos.ts +++ b/shared/src/bundles/videos/videos.ts @@ -5,3 +5,4 @@ export { type VideoGetAllResponseDto, type VideoGetOneRequestDto, } from './types/types.js'; +export { createVideo as createVideoValidationSchema } from './validation-schemas/validation-schemas.js'; diff --git a/shared/src/index.ts b/shared/src/index.ts index cbf5a1344..9a9782bcc 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -16,6 +16,7 @@ export { type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, type VideoGetOneRequestDto, + createVideoValidationSchema, VideosApiPath, VideoValidationMessage, } from './bundles/videos/videos.js'; From 6fee4f5f0605d29bcef05a444bea363ed3e4dfaa Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Sun, 25 Aug 2024 20:03:51 +0200 Subject: [PATCH 18/37] OV-59: + create video route --- .../validation-schemas/validation-schemas.ts | 1 + .../src/bundles/videos/video.controller.ts | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 backend/src/bundles/videos/validation-schemas/validation-schemas.ts diff --git a/backend/src/bundles/videos/validation-schemas/validation-schemas.ts b/backend/src/bundles/videos/validation-schemas/validation-schemas.ts new file mode 100644 index 000000000..c83ca1087 --- /dev/null +++ b/backend/src/bundles/videos/validation-schemas/validation-schemas.ts @@ -0,0 +1 @@ +export { createVideoValidationSchema } from 'shared'; diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index e682eaab0..8a2278102 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -9,7 +9,11 @@ import { HttpCode } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; import { VideosApiPath } from './enums/enums.js'; -import { type VideoGetOneRequestDto } from './types/types.js'; +import { + type CreateVideoRequestDto, + type VideoGetOneRequestDto, +} from './types/types.js'; +import { createVideoValidationSchema } from './validation-schemas/validation-schemas.js'; class VideoController extends BaseController { private videoService: VideoService; @@ -35,6 +39,20 @@ class VideoController extends BaseController { }>, ), }); + + this.addRoute({ + path: VideosApiPath.ROOT, + method: 'POST', + validation: { + body: createVideoValidationSchema, + }, + handler: (options) => + this.create( + options as ApiHandlerOptions<{ + body: CreateVideoRequestDto; + }>, + ), + }); } private async findAll(): Promise { @@ -54,6 +72,17 @@ class VideoController extends BaseController { payload: await this.videoService.find(options.params.videoId), }; } + + private async create( + options: ApiHandlerOptions<{ + body: CreateVideoRequestDto; + }>, + ): Promise { + return { + status: HttpCode.CREATED, + payload: await this.videoService.create(options.body), + }; + } } export { VideoController }; From 9318b4b9af0e79b0db986ca5f1089bf44b08198a Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 16:20:33 +0200 Subject: [PATCH 19/37] OV-59: * implement update method in video repository --- backend/src/bundles/videos/video.repository.ts | 12 ++++++++++-- backend/src/common/types/repository.type.ts | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/src/bundles/videos/video.repository.ts b/backend/src/bundles/videos/video.repository.ts index 895322794..2759da640 100644 --- a/backend/src/bundles/videos/video.repository.ts +++ b/backend/src/bundles/videos/video.repository.ts @@ -36,8 +36,16 @@ class VideoRepository implements Repository { return VideoEntity.initialize(item); } - public update(): ReturnType { - return Promise.resolve(null); + public async update( + videoId: string, + data: { userId?: string; name?: string; url?: string }, + ): Promise { + const updatedItem = await this.videoModel + .query() + .patchAndFetchById(videoId, data) + .execute(); + + return updatedItem ? VideoEntity.initialize(updatedItem) : null; } public delete(): ReturnType { diff --git a/backend/src/common/types/repository.type.ts b/backend/src/common/types/repository.type.ts index c1351f138..ba5a1384b 100644 --- a/backend/src/common/types/repository.type.ts +++ b/backend/src/common/types/repository.type.ts @@ -2,7 +2,7 @@ type Repository = { find(id: string): Promise; findAll(): Promise; create(payload: unknown): Promise; - update(): Promise; + update(id: string, payload: unknown): Promise; delete(): Promise; }; From c772eb409a806edb7d254911b89b164b4d015624 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 17:04:28 +0200 Subject: [PATCH 20/37] OV-59: * implement update method in video service --- backend/src/bundles/videos/video.service.ts | 16 ++++++++++++++-- backend/src/common/types/service.type.ts | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index 939cb9847..b125697f3 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -48,8 +48,20 @@ class VideoService implements Service { return video.toObject(); } - public update(): ReturnType { - return Promise.resolve(null); + public async update( + videoId: string, + data: { userId?: string; name?: string; url?: string }, + ): Promise { + const updatedVideo = await this.videoRepository.update(videoId, data); + + if (!updatedVideo) { + throw new HttpError({ + message: VideoValidationMessage.VIDEO_DOESNT_EXIST, + status: HttpCode.BAD_REQUEST, + }); + } + + return updatedVideo.toObject(); } public delete(): ReturnType { diff --git a/backend/src/common/types/service.type.ts b/backend/src/common/types/service.type.ts index ca4232685..5c663a5b2 100644 --- a/backend/src/common/types/service.type.ts +++ b/backend/src/common/types/service.type.ts @@ -4,7 +4,7 @@ type Service = { items: T[]; }>; create(payload: unknown): Promise; - update(): Promise; + update(id: string, data: unknown): Promise; delete(): Promise; }; From 99c227813e8ad2549290ddcf632482040b7defb8 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 17:10:51 +0200 Subject: [PATCH 21/37] OV-59: + type for update video request payload --- backend/src/bundles/videos/types/types.ts | 1 + backend/src/bundles/videos/video.repository.ts | 3 ++- backend/src/bundles/videos/video.service.ts | 3 ++- shared/src/bundles/videos/types/types.ts | 1 + .../bundles/videos/types/update-video-request-dto.type.ts | 5 +++++ shared/src/bundles/videos/videos.ts | 1 + shared/src/index.ts | 1 + 7 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 shared/src/bundles/videos/types/update-video-request-dto.type.ts diff --git a/backend/src/bundles/videos/types/types.ts b/backend/src/bundles/videos/types/types.ts index af7c6cb05..1139c6979 100644 --- a/backend/src/bundles/videos/types/types.ts +++ b/backend/src/bundles/videos/types/types.ts @@ -1,5 +1,6 @@ export { type CreateVideoRequestDto, + type UpdateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, type VideoGetOneRequestDto, diff --git a/backend/src/bundles/videos/video.repository.ts b/backend/src/bundles/videos/video.repository.ts index 2759da640..dab3448b5 100644 --- a/backend/src/bundles/videos/video.repository.ts +++ b/backend/src/bundles/videos/video.repository.ts @@ -1,3 +1,4 @@ +import { type UpdateVideoRequestDto } from '~/bundles/videos/types/types.js'; import { VideoEntity } from '~/bundles/videos/video.entity.js'; import { type VideoModel } from '~/bundles/videos/video.model.js'; import { type Repository } from '~/common/types/types.js'; @@ -38,7 +39,7 @@ class VideoRepository implements Repository { public async update( videoId: string, - data: { userId?: string; name?: string; url?: string }, + data: UpdateVideoRequestDto, ): Promise { const updatedItem = await this.videoModel .query() diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index b125697f3..0641c53cd 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -6,6 +6,7 @@ import { type Service } from '~/common/types/types.js'; import { VideoValidationMessage } from './enums/enums.js'; import { type CreateVideoRequestDto, + type UpdateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, } from './types/types.js'; @@ -50,7 +51,7 @@ class VideoService implements Service { public async update( videoId: string, - data: { userId?: string; name?: string; url?: string }, + data: UpdateVideoRequestDto, ): Promise { const updatedVideo = await this.videoRepository.update(videoId, data); diff --git a/shared/src/bundles/videos/types/types.ts b/shared/src/bundles/videos/types/types.ts index cb3c5c4da..f20f0ace9 100644 --- a/shared/src/bundles/videos/types/types.ts +++ b/shared/src/bundles/videos/types/types.ts @@ -1,4 +1,5 @@ export { type CreateVideoRequestDto } from './create-video-request-dto.type.js'; +export { type UpdateVideoRequestDto } from './update-video-request-dto.type.js'; export { type VideoGetAllItemResponseDto } from './video-get-all-item-response-dto.type.js'; export { type VideoGetAllResponseDto } from './video-get-all-response-dto.type.js'; export { type VideoGetOneRequestDto } from './video-get-one-request-dto.type.js'; diff --git a/shared/src/bundles/videos/types/update-video-request-dto.type.ts b/shared/src/bundles/videos/types/update-video-request-dto.type.ts new file mode 100644 index 000000000..e54b0e8e2 --- /dev/null +++ b/shared/src/bundles/videos/types/update-video-request-dto.type.ts @@ -0,0 +1,5 @@ +import { type CreateVideoRequestDto } from './create-video-request-dto.type.js'; + +type UpdateVideoRequestDto = Partial; + +export { type UpdateVideoRequestDto }; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts index b0ad14a66..d272db13f 100644 --- a/shared/src/bundles/videos/videos.ts +++ b/shared/src/bundles/videos/videos.ts @@ -1,6 +1,7 @@ export { VideosApiPath, VideoValidationMessage } from './enums/enums.js'; export { type CreateVideoRequestDto, + type UpdateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, type VideoGetOneRequestDto, diff --git a/shared/src/index.ts b/shared/src/index.ts index 9a9782bcc..28c1081be 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -13,6 +13,7 @@ export { } from './bundles/users/users.js'; export { type CreateVideoRequestDto, + type UpdateVideoRequestDto, type VideoGetAllItemResponseDto, type VideoGetAllResponseDto, type VideoGetOneRequestDto, From 31ff0a2efa2dfa66f9a5e5257fb980743a5157e7 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 17:13:37 +0200 Subject: [PATCH 22/37] OV-59: * rename data parameter to payload --- backend/src/bundles/videos/video.repository.ts | 4 ++-- backend/src/bundles/videos/video.service.ts | 7 +++++-- backend/src/common/types/service.type.ts | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/src/bundles/videos/video.repository.ts b/backend/src/bundles/videos/video.repository.ts index dab3448b5..b146c32dc 100644 --- a/backend/src/bundles/videos/video.repository.ts +++ b/backend/src/bundles/videos/video.repository.ts @@ -39,11 +39,11 @@ class VideoRepository implements Repository { public async update( videoId: string, - data: UpdateVideoRequestDto, + payload: UpdateVideoRequestDto, ): Promise { const updatedItem = await this.videoModel .query() - .patchAndFetchById(videoId, data) + .patchAndFetchById(videoId, payload) .execute(); return updatedItem ? VideoEntity.initialize(updatedItem) : null; diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index 0641c53cd..db0a0f73a 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -51,9 +51,12 @@ class VideoService implements Service { public async update( videoId: string, - data: UpdateVideoRequestDto, + payload: UpdateVideoRequestDto, ): Promise { - const updatedVideo = await this.videoRepository.update(videoId, data); + const updatedVideo = await this.videoRepository.update( + videoId, + payload, + ); if (!updatedVideo) { throw new HttpError({ diff --git a/backend/src/common/types/service.type.ts b/backend/src/common/types/service.type.ts index 5c663a5b2..ea812eabd 100644 --- a/backend/src/common/types/service.type.ts +++ b/backend/src/common/types/service.type.ts @@ -4,7 +4,7 @@ type Service = { items: T[]; }>; create(payload: unknown): Promise; - update(id: string, data: unknown): Promise; + update(id: string, payload: unknown): Promise; delete(): Promise; }; From 8cd08b3d8f87944a6696a8dd290b88745c31ed54 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 17:24:53 +0200 Subject: [PATCH 23/37] OV-59: + route for update video --- .../src/bundles/videos/video.controller.ts | 29 +++++++++++++++++++ .../framework/http/types/http-method.type.ts | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index 8a2278102..20a122427 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -11,6 +11,7 @@ import { type Logger } from '~/common/logger/logger.js'; import { VideosApiPath } from './enums/enums.js'; import { type CreateVideoRequestDto, + type UpdateVideoRequestDto, type VideoGetOneRequestDto, } from './types/types.js'; import { createVideoValidationSchema } from './validation-schemas/validation-schemas.js'; @@ -53,6 +54,19 @@ class VideoController extends BaseController { }>, ), }); + + this.addRoute({ + path: VideosApiPath.VIDEO, + method: 'PATCH', + validation: {}, + handler: (options) => + this.update( + options as ApiHandlerOptions<{ + params: VideoGetOneRequestDto; + body: UpdateVideoRequestDto; + }>, + ), + }); } private async findAll(): Promise { @@ -83,6 +97,21 @@ class VideoController extends BaseController { payload: await this.videoService.create(options.body), }; } + + private async update( + options: ApiHandlerOptions<{ + params: VideoGetOneRequestDto; + body: UpdateVideoRequestDto; + }>, + ): Promise { + return { + status: HttpCode.OK, + payload: await this.videoService.update( + options.params.videoId, + options.body, + ), + }; + } } export { VideoController }; diff --git a/shared/src/framework/http/types/http-method.type.ts b/shared/src/framework/http/types/http-method.type.ts index 884797ac9..4995d8e97 100644 --- a/shared/src/framework/http/types/http-method.type.ts +++ b/shared/src/framework/http/types/http-method.type.ts @@ -1,3 +1,3 @@ -type HttpMethod = 'GET' | 'POST'; +type HttpMethod = 'GET' | 'POST' | 'PATCH'; export { type HttpMethod }; From f0f5d2513dc851c0e4323ce2a0c56243989d2c3d Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 18:33:16 +0200 Subject: [PATCH 24/37] OV-38: * use enum for video validation messages --- .../videos/enums/video-validation-message.enum.ts | 6 ++++++ .../create-video.validation-schema.ts | 14 ++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/shared/src/bundles/videos/enums/video-validation-message.enum.ts b/shared/src/bundles/videos/enums/video-validation-message.enum.ts index 7c450a1e6..a3922b2ea 100644 --- a/shared/src/bundles/videos/enums/video-validation-message.enum.ts +++ b/shared/src/bundles/videos/enums/video-validation-message.enum.ts @@ -1,5 +1,11 @@ const VideoValidationMessage = { VIDEO_DOESNT_EXIST: 'Video with this id does not exist', + USER_ID_REQUIRE: 'User id is required', + UUID_WRONG: 'Invalid UUID', + NAME_REQUIRE: 'The video name is required', + NAME_LENGTH: 'The video name should have at least 1 character', + URL_REQUIRE: 'The video url is required', + URL_WRONG: 'Invalid url', } as const; export { VideoValidationMessage }; diff --git a/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts index c7762ed74..54954dd79 100644 --- a/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts +++ b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts @@ -1,5 +1,7 @@ import { z } from 'zod'; +import { VideoValidationMessage } from '../enums/enums.js'; + type CreateVideoValidationDto = { userId: z.ZodString; name: z.ZodString; @@ -9,19 +11,19 @@ type CreateVideoValidationDto = { const createVideo = z .object({ userId: z - .string({ required_error: 'User id is required' }) + .string({ required_error: VideoValidationMessage.USER_ID_REQUIRE }) .trim() - .uuid({ message: 'Invalid UUID' }), + .uuid({ message: VideoValidationMessage.UUID_WRONG }), name: z - .string({ required_error: 'The video name is required' }) + .string({ required_error: VideoValidationMessage.NAME_REQUIRE }) .trim() .min(1, { - message: 'The video name should have at least 1 character', + message: VideoValidationMessage.NAME_LENGTH, }), url: z - .string({ required_error: 'The video url is required' }) + .string({ required_error: VideoValidationMessage.URL_REQUIRE }) .trim() - .url({ message: 'Invalid url' }), + .url({ message: VideoValidationMessage.URL_WRONG }), }) .required(); From 500665b59b45555357e8d85b755582ec9895b0b4 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 18:41:09 +0200 Subject: [PATCH 25/37] OV-59: + validation schema for update video --- .../videos/validation-schemas/validation-schemas.ts | 5 ++++- backend/src/bundles/videos/video.controller.ts | 9 +++++++-- .../validation-schemas/update-video.validation-schema.ts | 5 +++++ .../videos/validation-schemas/validation-schemas.ts | 1 + shared/src/bundles/videos/videos.ts | 5 ++++- shared/src/index.ts | 1 + 6 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 shared/src/bundles/videos/validation-schemas/update-video.validation-schema.ts diff --git a/backend/src/bundles/videos/validation-schemas/validation-schemas.ts b/backend/src/bundles/videos/validation-schemas/validation-schemas.ts index c83ca1087..debea87a1 100644 --- a/backend/src/bundles/videos/validation-schemas/validation-schemas.ts +++ b/backend/src/bundles/videos/validation-schemas/validation-schemas.ts @@ -1 +1,4 @@ -export { createVideoValidationSchema } from 'shared'; +export { + createVideoValidationSchema, + updateVideoValidationSchema, +} from 'shared'; diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index 20a122427..97a87b5f3 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -14,7 +14,10 @@ import { type UpdateVideoRequestDto, type VideoGetOneRequestDto, } from './types/types.js'; -import { createVideoValidationSchema } from './validation-schemas/validation-schemas.js'; +import { + createVideoValidationSchema, + updateVideoValidationSchema, +} from './validation-schemas/validation-schemas.js'; class VideoController extends BaseController { private videoService: VideoService; @@ -58,7 +61,9 @@ class VideoController extends BaseController { this.addRoute({ path: VideosApiPath.VIDEO, method: 'PATCH', - validation: {}, + validation: { + body: updateVideoValidationSchema, + }, handler: (options) => this.update( options as ApiHandlerOptions<{ diff --git a/shared/src/bundles/videos/validation-schemas/update-video.validation-schema.ts b/shared/src/bundles/videos/validation-schemas/update-video.validation-schema.ts new file mode 100644 index 000000000..c22583e07 --- /dev/null +++ b/shared/src/bundles/videos/validation-schemas/update-video.validation-schema.ts @@ -0,0 +1,5 @@ +import { createVideo } from './validation-schemas.js'; + +const updateVideo = createVideo.partial(); + +export { updateVideo }; diff --git a/shared/src/bundles/videos/validation-schemas/validation-schemas.ts b/shared/src/bundles/videos/validation-schemas/validation-schemas.ts index f36f1d09e..04dad0671 100644 --- a/shared/src/bundles/videos/validation-schemas/validation-schemas.ts +++ b/shared/src/bundles/videos/validation-schemas/validation-schemas.ts @@ -1 +1,2 @@ export { createVideo } from './create-video.validation-schema.js'; +export { updateVideo } from './update-video.validation-schema.js'; diff --git a/shared/src/bundles/videos/videos.ts b/shared/src/bundles/videos/videos.ts index d272db13f..168496252 100644 --- a/shared/src/bundles/videos/videos.ts +++ b/shared/src/bundles/videos/videos.ts @@ -6,4 +6,7 @@ export { type VideoGetAllResponseDto, type VideoGetOneRequestDto, } from './types/types.js'; -export { createVideo as createVideoValidationSchema } from './validation-schemas/validation-schemas.js'; +export { + createVideo as createVideoValidationSchema, + updateVideo as updateVideoValidationSchema, +} from './validation-schemas/validation-schemas.js'; diff --git a/shared/src/index.ts b/shared/src/index.ts index 28c1081be..14a67eecc 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -18,6 +18,7 @@ export { type VideoGetAllResponseDto, type VideoGetOneRequestDto, createVideoValidationSchema, + updateVideoValidationSchema, VideosApiPath, VideoValidationMessage, } from './bundles/videos/videos.js'; From 52398e91409f7913c52bab73ca73dc050fd6ada3 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 18:59:46 +0200 Subject: [PATCH 26/37] OV-59: + delete video method in repository --- backend/src/bundles/videos/video.repository.ts | 9 +++++++-- backend/src/common/types/repository.type.ts | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/src/bundles/videos/video.repository.ts b/backend/src/bundles/videos/video.repository.ts index b146c32dc..f86474034 100644 --- a/backend/src/bundles/videos/video.repository.ts +++ b/backend/src/bundles/videos/video.repository.ts @@ -49,8 +49,13 @@ class VideoRepository implements Repository { return updatedItem ? VideoEntity.initialize(updatedItem) : null; } - public delete(): ReturnType { - return Promise.resolve(true); + public async delete(videoId: string): Promise { + const numberOfDeletedRows = await this.videoModel + .query() + .deleteById(videoId) + .execute(); + + return Boolean(numberOfDeletedRows); } } diff --git a/backend/src/common/types/repository.type.ts b/backend/src/common/types/repository.type.ts index ba5a1384b..2564c5132 100644 --- a/backend/src/common/types/repository.type.ts +++ b/backend/src/common/types/repository.type.ts @@ -3,7 +3,7 @@ type Repository = { findAll(): Promise; create(payload: unknown): Promise; update(id: string, payload: unknown): Promise; - delete(): Promise; + delete(id: string): Promise; }; export { type Repository }; From 9ce425e5ed75761bb7e1abf0ed208e3dad8e1575 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 19:06:37 +0200 Subject: [PATCH 27/37] OV-59: + delete video method in service --- backend/src/bundles/videos/video.service.ts | 4 ++-- backend/src/common/types/service.type.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index db0a0f73a..706451f3c 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -68,8 +68,8 @@ class VideoService implements Service { return updatedVideo.toObject(); } - public delete(): ReturnType { - return Promise.resolve(true); + public async delete(videoId: string): Promise { + return await this.videoRepository.delete(videoId); } } diff --git a/backend/src/common/types/service.type.ts b/backend/src/common/types/service.type.ts index ea812eabd..1aaa079a6 100644 --- a/backend/src/common/types/service.type.ts +++ b/backend/src/common/types/service.type.ts @@ -5,7 +5,7 @@ type Service = { }>; create(payload: unknown): Promise; update(id: string, payload: unknown): Promise; - delete(): Promise; + delete(id: string): Promise; }; export { type Service }; From 6dea829b872f46e582979eff995a92d0bd954c48 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Mon, 26 Aug 2024 19:11:40 +0200 Subject: [PATCH 28/37] OV-59: + delete video route --- .../src/bundles/videos/video.controller.ts | 22 +++++++++++++++++++ .../framework/http/types/http-method.type.ts | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index 97a87b5f3..288b373d2 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -72,6 +72,17 @@ class VideoController extends BaseController { }>, ), }); + + this.addRoute({ + path: VideosApiPath.VIDEO, + method: 'DELETE', + handler: (options) => + this.delete( + options as ApiHandlerOptions<{ + params: VideoGetOneRequestDto; + }>, + ), + }); } private async findAll(): Promise { @@ -117,6 +128,17 @@ class VideoController extends BaseController { ), }; } + + private async delete( + options: ApiHandlerOptions<{ + params: VideoGetOneRequestDto; + }>, + ): Promise { + return { + status: HttpCode.OK, + payload: await this.videoService.delete(options.params.videoId), + }; + } } export { VideoController }; diff --git a/shared/src/framework/http/types/http-method.type.ts b/shared/src/framework/http/types/http-method.type.ts index 4995d8e97..2609fc332 100644 --- a/shared/src/framework/http/types/http-method.type.ts +++ b/shared/src/framework/http/types/http-method.type.ts @@ -1,3 +1,3 @@ -type HttpMethod = 'GET' | 'POST' | 'PATCH'; +type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE'; export { type HttpMethod }; From a8a792038c8a23a034e9515bdad0679e0933c940 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Tue, 27 Aug 2024 16:17:53 +0200 Subject: [PATCH 29/37] OV-59: * throw http error when deleting video failed --- backend/src/bundles/videos/video.service.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index 706451f3c..9f2b5ef5b 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -69,7 +69,16 @@ class VideoService implements Service { } public async delete(videoId: string): Promise { - return await this.videoRepository.delete(videoId); + const isVideoDeleted = await this.videoRepository.delete(videoId); + + if (!isVideoDeleted) { + throw new HttpError({ + message: VideoValidationMessage.VIDEO_DOESNT_EXIST, + status: HttpCode.BAD_REQUEST, + }); + } + + return isVideoDeleted; } } From 0bf23685c8fe5d940a8cf9658ece0889d0353b2d Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Tue, 27 Aug 2024 16:23:32 +0200 Subject: [PATCH 30/37] OV-59: * change query param videoId to id --- backend/src/bundles/videos/video.controller.ts | 6 +++--- shared/src/bundles/videos/enums/videos-api-path.enum.ts | 2 +- .../bundles/videos/types/video-get-one-request-dto.type.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index 288b373d2..d718b4eca 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -99,7 +99,7 @@ class VideoController extends BaseController { ): Promise { return { status: HttpCode.OK, - payload: await this.videoService.find(options.params.videoId), + payload: await this.videoService.find(options.params.id), }; } @@ -123,7 +123,7 @@ class VideoController extends BaseController { return { status: HttpCode.OK, payload: await this.videoService.update( - options.params.videoId, + options.params.id, options.body, ), }; @@ -136,7 +136,7 @@ class VideoController extends BaseController { ): Promise { return { status: HttpCode.OK, - payload: await this.videoService.delete(options.params.videoId), + payload: await this.videoService.delete(options.params.id), }; } } diff --git a/shared/src/bundles/videos/enums/videos-api-path.enum.ts b/shared/src/bundles/videos/enums/videos-api-path.enum.ts index b6c24855a..509b941e3 100644 --- a/shared/src/bundles/videos/enums/videos-api-path.enum.ts +++ b/shared/src/bundles/videos/enums/videos-api-path.enum.ts @@ -1,6 +1,6 @@ const VideosApiPath = { ROOT: '/', - VIDEO: '/:videoId', + VIDEO: '/:id', } as const; export { VideosApiPath }; diff --git a/shared/src/bundles/videos/types/video-get-one-request-dto.type.ts b/shared/src/bundles/videos/types/video-get-one-request-dto.type.ts index ffe4d1b85..8f081705d 100644 --- a/shared/src/bundles/videos/types/video-get-one-request-dto.type.ts +++ b/shared/src/bundles/videos/types/video-get-one-request-dto.type.ts @@ -1,5 +1,5 @@ type VideoGetOneRequestDto = { - videoId: string; + id: string; }; export { type VideoGetOneRequestDto }; From c50d25ab11d7d8cdf1160e5678d2183ceb3eb9eb Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Tue, 27 Aug 2024 17:15:20 +0200 Subject: [PATCH 31/37] OV-59: * change return type of update method in service to except null --- backend/src/common/types/repository.type.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/common/types/repository.type.ts b/backend/src/common/types/repository.type.ts index 2564c5132..669339108 100644 --- a/backend/src/common/types/repository.type.ts +++ b/backend/src/common/types/repository.type.ts @@ -2,7 +2,7 @@ type Repository = { find(id: string): Promise; findAll(): Promise; create(payload: unknown): Promise; - update(id: string, payload: unknown): Promise; + update(id: string, payload: unknown): Promise; delete(id: string): Promise; }; From c0ec426f9552d63ceed33dfa34fe8d6e726de655 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Tue, 27 Aug 2024 18:27:38 +0200 Subject: [PATCH 32/37] OV-59: * fix typo to required --- .../bundles/videos/enums/video-validation-message.enum.ts | 6 +++--- .../validation-schemas/create-video.validation-schema.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/src/bundles/videos/enums/video-validation-message.enum.ts b/shared/src/bundles/videos/enums/video-validation-message.enum.ts index a3922b2ea..115359de0 100644 --- a/shared/src/bundles/videos/enums/video-validation-message.enum.ts +++ b/shared/src/bundles/videos/enums/video-validation-message.enum.ts @@ -1,10 +1,10 @@ const VideoValidationMessage = { VIDEO_DOESNT_EXIST: 'Video with this id does not exist', - USER_ID_REQUIRE: 'User id is required', + USER_ID_REQUIRED: 'User id is required', UUID_WRONG: 'Invalid UUID', - NAME_REQUIRE: 'The video name is required', + NAME_REQUIRED: 'The video name is required', NAME_LENGTH: 'The video name should have at least 1 character', - URL_REQUIRE: 'The video url is required', + URL_REQUIRED: 'The video url is required', URL_WRONG: 'Invalid url', } as const; diff --git a/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts index 54954dd79..f2e0a6f2a 100644 --- a/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts +++ b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts @@ -11,17 +11,17 @@ type CreateVideoValidationDto = { const createVideo = z .object({ userId: z - .string({ required_error: VideoValidationMessage.USER_ID_REQUIRE }) + .string({ required_error: VideoValidationMessage.USER_ID_REQUIRED }) .trim() .uuid({ message: VideoValidationMessage.UUID_WRONG }), name: z - .string({ required_error: VideoValidationMessage.NAME_REQUIRE }) + .string({ required_error: VideoValidationMessage.NAME_REQUIRED }) .trim() .min(1, { message: VideoValidationMessage.NAME_LENGTH, }), url: z - .string({ required_error: VideoValidationMessage.URL_REQUIRE }) + .string({ required_error: VideoValidationMessage.URL_REQUIRED }) .trim() .url({ message: VideoValidationMessage.URL_WRONG }), }) From fbacb450b4d7d13d08e277518d969210dbe2aa7d Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Tue, 27 Aug 2024 20:25:16 +0200 Subject: [PATCH 33/37] OV-59: * check if userId field is not empty --- .../videos/validation-schemas/create-video.validation-schema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts index f2e0a6f2a..54237e345 100644 --- a/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts +++ b/shared/src/bundles/videos/validation-schemas/create-video.validation-schema.ts @@ -13,6 +13,7 @@ const createVideo = z userId: z .string({ required_error: VideoValidationMessage.USER_ID_REQUIRED }) .trim() + .min(1, { message: VideoValidationMessage.USER_ID_REQUIRED }) .uuid({ message: VideoValidationMessage.UUID_WRONG }), name: z .string({ required_error: VideoValidationMessage.NAME_REQUIRED }) From e2c6e81a175b58d2b2c9e7e70c9d108573a0a65a Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Wed, 28 Aug 2024 15:52:26 +0200 Subject: [PATCH 34/37] OV-59: + add swagger documentation for video routes --- .../src/bundles/videos/video.controller.ts | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index d718b4eca..4fc4fa5a0 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -19,6 +19,25 @@ import { updateVideoValidationSchema, } from './validation-schemas/validation-schemas.js'; +/** + * @swagger + * components: + * schemas: + * Video: + * type: object + * properties: + * id: + * type: string + * format: uuid + * userId: + * type: string + * format: uuid + * name: + * type: string + * url: + * type: string + * format: url + */ class VideoController extends BaseController { private videoService: VideoService; @@ -85,6 +104,26 @@ class VideoController extends BaseController { }); } + /** + * @swagger + * /videos: + * get: + * description: Get all videos + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * type: object + * properties: + * items: + * type: array + * description: A list of video objects + * items: + * $ref: '#/components/schemas/Video' + */ + private async findAll(): Promise { return { status: HttpCode.OK, @@ -92,6 +131,35 @@ class VideoController extends BaseController { }; } + /** + * @swagger + * /videos/{id}: + * get: + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * format: uuid + * description: The video id + * description: Get video by id + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Video' + * 404: + * description: Failed operation. The resource was not found. + * content: + * application/json: + * schema: + * type: object + * $ref: '#/components/schemas/Error' + */ + private async find( options: ApiHandlerOptions<{ params: VideoGetOneRequestDto; @@ -103,6 +171,37 @@ class VideoController extends BaseController { }; } + /** + * @swagger + * /videos: + * post: + * description: Create new video + * requestBody: + * description: Video data + * required: true + * content: + * application/json: + * schema: + * type: object + * required: [userId, name, url] + * properties: + * userId: + * type: string + * format: uuid + * name: + * type: string + * url: + * type: string + * format: url + * responses: + * 201: + * description: Successful operation + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Video' + */ + private async create( options: ApiHandlerOptions<{ body: CreateVideoRequestDto; @@ -114,6 +213,50 @@ class VideoController extends BaseController { }; } + /** + * @swagger + * /videos/{id}: + * patch: + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * format: uuid + * description: The video id + * description: Update video by id + * requestBody: + * description: Video data + * content: + * application/json: + * schema: + * type: object + * properties: + * userId: + * type: string + * format: uuid + * name: + * type: string + * url: + * type: string + * format: url + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Video' + * 404: + * description: Failed operation. The resource was not found. + * content: + * application/json: + * schema: + * type: object + * $ref: '#/components/schemas/Error' + */ + private async update( options: ApiHandlerOptions<{ params: VideoGetOneRequestDto; @@ -129,6 +272,35 @@ class VideoController extends BaseController { }; } + /** + * @swagger + * /videos/{id}: + * delete: + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * format: uuid + * description: The video id + * description: Delete video by id + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * type: boolean + * 404: + * description: Failed operation. The resource was not found. + * content: + * application/json: + * schema: + * type: object + * $ref: '#/components/schemas/Error' + */ + private async delete( options: ApiHandlerOptions<{ params: VideoGetOneRequestDto; From 9276b4e402997dbdbf20a0e1155b05cada648f57 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Wed, 28 Aug 2024 16:14:50 +0200 Subject: [PATCH 35/37] OV-59: * bad request 400 -> not found 404 http code --- backend/src/bundles/videos/video.service.ts | 6 +++--- shared/src/framework/http/enums/http-code.enum.ts | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/bundles/videos/video.service.ts b/backend/src/bundles/videos/video.service.ts index 9f2b5ef5b..652772edf 100644 --- a/backend/src/bundles/videos/video.service.ts +++ b/backend/src/bundles/videos/video.service.ts @@ -24,7 +24,7 @@ class VideoService implements Service { if (!video) { throw new HttpError({ message: VideoValidationMessage.VIDEO_DOESNT_EXIST, - status: HttpCode.BAD_REQUEST, + status: HttpCode.NOT_FOUND, }); } @@ -61,7 +61,7 @@ class VideoService implements Service { if (!updatedVideo) { throw new HttpError({ message: VideoValidationMessage.VIDEO_DOESNT_EXIST, - status: HttpCode.BAD_REQUEST, + status: HttpCode.NOT_FOUND, }); } @@ -74,7 +74,7 @@ class VideoService implements Service { if (!isVideoDeleted) { throw new HttpError({ message: VideoValidationMessage.VIDEO_DOESNT_EXIST, - status: HttpCode.BAD_REQUEST, + status: HttpCode.NOT_FOUND, }); } diff --git a/shared/src/framework/http/enums/http-code.enum.ts b/shared/src/framework/http/enums/http-code.enum.ts index 6d2ad89ba..f4ea2347e 100644 --- a/shared/src/framework/http/enums/http-code.enum.ts +++ b/shared/src/framework/http/enums/http-code.enum.ts @@ -2,6 +2,7 @@ const HttpCode = { OK: 200, CREATED: 201, BAD_REQUEST: 400, + NOT_FOUND: 404, UNPROCESSED_ENTITY: 422, INTERNAL_SERVER_ERROR: 500, } as const; From a302b014a664afc4c42f9330776a4f797d4822a9 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Wed, 28 Aug 2024 18:45:26 +0300 Subject: [PATCH 36/37] OV-76: * .env.example --- backend/.env.example | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/.env.example b/backend/.env.example index fa8ac180f..41fd4ce5e 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -20,3 +20,13 @@ AWS_SECRET_ACCESS_KEY=see-in-slack AWS_S3_REGION=eu-north-1 AWS_S3_BUCKET_NAME=bsa-2024-outreachvids AWS_CLOUDFRONT_DOMAIN_ID=d2tm5q3cg1nlwf + +# +# OPEN AI +# +OPEN_AI_KEY=SOME_SECRET_KEY + +# +# SESSION +# +SESSION_KEY=SOME_SECRET_KEY From e88de810ee2c4701e5e77194d0f8384900b76922 Mon Sep 17 00:00:00 2001 From: Oleksandra Okhotnykova Date: Wed, 28 Aug 2024 18:57:03 +0200 Subject: [PATCH 37/37] OV-59: * rename video api path --- backend/src/bundles/videos/video.controller.ts | 6 +++--- shared/src/bundles/videos/enums/videos-api-path.enum.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/bundles/videos/video.controller.ts b/backend/src/bundles/videos/video.controller.ts index 4fc4fa5a0..ceb51b8a5 100644 --- a/backend/src/bundles/videos/video.controller.ts +++ b/backend/src/bundles/videos/video.controller.ts @@ -53,7 +53,7 @@ class VideoController extends BaseController { }); this.addRoute({ - path: VideosApiPath.VIDEO, + path: VideosApiPath.ID, method: 'GET', handler: (options) => this.find( @@ -78,7 +78,7 @@ class VideoController extends BaseController { }); this.addRoute({ - path: VideosApiPath.VIDEO, + path: VideosApiPath.ID, method: 'PATCH', validation: { body: updateVideoValidationSchema, @@ -93,7 +93,7 @@ class VideoController extends BaseController { }); this.addRoute({ - path: VideosApiPath.VIDEO, + path: VideosApiPath.ID, method: 'DELETE', handler: (options) => this.delete( diff --git a/shared/src/bundles/videos/enums/videos-api-path.enum.ts b/shared/src/bundles/videos/enums/videos-api-path.enum.ts index 509b941e3..82abbdcfa 100644 --- a/shared/src/bundles/videos/enums/videos-api-path.enum.ts +++ b/shared/src/bundles/videos/enums/videos-api-path.enum.ts @@ -1,6 +1,6 @@ const VideosApiPath = { ROOT: '/', - VIDEO: '/:id', + ID: '/:id', } as const; export { VideosApiPath };