| @@ -0,0 +1,25 @@ | |||
| module.exports = { | |||
| parser: '@typescript-eslint/parser', | |||
| parserOptions: { | |||
| project: 'tsconfig.json', | |||
| sourceType: 'module', | |||
| }, | |||
| plugins: ['@typescript-eslint/eslint-plugin'], | |||
| extends: [ | |||
| 'plugin:@typescript-eslint/eslint-recommended', | |||
| 'plugin:@typescript-eslint/recommended', | |||
| 'prettier', | |||
| 'prettier/@typescript-eslint', | |||
| ], | |||
| root: true, | |||
| env: { | |||
| node: true, | |||
| jest: true, | |||
| }, | |||
| rules: { | |||
| '@typescript-eslint/interface-name-prefix': 'off', | |||
| '@typescript-eslint/explicit-function-return-type': 'off', | |||
| '@typescript-eslint/explicit-module-boundary-types': 'off', | |||
| '@typescript-eslint/no-explicit-any': 'off', | |||
| }, | |||
| }; | |||
| @@ -0,0 +1,34 @@ | |||
| # compiled output | |||
| /dist | |||
| /node_modules | |||
| # Logs | |||
| logs | |||
| *.log | |||
| npm-debug.log* | |||
| yarn-debug.log* | |||
| yarn-error.log* | |||
| lerna-debug.log* | |||
| # OS | |||
| .DS_Store | |||
| # Tests | |||
| /coverage | |||
| /.nyc_output | |||
| # IDEs and editors | |||
| /.idea | |||
| .project | |||
| .classpath | |||
| .c9/ | |||
| *.launch | |||
| .settings/ | |||
| *.sublime-workspace | |||
| # IDE - VSCode | |||
| .vscode/* | |||
| !.vscode/settings.json | |||
| !.vscode/tasks.json | |||
| !.vscode/launch.json | |||
| !.vscode/extensions.json | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| "singleQuote": true, | |||
| "trailingComma": "all" | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| start db `docker run --name geekfights-db -e MONGO_INITDB_DATABASE=geekfights -d -p 27017:27017 -v ~/data:/data/db mongo` | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| "collection": "@nestjs/schematics", | |||
| "sourceRoot": "src" | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| { | |||
| "name": "geekfights-service", | |||
| "version": "0.0.1", | |||
| "description": "", | |||
| "author": "", | |||
| "private": true, | |||
| "license": "UNLICENSED", | |||
| "scripts": { | |||
| "prebuild": "rimraf dist", | |||
| "build": "nest build", | |||
| "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", | |||
| "start": "nest start", | |||
| "start:dev": "nest start --watch", | |||
| "start:debug": "nest start --debug --watch", | |||
| "start:prod": "node dist/main", | |||
| "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", | |||
| "test": "jest", | |||
| "test:watch": "jest --watch", | |||
| "test:cov": "jest --coverage", | |||
| "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", | |||
| "test:e2e": "jest --config ./test/jest-e2e.json" | |||
| }, | |||
| "dependencies": { | |||
| "@nestjs/common": "^7.0.0", | |||
| "@nestjs/core": "^7.0.0", | |||
| "@nestjs/mongoose": "^7.0.2", | |||
| "@nestjs/platform-express": "^7.0.0", | |||
| "@types/podcast": "^1.3.0", | |||
| "mongoose": "^5.10.9", | |||
| "podcast": "^1.3.0", | |||
| "reflect-metadata": "^0.1.13", | |||
| "rimraf": "^3.0.2", | |||
| "rxjs": "^6.5.4" | |||
| }, | |||
| "devDependencies": { | |||
| "@nestjs/cli": "^7.0.0", | |||
| "@nestjs/schematics": "^7.0.0", | |||
| "@nestjs/testing": "^7.0.0", | |||
| "@types/express": "^4.17.3", | |||
| "@types/jest": "26.0.10", | |||
| "@types/mongoose": "^5.7.36", | |||
| "@types/node": "^13.9.1", | |||
| "@types/supertest": "^2.0.8", | |||
| "@typescript-eslint/eslint-plugin": "3.9.1", | |||
| "@typescript-eslint/parser": "3.9.1", | |||
| "eslint": "7.7.0", | |||
| "eslint-config-prettier": "^6.10.0", | |||
| "eslint-plugin-import": "^2.20.1", | |||
| "jest": "26.4.2", | |||
| "prettier": "^1.19.1", | |||
| "supertest": "^4.0.2", | |||
| "ts-jest": "26.2.0", | |||
| "ts-loader": "^6.2.1", | |||
| "ts-node": "9.0.0", | |||
| "tsconfig-paths": "^3.9.0", | |||
| "typescript": "^3.7.4" | |||
| }, | |||
| "jest": { | |||
| "moduleFileExtensions": [ | |||
| "js", | |||
| "json", | |||
| "ts" | |||
| ], | |||
| "rootDir": "src", | |||
| "testRegex": ".spec.ts$", | |||
| "transform": { | |||
| "^.+\\.(t|j)s$": "ts-jest" | |||
| }, | |||
| "coverageDirectory": "../coverage", | |||
| "testEnvironment": "node" | |||
| } | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| import { Episode } from "schemas/entity/episode.entity"; | |||
| export class CreateEpisodeDto extends Episode { | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | |||
| import Podcast from 'podcast'; | |||
| import { Document } from 'mongoose'; | |||
| export type EpisodeEnclosureDocument = EpisodeEnclosure & Document; | |||
| @Schema() | |||
| export class EpisodeEnclosure implements Podcast.ItemEnclosure { | |||
| @Prop() | |||
| url: string; | |||
| @Prop() | |||
| file?: string; | |||
| @Prop() | |||
| size?: number; | |||
| @Prop() | |||
| type?: string; | |||
| } | |||
| export const EpisodeEnclosureSchema = SchemaFactory.createForClass( | |||
| EpisodeEnclosure, | |||
| ); | |||
| @@ -0,0 +1,55 @@ | |||
| import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | |||
| import Podcast from 'podcast'; | |||
| import { ItunesEpisodeTypeEnum } from 'schemas/enum/itunes-episode-type.enum'; | |||
| import { EpisodeEnclosure } from './episode-enclosure'; | |||
| import { Document } from 'mongoose'; | |||
| export type EpisodeDocument = Episode & Document; | |||
| @Schema() | |||
| export class Episode implements Podcast.Item { | |||
| @Prop() | |||
| title?: string; | |||
| @Prop() | |||
| description?: string; | |||
| @Prop() | |||
| url: string; | |||
| @Prop() | |||
| guid?: string; | |||
| @Prop([String]) | |||
| categories?: string[]; | |||
| @Prop() | |||
| author?: string; | |||
| @Prop() | |||
| date: Date; | |||
| @Prop() | |||
| lat?: number; | |||
| @Prop() | |||
| long?: number; | |||
| @Prop(EpisodeEnclosure) | |||
| enclosure?: EpisodeEnclosure; | |||
| @Prop() | |||
| content?: string; | |||
| @Prop() | |||
| itunesAuthor?: string; | |||
| @Prop() | |||
| itunesExplicit?: boolean; | |||
| @Prop() | |||
| itunesSubtitle?: string; | |||
| @Prop() | |||
| itunesSummary?: string; | |||
| @Prop() | |||
| itunesDuration?: number; | |||
| @Prop() | |||
| itunesImage?: string; | |||
| @Prop() | |||
| itunesSeason?: number; | |||
| @Prop() | |||
| itunesEpisode?: number; | |||
| @Prop() | |||
| itunesTitle?: string; | |||
| @Prop(ItunesEpisodeTypeEnum) | |||
| itunesEpisodeType?: ItunesEpisodeTypeEnum; | |||
| } | |||
| export const EpisodeSchema = SchemaFactory.createForClass(Episode); | |||
| @@ -0,0 +1,5 @@ | |||
| export enum ItunesEpisodeTypeEnum { | |||
| FULL = "full", | |||
| TRAILER = "trailer", | |||
| BONUS = "bonus", | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| import { Test, TestingModule } from '@nestjs/testing'; | |||
| import { AppController } from './app.controller'; | |||
| import { AppService } from './app.service'; | |||
| describe('AppController', () => { | |||
| let appController: AppController; | |||
| beforeEach(async () => { | |||
| const app: TestingModule = await Test.createTestingModule({ | |||
| controllers: [AppController], | |||
| providers: [AppService], | |||
| }).compile(); | |||
| appController = app.get<AppController>(AppController); | |||
| }); | |||
| describe('root', () => { | |||
| it('should return "Hello World!"', () => { | |||
| expect(appController.getHello()).toBe('Hello World!'); | |||
| }); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,14 @@ | |||
| import { Module } from '@nestjs/common'; | |||
| import { MongooseModule } from '@nestjs/mongoose'; | |||
| import { Episode, EpisodeSchema } from 'schemas/entity/episode.entity'; | |||
| import { AppService } from './app.service'; | |||
| import { EpisodeService } from './episode/episode.service'; | |||
| @Module({ | |||
| imports: [ | |||
| MongooseModule.forFeature([{ name: Episode.name, schema: EpisodeSchema }]), | |||
| MongooseModule.forRoot('mongodb://localhost:27017/test') | |||
| ], | |||
| providers: [AppService, EpisodeService], | |||
| }) | |||
| export class AppModule {} | |||
| @@ -0,0 +1,8 @@ | |||
| import { Injectable } from '@nestjs/common'; | |||
| @Injectable() | |||
| export class AppService { | |||
| getHello(): string { | |||
| return 'Hello World!'; | |||
| } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| import { Test, TestingModule } from '@nestjs/testing'; | |||
| import { EpisodeService } from './episode.service'; | |||
| describe('EpisodeService', () => { | |||
| let service: EpisodeService; | |||
| beforeEach(async () => { | |||
| const module: TestingModule = await Test.createTestingModule({ | |||
| providers: [EpisodeService], | |||
| }).compile(); | |||
| service = module.get<EpisodeService>(EpisodeService); | |||
| }); | |||
| it('should be defined', () => { | |||
| expect(service).toBeDefined(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,20 @@ | |||
| import { Injectable } from '@nestjs/common'; | |||
| import { InjectModel } from '@nestjs/mongoose'; | |||
| import { Model } from 'mongoose'; | |||
| import { CreateEpisodeDto } from 'schemas/dto/create-episode.dto'; | |||
| import { Episode, EpisodeDocument } from 'schemas/entity/episode.entity'; | |||
| @Injectable() | |||
| export class EpisodeService { | |||
| constructor( | |||
| @InjectModel(Episode.name) private episodeModel: Model<EpisodeDocument>, | |||
| ) {} | |||
| async create(createEpisodeDto: CreateEpisodeDto): Promise<Episode> { | |||
| const createdEpisode = new this.episodeModel(createEpisodeDto); | |||
| return createdEpisode.save(); | |||
| } | |||
| async findAll(): Promise<Episode[]> { | |||
| return this.episodeModel.find().exec(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| import { NestFactory } from '@nestjs/core'; | |||
| import { AppModule } from './app.module'; | |||
| async function bootstrap() { | |||
| const app = await NestFactory.create(AppModule); | |||
| await app.listen(3000); | |||
| } | |||
| bootstrap(); | |||
| @@ -0,0 +1,24 @@ | |||
| import { Test, TestingModule } from '@nestjs/testing'; | |||
| import { INestApplication } from '@nestjs/common'; | |||
| import * as request from 'supertest'; | |||
| import { AppModule } from './../src/app.module'; | |||
| describe('AppController (e2e)', () => { | |||
| let app: INestApplication; | |||
| beforeEach(async () => { | |||
| const moduleFixture: TestingModule = await Test.createTestingModule({ | |||
| imports: [AppModule], | |||
| }).compile(); | |||
| app = moduleFixture.createNestApplication(); | |||
| await app.init(); | |||
| }); | |||
| it('/ (GET)', () => { | |||
| return request(app.getHttpServer()) | |||
| .get('/') | |||
| .expect(200) | |||
| .expect('Hello World!'); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,9 @@ | |||
| { | |||
| "moduleFileExtensions": ["js", "json", "ts"], | |||
| "rootDir": ".", | |||
| "testEnvironment": "node", | |||
| "testRegex": ".e2e-spec.ts$", | |||
| "transform": { | |||
| "^.+\\.(t|j)s$": "ts-jest" | |||
| } | |||
| } | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| "extends": "./tsconfig.json", | |||
| "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| { | |||
| "compilerOptions": { | |||
| "module": "commonjs", | |||
| "declaration": true, | |||
| "removeComments": true, | |||
| "emitDecoratorMetadata": true, | |||
| "experimentalDecorators": true, | |||
| "allowSyntheticDefaultImports": true, | |||
| "target": "es2017", | |||
| "sourceMap": true, | |||
| "outDir": "./dist", | |||
| "baseUrl": "./", | |||
| "incremental": true | |||
| } | |||
| } | |||