Skip to content

Commit

Permalink
feat(rest-api): Added the movies endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
TriPSs committed Nov 11, 2020
1 parent 14f121c commit cde3a11
Show file tree
Hide file tree
Showing 37 changed files with 851 additions and 85 deletions.
1 change: 1 addition & 0 deletions apps/rest-api/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "extends": "../../.eslintrc.json", "ignorePatterns": ["!**/*"], "rules": {} }
14 changes: 14 additions & 0 deletions apps/rest-api/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
displayName: 'rest-api',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
tsConfig: '<rootDir>/tsconfig.spec.json',
},
},
transform: {
'^.+\\.[tj]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/rest-api',
};
34 changes: 34 additions & 0 deletions apps/rest-api/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Module } from '@nestjs/common'
import { MongooseModule } from '@nestjs/mongoose'

import { ModelsModule } from './shared/models.module'
import { ConfigModule } from './shared/config/config.module'
import { ConfigService } from './shared/config/config.service'

import { MoviesModule } from './routes/movies/movies.module'
import { ShowsModule } from './routes/shows/shows.module'

@Module({
imports: [
ModelsModule,
ConfigModule,

// Routes
MoviesModule,
ShowsModule,

// Enable Mongoose
MongooseModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
uri: configService.databaseUri,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false
})
})
]
})
export class AppModule {
}
39 changes: 39 additions & 0 deletions apps/rest-api/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { NestFactory } from '@nestjs/core'
import { Logger, ValidationPipe } from '@nestjs/common'
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'

import { AppModule } from './app.module'
import { ConfigService } from './shared/config/config.service'

declare const module: any

async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
{
logger: ConfigService.logLevel
}
)

const configService = app.get('ConfigService')
const port = configService.get(ConfigService.PORT)

app.useGlobalPipes(new ValidationPipe({
transform: true,
transformOptions: {
enableImplicitConversion: true
}
}))

await app.listen(port, '0.0.0.0').then(() => {
Logger.log(`Server running on http://localhost:${port}`)
})

if (module.hot) {
module.hot.accept()
module.hot.dispose(() => app.close())
}
}

bootstrap()
76 changes: 76 additions & 0 deletions apps/rest-api/src/routes/movies/movies.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Controller, Get, Inject, Param, Query } from '@nestjs/common'
import { MoviesService, MoviesArgs } from '@pct-org/movies'
import { Movie } from '../../shared/movie.interface'

@Controller('/movies')
export class MoviesController {

@Inject()
private readonly moviesService: MoviesService

@Get('')
public async getMovies(): Promise<string[]> {
const totalMovies = await this.moviesService.count()

return Array(Math.round(totalMovies / 50)).fill(null).map((empty, index) => (
`/movies/${index + 1}`
))
}

@Get('/:page')
public async getMoviesPage(
@Param('page') page: number,
@Query() args: MoviesArgs
): Promise<Movie[]> {
args.offset = (page - 1) * args.limit
args.query = args.keywords

const movies = await this.moviesService.findAll(args)

return movies.map((movie) => {
const released = new Date(movie.released)

return {
_id: movie._id,
imdb_id: movie._id,
title: movie.title,
year: `${released.getFullYear()}`,
synopsis: movie.synopsis,
runtime: `${(movie.runtime.hours * 60) + movie.runtime.minutes}`,
released: movie.released,
trailer: movie.trailer,
certification: '',
torrents: {
en: {
...movie.torrents.reduce((newTorrents, torrent) => {
newTorrents[torrent.quality] = {
url: torrent.url,
seed: torrent.seeds,
peer: torrent.peers,
size: torrent.size,
fileSize: torrent.sizeString,
provider: torrent.provider
}

return newTorrents
}, {})
}
},
genres: movie.genres,
images: {
poster: movie.images.poster.medium,
fanart: movie.images.backdrop.medium,
banner: movie.images.poster.medium
},
rating: {
percentage: movie.rating.percentage,
watching: movie.rating.watching,
votes: movie.rating.votes,
loved: 100,
hated: 100
}
}
})
}

}
15 changes: 15 additions & 0 deletions apps/rest-api/src/routes/movies/movies.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Module } from '@nestjs/common'
import { MoviesService } from '@pct-org/movies'

import { MoviesController } from './movies.controller'

@Module({
providers: [
MoviesService
],
controllers: [
MoviesController
]
})
export class MoviesModule {
}
11 changes: 11 additions & 0 deletions apps/rest-api/src/routes/shows/shows.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Controller, Get } from '@nestjs/common'

