[
  {
    "path": ".gitignore",
    "content": "# compiled output\n/dist\n/node_modules\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# OS\n.DS_Store\n\n# Tests\n/coverage\n/.nyc_output\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n.env"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}"
  },
  {
    "path": "README.md",
    "content": " <p align=\"center\">A progressive <a href=\"http://nodejs.org\" target=\"blank\">Node.js</a> framework for building efficient and scalable server-side applications, heavily inspired by <a href=\"https://angular.io\" target=\"blank\">Angular</a>.\n </p>\n\n## Description\nA Simple CRUD Web API with NestJs, Postgres, Sequelize ORM. \n\n## Installation\n\n```bash\n$ git clone https://github.com/onwuvic/nest-blog-api.git\n```\n\n## Running the app\n\n- cd into `nest-blog-api`\n- run `npm install`\n- set up your postgres database\n- rename `.env.sample` to `.env` and populate the required parameters\n- run `npm run start:dev`\n\n```bash\n# development\n$ npm run start\n\n# watch mode\n$ npm run start:dev\n\n# production mode\n$ npm run start:prod\n```\n\n\n## Stay in touch\n\n- Author - Victor Onwuzor\n- Twitter - [@victoronwuzor](https://twitter.com/victoronwuzor)\n\n## License\n[MIT licensed](LICENSE).\n"
  },
  {
    "path": "nest-cli.json",
    "content": "{\n  \"language\": \"ts\",\n  \"collection\": \"@nestjs/schematics\",\n  \"sourceRoot\": \"src\"\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"nest-blog-api\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsc -p tsconfig.build.json\",\n    \"format\": \"prettier --write \\\"src/**/*.ts\\\"\",\n    \"start\": \"ts-node -r tsconfig-paths/register src/main.ts\",\n    \"start:dev\": \"tsc-watch -p tsconfig.build.json --onSuccess \\\"node dist/main.js\\\"\",\n    \"start:debug\": \"tsc-watch -p tsconfig.build.json --onSuccess \\\"node --inspect-brk dist/main.js\\\"\",\n    \"start:prod\": \"node dist/main.js\",\n    \"lint\": \"tslint -p tsconfig.json -c tslint.json\",\n    \"test\": \"jest\",\n    \"test:watch\": \"jest --watch\",\n    \"test:cov\": \"jest --coverage\",\n    \"test:debug\": \"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand\",\n    \"test:e2e\": \"jest --config ./test/jest-e2e.json\"\n  },\n  \"dependencies\": {\n    \"@nestjs/common\": \"^6.0.0\",\n    \"@nestjs/config\": \"0.4.0\",\n    \"@nestjs/core\": \"^6.0.0\",\n    \"@nestjs/jwt\": \"7.0.0\",\n    \"@nestjs/passport\": \"7.0.0\",\n    \"@nestjs/platform-express\": \"^6.0.0\",\n    \"bcrypt\": \"^5.0.0\",\n    \"class-transformer\": \"0.2.3\",\n    \"class-validator\": \"0.12.2\",\n    \"dotenv\": \"8.2.0\",\n    \"passport\": \"0.4.1\",\n    \"passport-jwt\": \"4.0.0\",\n    \"passport-local\": \"1.0.0\",\n    \"pg\": \"7.18.2\",\n    \"pg-hstore\": \"2.3.3\",\n    \"reflect-metadata\": \"^0.1.12\",\n    \"rimraf\": \"^2.6.2\",\n    \"rxjs\": \"^6.3.3\",\n    \"sequelize\": \"5.21.5\",\n    \"sequelize-typescript\": \"1.1.0\"\n  },\n  \"devDependencies\": {\n    \"@nestjs/testing\": \"^6.0.0\",\n    \"@types/express\": \"4.16.1\",\n    \"@types/jest\": \"24.0.11\",\n    \"@types/node\": \"11.13.4\",\n    \"@types/passport-jwt\": \"3.0.3\",\n    \"@types/passport-local\": \"1.0.33\",\n    \"@types/sequelize\": \"4.28.8\",\n    \"@types/supertest\": \"2.0.7\",\n    \"jest\": \"24.7.1\",\n    \"prettier\": \"1.17.0\",\n    \"supertest\": \"4.0.2\",\n    \"ts-jest\": \"^26.4.1\",\n    \"ts-node\": \"8.1.0\",\n    \"tsc-watch\": \"2.2.1\",\n    \"tsconfig-paths\": \"3.8.0\",\n    \"tslint\": \"5.16.0\",\n    \"typescript\": \"3.7.2\"\n  },\n  \"jest\": {\n    \"moduleFileExtensions\": [\n      \"js\",\n      \"json\",\n      \"ts\"\n    ],\n    \"rootDir\": \"src\",\n    \"testRegex\": \".spec.ts$\",\n    \"transform\": {\n      \"^.+\\\\.(t|j)s$\": \"ts-jest\"\n    },\n    \"coverageDirectory\": \"../coverage\",\n    \"testEnvironment\": \"node\"\n  }\n}\n"
  },
  {
    "path": "src/app.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\n\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\n\ndescribe('AppController', () => {\n  let appController: AppController;\n\n  beforeEach(async () => {\n    const app: TestingModule = await Test.createTestingModule({\n      controllers: [AppController],\n      providers: [AppService],\n    }).compile();\n\n    appController = app.get<AppController>(AppController);\n  });\n\n  describe('root', () => {\n    it('should return \"Hello World!\"', () => {\n      expect(appController.getHello()).toBe('Hello World!');\n    });\n  });\n});\n"
  },
  {
    "path": "src/app.controller.ts",
    "content": "import { Controller, Get } from '@nestjs/common';\n\nimport { AppService } from './app.service';\n\n@Controller()\nexport class AppController {\n  constructor(private readonly appService: AppService) {}\n\n  @Get()\n  getHello(): string {\n    return this.appService.getHello();\n  }\n}\n"
  },
  {
    "path": "src/app.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { ConfigModule } from '@nestjs/config';\n\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\nimport { DatabaseModule } from './core/database/database.module';\nimport { UsersModule } from './modules/users/users.module';\nimport { AuthModule } from './modules/auth/auth.module';\nimport { PostsModule } from './modules/posts/posts.module';\n\n@Module({\n  imports: [\n    ConfigModule.forRoot({ isGlobal: true }),\n    DatabaseModule,\n    UsersModule,\n    AuthModule,\n    PostsModule,\n  ],\n  controllers: [AppController],\n  providers: [AppService],\n})\nexport class AppModule {}\n"
  },
  {
    "path": "src/app.service.ts",
    "content": "import { Injectable } from '@nestjs/common';\n\n@Injectable()\nexport class AppService {\n  getHello(): string {\n    return 'Hello World!';\n  }\n}\n"
  },
  {
    "path": "src/core/constants/index.ts",
    "content": "export const SEQUELIZE = 'SEQUELIZE';\nexport const DEVELOPMENT = 'development';\nexport const TEST = 'test';\nexport const PRODUCTION = 'production';\nexport const USER_REPOSITORY = 'USER_REPOSITORY';\nexport const POST_REPOSITORY = 'POST_REPOSITORY';\n"
  },
  {
    "path": "src/core/database/database.config.ts",
    "content": "import * as dotenv from 'dotenv';\n\nimport { IDatabaseConfig } from './interfaces/dbConfig.interface';\n\ndotenv.config();\n\nexport const databaseConfig: IDatabaseConfig = {\n    development: {\n        username: process.env.DB_USER,\n        password: process.env.DB_PASS,\n        database: process.env.DB_NAME_DEVELOPMENT,\n        host: process.env.DB_HOST,\n        port: process.env.DB_PORT,\n        dialect: process.env.DB_DIALECT,\n    },\n    test: {\n        username: process.env.DB_USER,\n        password: process.env.DB_PASS,\n        database: process.env.DB_NAME_TEST,\n        host: process.env.DB_HOST,\n        port: process.env.DB_PORT,\n        dialect: process.env.DB_DIALECT,\n    },\n    production: {\n        username: process.env.DB_USER,\n        password: process.env.DB_PASS,\n        database: process.env.DB_NAME_PRODUCTION,\n        host: process.env.DB_HOST,\n        dialect: process.env.DB_DIALECT,\n    },\n};\n"
  },
  {
    "path": "src/core/database/database.module.ts",
    "content": "import { Module } from '@nestjs/common';\n\nimport { databaseProviders } from './database.providers';\n\n@Module({\n    providers: [...databaseProviders],\n    exports: [...databaseProviders],\n})\nexport class DatabaseModule { }\n"
  },
  {
    "path": "src/core/database/database.providers.ts",
    "content": "import { Sequelize } from 'sequelize-typescript';\n\nimport { SEQUELIZE, DEVELOPMENT, TEST, PRODUCTION } from '../constants';\nimport { databaseConfig } from './database.config';\nimport { User } from '../../modules/users/user.entity';\nimport { Post } from '../../modules/posts/post.entity';\n\nexport const databaseProviders = [\n    {\n        provide: SEQUELIZE,\n        useFactory: async () => {\n            let config;\n            switch (process.env.NODE_ENV) {\n                case DEVELOPMENT:\n                    config = databaseConfig.development;\n                    break;\n                case TEST:\n                    config = databaseConfig.test;\n                    break;\n                case PRODUCTION:\n                    config = databaseConfig.production;\n                    break;\n                default:\n                    config = databaseConfig.development;\n            }\n            const sequelize = new Sequelize(config);\n            sequelize.addModels([User, Post]);\n            await sequelize.sync();\n            return sequelize;\n        },\n    },\n];\n"
  },
  {
    "path": "src/core/database/interfaces/dbConfig.interface.ts",
    "content": "export interface IDatabaseConfigAttributes {\n    username?: string;\n    password?: string;\n    database?: string;\n    host?: string;\n    port?: number | string;\n    dialect?: string;\n    urlDatabase?: string;\n}\n\nexport interface IDatabaseConfig {\n    development: IDatabaseConfigAttributes;\n    test: IDatabaseConfigAttributes;\n    production: IDatabaseConfigAttributes;\n}"
  },
  {
    "path": "src/core/guards/doesUserExist.guard.ts",
    "content": "import { CanActivate, ExecutionContext, Injectable, ForbiddenException } from '@nestjs/common';\nimport { Observable } from 'rxjs';\n\nimport { UsersService } from '../../modules/users/users.service';\n\n@Injectable()\nexport class DoesUserExist implements CanActivate {\n    constructor(private readonly userService: UsersService) { }\n\n    canActivate(\n        context: ExecutionContext,\n    ): boolean | Promise<boolean> | Observable<boolean> {\n        const request = context.switchToHttp().getRequest();\n        return this.validateRequest(request);\n    }\n\n    async validateRequest(request) {\n        const userExist = await this.userService.findOneByEmail(request.body.email);\n        if (userExist) {\n            throw new ForbiddenException('This email already exist');\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/core/pipes/validate.pipe.ts",
    "content": "import { Injectable, ArgumentMetadata, BadRequestException, ValidationPipe, UnprocessableEntityException } from '@nestjs/common';\n\n@Injectable()\nexport class ValidateInputPipe extends ValidationPipe {\n    public async transform(value, metadata: ArgumentMetadata) {\n        try {\n            return await super.transform(value, metadata);\n        } catch (e) {\n            if (e instanceof BadRequestException) {\n                throw new UnprocessableEntityException(this.handleError(e.message.message));\n            }\n        }\n    }\n\n    private handleError(errors) {\n        return errors.map(error => error.constraints);\n    }\n}\n"
  },
  {
    "path": "src/main.ts",
    "content": "import { NestFactory } from '@nestjs/core';\n\nimport { AppModule } from './app.module';\nimport { ValidateInputPipe } from './core/pipes/validate.pipe';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n  app.setGlobalPrefix('api/v1');\n  // handle all user input validation globally\n  app.useGlobalPipes(new ValidateInputPipe());\n  await app.listen(3000);\n}\nbootstrap();\n"
  },
  {
    "path": "src/modules/auth/auth.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\n\nimport { AuthController } from './auth.controller';\n\ndescribe('Auth Controller', () => {\n  let controller: AuthController;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      controllers: [AuthController],\n    }).compile();\n\n    controller = module.get<AuthController>(AuthController);\n  });\n\n  it('should be defined', () => {\n    expect(controller).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "src/modules/auth/auth.controller.ts",
    "content": "import { Controller, Body, Post, UseGuards, Request } from '@nestjs/common';\nimport { AuthGuard } from '@nestjs/passport';\n\nimport { AuthService } from './auth.service';\nimport { UserDto } from '../users/dto/user.dto';\nimport { DoesUserExist } from '../../core/guards/doesUserExist.guard';\n\n@Controller('auth')\nexport class AuthController {\n    constructor(private authService: AuthService) { }\n\n    @UseGuards(AuthGuard('local'))\n    @Post('login')\n    async login(@Request() req) {\n        return await this.authService.login(req.user);\n    }\n\n    @UseGuards(DoesUserExist)\n    @Post('signup')\n    async signUp(@Body() user: UserDto) {\n        return await this.authService.create(user);\n    }\n}\n"
  },
  {
    "path": "src/modules/auth/auth.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { PassportModule } from '@nestjs/passport';\nimport { JwtModule } from '@nestjs/jwt';\n\nimport { AuthService } from './auth.service';\nimport { AuthController } from './auth.controller';\nimport { UsersModule } from '../users/users.module';\nimport { LocalStrategy } from './local.strategy';\nimport { JwtStrategy } from './jwt.strategy';\n\n@Module({\n  imports: [\n    PassportModule,\n    UsersModule,\n    JwtModule.register({\n      secret: process.env.JWTKEY,\n      signOptions: { expiresIn: process.env.TOKEN_EXPIRATION },\n    }),\n  ],\n  providers: [\n    AuthService,\n    LocalStrategy,\n    JwtStrategy,\n  ],\n  controllers: [AuthController],\n})\nexport class AuthModule {}\n"
  },
  {
    "path": "src/modules/auth/auth.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\n\nimport { AuthService } from './auth.service';\n\ndescribe('AuthService', () => {\n  let service: AuthService;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      providers: [AuthService],\n    }).compile();\n\n    service = module.get<AuthService>(AuthService);\n  });\n\n  it('should be defined', () => {\n    expect(service).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "src/modules/auth/auth.service.ts",
    "content": "import { Injectable } from '@nestjs/common';\nimport * as bcrypt from 'bcrypt';\nimport { JwtService } from '@nestjs/jwt';\n\nimport { UsersService } from '../users/users.service';\n\n@Injectable()\nexport class AuthService {\n    constructor(\n        private readonly userService: UsersService,\n        private readonly jwtService: JwtService,\n    ) { }\n\n    async validateUser(username: string, pass: string) {\n        // find if user exist with this email\n        const user = await this.userService.findOneByEmail(username);\n        if (!user) {\n            return null;\n        }\n\n        // find if user password match\n        const match = await this.comparePassword(pass, user.password);\n\n        if (!match) {\n            return null;\n        }\n\n        // tslint:disable-next-line: no-string-literal\n        const { password, ...result } = user['dataValues'];\n        return result;\n    }\n\n    public async login(user) {\n        const token = await this.generateToken(user);\n        return { user, token };\n    }\n\n    public async create(user) {\n        // hash the password\n        const pass = await this.hashPassword(user.password);\n\n        // create the user\n        const newUser = await this.userService.create({ ...user, password: pass });\n\n        // tslint:disable-next-line: no-string-literal\n        const { password, ...result } = newUser['dataValues'];\n\n        // generate token\n        const token = await this.generateToken(result);\n\n        // return the user and the token\n        return { user: result, token };\n    }\n\n    private async generateToken(user) {\n        const token = await this.jwtService.signAsync(user);\n        return token;\n    }\n\n    private async hashPassword(password) {\n        const hash = await bcrypt.hash(password, 10);\n        return hash;\n    }\n\n    private async comparePassword(enteredPassword, dbPassword) {\n        const match = await bcrypt.compare(enteredPassword, dbPassword);\n        return match;\n    }\n}\n"
  },
  {
    "path": "src/modules/auth/jwt.strategy.ts",
    "content": "import { ExtractJwt, Strategy } from 'passport-jwt';\nimport { PassportStrategy } from '@nestjs/passport';\nimport { Injectable, UnauthorizedException } from '@nestjs/common';\n\nimport { UsersService } from '../users/users.service';\n\n@Injectable()\nexport class JwtStrategy extends PassportStrategy(Strategy) {\n    constructor(private readonly userService: UsersService) {\n        super({\n            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),\n            ignoreExpiration: false,\n            secretOrKey: process.env.JWTKEY,\n        });\n    }\n\n    async validate(payload: any) {\n        // check if user in the token actually exist\n        const user = await this.userService.findOneById(payload.id);\n        if (!user) {\n            throw new UnauthorizedException('You are not authorized to perform the operation');\n        }\n        return payload;\n    }\n}\n"
  },
  {
    "path": "src/modules/auth/local.strategy.ts",
    "content": "import { Strategy } from 'passport-local';\nimport { PassportStrategy } from '@nestjs/passport';\nimport { Injectable, UnauthorizedException } from '@nestjs/common';\n\nimport { AuthService } from './auth.service';\n\n@Injectable()\nexport class LocalStrategy extends PassportStrategy(Strategy) {\n    constructor(private readonly authService: AuthService) {\n        super();\n    }\n\n    async validate(username: string, password: string): Promise<any> {\n        const user = await this.authService.validateUser(username, password);\n        if (!user) {\n            throw new UnauthorizedException('Invalid user credentials');\n        }\n        return user;\n    }\n}\n"
  },
  {
    "path": "src/modules/posts/dto/post.dto.ts",
    "content": "import { IsNotEmpty, MinLength } from 'class-validator';\n\nexport class PostDto {\n\n    @IsNotEmpty()\n    @MinLength(4)\n    readonly title: string;\n\n    @IsNotEmpty()\n    readonly body: string;\n}\n"
  },
  {
    "path": "src/modules/posts/post.entity.ts",
    "content": "import { Table, Column, Model, DataType, ForeignKey, BelongsTo } from 'sequelize-typescript';\n\nimport { User } from '../users/user.entity';\n\n@Table\nexport class Post extends Model<Post> {\n    @Column({\n        type: DataType.STRING,\n        allowNull: false,\n    })\n    title: string;\n\n    @Column({\n        type: DataType.TEXT,\n        allowNull: false,\n    })\n    body: string;\n\n    @ForeignKey(() => User)\n    @Column({\n        type: DataType.INTEGER,\n        allowNull: false,\n    })\n    userId: number;\n\n    @BelongsTo(() => User)\n    user: User;\n}\n"
  },
  {
    "path": "src/modules/posts/posts.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\n\nimport { PostsController } from './posts.controller';\n\ndescribe('Posts Controller', () => {\n  let controller: PostsController;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      controllers: [PostsController],\n    }).compile();\n\n    controller = module.get<PostsController>(PostsController);\n  });\n\n  it('should be defined', () => {\n    expect(controller).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "src/modules/posts/posts.controller.ts",
    "content": "import { Controller, Get, Post, Put, Delete, Param, Body, NotFoundException, UseGuards, Request } from '@nestjs/common';\nimport { AuthGuard } from '@nestjs/passport';\n\nimport { PostsService } from './posts.service';\nimport { Post as PostEntity } from './post.entity';\nimport { PostDto } from './dto/post.dto';\n\n@Controller('posts')\nexport class PostsController {\n    constructor(private readonly postService: PostsService) { }\n\n    @Get()\n    async findAll() {\n        // get all posts in the db\n        return await this.postService.findAll();\n    }\n\n    @Get(':id')\n    async findOne(@Param('id') id: number): Promise<PostEntity> {\n        // find the post with this id\n        const post = await this.postService.findOne(id);\n\n        // if the post doesn't exit in the db, throw a 404 error\n        if (!post) {\n            throw new NotFoundException('This Post doesn\\'t exist');\n        }\n\n        // if post exist, return the post\n        return post;\n    }\n\n    @UseGuards(AuthGuard('jwt'))\n    @Post()\n    async create(@Body() post: PostDto, @Request() req): Promise<PostEntity> {\n        // create a new post and return the newly created post\n        return await this.postService.create(post, req.user.id);\n    }\n\n    @UseGuards(AuthGuard('jwt'))\n    @Put(':id')\n    async update(@Param('id') id: number, @Body() post: PostDto, @Request() req): Promise<PostEntity> {\n        // get the number of row affected and the updated post\n        const { numberOfAffectedRows, updatedPost } = await this.postService.update(id, post, req.user.id);\n\n        // if the number of row affected is zero, it means the post doesn't exist in our db\n        if (numberOfAffectedRows === 0) {\n            throw new NotFoundException('This Post doesn\\'t exist');\n        }\n\n        // return the updated post\n        return updatedPost;\n    }\n\n    @UseGuards(AuthGuard('jwt'))\n    @Delete(':id')\n    async remove(@Param('id') id: number, @Request() req) {\n        // delete the post with this id\n        const deleted = await this.postService.delete(id, req.user.id);\n\n        // if the number of row affected is zero, then the post doesn't exist in our db\n        if (deleted === 0) {\n            throw new NotFoundException('This Post doesn\\'t exist');\n        }\n\n        // return success message\n        return 'Successfully deleted';\n    }\n}\n"
  },
  {
    "path": "src/modules/posts/posts.module.ts",
    "content": "import { Module } from '@nestjs/common';\n\nimport { PostsService } from './posts.service';\nimport { PostsController } from './posts.controller';\nimport { postsProviders } from './posts.providers';\n\n@Module({\n  providers: [PostsService, ...postsProviders],\n  controllers: [PostsController],\n})\nexport class PostsModule {}\n"
  },
  {
    "path": "src/modules/posts/posts.providers.ts",
    "content": "import { Post } from './post.entity';\nimport { POST_REPOSITORY } from '../../core/constants';\n\nexport const postsProviders = [\n    {\n        provide: POST_REPOSITORY,\n        useValue: Post,\n    },\n];\n"
  },
  {
    "path": "src/modules/posts/posts.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\n\nimport { PostsService } from './posts.service';\n\ndescribe('PostsService', () => {\n  let service: PostsService;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      providers: [PostsService],\n    }).compile();\n\n    service = module.get<PostsService>(PostsService);\n  });\n\n  it('should be defined', () => {\n    expect(service).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "src/modules/posts/posts.service.ts",
    "content": "import { Injectable, Inject } from '@nestjs/common';\n\nimport { Post } from './post.entity';\nimport { PostDto } from './dto/post.dto';\nimport { User } from '../users/user.entity';\nimport { POST_REPOSITORY } from '../../core/constants';\n\n@Injectable()\nexport class PostsService {\n    constructor(@Inject(POST_REPOSITORY) private readonly postRepository: typeof Post) { }\n\n    async create(post: PostDto, userId): Promise<Post> {\n        return await this.postRepository.create<Post>({ ...post, userId });\n    }\n\n    async findAll(): Promise<Post[]> {\n        return await this.postRepository.findAll<Post>({\n            include: [{ model: User, attributes: { exclude: ['password'] } }],\n        });\n    }\n\n    async findOne(id): Promise<Post> {\n        return await this.postRepository.findOne({\n            where: { id },\n            include: [{ model: User, attributes: { exclude: ['password'] } }],\n        });\n    }\n\n    async delete(id, userId) {\n        return await this.postRepository.destroy({ where: { id, userId } });\n    }\n\n    async update(id, data, userId) {\n        const [numberOfAffectedRows, [updatedPost]] = await this.postRepository.update({ ...data }, { where: { id, userId }, returning: true });\n        return { numberOfAffectedRows, updatedPost };\n    }\n}\n"
  },
  {
    "path": "src/modules/users/dto/user.dto.ts",
    "content": "import { IsNotEmpty, MinLength, IsEmail, IsEnum } from 'class-validator';\n\nenum Gender {\n    MALE = 'male',\n    FEMALE = 'female',\n}\n\nexport class UserDto {\n\n    @IsNotEmpty()\n    readonly name: string;\n\n    @IsNotEmpty()\n    @IsEmail()\n    readonly email: string;\n\n    @IsNotEmpty()\n    @MinLength(6)\n    readonly password: string;\n\n    @IsNotEmpty()\n    @IsEnum(Gender, {\n        message: 'gender must be either male or female',\n    })\n    readonly gender: Gender;\n}\n"
  },
  {
    "path": "src/modules/users/user.entity.ts",
    "content": "import { Table, Column, Model, DataType } from 'sequelize-typescript';\n\n@Table\nexport class User extends Model<User> {\n    @Column({\n        type: DataType.STRING,\n        allowNull: false,\n    })\n    name: string;\n    @Column({\n        type: DataType.STRING,\n        unique: true,\n        allowNull: false,\n    })\n    email: string;\n    @Column({\n        type: DataType.STRING,\n        allowNull: false,\n    })\n    password: string;\n    @Column({\n        type: DataType.ENUM,\n        values: ['male', 'female'],\n        allowNull: false,\n    })\n    gender: string;\n}\n"
  },
  {
    "path": "src/modules/users/users.module.ts",
    "content": "import { Module } from '@nestjs/common';\n\nimport { UsersService } from './users.service';\nimport { usersProviders } from './users.providers';\n\n@Module({\n  providers: [UsersService, ...usersProviders],\n  exports: [UsersService],\n})\nexport class UsersModule {}\n"
  },
  {
    "path": "src/modules/users/users.providers.ts",
    "content": "import { User } from './user.entity';\nimport { USER_REPOSITORY } from '../../core/constants';\n\nexport const usersProviders = [\n    {\n        provide: USER_REPOSITORY,\n        useValue: User,\n    },\n];\n"
  },
  {
    "path": "src/modules/users/users.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\n\nimport { UsersService } from './users.service';\n\ndescribe('UsersService', () => {\n  let service: UsersService;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      providers: [UsersService],\n    }).compile();\n\n    service = module.get<UsersService>(UsersService);\n  });\n\n  it('should be defined', () => {\n    expect(service).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "src/modules/users/users.service.ts",
    "content": "import { Injectable, Inject } from '@nestjs/common';\n\nimport { User } from './user.entity';\nimport { UserDto } from './dto/user.dto';\nimport { USER_REPOSITORY } from '../../core/constants';\n\n@Injectable()\nexport class UsersService {\n    constructor(@Inject(USER_REPOSITORY) private readonly userRepository: typeof User) { }\n\n    async create(user: UserDto): Promise<User> {\n        return await this.userRepository.create<User>(user);\n    }\n\n    async findOneByEmail(email: string): Promise<User> {\n        return await this.userRepository.findOne<User>({ where: { email } });\n    }\n\n    async findOneById(id: number): Promise<User> {\n        return await this.userRepository.findOne<User>({ where: { id } });\n    }\n\n}\n"
  },
  {
    "path": "test/app.e2e-spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport * as request from 'supertest';\nimport { AppModule } from './../src/app.module';\n\ndescribe('AppController (e2e)', () => {\n  let app;\n\n  beforeEach(async () => {\n    const moduleFixture: TestingModule = await Test.createTestingModule({\n      imports: [AppModule],\n    }).compile();\n\n    app = moduleFixture.createNestApplication();\n    await app.init();\n  });\n\n  it('/ (GET)', () => {\n    return request(app.getHttpServer())\n      .get('/')\n      .expect(200)\n      .expect('Hello World!');\n  });\n});\n"
  },
  {
    "path": "test/jest-e2e.json",
    "content": "{\n  \"moduleFileExtensions\": [\"js\", \"json\", \"ts\"],\n  \"rootDir\": \".\",\n  \"testEnvironment\": \"node\",\n  \"testRegex\": \".e2e-spec.ts$\",\n  \"transform\": {\n    \"^.+\\\\.(t|j)s$\": \"ts-jest\"\n  }\n}\n"
  },
  {
    "path": "tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"exclude\": [\"node_modules\", \"test\", \"dist\", \"**/*spec.ts\"]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"removeComments\": true,\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"target\": \"es2017\",\n    \"sourceMap\": true,\n    \"outDir\": \"./dist\",\n    \"baseUrl\": \"./\",\n    \"incremental\": true\n  },\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  },
  {
    "path": "tslint.json",
    "content": "{\n  \"defaultSeverity\": \"error\",\n  \"extends\": [\"tslint:recommended\"],\n  \"jsRules\": {\n    \"no-unused-expression\": true\n  },\n  \"rules\": {\n    \"quotemark\": [true, \"single\"],\n    \"member-access\": [false],\n    \"ordered-imports\": [false],\n    \"max-line-length\": [true, 150],\n    \"member-ordering\": [false],\n    \"interface-name\": [false],\n    \"arrow-parens\": false,\n    \"object-literal-sort-keys\": false\n  },\n  \"rulesDirectory\": []\n}\n"
  }
]