feat: add movie and category services
This commit is contained in:
parent
b2e02e0ae2
commit
471ac1ba44
@ -4,7 +4,9 @@ import { PassportModule } from '@teacinema/passport'
|
|||||||
|
|
||||||
import { AccountModule } from '../modules/account/account.module'
|
import { AccountModule } from '../modules/account/account.module'
|
||||||
import { AuthModule } from '../modules/auth/auth.module'
|
import { AuthModule } from '../modules/auth/auth.module'
|
||||||
|
import { CategoryModule } from '../modules/category/category.module'
|
||||||
import { MediaModule } from '../modules/media/media.module'
|
import { MediaModule } from '../modules/media/media.module'
|
||||||
|
import { MovieModule } from '../modules/movie/movie.module'
|
||||||
import { UsersModule } from '../modules/users/users.module'
|
import { UsersModule } from '../modules/users/users.module'
|
||||||
import { ObservabilityModule } from '../observability/observability.module'
|
import { ObservabilityModule } from '../observability/observability.module'
|
||||||
|
|
||||||
@ -27,6 +29,8 @@ import { getPassportConfig } from './config'
|
|||||||
AccountModule,
|
AccountModule,
|
||||||
MediaModule,
|
MediaModule,
|
||||||
UsersModule,
|
UsersModule,
|
||||||
|
MovieModule,
|
||||||
|
CategoryModule,
|
||||||
PassportModule.registerAsync({
|
PassportModule.registerAsync({
|
||||||
useFactory: getPassportConfig,
|
useFactory: getPassportConfig,
|
||||||
inject: [ConfigService]
|
inject: [ConfigService]
|
||||||
|
|||||||
20
src/modules/category/category.controller.ts
Normal file
20
src/modules/category/category.controller.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
HttpCode,
|
||||||
|
HttpStatus,
|
||||||
|
} from '@nestjs/common'
|
||||||
|
|
||||||
|
import { CategoryClientGrpc } from './category.grpc'
|
||||||
|
|
||||||
|
@Controller('categories')
|
||||||
|
export class CategoryController {
|
||||||
|
constructor(private readonly client: CategoryClientGrpc) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
public async getAll() {
|
||||||
|
const { categories } = await this.client.call('getAllCategories', {})
|
||||||
|
return categories
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/modules/category/category.grpc.ts
Normal file
13
src/modules/category/category.grpc.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import type { ClientGrpc } from '@nestjs/microservices'
|
||||||
|
import { InjectGrpc } from '@teacinema/common'
|
||||||
|
import { CategoryServiceClient } from '@teacinema/contracts/gen/ts/category'
|
||||||
|
|
||||||
|
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CategoryClientGrpc extends AbstractGrpcClient<CategoryServiceClient> {
|
||||||
|
constructor(@InjectGrpc('CATEGORY_PACKAGE') client: ClientGrpc) {
|
||||||
|
super(client, 'CategoryService')
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/modules/category/category.module.ts
Normal file
13
src/modules/category/category.module.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { GrpcModule } from '@teacinema/common'
|
||||||
|
|
||||||
|
import { CategoryController } from './category.controller'
|
||||||
|
import { CategoryClientGrpc } from './category.grpc'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [GrpcModule.register(['CATEGORY_PACKAGE'])],
|
||||||
|
controllers: [CategoryController],
|
||||||
|
providers: [CategoryClientGrpc],
|
||||||
|
exports: [CategoryClientGrpc]
|
||||||
|
})
|
||||||
|
export class CategoryModule {}
|
||||||
1
src/modules/movie/dto/index.ts
Normal file
1
src/modules/movie/dto/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './rq'
|
||||||
46
src/modules/movie/dto/rq/get-movies.request.dto.ts
Normal file
46
src/modules/movie/dto/rq/get-movies.request.dto.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger'
|
||||||
|
import { Transform } from 'class-transformer'
|
||||||
|
import {
|
||||||
|
IsBoolean,
|
||||||
|
IsInt,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
Max,
|
||||||
|
Min
|
||||||
|
} from 'class-validator'
|
||||||
|
|
||||||
|
export class GetMoviesRequestDto {
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
example: 'classic'
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call
|
||||||
|
@Transform(({ value }) => value.toString().trim())
|
||||||
|
public category: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
example: true
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
@Transform(({ value }) => {
|
||||||
|
if (value === 'true') return true
|
||||||
|
if (value === 'false') return false
|
||||||
|
return value as boolean
|
||||||
|
})
|
||||||
|
public random: boolean
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
example: 10
|
||||||
|
})
|
||||||
|
@IsInt()
|
||||||
|
@IsOptional()
|
||||||
|
@Min(1)
|
||||||
|
@Max(100)
|
||||||
|
@Transform(({ value }) => {
|
||||||
|
if (value !== undefined) return Number(value)
|
||||||
|
return undefined
|
||||||
|
})
|
||||||
|
public limit: number
|
||||||
|
}
|
||||||
1
src/modules/movie/dto/rq/index.ts
Normal file
1
src/modules/movie/dto/rq/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './get-movies.request.dto'
|
||||||
35
src/modules/movie/movie.controller.ts
Normal file
35
src/modules/movie/movie.controller.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
HttpCode,
|
||||||
|
HttpStatus,
|
||||||
|
Param,
|
||||||
|
Query
|
||||||
|
} from '@nestjs/common'
|
||||||
|
import { Movie, MovieDetails } from '@teacinema/contracts/gen/ts/movie'
|
||||||
|
|
||||||
|
import { GetMoviesRequestDto } from './dto'
|
||||||
|
import { MovieClientGrpc } from './movie.grpc'
|
||||||
|
import { MovieMapper } from './movie.mapper'
|
||||||
|
|
||||||
|
@Controller('movies')
|
||||||
|
export class MovieController {
|
||||||
|
constructor(private readonly client: MovieClientGrpc) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
public async getAll(@Query() dto: GetMoviesRequestDto) {
|
||||||
|
const { movies } = await this.client.call('listMovies', dto)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
return movies.map(MovieMapper.toMovie<Movie>)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':slug')
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
public async getBySlug(@Param('slug') slug: string) {
|
||||||
|
const { movie } = await this.client.call('getMovie', { slug })
|
||||||
|
|
||||||
|
// @ts-expect-error -- ok
|
||||||
|
return MovieMapper.toMovie<MovieDetails>(movie)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/modules/movie/movie.grpc.ts
Normal file
13
src/modules/movie/movie.grpc.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import type { ClientGrpc } from '@nestjs/microservices'
|
||||||
|
import { InjectGrpc } from '@teacinema/common'
|
||||||
|
import { MovieServiceClient } from '@teacinema/contracts/gen/ts/movie'
|
||||||
|
|
||||||
|
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MovieClientGrpc extends AbstractGrpcClient<MovieServiceClient> {
|
||||||
|
constructor(@InjectGrpc('MOVIE_PACKAGE') client: ClientGrpc) {
|
||||||
|
super(client, 'MovieService')
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/modules/movie/movie.mapper.ts
Normal file
13
src/modules/movie/movie.mapper.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { timestampToISO } from '@teacinema/common'
|
||||||
|
import { Movie, MovieDetails } from '@teacinema/contracts/gen/ts/movie'
|
||||||
|
|
||||||
|
export class MovieMapper {
|
||||||
|
public static toMovie<T extends Movie | MovieDetails>(entity: T) {
|
||||||
|
if (!entity.releaseDate) return entity
|
||||||
|
|
||||||
|
return {
|
||||||
|
...entity,
|
||||||
|
releaseDate: timestampToISO(entity.releaseDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/modules/movie/movie.module.ts
Normal file
13
src/modules/movie/movie.module.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { GrpcModule } from '@teacinema/common'
|
||||||
|
|
||||||
|
import { MovieController } from './movie.controller'
|
||||||
|
import { MovieClientGrpc } from './movie.grpc'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [GrpcModule.register(['MOVIE_PACKAGE'])],
|
||||||
|
controllers: [MovieController],
|
||||||
|
providers: [MovieClientGrpc],
|
||||||
|
exports: [MovieClientGrpc]
|
||||||
|
})
|
||||||
|
export class MovieModule {}
|
||||||
60
yarn.lock
60
yarn.lock
@ -1028,12 +1028,12 @@
|
|||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
|
|
||||||
"@nestjs/common@^11.1.16":
|
"@nestjs/common@^11.1.16":
|
||||||
version "11.1.17"
|
version "11.1.18"
|
||||||
resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-11.1.17.tgz#58a330f3f6748cf92b0a244a2a232cfddba1bfd2"
|
resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-11.1.18.tgz#329b214aadea5a4a1b12b4eee61c32b9c5b5082c"
|
||||||
integrity sha512-hLODw5Abp8OQgA+mUO4tHou4krKgDtUcM9j5Ihxncst9XeyxYBTt2bwZm4e4EQr5E352S4Fyy6V3iFx9ggxKAg==
|
integrity sha512-0sLq8Z+TIjLnz1Tqp0C/x9BpLbqpt1qEu0VcH4/fkE0y3F5JxhfK1AdKQ/SPbKhKgwqVDoY4gS8GQr2G6ujaWg==
|
||||||
dependencies:
|
dependencies:
|
||||||
uid "2.0.2"
|
uid "2.0.2"
|
||||||
file-type "21.3.2"
|
file-type "21.3.4"
|
||||||
iterare "1.2.1"
|
iterare "1.2.1"
|
||||||
load-esm "1.0.3"
|
load-esm "1.0.3"
|
||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
@ -1048,13 +1048,13 @@
|
|||||||
lodash "4.17.21"
|
lodash "4.17.21"
|
||||||
|
|
||||||
"@nestjs/config@^4.0.3":
|
"@nestjs/config@^4.0.3":
|
||||||
version "4.0.3"
|
version "4.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-4.0.3.tgz#bb24a5f64e4e3ccf6fbf9e02f63303d14d7f308e"
|
resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-4.0.4.tgz#311d806fdc32a8bf29cf9ced903b97cbdb7e064b"
|
||||||
integrity sha512-FQ3M3Ohqfl+nHAn5tp7++wUQw0f2nAk+SFKe8EpNRnIifPqvfJP6JQxPKtFLMOHbyer4X646prFG4zSRYEssQQ==
|
integrity sha512-CJPjNitr0bAufSEnRe2N+JbnVmMmDoo6hvKCPzXgZoGwJSmp/dZPk9f/RMbuD/+Q1ZJPjwsRpq0vxna++Knwow==
|
||||||
dependencies:
|
dependencies:
|
||||||
dotenv "17.2.3"
|
dotenv "17.4.1"
|
||||||
dotenv-expand "12.0.3"
|
dotenv-expand "12.0.3"
|
||||||
lodash "4.17.23"
|
lodash "4.18.1"
|
||||||
|
|
||||||
"@nestjs/core@^11.0.1":
|
"@nestjs/core@^11.0.1":
|
||||||
version "11.1.12"
|
version "11.1.12"
|
||||||
@ -1094,9 +1094,9 @@
|
|||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
|
|
||||||
"@nestjs/microservices@^11.1.16":
|
"@nestjs/microservices@^11.1.16":
|
||||||
version "11.1.17"
|
version "11.1.18"
|
||||||
resolved "https://registry.yarnpkg.com/@nestjs/microservices/-/microservices-11.1.17.tgz#f2b1aa25e24532377477a437583f1af002118602"
|
resolved "https://registry.yarnpkg.com/@nestjs/microservices/-/microservices-11.1.18.tgz#3f5edd756e32f7c85c1c67c65f8ba3b62a736ebf"
|
||||||
integrity sha512-rubBPEEXS9PwA3LwdNN/ytjEUmON+d8+4fbiUCIFGW8i+rR/g36vrpwuvoAzcGpxlu45/TpZPfHTb0nJciG9Yw==
|
integrity sha512-sodzBqqKAcOv5GctTbb0j3vzgx+X3/IxmJ8pBKL9hEmsarsYPkig6dcOcVFmM2Pknm+o6Cxaqv1YZZETISNi+w==
|
||||||
dependencies:
|
dependencies:
|
||||||
iterare "1.2.1"
|
iterare "1.2.1"
|
||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
@ -1997,9 +1997,9 @@
|
|||||||
"@sinonjs/commons" "^3.0.1"
|
"@sinonjs/commons" "^3.0.1"
|
||||||
|
|
||||||
"@teacinema/common@^1.0.0":
|
"@teacinema/common@^1.0.0":
|
||||||
version "1.1.6"
|
version "1.3.2"
|
||||||
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcommon/-/1.1.6/common-1.1.6.tgz#4b43fc7c1f19cef0ba138a3a7988918f54f52ebb"
|
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcommon/-/1.3.2/common-1.3.2.tgz#51ef68a7a92bb9fbd604052953a10b84846ddd77"
|
||||||
integrity sha512-a0wU0EaJ92PdMlwFQ5pA0EZ9G1/f9Gca8CCN2qUy75q0HldNTGKKYUEyDHx4Y0z16N1e3/RO12gagebOrV6Nbg==
|
integrity sha512-uD83OWCPZrjDknQNvDGz90WyHDHsRvzn/kE3ofK5oToOOG5f0WXrq0vr1UGi7+DZzTbRfsUe06mgMyahuJ/j4w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nestjs/common" "^11.1.16"
|
"@nestjs/common" "^11.1.16"
|
||||||
"@nestjs/config" "^4.0.3"
|
"@nestjs/config" "^4.0.3"
|
||||||
@ -2007,9 +2007,9 @@
|
|||||||
"@teacinema/contracts" "^1.1.3"
|
"@teacinema/contracts" "^1.1.3"
|
||||||
|
|
||||||
"@teacinema/contracts@^1.0.0", "@teacinema/contracts@^1.1.3":
|
"@teacinema/contracts@^1.0.0", "@teacinema/contracts@^1.1.3":
|
||||||
version "1.1.8"
|
version "1.2.3"
|
||||||
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.1.8/contracts-1.1.8.tgz#e96c23a957d2682503c157250672eb4c46bf4ef9"
|
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.2.3/contracts-1.2.3.tgz#d356a9dc7395b304a9d5ab639565fa9bcebb9c74"
|
||||||
integrity sha512-wSFTntA0IoQrC/iYz3rylJW6qK6KGWa25oQrl/n55aSOcMk1ACmSBt0aqAPML86SQWAsn7yikpr/foaTgJH3zg==
|
integrity sha512-Rvw8DVmIpRD/I2Yk1gQyO8ZmxyOIY3FW+purxwiLBIi22gHQtVAXV27a9xK6sO/XXHx70KhrY/8fU8JH/+ehkw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nestjs/microservices" "^11.1.12"
|
"@nestjs/microservices" "^11.1.12"
|
||||||
protoc "33.4.0"
|
protoc "33.4.0"
|
||||||
@ -3455,10 +3455,10 @@ dotenv@16.4.7:
|
|||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
|
||||||
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
|
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
|
||||||
|
|
||||||
dotenv@17.2.3:
|
dotenv@17.4.1:
|
||||||
version "17.2.3"
|
version "17.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.3.tgz#ad995d6997f639b11065f419a22fabf567cdb9a2"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.4.1.tgz#d8e2179fe287365ef3aecb9459668454168eda88"
|
||||||
integrity sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==
|
integrity sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==
|
||||||
|
|
||||||
dotenv@^16.4.5:
|
dotenv@^16.4.5:
|
||||||
version "16.6.1"
|
version "16.6.1"
|
||||||
@ -3853,10 +3853,10 @@ file-type@21.3.0:
|
|||||||
token-types "^6.1.1"
|
token-types "^6.1.1"
|
||||||
uint8array-extras "^1.4.0"
|
uint8array-extras "^1.4.0"
|
||||||
|
|
||||||
file-type@21.3.2:
|
file-type@21.3.4:
|
||||||
version "21.3.2"
|
version "21.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-21.3.2.tgz#b28bb3a19ea4b03f59af31546b9d95ee8a3623eb"
|
resolved "https://registry.yarnpkg.com/file-type/-/file-type-21.3.4.tgz#e3f902faee8ec4aa152909fc902a7a77f9c06725"
|
||||||
integrity sha512-DLkUvGwep3poOV2wpzbHCOnSKGk1LzyXTv+aHFgN2VFl96wnp8YA9YjO2qPzg5PuL8q/SW9Pdi6WTkYOIh995w==
|
integrity sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@tokenizer/inflate" "^0.4.1"
|
"@tokenizer/inflate" "^0.4.1"
|
||||||
strtok3 "^10.3.4"
|
strtok3 "^10.3.4"
|
||||||
@ -4909,10 +4909,10 @@ lodash@4.17.21, lodash@^4.17.21:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
|
||||||
lodash@4.17.23:
|
lodash@4.18.1:
|
||||||
version "4.17.23"
|
version "4.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c"
|
||||||
integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==
|
integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==
|
||||||
|
|
||||||
log-symbols@^4.1.0:
|
log-symbols@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user