@Controller('/shows')
export class ShowsController {

@Get('')
public watch() {
return 'ok'
}

}
12 changes: 12 additions & 0 deletions apps/rest-api/src/routes/shows/shows.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common'

import { ShowsController } from './shows.controller'

@Module({
providers: [],
controllers: [
ShowsController
]
})
export class ShowsModule {
}
10 changes: 10 additions & 0 deletions apps/rest-api/src/shared/config/config.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module, Global } from '@nestjs/common'
import { ConfigService } from './config.service'

@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService]
})
export class ConfigModule {
}
98 changes: 98 additions & 0 deletions apps/rest-api/src/shared/config/config.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { LogLevel } from '@nestjs/common'
import * as Joi from '@hapi/joi'

export interface EnvConfig {
[key: string]: string;
}

export class ConfigService {

public static readonly NODE_ENV: string = 'NODE_ENV'
public static readonly PORT: string = 'API_PORT'
public static readonly MONGO_USER: string = 'MONGO_USER'
public static readonly MONGO_PASS: string = 'MONGO_PASS'
public static readonly MONGO_URI: string = 'MONGO_URI'
public static readonly MONGO_PORT: string = 'MONGO_PORT'
public static readonly MONGO_DATABASE: string = 'MONGO_DATABASE'

private readonly envConfig: { [key: string]: string }

constructor() {
this.envConfig = this.validateInput(process.env)
}

/**
* Get a key from the config
*
* @param {string} key
*/
get(key: string): string {
return this.envConfig[key] || ''
}

/**
* Get the correct formatted database uri
*/
get databaseUri(): string {
const uri = new URL(
`mongodb://${this.get('MONGO_USER')}:${this.get('MONGO_PASS')}@${this.get('MONGO_URI')}:${this.get('MONGO_PORT')}/${this.get('MONGO_DATABASE')}`
)

return uri.href
}

/**
* Is the current env development
*/
get isDevelopment(): boolean {
return this.get('NODE_ENV') === 'development'
}

static get logLevel(): LogLevel[] {
const env = process.env.NODE_ENV || 'development'

if (env === 'development') {
return ['log', 'error', 'warn', 'debug', 'verbose']
}

return ['log', 'error', 'warn']
}

/**
* Ensures all needed variables are set, and returns the validated JavaScript object
* including the applied default values.
*/
private validateInput(envConfig: EnvConfig): EnvConfig {
const envVarsSchema: Joi.ObjectSchema = Joi.object({
[ConfigService.NODE_ENV]: Joi.string()
// .valid(['development', 'production', 'test', 'provision'])
.default('development'),

[ConfigService.PORT]: Joi.number()
.default(3000),

[ConfigService.MONGO_USER]: Joi.string()
.optional(),

[ConfigService.MONGO_PASS]: Joi.string()
.optional(),

[ConfigService.MONGO_URI]: Joi.string()
.default('127.0.0.1'),

[ConfigService.MONGO_PORT]: Joi.number()
.default('27017'),

[ConfigService.MONGO_DATABASE]: Joi.string()
.required(),
})

const { error, value: validatedEnvConfig } = envVarsSchema.validate(envConfig, { stripUnknown: true })

if (error) {
throw new Error(`Config validation error: ${error.message}`)
}

return validatedEnvConfig
}
}
15 changes: 15 additions & 0 deletions apps/rest-api/src/shared/models.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Global, Module } from '@nestjs/common'
import { MOVIES_MONGOOSE_FEATURE } from '@pct-org/movies'


@Global()
@Module({
imports: [
MOVIES_MONGOOSE_FEATURE
],
exports: [
MOVIES_MONGOOSE_FEATURE
]
})
export class ModelsModule {
}
31 changes: 31 additions & 0 deletions apps/rest-api/src/shared/movie.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Torrents } from './torrents.interface'

export interface Movie {

_id: string
imdb_id: string
title: string
year: string
synopsis: string
runtime: string
released: number
trailer: string
certification: string
torrents: Torrents,
genres: string[]

images: {
poster: string
fanart: string
banner: string
},

rating: {
percentage: number
watching: number
votes: number
loved: number
hated: number
}

}
14 changes: 14 additions & 0 deletions apps/rest-api/src/shared/torrents.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface Torrents {

en: {
[key: string]: {
url: string
seed: number
peer: number
size: number
filesize: string
provider: string
},
}

}
11 changes: 11 additions & 0 deletions apps/rest-api/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"],
"emitDecoratorMetadata": true,
"target": "es2015"
},
"exclude": ["**/*.spec.ts"],
"include": ["**/*.ts"]
}

0 comments on commit cde3a11

Please sign in to comment.