[
  {
    "path": ".gitignore",
    "content": "\n# Created by https://www.gitignore.io/api/node,windows,visualstudiocode\n# Edit at https://www.gitignore.io/?templates=node,windows,visualstudiocode\n\n### Node ###\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n.env.test\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# next.js build output\n.next\n\n# nuxt.js build output\n.nuxt\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless/\n\n# FuseBox cache\n.fusebox/\n\n# DynamoDB Local files\n.dynamodb/\n\n### VisualStudioCode ###\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n### VisualStudioCode Patch ###\n# Ignore all local history of files\n.history\n\n### Windows ###\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Dump file\n*.stackdump\n\n# Folder config file\n[Dd]esktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n# End of https://www.gitignore.io/api/node,windows,visualstudiocode\n\ndist/\n\n.DS_Store"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"name\": \"Launch Program\",\n            \"program\": \"${workspaceFolder}/server/src/auth/auth.module.ts\",\n            \"outFiles\": [\n                \"${workspaceFolder}/**/*.js\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": "README.md",
    "content": "# nestjs-todo-app\nA full stack application written in Nest.js, Angular and PostgreSQL.\n"
  },
  {
    "path": "server/.gitignore",
    "content": ".idea/\n.vscode/\n.DS_Store\nnode_modules/\nbuild/\ntmp/\ntemp/"
  },
  {
    "path": "server/.prettierrc",
    "content": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}"
  },
  {
    "path": "server/README.md",
    "content": "<p align=\"center\">\n  <a href=\"http://nestjs.com/\" target=\"blank\"><img src=\"https://nestjs.com/img/logo_text.svg\" width=\"320\" alt=\"Nest Logo\" /></a>\n</p>\n\n[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master\n[travis-url]: https://travis-ci.org/nestjs/nest\n[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux\n[linux-url]: https://travis-ci.org/nestjs/nest\n  \n  <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>.</p>\n    <p align=\"center\">\n<a href=\"https://www.npmjs.com/~nestjscore\"><img src=\"https://img.shields.io/npm/v/@nestjs/core.svg\" alt=\"NPM Version\" /></a>\n<a href=\"https://www.npmjs.com/~nestjscore\"><img src=\"https://img.shields.io/npm/l/@nestjs/core.svg\" alt=\"Package License\" /></a>\n<a href=\"https://www.npmjs.com/~nestjscore\"><img src=\"https://img.shields.io/npm/dm/@nestjs/core.svg\" alt=\"NPM Downloads\" /></a>\n<a href=\"https://travis-ci.org/nestjs/nest\"><img src=\"https://api.travis-ci.org/nestjs/nest.svg?branch=master\" alt=\"Travis\" /></a>\n<a href=\"https://travis-ci.org/nestjs/nest\"><img src=\"https://img.shields.io/travis/nestjs/nest/master.svg?label=linux\" alt=\"Linux\" /></a>\n<a href=\"https://coveralls.io/github/nestjs/nest?branch=master\"><img src=\"https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#5\" alt=\"Coverage\" /></a>\n<a href=\"https://gitter.im/nestjs/nestjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge\"><img src=\"https://badges.gitter.im/nestjs/nestjs.svg\" alt=\"Gitter\" /></a>\n<a href=\"https://opencollective.com/nest#backer\"><img src=\"https://opencollective.com/nest/backers/badge.svg\" alt=\"Backers on Open Collective\" /></a>\n<a href=\"https://opencollective.com/nest#sponsor\"><img src=\"https://opencollective.com/nest/sponsors/badge.svg\" alt=\"Sponsors on Open Collective\" /></a>\n  <a href=\"https://paypal.me/kamilmysliwiec\"><img src=\"https://img.shields.io/badge/Donate-PayPal-dc3d53.svg\"/></a>\n  <a href=\"https://twitter.com/nestframework\"><img src=\"https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow\"></a>\n</p>\n  <!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)\n  [![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->\n\n## Description\n\n[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.\n\n## Installation\n\n```bash\n$ npm install\n```\n\n## Running the app\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## Test\n\n```bash\n# unit tests\n$ npm run test\n\n# e2e tests\n$ npm run test:e2e\n\n# test coverage\n$ npm run test:cov\n```\n\n## Support\n\nNest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).\n\n## Stay in touch\n\n- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)\n- Website - [https://nestjs.com](https://nestjs.com/)\n- Twitter - [@nestframework](https://twitter.com/nestframework)\n\n## License\n\n  Nest is [MIT licensed](LICENSE).\n"
  },
  {
    "path": "server/db/initdb.d/init-users-db.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\npsql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname \"$POSTGRES_DB\" <<-EOSQL\n    CREATE USER todo;\n    CREATE DATABASE todo_db ENCODING UTF8;\n    GRANT ALL PRIVILEGES ON DATABASE todo_db TO todo;\n\n    ALTER USER todo WITH PASSWORD 'password123';\n    ALTER USER todo WITH SUPERUSER;\nEOSQL\n"
  },
  {
    "path": "server/docker-compose.yml",
    "content": "version: '3'\nservices:\n  db:\n    container_name: todo_db\n    image: postgres:10.7\n    volumes:\n      - ./db/initdb.d:/docker-entrypoint-initdb.d\n    ports:\n      - '5445:5432'\n"
  },
  {
    "path": "server/nest-cli.json",
    "content": "{\n  \"language\": \"ts\",\n  \"collection\": \"@nestjs/schematics\",\n  \"sourceRoot\": \"src\"\n}\n"
  },
  {
    "path": "server/nodemon-debug.json",
    "content": "{\n  \"watch\": [\"src\"],\n  \"ext\": \"ts\",\n  \"ignore\": [\"src/**/*.spec.ts\"],\n  \"exec\": \"node --inspect-brk -r ts-node/register -r tsconfig-paths/register src/main.ts\"\n}\n"
  },
  {
    "path": "server/nodemon.json",
    "content": "{\n  \"watch\": [\"src\"],\n  \"ext\": \"ts\",\n  \"ignore\": [\"src/**/*.spec.ts\"],\n  \"exec\": \"ts-node -r tsconfig-paths/register src/main.ts\"\n}\n"
  },
  {
    "path": "server/ormconfig.json",
    "content": "[\n  {\n    \"name\": \"production\",\n    \"type\": \"postgres\",\n    \"synchronize\": false,\n    \"dropSchema\": false,\n    \"logging\": true\n  },\n  {\n    \"name\": \"development\",\n    \"type\": \"postgres\",\n    \"host\": \"localhost\",\n    \"port\": 5445,\n    \"username\": \"todo\",\n    \"password\": \"password123\",\n    \"database\": \"todo_db\",\n    \"synchronize\": false,\n    \"logging\": true,\n    \"entities\": [\"src/**/*.entity.ts\"],\n    \"migrations\": [\"src/migration/**/*.ts\"],\n    \"subscribers\": [\"src/subscriber/**/*.ts\"],\n    \"cli\": {\n      \"entitiesDir\": \"src/**/*.entity.ts\",\n      \"migrationsDir\": \"src/migration\",\n      \"subscribersDir\": \"src/subscriber\"\n    }\n  },\n  {\n    \"type\": \"postgres\",\n    \"host\": \"localhost\",\n    \"port\": 5445,\n    \"username\": \"todo\",\n    \"password\": \"password123\",\n    \"database\": \"todo_db\",\n    \"synchronize\": false,\n    \"logging\": true,\n    \"entities\": [\"src/**/*.entity.ts\"],\n    \"migrations\": [\"src/migration/**/*.ts\"],\n    \"subscribers\": [\"src/subscriber/**/*.ts\"],\n    \"cli\": {\n      \"entitiesDir\": \"src\",\n      \"migrationsDir\": \"src/migration\",\n      \"subscribersDir\": \"src/subscriber\"\n    }\n  }\n]\n"
  },
  {
    "path": "server/package.json",
    "content": "{\n  \"name\": \"server\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A nest todo app\",\n  \"author\": \"Bilal Haidar\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"tsc -p tsconfig.build.json\",\n    \"format\": \"prettier --write \\\"src/**/*.ts\\\"\",\n    \"run:services\": \"docker-compose up -d && exit 0\",\n    \"stop:services\": \"docker-compose kill\",\n    \"start\": \"ts-node src/index.ts\",\n    \"start:dev\": \"nodemon\",\n    \"start:debug\": \"nodemon --config nodemon-debug.json\",\n    \"typeorm:cli\": \"ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js -f ormconfig.json\",\n    \"db:migration:generate\": \"npm-run-all -s -l clean build:server && yarn typeorm:cli migration:generate\",\n    \"db:migration:create\": \"yarn typeorm:cli migration:create\",\n    \"db:migrate\": \"npm-run-all -s -l clean build:server && yarn typeorm:cli migration:run\",\n    \"query\": \"yarn typeorm:cli query\",\n    \"prestart:prod\": \"rimraf dist && npm run build\",\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.2.3\",\n    \"@nestjs/core\": \"6.2.3\",\n    \"@nestjs/jwt\": \"6.1.0\",\n    \"@nestjs/passport\": \"6.1.0\",\n    \"@nestjs/platform-express\": \"6.2.3\",\n    \"@nestjs/typeorm\": \"^6.1.1\",\n    \"bcrypt\": \"^3.0.6\",\n    \"class-transformer\": \"0.2.3\",\n    \"class-validator\": \"0.9.1\",\n    \"cookie-parser\": \"^1.4.4\",\n    \"cors\": \"^2.8.5\",\n    \"csurf\": \"^1.9.0\",\n    \"dotenv\": \"7.0.0\",\n    \"express-rate-limit\": \"^3.4.0\",\n    \"global\": \"^4.3.2\",\n    \"helmet\": \"^3.16.0\",\n    \"passport\": \"^0.4.0\",\n    \"passport-http-bearer\": \"^1.0.1\",\n    \"passport-jwt\": \"^4.0.0\",\n    \"pg\": \"7.9.0\",\n    \"reflect-metadata\": \"0.1.12\",\n    \"rxjs\": \"6.4.0\",\n    \"typeorm\": \"0.2.16\",\n    \"uuid\": \"3.3.2\"\n  },\n  \"devDependencies\": {\n    \"@nestjs/testing\": \"6.2.4\",\n    \"@types/bcrypt\": \"^3.0.0\",\n    \"@types/cookie-parser\": \"^1.4.1\",\n    \"@types/cors\": \"^2.8.4\",\n    \"@types/csurf\": \"^1.9.35\",\n    \"@types/dotenv\": \"6.1.1\",\n    \"@types/express\": \"4.16.1\",\n    \"@types/express-rate-limit\": \"^3.3.0\",\n    \"@types/helmet\": \"^0.0.43\",\n    \"@types/jest\": \"24.0.11\",\n    \"@types/node\": \"10.14.4\",\n    \"@types/passport\": \"^1.0.0\",\n    \"@types/passport-jwt\": \"^3.0.1\",\n    \"@types/supertest\": \"2.0.7\",\n    \"@types/uuid\": \"3.4.4\",\n    \"jest\": \"^23.5.0\",\n    \"nodemon\": \"1.18.11\",\n    \"prettier\": \"1.17.0\",\n    \"supertest\": \"^3.1.0\",\n    \"ts-jest\": \"^23.1.3\",\n    \"ts-loader\": \"5.3.3\",\n    \"ts-node\": \"8.0.3\",\n    \"tsconfig-paths\": \"3.8.0\",\n    \"tslint\": \"5.15.0\",\n    \"typescript\": \"3.4.3\"\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": "server/src/app.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\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": "server/src/app.controller.ts",
    "content": "import { Controller, Get } from '@nestjs/common';\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": "server/src/app.module.ts",
    "content": "import { Module, DynamicModule } from '@nestjs/common';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\nimport { TodoModule } from './todo/todo.module';\nimport { ConnectionOptions } from 'typeorm';\nimport { UsersModule } from './users/users.module';\nimport { CoreModule } from './core/core.module';\nimport { AuthModule } from './auth/auth.module';\n\n@Module({})\nexport class AppModule {\n  static forRoot(connOptions: ConnectionOptions): DynamicModule {\n    return {\n      module: AppModule,\n      controllers: [AppController],\n      imports: [\n        AuthModule,\n        TodoModule,\n        UsersModule,\n        CoreModule,\n        TypeOrmModule.forRoot(connOptions),\n      ],\n      providers: [AppService],\n    };\n  }\n}\n"
  },
  {
    "path": "server/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": "server/src/auth/auth.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\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": "server/src/auth/auth.controller.ts",
    "content": "import {\n  Controller,\n  Body,\n  Post,\n  HttpException,\n  HttpStatus,\n  UsePipes,\n  Get,\n  Req,\n  UseGuards,\n} from '@nestjs/common';\nimport { CreateUserDto } from '@user/dto/user.create.dto';\nimport { RegistrationStatus } from './interfaces/regisration-status.interface';\nimport { AuthService } from './auth.service';\nimport { LoginStatus } from './interfaces/login-status.interface';\nimport { LoginUserDto } from '../users/dto/user-login.dto';\nimport { JwtPayload } from './interfaces/payload.interface';\nimport { AuthGuard } from '@nestjs/passport';\n\n@Controller('auth')\nexport class AuthController {\n  constructor(private readonly authService: AuthService) {}\n\n  @Post('register')\n  public async register(\n    @Body() createUserDto: CreateUserDto,\n  ): Promise<RegistrationStatus> {\n    const result: RegistrationStatus = await this.authService.register(\n      createUserDto,\n    );\n\n    if (!result.success) {\n      throw new HttpException(result.message, HttpStatus.BAD_REQUEST);\n    }\n\n    return result;\n  }\n\n  @Post('login')\n  public async login(@Body() loginUserDto: LoginUserDto): Promise<LoginStatus> {\n    return await this.authService.login(loginUserDto);\n  }\n\n  @Get('whoami')\n  @UseGuards(AuthGuard())\n  public async testAuth(@Req() req: any): Promise<JwtPayload> {\n    return req.user;\n  }\n}\n"
  },
  {
    "path": "server/src/auth/auth.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { AuthController } from './auth.controller';\nimport { AuthService } from './auth.service';\nimport { UsersModule } from '@user/users.module';\nimport { JwtModule } from '@nestjs/jwt';\nimport { PassportModule } from '@nestjs/passport';\nimport { JwtStrategy } from './jwt.strategy';\n\n@Module({\n  imports: [\n    UsersModule,\n    PassportModule.register({\n      defaultStrategy: 'jwt',\n      property: 'user',\n      session: false,\n    }),\n    JwtModule.register({\n      secret: process.env.SECRETKEY,\n      signOptions: {\n        expiresIn: process.env.EXPIRESIN,\n      },\n    }),\n  ],\n  controllers: [AuthController],\n  providers: [AuthService, JwtStrategy],\n  exports: [PassportModule, JwtModule],\n})\nexport class AuthModule {}\n"
  },
  {
    "path": "server/src/auth/auth.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\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": "server/src/auth/auth.service.ts",
    "content": "import { Injectable, HttpException, HttpStatus } from '@nestjs/common';\nimport { CreateUserDto } from '@user/dto/user.create.dto';\nimport { RegistrationStatus } from './interfaces/regisration-status.interface';\nimport { UsersService } from '@user/users.service';\nimport { LoginStatus } from './interfaces/login-status.interface';\nimport { LoginUserDto } from '../users/dto/user-login.dto';\nimport { UserDto } from '@user/dto/user.dto';\nimport { JwtPayload } from './interfaces/payload.interface';\nimport { JwtService } from '@nestjs/jwt';\n\n@Injectable()\nexport class AuthService {\n  constructor(\n    private readonly usersService: UsersService,\n    private readonly jwtService: JwtService,\n  ) {}\n\n  async register(userDto: CreateUserDto): Promise<RegistrationStatus> {\n    let status: RegistrationStatus = {\n      success: true,\n      message: 'user registered',\n    };\n\n    try {\n      await this.usersService.create(userDto);\n    } catch (err) {\n      status = {\n        success: false,\n        message: err,\n      };\n    }\n\n    return status;\n  }\n\n  async login(loginUserDto: LoginUserDto): Promise<LoginStatus> {\n    // find user in db\n    const user = await this.usersService.findByLogin(loginUserDto);\n\n    // generate and sign token\n    const token = this._createToken(user);\n\n    return {\n      username: user.username,\n      ...token,\n    };\n  }\n\n  async validateUser(payload: JwtPayload): Promise<UserDto> {\n    const user = await this.usersService.findByPayload(payload);\n    if (!user) {\n      throw new HttpException('Invalid token', HttpStatus.UNAUTHORIZED);\n    }\n    return user;\n  }\n\n  private _createToken({ username }: UserDto): any {\n    const expiresIn = process.env.EXPIRESIN;\n\n    const user: JwtPayload = { username };\n    const accessToken = this.jwtService.sign(user);\n    return {\n      expiresIn,\n      accessToken,\n    };\n  }\n}\n"
  },
  {
    "path": "server/src/auth/interfaces/login-status.interface.ts",
    "content": "import { UserDto } from '@user/dto/user.dto';\n\nexport interface LoginStatus {\n  username: string;\n  accessToken: any;\n  expiresIn: any;\n}\n"
  },
  {
    "path": "server/src/auth/interfaces/payload.interface.ts",
    "content": "export interface JwtPayload {\n  username: string;\n}\n"
  },
  {
    "path": "server/src/auth/interfaces/regisration-status.interface.ts",
    "content": "export interface RegistrationStatus {\n  success: boolean;\n  message: string;\n}\n"
  },
  {
    "path": "server/src/auth/jwt.strategy.ts",
    "content": "import { PassportStrategy } from '@nestjs/passport';\nimport { ExtractJwt, Strategy } from 'passport-jwt';\nimport { AuthService } from './auth.service';\nimport { Injectable, HttpException, HttpStatus } from '@nestjs/common';\nimport { JwtPayload } from './interfaces/payload.interface';\nimport { UserDto } from '@user/dto/user.dto';\n\n@Injectable()\nexport class JwtStrategy extends PassportStrategy(Strategy) {\n  constructor(private readonly authService: AuthService) {\n    super({\n      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),\n      secretOrKey: process.env.SECRETKEY,\n    });\n  }\n\n  async validate(payload: JwtPayload): Promise<UserDto> {\n    const user = await this.authService.validateUser(payload);\n    if (!user) {\n      throw new HttpException('Invalid token', HttpStatus.UNAUTHORIZED);\n    }\n    return user;\n  }\n}\n"
  },
  {
    "path": "server/src/core/core.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { HttpExceptionFilter } from './http-exception.filter';\nimport { APP_FILTER } from '@nestjs/core';\n\n@Module({\n  providers: [\n    {\n      provide: APP_FILTER,\n      useClass: HttpExceptionFilter,\n    },\n  ],\n})\nexport class CoreModule {}\n"
  },
  {
    "path": "server/src/core/http-exception.filter.ts",
    "content": "import {\n  ExceptionFilter,\n  HttpException,\n  HttpStatus,\n  ArgumentsHost,\n  Catch,\n  Logger,\n} from '@nestjs/common';\n\n@Catch()\nexport class HttpExceptionFilter implements ExceptionFilter {\n  catch(exception: HttpException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse();\n    const request = ctx.getRequest();\n    const status = exception.getStatus\n      ? exception.getStatus()\n      : HttpStatus.INTERNAL_SERVER_ERROR;\n\n    const errorResponse = {\n      code: status,\n      timestamp: new Date().toLocaleDateString(),\n      path: request.url,\n      method: request.method,\n      message:\n        status !== HttpStatus.INTERNAL_SERVER_ERROR\n          ? exception.message.error || exception.message || null\n          : 'Internal server error',\n    };\n\n    Logger.error(\n      `${request.method} ${request.url}`,\n      exception.stack,\n      'HttpExceptionFilter',\n    );\n\n    response.status(status).json(errorResponse);\n  }\n}\n"
  },
  {
    "path": "server/src/main.ts",
    "content": "import 'dotenv/config';\n\nimport { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\nimport { Logger, ValidationPipe } from '@nestjs/common';\nimport { getDbConnectionOptions, runDbMigrations } from '@shared/utils';\nimport * as helmet from 'helmet';\nimport * as rateLimit from 'express-rate-limit';\n\nconst port = process.env.PORT;\n\nasync function bootstrap() {\n  const app = await NestFactory.create(\n    AppModule.forRoot(await getDbConnectionOptions(process.env.NODE_ENV)),\n    {\n      // logger: Boolean(process.env.ENABLELOGGING),\n      logger: console,\n    },\n  );\n\n  /**\n   * Helmet can help protect your app from some well-known\n   * web vulnerabilities by setting HTTP headers appropriately.\n   * Generally, Helmet is just a collection of 12 smaller\n   * middleware functions that set security-related HTTP headers\n   *\n   * https://github.com/helmetjs/helmet#how-it-works\n   */\n  app.use(helmet());\n\n  app.enableCors();\n\n  // /**\n  //  * we need this because \"cookie\" is true in csrfProtection\n  //  */\n  // app.use(cookieParser());\n\n  // app.use(csurf({ cookie: true }));\n\n  /**\n   * To protect your applications from brute-force attacks\n   */\n  app.use(\n    new rateLimit({\n      windowMs: 15 * 60 * 1000,\n      max: 100,\n    }),\n  );\n\n  /**\n   * Apply validation for all inputs globally\n   */\n  app.useGlobalPipes(\n    new ValidationPipe({\n      /**\n       * Strip away all none-object existing properties\n       */\n      whitelist: true,\n      /***\n       * Transform input objects to their corresponding DTO objects\n       */\n      transform: true,\n    }),\n  );\n\n  /**\n   * Run DB migrations\n   */\n  await runDbMigrations();\n\n  await app.listen(port);\n\n  Logger.log(`Server started running on http://localhost:${port}`, 'Bootstrap');\n}\n\nbootstrap();\n"
  },
  {
    "path": "server/src/migration/1551865385236-InitialCreate.ts",
    "content": "import {MigrationInterface, QueryRunner} from \"typeorm\";\n\nexport class InitialCreate1551865385236 implements MigrationInterface {\n\n    public async up(queryRunner: QueryRunner): Promise<any> {\n        await queryRunner.query(`CREATE TABLE \"todo\" (\"id\" uuid NOT NULL DEFAULT uuid_generate_v4(), \"name\" character varying NOT NULL, \"description\" text, \"createdOn\" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT \"PK_d429b7114371f6a35c5cb4776a7\" PRIMARY KEY (\"id\"))`);\n        await queryRunner.query(`CREATE TABLE \"task\" (\"id\" uuid NOT NULL DEFAULT uuid_generate_v4(), \"name\" character varying NOT NULL, \"createdOn\" TIMESTAMP NOT NULL DEFAULT now(), \"todoId\" uuid, CONSTRAINT \"PK_fb213f79ee45060ba925ecd576e\" PRIMARY KEY (\"id\"))`);\n        await queryRunner.query(`ALTER TABLE \"task\" ADD CONSTRAINT \"FK_91440d017e7b30d2ac16a27d762\" FOREIGN KEY (\"todoId\") REFERENCES \"todo\"(\"id\") ON DELETE NO ACTION ON UPDATE NO ACTION`);\n    }\n\n    public async down(queryRunner: QueryRunner): Promise<any> {\n        await queryRunner.query(`ALTER TABLE \"task\" DROP CONSTRAINT \"FK_91440d017e7b30d2ac16a27d762\"`);\n        await queryRunner.query(`DROP TABLE \"task\"`);\n        await queryRunner.query(`DROP TABLE \"todo\"`);\n    }\n\n}\n"
  },
  {
    "path": "server/src/migration/1552392671960-AddUpdatedOnFieldToTodoEntity.ts",
    "content": "import {MigrationInterface, QueryRunner} from \"typeorm\";\n\nexport class AddUpdatedOnFieldToTodoEntity1552392671960 implements MigrationInterface {\n\n    public async up(queryRunner: QueryRunner): Promise<any> {\n        await queryRunner.query(`ALTER TABLE \"todo\" ADD \"updatedOn\" TIMESTAMP NOT NULL DEFAULT now()`);\n    }\n\n    public async down(queryRunner: QueryRunner): Promise<any> {\n        await queryRunner.query(`ALTER TABLE \"todo\" DROP COLUMN \"updatedOn\"`);\n    }\n\n}\n"
  },
  {
    "path": "server/src/migration/1555148302681-AddUser.ts",
    "content": "import { MigrationInterface, QueryRunner } from 'typeorm';\n\nexport class AddUser1555148302681 implements MigrationInterface {\n  public async up(queryRunner: QueryRunner): Promise<any> {\n    await queryRunner.query(\n      // tslint:disable-next-line: max-line-length\n      `CREATE TABLE \"users\" (\"id\" uuid NOT NULL DEFAULT uuid_generate_v4(), \"username\" character varying NOT NULL, \"password\" character varying NOT NULL, \"email\" character varying NOT NULL, \"createdOn\" TIMESTAMP NOT NULL DEFAULT now(), \"updatedOn\" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT \"UQ_78a916df40e02a9deb1c4b75edb\" UNIQUE (\"username\"), CONSTRAINT \"PK_cace4a159ff9f2512dd42373760\" PRIMARY KEY (\"id\"))`,\n    );\n  }\n\n  public async down(queryRunner: QueryRunner): Promise<any> {\n    await queryRunner.query(`DROP TABLE \"users\"`);\n  }\n}\n"
  },
  {
    "path": "server/src/migration/1555166680617-AddOwnerFieldToTodoEntity.ts",
    "content": "import { MigrationInterface, QueryRunner } from 'typeorm';\n\nexport class AddOwnerFieldToTodoEntity1555166680617\n  implements MigrationInterface {\n  public async up(queryRunner: QueryRunner): Promise<any> {\n    await queryRunner.query(`ALTER TABLE \"todo\" ADD \"ownerId\" uuid`);\n    await queryRunner.query(\n      // tslint:disable-next-line: max-line-length\n      `ALTER TABLE \"todo\" ADD CONSTRAINT \"FK_05552e862619dc4ad7ec8fc9cb8\" FOREIGN KEY (\"ownerId\") REFERENCES \"users\"(\"id\") ON DELETE NO ACTION ON UPDATE NO ACTION`,\n    );\n  }\n\n  public async down(queryRunner: QueryRunner): Promise<any> {\n    await queryRunner.query(\n      `ALTER TABLE \"todo\" DROP CONSTRAINT \"FK_05552e862619dc4ad7ec8fc9cb8\"`,\n    );\n    await queryRunner.query(`ALTER TABLE \"todo\" DROP COLUMN \"ownerId\"`);\n  }\n}\n"
  },
  {
    "path": "server/src/migration/1565812987671-SeedUserRecord.ts",
    "content": "// https://github.com/typeorm/typeorm/blob/master/docs/transactions.md\n\nimport { MigrationInterface, QueryRunner } from 'typeorm';\nimport { UserEntity } from '../users/entity/user.entity';\n\nexport class SeedUserRecord1565812987671 implements MigrationInterface {\n  public async up(queryRunner: QueryRunner): Promise<any> {\n    const userRepo = queryRunner.manager.getRepository(UserEntity);\n\n    const user = userRepo.create({\n      username: 'bhaidar',\n      password: '@dF%^hGb03W~',\n      email: 'bhaidar@gmail.com',\n    });\n\n    await userRepo.save(user);\n  }\n\n  // tslint:disable-next-line: no-empty\n  public async down(queryRunner: QueryRunner): Promise<any> {}\n}\n"
  },
  {
    "path": "server/src/mock/todos.mock.ts",
    "content": "import { TodoEntity } from 'src/todo/entity/todo.entity';\n\nexport const todos: TodoEntity[] = [\n  {\n    id: 'eac400ba-3c78-11e9-b210-d663bd873d93',\n    name: 'Supermarket Todo list',\n    tasks: [\n      {\n        id: 'b91a5400-3cce-11e9-b210-d663bd873d93',\n        name: 'Bring coffee',\n      },\n      {\n        id: 'b91a56c6-3cce-11e9-b210-d663bd873d93',\n        name: 'Bring banana',\n      },\n    ],\n  },\n  {\n    id: 'eac40736-3c78-11e9-b210-d663bd873d93',\n    name: 'Office Todo list',\n    tasks: [\n      {\n        id: 'b91a5a90-3cce-11e9-b210-d663bd873d93',\n        name: 'Bring chairs',\n      },\n      {\n        id: 'b91a5bf8-3cce-11e9-b210-d663bd873d93',\n        name: 'Bring tables',\n      },\n    ],\n  },\n  {\n    id: 'eac408d0-3c78-11e9-b210-d663bd873d93',\n    name: 'Traveling Todo  list',\n  },\n  {\n    id: 'eac40a7e-3c78-11e9-b210-d663bd873d93',\n    name: 'Studying Todo list',\n  },\n  {\n    id: 'eac40c90-3c78-11e9-b210-d663bd873d93',\n    name: 'Monday Todo list',\n  },\n  {\n    id: '5ea5f9ed-dd64-4e08-bdb6-d3d5-354fe48',\n    name: 'My awesome todo list',\n    description: 'A new awesome and cool todo list',\n  },\n];\n"
  },
  {
    "path": "server/src/shared/mapper.ts",
    "content": "import { TaskDto } from '@todo/dto/task.dto';\nimport { TodoEntity } from '@todo/entity/todo.entity';\nimport { TodoDto } from '@todo/dto/todo.dto';\nimport { TaskEntity } from '@todo/entity/task.entity';\nimport { UserEntity } from '@user/entity/user.entity';\nimport { UserDto } from '@user/dto/user.dto';\n\nexport const toTodoDto = (data: TodoEntity): TodoDto => {\n  const { id, name, description, tasks, owner } = data;\n\n  let todoDto: TodoDto = {\n    id,\n    name,\n    description,\n    owner: owner ? toUserDto(owner) : null,\n  };\n\n  if (tasks) {\n    todoDto = {\n      ...todoDto,\n      tasks: tasks.map((task: TaskEntity) => toTaskDto(task)),\n    };\n  }\n\n  return todoDto;\n};\n\nexport const toTaskDto = (data: TaskEntity): TaskDto => {\n  const { id, name } = data;\n\n  let taskDto: TaskDto = {\n    id,\n    name,\n  };\n\n  return taskDto;\n};\n\nexport const toUserDto = (data: UserEntity): UserDto => {\n  const { id, username, email } = data;\n\n  let userDto: UserDto = {\n    id,\n    username,\n    email,\n  };\n\n  return userDto;\n};\n"
  },
  {
    "path": "server/src/shared/utils.ts",
    "content": "import { getConnectionOptions, getConnection } from 'typeorm';\nimport * as bcrypt from 'bcrypt';\nimport { Logger } from '@nestjs/common';\n\nexport const toPromise = <T>(data: T): Promise<T> => {\n  return new Promise<T>(resolve => {\n    resolve(data);\n  });\n};\n\nexport const getDbConnectionOptions = async (\n  connectionName: string = 'default',\n) => {\n  const options = await getConnectionOptions(\n    process.env.NODE_ENV || 'development',\n  );\n  return {\n    ...options,\n    name: connectionName,\n  };\n};\n\nexport const getDbConnection = async (connectionName: string = 'default') => {\n  return await getConnection(connectionName);\n};\n\nexport const runDbMigrations = async (connectionName: string = 'default') => {\n  const conn = await getDbConnection(connectionName);\n  await conn.runMigrations();\n};\n\nexport const comparePasswords = async (userPassword, currentPassword) => {\n  return await bcrypt.compare(currentPassword, userPassword);\n};\n"
  },
  {
    "path": "server/src/todo/dto/task.create.dto.ts",
    "content": "import { IsNotEmpty } from 'class-validator';\n\nexport class CreateTaskDto {\n  @IsNotEmpty()\n  name: string;\n}\n"
  },
  {
    "path": "server/src/todo/dto/task.dto.ts",
    "content": "import { IsNotEmpty, IsString } from 'class-validator';\n\nexport class TaskDto {\n  @IsNotEmpty()\n  id: string;\n\n  @IsNotEmpty()\n  @IsString()\n  name: string;\n\n  createdOn?: Date;\n}\n"
  },
  {
    "path": "server/src/todo/dto/task.list.dto.ts",
    "content": "import { TaskDto } from './task.dto';\n\nexport class TaskListDto {\n  tasks: TaskDto[];\n}\n"
  },
  {
    "path": "server/src/todo/dto/todo.create.dto.ts",
    "content": "import { IsNotEmpty, MaxLength, IsOptional } from 'class-validator';\nimport { UserDto } from '@user/dto/user.dto';\n\nexport class CreateTodoDto {\n  @IsNotEmpty()\n  name: string;\n\n  @IsOptional()\n  @MaxLength(500)\n  description?: string;\n}\n"
  },
  {
    "path": "server/src/todo/dto/todo.dto.ts",
    "content": "import { TaskDto } from './task.dto';\nimport { IsNotEmpty } from 'class-validator';\nimport { UserDto } from '@user/dto/user.dto';\n\nexport class TodoDto {\n  @IsNotEmpty()\n  id: string;\n\n  @IsNotEmpty()\n  name: string;\n\n  createdOn?: Date;\n  description?: string;\n\n  owner: UserDto;\n\n  tasks?: TaskDto[];\n}\n"
  },
  {
    "path": "server/src/todo/dto/todo.list.dto.ts",
    "content": "import { TodoDto } from './todo.dto';\n\nexport class TodoListDto {\n  todos: TodoDto[];\n}\n"
  },
  {
    "path": "server/src/todo/entity/task.entity.ts",
    "content": "import {\n  Entity,\n  PrimaryGeneratedColumn,\n  Column,\n  CreateDateColumn,\n  ManyToOne,\n} from 'typeorm';\nimport { TodoEntity } from '@todo/entity/todo.entity';\n\n@Entity('task')\nexport class TaskEntity {\n  @PrimaryGeneratedColumn('uuid') id: string;\n  @Column({ type: 'varchar', nullable: false }) name: string;\n  @CreateDateColumn() createdOn?: Date;\n\n  @ManyToOne(type => TodoEntity, todo => todo.tasks)\n  todo?: TodoEntity;\n}\n"
  },
  {
    "path": "server/src/todo/entity/todo.entity.ts",
    "content": "import { TaskEntity } from '@todo/entity/task.entity';\nimport {\n  Entity,\n  PrimaryGeneratedColumn,\n  Column,\n  CreateDateColumn,\n  OneToMany,\n  ManyToOne,\n  JoinTable,\n} from 'typeorm';\nimport { UserEntity } from '@user/entity/user.entity';\n\n@Entity('todo')\nexport class TodoEntity {\n  @PrimaryGeneratedColumn('uuid') id: string;\n  @Column({ type: 'varchar', nullable: false }) name: string;\n  @Column({ type: 'text', nullable: true }) description?: string;\n  @CreateDateColumn() createdOn?: Date;\n  @CreateDateColumn() updatedOn?: Date;\n\n  @ManyToOne(type => UserEntity)\n  owner?: UserEntity;\n\n  @OneToMany(type => TaskEntity, task => task.todo)\n  tasks?: TaskEntity[];\n}\n"
  },
  {
    "path": "server/src/todo/task/task.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport { TaskController } from './task.controller';\n\ndescribe('Task Controller', () => {\n  let controller: TaskController;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      controllers: [TaskController],\n    }).compile();\n\n    controller = module.get<TaskController>(TaskController);\n  });\n\n  it('should be defined', () => {\n    expect(controller).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "server/src/todo/task/task.controller.ts",
    "content": "import {\n  Controller,\n  Param,\n  Get,\n  Post,\n  Body,\n  Delete,\n  UsePipes,\n  UseGuards,\n} from '@nestjs/common';\nimport { TaskService } from './task.service';\nimport { TaskListDto } from '../dto/task.list.dto';\nimport { TaskDto } from '../dto/task.dto';\nimport { CreateTaskDto } from '@todo/dto/task.create.dto';\nimport { AuthGuard } from '@nestjs/passport';\n\n@Controller('api/tasks')\nexport class TaskController {\n  constructor(private taskService: TaskService) {}\n\n  @Get(':id')\n  async findOneTask(@Param('id') id: string): Promise<TaskDto> {\n    return await this.taskService.getTask(id);\n  }\n\n  @Get('todo/:id')\n  async findTasksByTodo(@Param('id') id: string): Promise<TaskListDto> {\n    const tasks = await this.taskService.getTasksByTodo(id);\n    return { tasks };\n  }\n\n  @Post('todo/:id')\n  @UseGuards(AuthGuard())\n  async create(\n    @Param('id') todo: string,\n    @Body() createTaskDto: CreateTaskDto,\n  ): Promise<TaskDto> {\n    return await this.taskService.createTask(todo, createTaskDto);\n  }\n\n  @Delete(':id')\n  @UseGuards(AuthGuard())\n  async destory(@Param('id') id: string): Promise<TaskDto> {\n    return await this.taskService.destoryTask(id);\n  }\n}\n"
  },
  {
    "path": "server/src/todo/task/task.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport { TaskService } from './task.service';\n\ndescribe('TaskService', () => {\n  let service: TaskService;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      providers: [TaskService],\n    }).compile();\n\n    service = module.get<TaskService>(TaskService);\n  });\n\n  it('should be defined', () => {\n    expect(service).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "server/src/todo/task/task.service.ts",
    "content": "import { Injectable, HttpException, HttpStatus } from '@nestjs/common';\nimport { CreateTaskDto } from '../dto/task.create.dto';\nimport { TaskDto } from '../dto/task.dto';\nimport { TaskEntity } from '@todo/entity/task.entity';\nimport { toTaskDto } from '@shared/mapper';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { Repository } from 'typeorm';\nimport { TodoEntity } from '@todo/entity/todo.entity';\n\n@Injectable()\nexport class TaskService {\n  constructor(\n    @InjectRepository(TaskEntity)\n    private readonly taskRepo: Repository<TaskEntity>,\n    @InjectRepository(TodoEntity)\n    private readonly todoRepo: Repository<TodoEntity>,\n  ) {}\n\n  async getTask(id: string): Promise<TaskDto> {\n    const task: TaskEntity = await this.taskRepo.findOne({ where: { id } });\n\n    if (!task) {\n      throw new HttpException(`Task doesn't exist`, HttpStatus.BAD_REQUEST);\n    }\n\n    return toTaskDto(task);\n  }\n\n  async getTasksByTodo(id: string): Promise<TaskDto[]> {\n    const tasks: TaskEntity[] = await this.taskRepo.find({\n      where: { todo: { id } },\n      relations: ['todo'],\n    });\n\n    return tasks.map(task => toTaskDto(task));\n  }\n\n  async createTask(todoId: string, taskDto: CreateTaskDto): Promise<TaskDto> {\n    const { name } = taskDto;\n\n    const todo: TodoEntity = await this.todoRepo.findOne({\n      where: { id: todoId },\n      relations: ['tasks', 'owner'],\n    });\n\n    const task: TaskEntity = await this.taskRepo.create({\n      name,\n      todo,\n    });\n\n    await this.taskRepo.save(task);\n\n    return toTaskDto(task);\n  }\n\n  async destoryTask(id: string): Promise<TaskDto> {\n    const task: TaskEntity = await this.taskRepo.findOne({ where: { id } });\n\n    if (!task) {\n      throw new HttpException(`Task doesn't exist`, HttpStatus.BAD_REQUEST);\n    }\n\n    await this.taskRepo.delete({ id });\n\n    return toTaskDto(task);\n  }\n}\n"
  },
  {
    "path": "server/src/todo/todo.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport { TodoController } from './todo.controller';\n\ndescribe('Todo Controller', () => {\n  let controller: TodoController;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      controllers: [TodoController],\n    }).compile();\n\n    controller = module.get<TodoController>(TodoController);\n  });\n\n  it('should be defined', () => {\n    expect(controller).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "server/src/todo/todo.controller.ts",
    "content": "import {\n  Controller,\n  Get,\n  Param,\n  Post,\n  Body,\n  Put,\n  Delete,\n  UsePipes,\n  UseGuards,\n  Req,\n} from '@nestjs/common';\nimport { TodoListDto } from './dto/todo.list.dto';\nimport { TodoDto } from './dto/todo.dto';\nimport { CreateTodoDto } from './dto/todo.create.dto';\nimport { TodoService } from './todo.service';\nimport { AuthGuard } from '@nestjs/passport';\nimport { UserDto } from '@user/dto/user.dto';\n\n@Controller('api/todos')\nexport class TodoController {\n  constructor(private readonly todoService: TodoService) {}\n\n  @Get()\n  async findAll(@Req() req: any): Promise<TodoListDto> {\n    const todos = await this.todoService.getAllTodo();\n    return { todos };\n  }\n\n  @Get(':id')\n  async findOne(@Param('id') id: string): Promise<TodoDto> {\n    return await this.todoService.getOneTodo(id);\n  }\n\n  @Post()\n  @UseGuards(AuthGuard())\n  async create(\n    @Body() createTodoDto: CreateTodoDto,\n    @Req() req: any,\n  ): Promise<TodoDto> {\n    const user = req.user as UserDto;\n\n    return await this.todoService.createTodo(user, createTodoDto);\n  }\n\n  @Put(':id')\n  @UseGuards(AuthGuard())\n  async update(\n    @Param('id') id: string,\n    @Body() todoDto: TodoDto,\n  ): Promise<TodoDto> {\n    return await this.todoService.updateTodo(id, todoDto);\n  }\n\n  @Delete(':id')\n  @UseGuards(AuthGuard())\n  async destory(@Param('id') id: string): Promise<TodoDto> {\n    return await this.todoService.destoryTodo(id);\n  }\n}\n"
  },
  {
    "path": "server/src/todo/todo.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { TodoController } from './todo.controller';\nimport { TodoService } from './todo.service';\nimport { TaskController } from './task/task.controller';\nimport { TaskService } from './task/task.service';\nimport { TodoEntity } from '@todo/entity/todo.entity';\nimport { TaskEntity } from '@todo/entity/task.entity';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { UserEntity } from '@user/entity/user.entity';\nimport { UsersModule } from '@user/users.module';\nimport { AuthModule } from 'src/auth/auth.module';\n\n@Module({\n  imports: [\n    UsersModule,\n    AuthModule,\n    TypeOrmModule.forFeature([TodoEntity, TaskEntity, UserEntity]),\n  ],\n  controllers: [TodoController, TaskController],\n  providers: [TodoService, TaskService],\n})\nexport class TodoModule {}\n"
  },
  {
    "path": "server/src/todo/todo.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport { TodoService } from './todo.service';\n\ndescribe('TodoService', () => {\n  let service: TodoService;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      providers: [TodoService],\n    }).compile();\n\n    service = module.get<TodoService>(TodoService);\n  });\n\n  it('should be defined', () => {\n    expect(service).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "server/src/todo/todo.service.ts",
    "content": "import { Injectable, HttpException, HttpStatus } from '@nestjs/common';\n\nimport { TodoEntity } from '@todo/entity/todo.entity';\nimport { TodoDto } from './dto/todo.dto';\nimport { toTodoDto } from '@shared/mapper';\nimport { CreateTodoDto } from './dto/todo.create.dto';\n\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { Repository } from 'typeorm';\nimport { UserDto } from '@user/dto/user.dto';\nimport { UsersService } from '@user/users.service';\n\n@Injectable()\nexport class TodoService {\n  constructor(\n    @InjectRepository(TodoEntity)\n    private readonly todoRepo: Repository<TodoEntity>,\n    private readonly usersService: UsersService,\n  ) {}\n\n  async getAllTodo(): Promise<TodoDto[]> {\n    const todos = await this.todoRepo.find({ relations: ['tasks', 'owner'] });\n    return todos.map(todo => toTodoDto(todo));\n  }\n\n  async getOneTodo(id: string): Promise<TodoDto> {\n    const todo = await this.todoRepo.findOne({\n      where: { id },\n      relations: ['tasks', 'owner'],\n    });\n\n    if (!todo) {\n      throw new HttpException(\n        `Todo list doesn't exist`,\n        HttpStatus.BAD_REQUEST,\n      );\n    }\n\n    return toTodoDto(todo);\n  }\n\n  async createTodo(\n    { username }: UserDto,\n    createTodoDto: CreateTodoDto,\n  ): Promise<TodoDto> {\n    const { name, description } = createTodoDto;\n\n    // get the user from db\n    const owner = await this.usersService.findOne({ where: { username } });\n\n    const todo: TodoEntity = await this.todoRepo.create({\n      name,\n      description,\n      owner,\n    });\n\n    await this.todoRepo.save(todo);\n\n    return toTodoDto(todo);\n  }\n\n  async updateTodo(id: string, todoDto: TodoDto): Promise<TodoDto> {\n    const { name, description } = todoDto;\n\n    let todo: TodoEntity = await this.todoRepo.findOne({ where: { id } });\n\n    if (!todo) {\n      throw new HttpException(\n        `Todo list doesn't exist`,\n        HttpStatus.BAD_REQUEST,\n      );\n    }\n\n    todo = {\n      id,\n      name,\n      description,\n    };\n\n    await this.todoRepo.update({ id }, todo); // update\n\n    todo = await this.todoRepo.findOne({\n      where: { id },\n      relations: ['tasks', 'owner'],\n    }); // re-query\n\n    return toTodoDto(todo);\n  }\n\n  async destoryTodo(id: string): Promise<TodoDto> {\n    const todo: TodoEntity = await this.todoRepo.findOne({\n      where: { id },\n      relations: ['tasks', 'owner'],\n    });\n\n    if (!todo) {\n      throw new HttpException(\n        `Todo list doesn't exist`,\n        HttpStatus.BAD_REQUEST,\n      );\n    }\n\n    if (todo.tasks && todo.tasks.length > 0) {\n      throw new HttpException(\n        `Cannot delete this Todo list, it has existing tasks`,\n        HttpStatus.FORBIDDEN,\n      );\n    }\n\n    await this.todoRepo.delete({ id }); // delete todo list\n\n    return toTodoDto(todo);\n  }\n}\n"
  },
  {
    "path": "server/src/users/dto/user-login.dto.ts",
    "content": "import { IsNotEmpty } from 'class-validator';\n\nexport class LoginUserDto {\n  @IsNotEmpty()\n  readonly username: string;\n\n  @IsNotEmpty()\n  readonly password: string;\n}\n"
  },
  {
    "path": "server/src/users/dto/user.create.dto.ts",
    "content": "import { IsNotEmpty, IsEmail } from 'class-validator';\n\nexport class CreateUserDto {\n  @IsNotEmpty()\n  username: string;\n\n  @IsNotEmpty()\n  password: string;\n\n  @IsNotEmpty()\n  @IsEmail()\n  email: string;\n}\n"
  },
  {
    "path": "server/src/users/dto/user.dto.ts",
    "content": "import { IsNotEmpty, IsEmail } from 'class-validator';\n\nexport class UserDto {\n  @IsNotEmpty()\n  id: string;\n\n  @IsNotEmpty()\n  username: string;\n\n  @IsNotEmpty()\n  @IsEmail()\n  email: string;\n\n  createdOn?: Date;\n}\n"
  },
  {
    "path": "server/src/users/entity/user.entity.ts",
    "content": "import { TaskEntity } from '@todo/entity/task.entity';\nimport {\n  Entity,\n  PrimaryGeneratedColumn,\n  Column,\n  CreateDateColumn,\n  OneToMany,\n  BeforeInsert,\n} from 'typeorm';\nimport * as bcrypt from 'bcrypt';\n\n@Entity('users')\nexport class UserEntity {\n  @PrimaryGeneratedColumn('uuid') id: string;\n  @Column({ type: 'varchar', nullable: false, unique: true }) username: string;\n  @Column({ type: 'varchar', nullable: false }) password: string;\n  @Column({ type: 'varchar', nullable: false }) email: string;\n  @CreateDateColumn() createdOn?: Date;\n  @CreateDateColumn() updatedOn?: Date;\n\n  @BeforeInsert()\n  async hashPassword() {\n    this.password = await bcrypt.hash(this.password, 10);\n  }\n}\n"
  },
  {
    "path": "server/src/users/users.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { UsersService } from './users.service';\nimport { UserEntity } from './entity/user.entity';\nimport { TypeOrmModule } from '@nestjs/typeorm';\n\n@Module({\n  imports: [TypeOrmModule.forFeature([UserEntity])],\n  controllers: [],\n  providers: [UsersService],\n  exports: [UsersService],\n})\nexport class UsersModule {}\n"
  },
  {
    "path": "server/src/users/users.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\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": "server/src/users/users.service.ts",
    "content": "import { Injectable, HttpException, HttpStatus } from '@nestjs/common';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { Repository } from 'typeorm';\nimport { UserDto } from './dto/user.dto';\nimport { UserEntity } from '@user/entity/user.entity';\nimport { toUserDto } from '@shared/mapper';\nimport { CreateUserDto } from './dto/user.create.dto';\nimport { LoginUserDto } from './dto/user-login.dto';\nimport { comparePasswords } from '@shared/utils';\n\n@Injectable()\nexport class UsersService {\n  constructor(\n    @InjectRepository(UserEntity)\n    private readonly userRepo: Repository<UserEntity>,\n  ) {}\n\n  async findOne(options?: object): Promise<UserDto> {\n    const user = await this.userRepo.findOne(options);\n    return toUserDto(user);\n  }\n\n  async findByLogin({ username, password }: LoginUserDto): Promise<UserDto> {\n    const user = await this.userRepo.findOne({ where: { username } });\n\n    if (!user) {\n      throw new HttpException('User not found', HttpStatus.UNAUTHORIZED);\n    }\n\n    // compare passwords\n    const areEqual = await comparePasswords(user.password, password);\n\n    if (!areEqual) {\n      throw new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED);\n    }\n\n    return toUserDto(user);\n  }\n\n  async findByPayload({ username }: any): Promise<UserDto> {\n    return await this.findOne({ where: { username } });\n  }\n\n  async create(userDto: CreateUserDto): Promise<UserDto> {\n    const { username, password, email } = userDto;\n\n    // check if the user exists in the db\n    const userInDb = await this.userRepo.findOne({ where: { username } });\n    if (userInDb) {\n      throw new HttpException('User already exists', HttpStatus.BAD_REQUEST);\n    }\n\n    const user: UserEntity = await this.userRepo.create({\n      username,\n      password,\n      email,\n    });\n\n    await this.userRepo.save(user);\n\n    return toUserDto(user);\n  }\n\n  private _sanitizeUser(user: UserEntity) {\n    delete user.password;\n    return user;\n  }\n}\n"
  },
  {
    "path": "server/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": "server/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": "server/tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"exclude\": [\"node_modules\", \"test\", \"**/*spec.ts\"]\n}\n"
  },
  {
    "path": "server/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"outDir\": \"./dist\",\n    \"baseUrl\": \"./\",\n    \"removeComments\": true,\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"sourceMap\": true,\n    \"lib\": [\"es2015\"],\n    \"paths\": {\n      \"@todo/*\": [\"src/todo/*\"],\n      \"@shared/*\": [\"src/shared/*\"],\n      \"@user/*\": [\"src/users/*\"]\n    }\n  },\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "server/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"
  },
  {
    "path": "todo-client/.editorconfig",
    "content": "# Editor configuration, see https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\nmax_line_length = off\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": "todo-client/.gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist\n/tmp\n/out-tsc\n# Only exists if Bazel was run\n/bazel-out\n\n# dependencies\n/node_modules\n\n# profiling files\nchrome-profiler-events.json\nspeed-measure-plugin.json\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.history/*\n\n# misc\n/.sass-cache\n/connect.lock\n/coverage\n/libpeerconnection.log\nnpm-debug.log\nyarn-error.log\ntestem.log\n/typings\n\n# System Files\n.DS_Store\nThumbs.db\n"
  },
  {
    "path": "todo-client/README.md",
    "content": "# TodoClient\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.1.1.\n\n## Development server\n\nRun `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.\n\n## Code scaffolding\n\nRun `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.\n\n## Build\n\nRun `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.\n\n## Running unit tests\n\nRun `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Running end-to-end tests\n\nRun `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).\n\n## Further help\n\nTo get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).\n"
  },
  {
    "path": "todo-client/angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"todo-client\": {\n      \"projectType\": \"application\",\n      \"schematics\": {\n        \"@schematics/angular:component\": {\n          \"style\": \"scss\"\n        }\n      },\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"prefix\": \"app\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist/todo-client\",\n            \"index\": \"src/index.html\",\n            \"main\": \"src/main.ts\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"aot\": false,\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [\"src/styles.scss\"],\n            \"scripts\": [\n              \"./node_modules/jquery/dist/jquery.min.js\",\n              \"./node_modules/bootstrap/dist/js/bootstrap.min.js\"\n            ]\n          },\n          \"configurations\": {\n            \"production\": {\n              \"fileReplacements\": [\n                {\n                  \"replace\": \"src/environments/environment.ts\",\n                  \"with\": \"src/environments/environment.prod.ts\"\n                }\n              ],\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"extractCss\": true,\n              \"namedChunks\": false,\n              \"aot\": true,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true,\n              \"budgets\": [\n                {\n                  \"type\": \"initial\",\n                  \"maximumWarning\": \"2mb\",\n                  \"maximumError\": \"5mb\"\n                }\n              ]\n            }\n          }\n        },\n        \"serve\": {\n          \"builder\": \"@angular-devkit/build-angular:dev-server\",\n          \"options\": {\n            \"browserTarget\": \"todo-client:build\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"browserTarget\": \"todo-client:build:production\"\n            }\n          }\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular-devkit/build-angular:extract-i18n\",\n          \"options\": {\n            \"browserTarget\": \"todo-client:build\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"src/test.ts\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"tsconfig.spec.json\",\n            \"karmaConfig\": \"karma.conf.js\",\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [\"src/styles.scss\"],\n            \"scripts\": []\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"tsconfig.app.json\",\n              \"tsconfig.spec.json\",\n              \"e2e/tsconfig.json\"\n            ],\n            \"exclude\": [\"**/node_modules/**\"]\n          }\n        },\n        \"e2e\": {\n          \"builder\": \"@angular-devkit/build-angular:protractor\",\n          \"options\": {\n            \"protractorConfig\": \"e2e/protractor.conf.js\",\n            \"devServerTarget\": \"todo-client:serve\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"devServerTarget\": \"todo-client:serve:production\"\n            }\n          }\n        }\n      }\n    },\n    \"auth\": {\n      \"projectType\": \"library\",\n      \"root\": \"projects/auth\",\n      \"sourceRoot\": \"projects/auth/src\",\n      \"prefix\": \"lib\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-ng-packagr:build\",\n          \"options\": {\n            \"tsConfig\": \"projects/auth/tsconfig.lib.json\",\n            \"project\": \"projects/auth/ng-package.json\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"projects/auth/src/test.ts\",\n            \"tsConfig\": \"projects/auth/tsconfig.spec.json\",\n            \"karmaConfig\": \"projects/auth/karma.conf.js\"\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"projects/auth/tsconfig.lib.json\",\n              \"projects/auth/tsconfig.spec.json\"\n            ],\n            \"exclude\": [\"**/node_modules/**\"]\n          }\n        }\n      }\n    },\n    \"app-common\": {\n      \"projectType\": \"library\",\n      \"root\": \"projects/app-common\",\n      \"sourceRoot\": \"projects/app-common/src\",\n      \"prefix\": \"lib\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-ng-packagr:build\",\n          \"options\": {\n            \"tsConfig\": \"projects/app-common/tsconfig.lib.json\",\n            \"project\": \"projects/app-common/ng-package.json\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"projects/app-common/src/test.ts\",\n            \"tsConfig\": \"projects/app-common/tsconfig.spec.json\",\n            \"karmaConfig\": \"projects/app-common/karma.conf.js\"\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"projects/app-common/tsconfig.lib.json\",\n              \"projects/app-common/tsconfig.spec.json\"\n            ],\n            \"exclude\": [\"**/node_modules/**\"]\n          }\n        }\n      }\n    },\n    \"todo\": {\n      \"projectType\": \"library\",\n      \"root\": \"projects/todo\",\n      \"sourceRoot\": \"projects/todo/src\",\n      \"prefix\": \"lib\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-ng-packagr:build\",\n          \"options\": {\n            \"tsConfig\": \"projects/todo/tsconfig.lib.json\",\n            \"project\": \"projects/todo/ng-package.json\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"projects/todo/src/test.ts\",\n            \"tsConfig\": \"projects/todo/tsconfig.spec.json\",\n            \"karmaConfig\": \"projects/todo/karma.conf.js\"\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"projects/todo/tsconfig.lib.json\",\n              \"projects/todo/tsconfig.spec.json\"\n            ],\n            \"exclude\": [\n              \"**/node_modules/**\"\n            ]\n          }\n        }\n      }\n    }\n  },\n  \"defaultProject\": \"todo-client\"\n}\n"
  },
  {
    "path": "todo-client/browserslist",
    "content": "# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.\n# For additional information regarding the format and rule options, please see:\n# https://github.com/browserslist/browserslist#queries\n\n# You can see what browsers were selected by your queries by running:\n#   npx browserslist\n\n> 0.5%\nlast 2 versions\nFirefox ESR\nnot dead\nnot IE 9-11 # For IE 9-11 support, remove 'not'."
  },
  {
    "path": "todo-client/e2e/protractor.conf.js",
    "content": "// @ts-check\n// Protractor configuration file, see link for more information\n// https://github.com/angular/protractor/blob/master/lib/config.ts\n\nconst { SpecReporter } = require('jasmine-spec-reporter');\n\n/**\n * @type { import(\"protractor\").Config }\n */\nexports.config = {\n  allScriptsTimeout: 11000,\n  specs: [\n    './src/**/*.e2e-spec.ts'\n  ],\n  capabilities: {\n    'browserName': 'chrome'\n  },\n  directConnect: true,\n  baseUrl: 'http://localhost:4200/',\n  framework: 'jasmine',\n  jasmineNodeOpts: {\n    showColors: true,\n    defaultTimeoutInterval: 30000,\n    print: function() {}\n  },\n  onPrepare() {\n    require('ts-node').register({\n      project: require('path').join(__dirname, './tsconfig.json')\n    });\n    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));\n  }\n};"
  },
  {
    "path": "todo-client/e2e/src/app.e2e-spec.ts",
    "content": "import { AppPage } from './app.po';\nimport { browser, logging } from 'protractor';\n\ndescribe('workspace-project App', () => {\n  let page: AppPage;\n\n  beforeEach(() => {\n    page = new AppPage();\n  });\n\n  it('should display welcome message', () => {\n    page.navigateTo();\n    expect(page.getTitleText()).toEqual('Welcome to todo-client!');\n  });\n\n  afterEach(async () => {\n    // Assert that there are no errors emitted from the browser\n    const logs = await browser.manage().logs().get(logging.Type.BROWSER);\n    expect(logs).not.toContain(jasmine.objectContaining({\n      level: logging.Level.SEVERE,\n    } as logging.Entry));\n  });\n});\n"
  },
  {
    "path": "todo-client/e2e/src/app.po.ts",
    "content": "import { browser, by, element } from 'protractor';\n\nexport class AppPage {\n  navigateTo() {\n    return browser.get(browser.baseUrl) as Promise<any>;\n  }\n\n  getTitleText() {\n    return element(by.css('app-root h1')).getText() as Promise<string>;\n  }\n}\n"
  },
  {
    "path": "todo-client/e2e/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/e2e\",\n    \"module\": \"commonjs\",\n    \"target\": \"es5\",\n    \"types\": [\n      \"jasmine\",\n      \"jasminewd2\",\n      \"node\"\n    ]\n  }\n}\n"
  },
  {
    "path": "todo-client/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular-devkit/build-angular'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular-devkit/build-angular/plugins/karma')\n    ],\n    client: {\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    coverageIstanbulReporter: {\n      dir: require('path').join(__dirname, './coverage/todo-client'),\n      reports: ['html', 'lcovonly', 'text-summary'],\n      fixWebpackSourcePaths: true\n    },\n    reporters: ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    singleRun: false,\n    restartOnFileChange: true\n  });\n};\n"
  },
  {
    "path": "todo-client/package.json",
    "content": "{\n  \"name\": \"todo-client\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve --proxy-config proxy.conf.json\",\n    \"build\": \"ng build\",\n    \"test\": \"ng test\",\n    \"lint\": \"ng lint\",\n    \"e2e\": \"ng e2e\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/animations\": \"~8.1.1\",\n    \"@angular/common\": \"~8.1.1\",\n    \"@angular/compiler\": \"~8.1.1\",\n    \"@angular/core\": \"~8.1.1\",\n    \"@angular/forms\": \"~8.1.1\",\n    \"@angular/platform-browser\": \"~8.1.1\",\n    \"@angular/platform-browser-dynamic\": \"~8.1.1\",\n    \"@angular/router\": \"~8.1.1\",\n    \"bootstrap\": \"^4.3.1\",\n    \"jquery\": \"^3.4.1\",\n    \"rxjs\": \"~6.4.0\",\n    \"tslib\": \"^1.9.0\",\n    \"zone.js\": \"~0.9.1\"\n  },\n  \"devDependencies\": {\n    \"@angular-devkit/build-angular\": \"~0.801.1\",\n    \"@angular-devkit/build-ng-packagr\": \"~0.801.3\",\n    \"@angular/cli\": \"~8.1.1\",\n    \"@angular/compiler-cli\": \"~8.1.1\",\n    \"@angular/language-service\": \"~8.1.1\",\n    \"@types/jasmine\": \"~3.3.8\",\n    \"@types/jasminewd2\": \"~2.0.3\",\n    \"@types/node\": \"~8.9.4\",\n    \"codelyzer\": \"^5.0.0\",\n    \"jasmine-core\": \"~3.4.0\",\n    \"jasmine-spec-reporter\": \"~4.2.1\",\n    \"karma\": \"~4.1.0\",\n    \"karma-chrome-launcher\": \"~2.2.0\",\n    \"karma-coverage-istanbul-reporter\": \"~2.0.1\",\n    \"karma-jasmine\": \"~2.0.1\",\n    \"karma-jasmine-html-reporter\": \"^1.4.0\",\n    \"ng-packagr\": \"^5.1.0\",\n    \"protractor\": \"~5.4.0\",\n    \"ts-node\": \"~7.0.0\",\n    \"tsickle\": \"^0.35.0\",\n    \"tslint\": \"~5.15.0\",\n    \"typescript\": \"~3.4.3\"\n  }\n}\n"
  },
  {
    "path": "todo-client/projects/app-common/README.md",
    "content": "# AppCommon\n\nThis library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.1.3.\n\n## Code scaffolding\n\nRun `ng generate component component-name --project app-common` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project app-common`.\n> Note: Don't forget to add `--project app-common` or else it will be added to the default project in your `angular.json` file. \n\n## Build\n\nRun `ng build app-common` to build the project. The build artifacts will be stored in the `dist/` directory.\n\n## Publishing\n\nAfter building your library with `ng build app-common`, go to the dist folder `cd dist/app-common` and run `npm publish`.\n\n## Running unit tests\n\nRun `ng test app-common` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Further help\n\nTo get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).\n"
  },
  {
    "path": "todo-client/projects/app-common/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular-devkit/build-angular'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular-devkit/build-angular/plugins/karma')\n    ],\n    client: {\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    coverageIstanbulReporter: {\n      dir: require('path').join(__dirname, '../../coverage/app-common'),\n      reports: ['html', 'lcovonly', 'text-summary'],\n      fixWebpackSourcePaths: true\n    },\n    reporters: ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    singleRun: false,\n    restartOnFileChange: true\n  });\n};\n"
  },
  {
    "path": "todo-client/projects/app-common/ng-package.json",
    "content": "{\n  \"$schema\": \"../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"dest\": \"../../dist/app-common\",\n  \"lib\": {\n    \"entryFile\": \"src/public-api.ts\"\n  }\n}"
  },
  {
    "path": "todo-client/projects/app-common/package.json",
    "content": "{\n  \"name\": \"app-common\",\n  \"version\": \"0.0.1\",\n  \"peerDependencies\": {\n    \"@angular/common\": \"^8.1.3\",\n    \"@angular/core\": \"^8.1.3\"\n  }\n}"
  },
  {
    "path": "todo-client/projects/app-common/src/lib/action.ts",
    "content": "export interface DoAction {\n\ttype: string;\n\tpayload: any;\n}\n"
  },
  {
    "path": "todo-client/projects/app-common/src/lib/app-common.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { HttpClientModule } from '@angular/common/http';\nimport { RouterModule } from '@angular/router';\n\n@NgModule({\n\tdeclarations: [],\n\timports: [\n\t\tCommonModule,\n\t\tFormsModule,\n\t\tHttpClientModule,\n\t\tReactiveFormsModule,\n\t\tRouterModule\n\t],\n\texports: [\n\t\tCommonModule,\n\t\tFormsModule,\n\t\tHttpClientModule,\n\t\tReactiveFormsModule,\n\t\tRouterModule\n\t]\n})\nexport class AppCommonModule {}\n"
  },
  {
    "path": "todo-client/projects/app-common/src/public-api.ts",
    "content": "/*\n * Public API Surface of app-common\n */\n\nexport * from './lib/app-common.module';\nexport * from './lib/action';\n"
  },
  {
    "path": "todo-client/projects/app-common/src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/zone';\nimport 'zone.js/dist/zone-testing';\nimport { getTestBed } from '@angular/core/testing';\nimport {\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting\n} from '@angular/platform-browser-dynamic/testing';\n\ndeclare const require: any;\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting()\n);\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n"
  },
  {
    "path": "todo-client/projects/app-common/tsconfig.lib.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/lib\",\n    \"target\": \"es2015\",\n    \"declaration\": true,\n    \"inlineSources\": true,\n    \"types\": [],\n    \"lib\": [\n      \"dom\",\n      \"es2018\"\n    ]\n  },\n  \"angularCompilerOptions\": {\n    \"annotateForClosureCompiler\": true,\n    \"skipTemplateCodegen\": true,\n    \"strictMetadataEmit\": true,\n    \"fullTemplateTypeCheck\": true,\n    \"strictInjectionParameters\": true,\n    \"enableResourceInlining\": true\n  },\n  \"exclude\": [\n    \"src/test.ts\",\n    \"**/*.spec.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/projects/app-common/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/spec\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"src/test.ts\"\n  ],\n  \"include\": [\n    \"**/*.spec.ts\",\n    \"**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/projects/app-common/tslint.json",
    "content": "{\n  \"extends\": \"../../tslint.json\",\n  \"rules\": {\n    \"directive-selector\": [\n      true,\n      \"attribute\",\n      \"lib\",\n      \"camelCase\"\n    ],\n    \"component-selector\": [\n      true,\n      \"element\",\n      \"lib\",\n      \"kebab-case\"\n    ]\n  }\n}\n"
  },
  {
    "path": "todo-client/projects/auth/README.md",
    "content": "# Auth\n\nThis library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.1.3.\n\n## Code scaffolding\n\nRun `ng generate component component-name --project auth` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project auth`.\n> Note: Don't forget to add `--project auth` or else it will be added to the default project in your `angular.json` file. \n\n## Build\n\nRun `ng build auth` to build the project. The build artifacts will be stored in the `dist/` directory.\n\n## Publishing\n\nAfter building your library with `ng build auth`, go to the dist folder `cd dist/auth` and run `npm publish`.\n\n## Running unit tests\n\nRun `ng test auth` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Further help\n\nTo get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).\n"
  },
  {
    "path": "todo-client/projects/auth/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular-devkit/build-angular'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular-devkit/build-angular/plugins/karma')\n    ],\n    client: {\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    coverageIstanbulReporter: {\n      dir: require('path').join(__dirname, '../../coverage/auth'),\n      reports: ['html', 'lcovonly', 'text-summary'],\n      fixWebpackSourcePaths: true\n    },\n    reporters: ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    singleRun: false,\n    restartOnFileChange: true\n  });\n};\n"
  },
  {
    "path": "todo-client/projects/auth/ng-package.json",
    "content": "{\n  \"$schema\": \"../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"dest\": \"../../dist/auth\",\n  \"lib\": {\n    \"entryFile\": \"src/public-api.ts\"\n  }\n}"
  },
  {
    "path": "todo-client/projects/auth/package.json",
    "content": "{\n  \"name\": \"auth\",\n  \"version\": \"0.0.1\",\n  \"peerDependencies\": {\n    \"@angular/common\": \"^8.1.3\",\n    \"@angular/core\": \"^8.1.3\"\n  }\n}"
  },
  {
    "path": "todo-client/projects/auth/src/lib/auth.guard.ts",
    "content": "import { Injectable } from '@angular/core';\n\nimport {\n\tActivatedRouteSnapshot,\n\tRouterStateSnapshot,\n\tCanActivate,\n\tRouter\n} from '@angular/router';\nimport { AuthService } from './services/auth.service';\n\n@Injectable({\n\tprovidedIn: 'root'\n})\nexport class AuthGuard implements CanActivate {\n\tconstructor(private router: Router, private authService: AuthService) {}\n\n\tcanActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {\n\t\tconst currentUser = this.authService.currentUserValue;\n\t\tif (currentUser) {\n\t\t\t// logged in so return true\n\t\t\treturn true;\n\t\t}\n\n\t\t// not logged in so redirect to login page with the return url\n\t\tthis.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/auth/src/lib/auth.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { LoginComponent } from './components/login/login.component';\nimport { AppCommonModule } from 'projects/app-common/src/public-api';\n\n@NgModule({\n\tdeclarations: [LoginComponent],\n\timports: [AppCommonModule],\n\texports: [LoginComponent]\n})\nexport class AuthModule {}\n"
  },
  {
    "path": "todo-client/projects/auth/src/lib/components/login/login.component.css",
    "content": ":host {\n  display: flex;\n  justify-content: center;\n}\n\n.alert-danger {\n  background-color: #f44336; /* Red */\n}\n.alert {\n  padding: 20px;\n  color: white;\n  margin-bottom: 15px;\n  text-align: center;\n}\n"
  },
  {
    "path": "todo-client/projects/auth/src/lib/components/login/login.component.html",
    "content": "<div class=\"container my-3\">\n  <div class=\"row text-center mb-5\">\n    <div class=\"col-md-12 bg-light p-3\">\n      <h2>Login</h2>\n    </div>\n  </div>\n\n  <div class=\"row\">\n    <div class=\"col-md-6 offset-md-3\">\n      <form [formGroup]=\"loginForm\" (ngSubmit)=\"onSubmit()\" autocomplete=\"off\">\n        <div class=\"form-group\">\n          <label for=\"usernam\">Username</label>\n          <input\n            type=\"text\"\n            class=\"form-control\"\n            id=\"username\"\n            formControlName=\"username\"\n            placeholder=\"Username\"\n          />\n          <div *ngIf=\"submitted && f.username.errors\">\n            <small\n              *ngIf=\"f.username.errors.required\"\n              class=\"form-text text-muted\"\n              >Username is required</small\n            >\n          </div>\n        </div>\n        <div class=\"form-group\">\n          <label for=\"password\">Password</label>\n          <input\n            type=\"password\"\n            class=\"form-control\"\n            id=\"password\"\n            placeholder=\"Password\"\n            formControlName=\"password\"\n          />\n          <div *ngIf=\"submitted && f.password.errors\">\n            <small\n              *ngIf=\"f.password.errors.required\"\n              class=\"form-text text-muted\"\n              >Password is required</small\n            >\n          </div>\n        </div>\n        <div *ngIf=\"error\" class=\"my-3\">\n          <small class=\"form-text text-muted\">{{ error | json }}</small>\n        </div>\n        <button type=\"submit\" class=\"btn btn-primary\">Submit</button>\n      </form>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "todo-client/projects/auth/src/lib/components/login/login.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { FormGroup, FormBuilder, Validators } from '@angular/forms';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { first } from 'rxjs/operators';\nimport { AuthService } from '../../services/auth.service';\n\n@Component({\n\ttemplateUrl: 'login.component.html',\n\tstyleUrls: ['login.component.css']\n})\nexport class LoginComponent implements OnInit {\n\tloginForm: FormGroup;\n\tsubmitted = false;\n\treturnUrl: string;\n\terror: string;\n\n\tconstructor(\n\t\tprivate formBuilder: FormBuilder,\n\t\tprivate route: ActivatedRoute,\n\t\tprivate router: Router,\n\t\tprivate authService: AuthService\n\t) {}\n\n\tngOnInit() {\n\t\tthis.loginForm = this.formBuilder.group({\n\t\t\tusername: ['bhaidar', Validators.required],\n\t\t\tpassword: ['@dF%^hGb03W~', Validators.required]\n\t\t});\n\n\t\t// reset login status\n\t\tthis.authService.logout();\n\n\t\t// get return url from route parameters or default to '/'\n\t\tthis.returnUrl = this.route.snapshot.queryParams.returnUrl || '/';\n\t}\n\n\tget f() {\n\t\treturn this.loginForm.controls;\n\t}\n\n\tonSubmit() {\n\t\tthis.submitted = true;\n\n\t\t// stop here if form is invalid\n\t\tif (this.loginForm.invalid) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.authService\n\t\t\t.login(this.f.username.value, this.f.password.value)\n\t\t\t.pipe(first())\n\t\t\t.subscribe(\n\t\t\t\tdata => {\n\t\t\t\t\tthis.error = '';\n\t\t\t\t\tthis.router.navigate([this.returnUrl]);\n\t\t\t\t},\n\t\t\t\terror => {\n\t\t\t\t\tthis.error = error;\n\t\t\t\t}\n\t\t\t);\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/auth/src/lib/services/auth.service.ts",
    "content": "/**\n * Based on\n * https://github.com/cornflourblue/angular-7-jwt-authentication-example\n */\n\nimport { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { HttpClient } from '@angular/common/http';\nimport { map } from 'rxjs/operators';\n\nexport interface ApplicationUser {\n\taccessToken: string;\n\texpiresIn: Date;\n\tusername: string;\n}\n\n@Injectable({\n\tprovidedIn: 'root'\n})\nexport class AuthService {\n\tprivate currentUserSubject: BehaviorSubject<ApplicationUser>;\n\tpublic currentUser: Observable<ApplicationUser>;\n\n\tconstructor(private readonly http: HttpClient) {\n\t\tthis.currentUserSubject = new BehaviorSubject<ApplicationUser>(\n\t\t\tJSON.parse(localStorage.getItem('currentUser'))\n\t\t);\n\t\tthis.currentUser = this.currentUserSubject.asObservable();\n\t}\n\n\tpublic get currentUserValue(): ApplicationUser {\n\t\treturn this.currentUserSubject.value;\n\t}\n\n\tlogin(username: string, password: string) {\n\t\treturn this.http.post<any>('/auth/login', { username, password }).pipe(\n\t\t\tmap(user => {\n\t\t\t\t// login successful if there's a jwt token in the response\n\t\t\t\tif (user && user.accessToken) {\n\t\t\t\t\t// store; user; details; and; jwt; token in local\n\t\t\t\t\t// storage; to; keep; user; logged in between; page; refreshes;\n\n\t\t\t\t\tlocalStorage.setItem('currentUser', JSON.stringify(user));\n\t\t\t\t\tthis.currentUserSubject.next(user);\n\t\t\t\t}\n\n\t\t\t\treturn user;\n\t\t\t})\n\t\t);\n\t}\n\n\tlogout() {\n\t\t// remove user from local storage to log user out\n\t\tlocalStorage.removeItem('currentUser');\n\t\tthis.currentUserSubject.next(null);\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/auth/src/lib/services/error.interceptor.ts",
    "content": "import { Injectable } from '@angular/core';\nimport {\n\tHttpInterceptor,\n\tHttpRequest,\n\tHttpHandler,\n\tHttpEvent,\n\tHttpErrorResponse,\n\tHTTP_INTERCEPTORS\n} from '@angular/common/http';\nimport { Observable, throwError } from 'rxjs';\nimport { catchError } from 'rxjs/operators';\nimport { AuthService } from './auth.service';\n\n@Injectable()\nexport class ErrorInterceptor implements HttpInterceptor {\n\tconstructor(private authService: AuthService) {}\n\n\tintercept(\n\t\trequest: HttpRequest<any>,\n\t\tnext: HttpHandler\n\t): Observable<HttpEvent<any>> {\n\t\treturn next.handle(request).pipe(\n\t\t\tcatchError((err: HttpErrorResponse) => {\n\t\t\t\tif (err.status === 401 && !window.location.href.includes('/login')) {\n\t\t\t\t\t// auto logout if 401 response returned from api\n\t\t\t\t\tthis.authService.logout();\n\t\t\t\t\tlocation.reload();\n\t\t\t\t}\n\n\t\t\t\tconst error = err.error.error || err.error.message || err.statusText;\n\n\t\t\t\talert(error);\n\n\t\t\t\treturn throwError(error);\n\t\t\t})\n\t\t);\n\t}\n}\n\nexport const errorInterceptorProvider = {\n\tprovide: HTTP_INTERCEPTORS,\n\tuseClass: ErrorInterceptor,\n\tmulti: true\n};\n"
  },
  {
    "path": "todo-client/projects/auth/src/lib/services/jwt-interceptor.ts",
    "content": "import {\n\tHttpInterceptor,\n\tHttpRequest,\n\tHttpHandler,\n\tHttpEvent,\n\tHTTP_INTERCEPTORS\n} from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { Injectable } from '@angular/core';\nimport { AuthService } from './auth.service';\n\n@Injectable()\nexport class JwtInterceptor implements HttpInterceptor {\n\tconstructor(private authService: AuthService) {}\n\n\tintercept(\n\t\trequest: HttpRequest<any>,\n\t\tnext: HttpHandler\n\t): Observable<HttpEvent<any>> {\n\t\t// add authorization header with jwt token if available\n\t\tconst currentUser = this.authService.currentUserValue;\n\t\tif (currentUser && currentUser.accessToken) {\n\t\t\trequest = request.clone({\n\t\t\t\tsetHeaders: {\n\t\t\t\t\tAuthorization: `Bearer ${currentUser.accessToken}`\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn next.handle(request);\n\t}\n}\n\nexport const jwtInterceptorProvider = {\n\tprovide: HTTP_INTERCEPTORS,\n\tuseClass: JwtInterceptor,\n\tmulti: true\n};\n"
  },
  {
    "path": "todo-client/projects/auth/src/public-api.ts",
    "content": "/*\n * Public API Surface of auth\n */\n\nexport * from './lib/services/auth.service';\nexport * from './lib/components/login/login.component';\nexport * from './lib/services/jwt-interceptor';\nexport * from './lib/auth.module';\n"
  },
  {
    "path": "todo-client/projects/auth/src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/zone';\nimport 'zone.js/dist/zone-testing';\nimport { getTestBed } from '@angular/core/testing';\nimport {\n\tBrowserDynamicTestingModule,\n\tplatformBrowserDynamicTesting\n} from '@angular/platform-browser-dynamic/testing';\n\ndeclare const require: any;\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(\n\tBrowserDynamicTestingModule,\n\tplatformBrowserDynamicTesting()\n);\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n"
  },
  {
    "path": "todo-client/projects/auth/tsconfig.lib.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/lib\",\n    \"target\": \"es2015\",\n    \"declaration\": true,\n    \"inlineSources\": true,\n    \"types\": [],\n    \"lib\": [\n      \"dom\",\n      \"es2018\"\n    ]\n  },\n  \"angularCompilerOptions\": {\n    \"annotateForClosureCompiler\": true,\n    \"skipTemplateCodegen\": true,\n    \"strictMetadataEmit\": true,\n    \"fullTemplateTypeCheck\": true,\n    \"strictInjectionParameters\": true,\n    \"enableResourceInlining\": true\n  },\n  \"exclude\": [\n    \"src/test.ts\",\n    \"**/*.spec.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/projects/auth/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/spec\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"src/test.ts\"\n  ],\n  \"include\": [\n    \"**/*.spec.ts\",\n    \"**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/projects/auth/tslint.json",
    "content": "{\n  \"extends\": \"../../tslint.json\",\n  \"rules\": {\n    \"directive-selector\": [\n      true,\n      \"attribute\",\n      \"lib\",\n      \"camelCase\"\n    ],\n    \"component-selector\": [\n      true,\n      \"element\",\n      \"lib\",\n      \"kebab-case\"\n    ]\n  }\n}\n"
  },
  {
    "path": "todo-client/projects/todo/README.md",
    "content": "# Todo\n\nThis library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.1.3.\n\n## Code scaffolding\n\nRun `ng generate component component-name --project todo` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project todo`.\n> Note: Don't forget to add `--project todo` or else it will be added to the default project in your `angular.json` file. \n\n## Build\n\nRun `ng build todo` to build the project. The build artifacts will be stored in the `dist/` directory.\n\n## Publishing\n\nAfter building your library with `ng build todo`, go to the dist folder `cd dist/todo` and run `npm publish`.\n\n## Running unit tests\n\nRun `ng test todo` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Further help\n\nTo get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).\n"
  },
  {
    "path": "todo-client/projects/todo/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular-devkit/build-angular'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular-devkit/build-angular/plugins/karma')\n    ],\n    client: {\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    coverageIstanbulReporter: {\n      dir: require('path').join(__dirname, '../../coverage/todo'),\n      reports: ['html', 'lcovonly', 'text-summary'],\n      fixWebpackSourcePaths: true\n    },\n    reporters: ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    singleRun: false,\n    restartOnFileChange: true\n  });\n};\n"
  },
  {
    "path": "todo-client/projects/todo/ng-package.json",
    "content": "{\n  \"$schema\": \"../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"dest\": \"../../dist/todo\",\n  \"lib\": {\n    \"entryFile\": \"src/public-api.ts\"\n  }\n}"
  },
  {
    "path": "todo-client/projects/todo/package.json",
    "content": "{\n  \"name\": \"todo\",\n  \"version\": \"0.0.1\",\n  \"peerDependencies\": {\n    \"@angular/common\": \"^8.1.3\",\n    \"@angular/core\": \"^8.1.3\"\n  }\n}"
  },
  {
    "path": "todo-client/projects/todo/src/lib/components/task-create/task-create.component.ts",
    "content": "import { Component, OnInit, EventEmitter, Output } from '@angular/core';\nimport { DoAction } from 'projects/app-common/src/public-api';\n\n@Component({\n\tselector: 'lib-task-create',\n\ttemplate: `\n    <div class=\"row my-2 mb-4\">\n      <div class=\"col-md-8 offset-md-2\">\n        <input\n          [(ngModel)]=\"task\"\n          (keyup.enter)=\"OnEnter()\"\n          class=\"form-control\"\n          placeholder=\"Type a Task and hit (Enter)\"\n        />\n      </div>\n    </div>\n  `\n})\nexport class TaskCreateComponent implements OnInit {\n\tpublic task = '';\n\n\t@Output()\n\tpublic action: EventEmitter<DoAction> = new EventEmitter();\n\n\tconstructor() {}\n\n\tngOnInit() {}\n\n\tpublic OnEnter() {\n\t\tthis.action.emit({ type: 'add-task', payload: this.task });\n\t\tthis.task = '';\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/components/task-list/task-list.component.ts",
    "content": "import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';\nimport { DoAction } from 'projects/app-common/src/public-api';\nimport { Task } from '../../models/task.model';\n\n@Component({\n\tselector: 'lib-task-list',\n\ttemplate: `\n    <div *ngIf=\"!tasks?.length; else show\"><p>No tasks yet!</p></div>\n    <ng-template #show>\n      <div class=\"list-group\">\n        <div\n          *ngFor=\"let task of tasks; let i = index; trackBy: trackByFn\"\n          class=\"tasks\"\n        >\n          <div class=\"action\">\n            <button\n              (click)=\"doAction(task)\"\n              class=\"btn btn-danger btn-lg\"\n              title=\"Delete {{ task?.name }}\"\n            >\n              <i class=\"fa fa-trash\"></i>\n            </button>\n          </div>\n          <div class=\"task\">\n            <div class=\"list-group-item\">({{ i + 1 }}) {{ task?.name }}</div>\n          </div>\n        </div>\n      </div>\n    </ng-template>\n  `,\n\tstyles: [\n\t\t`\n      .tasks {\n        display: flex;\n        justify-content: center;\n      }\n\n      .tasks .task {\n        flex-grow: 1;\n        flex-shrink: 0;\n      }\n\n      .tasks .action {\n        margin-right: 5px;\n      }\n    `\n\t]\n})\nexport class TaskListComponent implements OnInit {\n\t@Input()\n\tpublic tasks: Task[];\n\n\t@Output()\n\tpublic action: EventEmitter<DoAction> = new EventEmitter();\n\n\tconstructor() {}\n\n\tngOnInit() {}\n\n\tpublic trackByFn(index: number, item: Task) {\n\t\treturn index;\n\t}\n\n\tpublic doAction(task: Task): void {\n\t\tthis.action.emit({ type: 'delete-task', payload: task });\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/components/task.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { Observable, BehaviorSubject, combineLatest, Subject } from 'rxjs';\nimport { Task } from '../models/task.model';\nimport { switchMap, startWith, tap } from 'rxjs/operators';\nimport { DoAction } from 'projects/app-common/src/lib/action';\nimport { TaskService } from '../services/task.service';\nimport { ActivatedRoute, Params } from '@angular/router';\n\n@Component({\n\tselector: 'lib-task',\n\ttemplate: `\n    <lib-task-create (action)=\"doAction($event)\"></lib-task-create>\n    <lib-task-list\n      [tasks]=\"tasks$ | async\"\n      (action)=\"doAction($event)\"\n    ></lib-task-list>\n  `\n})\nexport class TaskComponent implements OnInit {\n\tconstructor(\n\t\tprivate readonly activeRoute: ActivatedRoute,\n\t\tprivate readonly taskService: TaskService\n\t) {}\n\tpublic tasks$: Observable<Task[]>;\n\tprivate refresh$ = new BehaviorSubject<any>('');\n\tprivate activeRoute$: Observable<Params>;\n\tprivate todoId = '';\n\n\tngOnInit() {\n\t\tthis.activeRoute$ = this.activeRoute.params;\n\n\t\tthis.tasks$ = combineLatest(this.activeRoute$, this.refresh$).pipe(\n\t\t\ttap(([param, _]) => (this.todoId = param.id)),\n\t\t\tswitchMap(([param, _]) => this.taskService.findAll(param.id))\n\t\t);\n\t}\n\n\tpublic doAction({ type, payload }: DoAction): void {\n\t\tswitch (type) {\n\t\t\tcase 'add-task':\n\t\t\t\tthis.createTask(payload);\n\t\t\t\tbreak;\n\t\t\tcase 'delete-task':\n\t\t\t\tthis.deleteTask(payload);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tconsole.log('Unknown action type');\n\t\t}\n\t}\n\n\tprivate createTask(task: string): void {\n\t\tthis.taskService\n\t\t\t.create(this.todoId, { name: task })\n\t\t\t.subscribe(() => this.refresh$.next(''));\n\t}\n\n\tprivate deleteTask(task: Task): void {\n\t\tif (confirm('Are you sure you want to delete this item?')) {\n\t\t\tthis.taskService.delete(task.id).subscribe(() => this.refresh$.next(''));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/components/todo-create/todo-create.component.ts",
    "content": "import { Component, OnInit, EventEmitter, Output } from '@angular/core';\nimport { DoAction } from 'projects/app-common/src/public-api';\n\n@Component({\n\tselector: 'lib-todo-create',\n\ttemplate: `\n    <div class=\"row my-2 mb-4\">\n      <div class=\"col-md-8 offset-md-2\">\n        <input\n          [(ngModel)]=\"todo\"\n          (keyup.enter)=\"OnEnter()\"\n          class=\"form-control\"\n          placeholder=\"Type a Todo and hit (Enter)\"\n        />\n      </div>\n    </div>\n  `\n})\nexport class TodoCreateComponent implements OnInit {\n\tpublic todo = '';\n\n\t@Output()\n\tpublic action: EventEmitter<DoAction> = new EventEmitter();\n\n\tconstructor() {}\n\n\tngOnInit() {}\n\n\tpublic OnEnter() {\n\t\tthis.action.emit({ type: 'add-todo', payload: this.todo });\n\t\tthis.todo = '';\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/components/todo-list/todo-list.component.ts",
    "content": "import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';\nimport { Todo } from '../../models/todo.model';\nimport { DoAction } from 'projects/app-common/src/public-api';\n\n@Component({\n\tselector: 'lib-todo-list',\n\ttemplate: `\n    <div *ngIf=\"!todos?.length; else show\">No todos yet!</div>\n    <ng-template #show>\n      <div class=\"list-group\">\n        <div\n          *ngFor=\"let todo of todos; let i = index; trackBy: trackByFn\"\n          class=\"todos\"\n        >\n          <div class=\"action\">\n            <button\n              (click)=\"doAction(todo)\"\n              class=\"btn btn-danger btn-lg\"\n              title=\"Delete {{ todo?.name }}\"\n            >\n              <i class=\"fa fa-trash\"></i>\n            </button>\n          </div>\n          <div class=\"todo\">\n            <a\n              href=\"#\"\n              [routerLink]=\"['tasks', todo.id]\"\n              routerLinkActive=\"list-group-item-primary\"\n              class=\"list-group-item list-group-item-action\"\n            >\n              ({{ i + 1 }}) {{ todo?.name }}\n            </a>\n          </div>\n        </div>\n      </div>\n    </ng-template>\n  `,\n\tstyles: [\n\t\t`\n      .todos {\n        display: flex;\n        justify-content: center;\n      }\n\n      .todos .todo {\n        flex-grow: 1;\n        flex-shrink: 0;\n        max-width: 90%;\n      }\n\n      .todos .action {\n        margin-right: 5px;\n      }\n    `\n\t]\n})\nexport class TodoListComponent implements OnInit {\n\t@Input()\n\tpublic todos: Todo[];\n\n\t@Output()\n\tpublic action: EventEmitter<DoAction> = new EventEmitter();\n\n\tconstructor() {}\n\n\tngOnInit() {}\n\n\tpublic trackByFn(index: number, item: Todo) {\n\t\treturn index;\n\t}\n\n\tpublic doAction(todo: Todo): void {\n\t\tthis.action.emit({ type: 'delete-todo', payload: todo });\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/components/todo.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { Observable, BehaviorSubject } from 'rxjs';\nimport { switchMap, tap } from 'rxjs/operators';\nimport { DoAction } from 'projects/app-common/src/public-api';\nimport { Todo } from '../models/todo.model';\nimport { TodoService } from '../services/todo.service';\nimport { Router } from '@angular/router';\n\n@Component({\n\tselector: 'lib-todo',\n\ttemplate: `\n    <lib-todo-create (action)=\"doAction($event)\"></lib-todo-create>\n    <lib-todo-list\n      [todos]=\"todos$ | async\"\n      (action)=\"doAction($event)\"\n    ></lib-todo-list>\n  `\n})\nexport class TodoComponent implements OnInit {\n\tpublic todos$: Observable<Todo[]>;\n\tprivate refresh$ = new BehaviorSubject<any>('');\n\n\tconstructor(\n\t\tprivate readonly router: Router,\n\t\tprivate readonly todoService: TodoService\n\t) {}\n\n\tngOnInit() {\n\t\tthis.todos$ = this.refresh$.pipe(\n\t\t\tswitchMap(() => this.todoService.findAll())\n\t\t);\n\t}\n\n\tpublic doAction({ type, payload }: DoAction): void {\n\t\tswitch (type) {\n\t\t\tcase 'add-todo':\n\t\t\t\tthis.createTodo(payload);\n\t\t\t\tbreak;\n\t\t\tcase 'delete-todo':\n\t\t\t\tthis.deleteTodo(payload);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tconsole.log('Unknown action type');\n\t\t}\n\t}\n\n\tprivate createTodo(todo: string): void {\n\t\tthis.todoService\n\t\t\t.create({ name: todo })\n\t\t\t.subscribe(() => this.refresh$.next(''));\n\t}\n\n\tprivate deleteTodo(todo: Todo): void {\n\t\tif (confirm('Are you sure you want to delete this item?')) {\n\t\t\tthis.todoService.delete(todo.id).subscribe(() => {\n\t\t\t\tthis.refresh$.next('');\n\t\t\t\tthis.router.navigate(['/todo']);\n\t\t\t});\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/models/task.model.ts",
    "content": "export interface Task {\n\tid?: string;\n\tname: string;\n\tcreatedOn?: Date;\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/models/todo.model.ts",
    "content": "export interface Todo {\n\tid?: string;\n\tname: string;\n\tcreatedOn?: Date;\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/services/task.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport {\n\tHttpHeaders,\n\tHttpClient,\n\tHttpErrorResponse\n} from '@angular/common/http';\nimport { Observable, throwError } from 'rxjs';\nimport { catchError, map } from 'rxjs/operators';\nimport { Task } from '../models/task.model';\n\nconst httpOptions = {\n\theaders: new HttpHeaders({\n\t\t'Content-Type': 'application/json',\n\t\tAuthorization: 'my-auth-token'\n\t})\n};\n\n@Injectable({\n\tprovidedIn: 'root'\n})\nexport class TaskService {\n\tprivate baseUrl = 'api/tasks'; // URL to web api\n\n\tconstructor(private readonly http: HttpClient) {}\n\n\tpublic create(todoId: string, task: Task): Observable<Task> {\n\t\treturn this.http\n\t\t\t.post<Task>(`${this.baseUrl}/todo/${todoId}`, task, httpOptions)\n\t\t\t.pipe(catchError(this.handleError));\n\t}\n\n\tpublic findAll(todoId: string): Observable<Task[]> {\n\t\treturn this.http\n\t\t\t.get<Task[]>(`${this.baseUrl}/todo/${todoId}`, httpOptions)\n\t\t\t.pipe(\n\t\t\t\tmap((results: any) => results.tasks),\n\t\t\t\tcatchError(this.handleError)\n\t\t\t);\n\t}\n\n\tpublic delete(id: string): Observable<{}> {\n\t\tconst url = `${this.baseUrl}/${id}`; // DELETE api/tasks/42-5c-...\n\t\treturn this.http\n\t\t\t.delete(url, httpOptions)\n\t\t\t.pipe(catchError(this.handleError));\n\t}\n\n\tprivate handleError(error: HttpErrorResponse) {\n\t\tif (error.error instanceof ErrorEvent) {\n\t\t\t// A client-side or network error occured. Handle it accordingly\n\t\t\tconsole.error('An error occured:', error.error.message);\n\t\t} else {\n\t\t\t// The backend returned an unsuccessful respone code.\n\t\t\t// The response body may contain clues as to what was wrong\n\t\t\tconsole.log(\n\t\t\t\t`Backend returned code ${error.status}, body was: ${error.status}`\n\t\t\t);\n\t\t}\n\n\t\t// return an observable wuth a user-facing error message\n\t\treturn throwError('Something bad happened; please try again later.');\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/services/todo.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport {\n\tHttpHeaders,\n\tHttpClient,\n\tHttpErrorResponse\n} from '@angular/common/http';\nimport { Observable, throwError } from 'rxjs';\nimport { Todo } from '../models/todo.model';\nimport { catchError, map } from 'rxjs/operators';\n\nconst httpOptions = {\n\theaders: new HttpHeaders({\n\t\t'Content-Type': 'application/json'\n\t})\n};\n\n@Injectable({\n\tprovidedIn: 'root'\n})\nexport class TodoService {\n\tprivate baseUrl = 'api/todos'; // URL to web api\n\n\tconstructor(private readonly http: HttpClient) {}\n\n\tpublic create(todo: Todo): Observable<Todo> {\n\t\treturn this.http\n\t\t\t.post<Todo>(this.baseUrl, todo, httpOptions)\n\t\t\t.pipe(catchError(this.handleError));\n\t}\n\n\tpublic findAll(): Observable<Todo[]> {\n\t\treturn this.http.get<Todo[]>(this.baseUrl, httpOptions).pipe(\n\t\t\tmap((results: any) => results.todos),\n\t\t\tcatchError(this.handleError)\n\t\t);\n\t}\n\n\tpublic delete(id: string): Observable<{}> {\n\t\tconst url = `${this.baseUrl}/${id}`; // DELETE api/todos/42-5c-...\n\t\treturn this.http\n\t\t\t.delete(url, httpOptions)\n\t\t\t.pipe(catchError(this.handleError));\n\t}\n\n\tprivate handleError(error: HttpErrorResponse) {\n\t\tif (error.error instanceof ErrorEvent) {\n\t\t\t// A client-side or network error occured. Handle it accordingly\n\t\t\tconsole.error('An error occured:', error.error.message);\n\t\t} else {\n\t\t\t// The backend returned an unsuccessful respone code.\n\t\t\t// The response body may contain clues as to what was wrong\n\t\t\tconsole.log(\n\t\t\t\t`Backend returned code ${error.status}, body was: ${error.status}`\n\t\t\t);\n\t\t}\n\n\t\t// return an observable wuth a user-facing error message\n\t\treturn throwError('Something bad happened; please try again later.');\n\t}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/todo-home.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n\tselector: 'lib-todo-home',\n\ttemplate: `\n    <div class=\"row my-2\">\n      <div class=\"col-md-6\">\n        <div class=\"row\">\n          <div class=\"col-md-12 bg-light py-3 text-center\">\n            <h5>Todo Lists</h5>\n          </div>\n        </div>\n        <div class=\"row\">\n          <div class=\"col-md-12 my-2\">\n            <lib-todo></lib-todo>\n          </div>\n        </div>\n      </div>\n      <div class=\"col-md-6\">\n        <div class=\"row\">\n          <div\n            class=\"col-md-12 bg-light py-3 border-left border-3 border-primary text-center\"\n          >\n            <h5>Tasks</h5>\n          </div>\n        </div>\n        <div class=\"row\">\n          <div class=\"col-md-12 my-2\">\n            <router-outlet></router-outlet>\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n\tstyles: [\n\t\t`\n      .border-3 {\n        border-width: 3px !important;\n      }\n    `\n\t]\n})\nexport class TodoHomeComponent implements OnInit {\n\tconstructor() {}\n\n\tngOnInit() {}\n}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/todo.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { AppCommonModule } from 'projects/app-common/src/public-api';\nimport { TodoListComponent } from './components/todo-list/todo-list.component';\nimport { TodoCreateComponent } from './components/todo-create/todo-create.component';\nimport { TaskComponent } from './components/task.component';\nimport { TodoHomeComponent } from './todo-home.component';\nimport { TodoComponent } from './components/todo.component';\nimport { TaskCreateComponent } from './components/task-create/task-create.component';\nimport { TaskListComponent } from './components/task-list/task-list.component';\n\n@NgModule({\n\tdeclarations: [\n\t\tTodoComponent,\n\t\tTodoCreateComponent,\n\t\tTodoListComponent,\n\t\tTaskComponent,\n\t\tTodoHomeComponent,\n\t\tTaskCreateComponent,\n\t\tTaskListComponent\n\t],\n\timports: [AppCommonModule],\n\texports: [TodoHomeComponent, TaskComponent]\n})\nexport class TodoModule {}\n"
  },
  {
    "path": "todo-client/projects/todo/src/lib/todo.service.spec.ts",
    "content": "import { TestBed } from '@angular/core/testing';\n\nimport { TodoService } from './todo.service';\n\ndescribe('TodoService', () => {\n  beforeEach(() => TestBed.configureTestingModule({}));\n\n  it('should be created', () => {\n    const service: TodoService = TestBed.get(TodoService);\n    expect(service).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "todo-client/projects/todo/src/public-api.ts",
    "content": "/*\n * Public API Surface of todo\n */\n\nexport * from './lib/todo-home.component';\nexport * from './lib/components/task.component';\nexport * from './lib/todo.module';\n"
  },
  {
    "path": "todo-client/projects/todo/src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/zone';\nimport 'zone.js/dist/zone-testing';\nimport { getTestBed } from '@angular/core/testing';\nimport {\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting\n} from '@angular/platform-browser-dynamic/testing';\n\ndeclare const require: any;\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting()\n);\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n"
  },
  {
    "path": "todo-client/projects/todo/tsconfig.lib.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/lib\",\n    \"target\": \"es2015\",\n    \"declaration\": true,\n    \"inlineSources\": true,\n    \"types\": [],\n    \"lib\": [\n      \"dom\",\n      \"es2018\"\n    ]\n  },\n  \"angularCompilerOptions\": {\n    \"annotateForClosureCompiler\": true,\n    \"skipTemplateCodegen\": true,\n    \"strictMetadataEmit\": true,\n    \"fullTemplateTypeCheck\": true,\n    \"strictInjectionParameters\": true,\n    \"enableResourceInlining\": true\n  },\n  \"exclude\": [\n    \"src/test.ts\",\n    \"**/*.spec.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/projects/todo/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/spec\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"src/test.ts\"\n  ],\n  \"include\": [\n    \"**/*.spec.ts\",\n    \"**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/projects/todo/tslint.json",
    "content": "{\n  \"extends\": \"../../tslint.json\",\n  \"rules\": {\n    \"directive-selector\": [\n      true,\n      \"attribute\",\n      \"lib\",\n      \"camelCase\"\n    ],\n    \"component-selector\": [\n      true,\n      \"element\",\n      \"lib\",\n      \"kebab-case\"\n    ]\n  }\n}\n"
  },
  {
    "path": "todo-client/proxy.conf.json",
    "content": "{\n  \"/api\": {\n    \"target\": \"http://localhost:4000\",\n    \"secure\": false\n  },\n  \"/auth\": {\n    \"target\": \"http://localhost:4000/auth/\",\n    \"secure\": false,\n    \"pathRewrite\": {\n      \"^/auth\": \"\"\n    }\n  }\n}\n"
  },
  {
    "path": "todo-client/src/app/app-routing.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { Routes, RouterModule } from '@angular/router';\nimport { LoginComponent } from 'projects/auth/src/public-api';\nimport { MasterComponent } from './shared/master/master.component';\nimport { HomeComponent } from './shared/home/home.component';\nimport { AuthGuard } from 'projects/auth/src/lib/auth.guard';\nimport { TodoHomeComponent, TaskComponent } from 'projects/todo/src/public-api';\n\nconst routes: Routes = [\n\t{\n\t\tpath: '',\n\t\tcomponent: MasterComponent,\n\t\tcanActivate: [AuthGuard],\n\t\tchildren: [\n\t\t\t{\n\t\t\t\tpath: '',\n\t\t\t\tcomponent: HomeComponent\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: 'todo',\n\t\t\t\tcomponent: TodoHomeComponent,\n\t\t\t\tchildren: [\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: 'tasks/:id',\n\t\t\t\t\t\tcomponent: TaskComponent\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\tpath: '',\n\t\tchildren: [\n\t\t\t{\n\t\t\t\tpath: 'login',\n\t\t\t\tcomponent: LoginComponent\n\t\t\t}\n\t\t]\n\t},\n\t{ path: '**', redirectTo: '' }\n];\n\n@NgModule({\n\timports: [RouterModule.forRoot(routes)],\n\texports: [RouterModule]\n})\nexport class AppRoutingModule {}\n"
  },
  {
    "path": "todo-client/src/app/app.component.html",
    "content": "<router-outlet></router-outlet>\n"
  },
  {
    "path": "todo-client/src/app/app.component.scss",
    "content": ""
  },
  {
    "path": "todo-client/src/app/app.component.spec.ts",
    "content": "import { TestBed, async } from '@angular/core/testing';\nimport { RouterTestingModule } from '@angular/router/testing';\nimport { AppComponent } from './app.component';\n\ndescribe('AppComponent', () => {\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      imports: [\n        RouterTestingModule\n      ],\n      declarations: [\n        AppComponent\n      ],\n    }).compileComponents();\n  }));\n\n  it('should create the app', () => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app).toBeTruthy();\n  });\n\n  it(`should have as title 'todo-client'`, () => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app.title).toEqual('todo-client');\n  });\n\n  it('should render title in a h1 tag', () => {\n    const fixture = TestBed.createComponent(AppComponent);\n    fixture.detectChanges();\n    const compiled = fixture.debugElement.nativeElement;\n    expect(compiled.querySelector('h1').textContent).toContain('Welcome to todo-client!');\n  });\n});\n"
  },
  {
    "path": "todo-client/src/app/app.component.ts",
    "content": "import { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html',\n  styleUrls: ['./app.component.scss']\n})\nexport class AppComponent {\n  title = 'todo-client';\n}\n"
  },
  {
    "path": "todo-client/src/app/app.module.ts",
    "content": "import { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\n\nimport { AppRoutingModule } from './app-routing.module';\nimport { AppComponent } from './app.component';\nimport {\n\tAuthModule,\n\tjwtInterceptorProvider\n} from 'projects/auth/src/public-api';\nimport { AppCommonModule } from 'projects/app-common/src/public-api';\nimport { MasterComponent } from './shared/master/master.component';\nimport { HomeComponent } from './shared/home/home.component';\nimport { TodoModule } from 'projects/todo/src/public-api';\nimport { errorInterceptorProvider } from 'projects/auth/src/lib/services/error.interceptor';\n\n@NgModule({\n\tdeclarations: [AppComponent, MasterComponent, HomeComponent],\n\timports: [\n\t\tBrowserModule,\n\t\tAppRoutingModule,\n\t\tAppCommonModule,\n\t\tAuthModule,\n\t\tTodoModule\n\t],\n\tproviders: [jwtInterceptorProvider, errorInterceptorProvider],\n\tbootstrap: [AppComponent]\n})\nexport class AppModule {}\n"
  },
  {
    "path": "todo-client/src/app/shared/home/home.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n\tselector: 'app-home',\n\ttemplate: `\n    <div class=\"row text-center\">\n      <div class=\"col-md-12\">\n        <h2 class=\"\">Welcome to Todozz App!</h2>\n\n        <p>Here you can manage your Todo Lists in a breeze!</p>\n      </div>\n    </div>\n  `\n})\nexport class HomeComponent implements OnInit {\n\tconstructor() {}\n\n\tngOnInit() {}\n}\n"
  },
  {
    "path": "todo-client/src/app/shared/master/master.component.html",
    "content": "<div class=\"navbar navbar-expand-lg navbar-light bg-light shadow fixed-top\">\n  <div class=\"container\">\n    <a class=\"navbar-brand\" href=\"#\">\n      <i class=\"fas fa-tasks\"></i>&nbsp;Todozz</a\n    >\n    <button\n      class=\"navbar-toggler\"\n      type=\"button\"\n      data-toggle=\"collapse\"\n      data-target=\"#navbarResponsive\"\n      aria-controls=\"navbarResponsive\"\n      aria-expanded=\"false\"\n      aria-label=\"Toggle navigation\"\n    >\n      <span class=\"navbar-toggler-icon\"></span>\n    </button>\n    <div class=\"collapse navbar-collapse\" id=\"navbarResponsive\">\n      <ul class=\"navbar-nav ml-auto\">\n        <li class=\"nav-item\" routerLinkActive=\"active\">\n          <a class=\"nav-link\" [routerLink]=\"['/']\">\n            Home\n          </a>\n        </li>\n        <li class=\"nav-item\" routerLinkActive=\"active\">\n          <a class=\"nav-link\" [routerLink]=\"['/todo']\">Todo</a>\n        </li>\n        <li *ngIf=\"loggedIn\" class=\"nav-item\" routerLinkActive=\"active\">\n          <a class=\"nav-link\" (click)=\"logout()\" href=\"\">Logout</a>\n        </li>\n      </ul>\n    </div>\n  </div>\n</div>\n<section class=\"py-5 mt-5\">\n  <div class=\"container\">\n    <router-outlet></router-outlet>\n  </div>\n</section>\n"
  },
  {
    "path": "todo-client/src/app/shared/master/master.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { AuthService } from 'projects/auth/src/public-api';\nimport { Router } from '@angular/router';\n\n@Component({\n\tselector: 'app-master',\n\ttemplate: `\n    <div class=\"navbar navbar-expand-lg navbar-light bg-light shadow fixed-top\">\n      <div class=\"container\">\n        <a class=\"navbar-brand\" href=\"#\">\n          <i class=\"fas fa-tasks\"></i>&nbsp;Todozz</a\n        >\n        <button\n          class=\"navbar-toggler\"\n          type=\"button\"\n          data-toggle=\"collapse\"\n          data-target=\"#navbarResponsive\"\n          aria-controls=\"navbarResponsive\"\n          aria-expanded=\"false\"\n          aria-label=\"Toggle navigation\"\n        >\n          <span class=\"navbar-toggler-icon\"></span>\n        </button>\n        <div class=\"collapse navbar-collapse\" id=\"navbarResponsive\">\n          <ul class=\"navbar-nav ml-auto\">\n            <li class=\"nav-item\">\n              <a\n                class=\"nav-link\"\n                [routerLink]=\"['/']\"\n                [routerLinkActiveOptions]=\"{ exact: true }\"\n                routerLinkActive=\"active\"\n              >\n                Home\n              </a>\n            </li>\n            <li class=\"nav-item\">\n              <a\n                class=\"nav-link\"\n                [routerLink]=\"['/todo']\"\n                [routerLinkActiveOptions]=\"{ exact: true }\"\n                routerLinkActive=\"active\"\n                >Todo</a\n              >\n            </li>\n            <li *ngIf=\"loggedIn\" class=\"nav-item\">\n              <a class=\"nav-link\" (click)=\"logout()\" href=\"\">Logout</a>\n            </li>\n          </ul>\n        </div>\n      </div>\n    </div>\n    <section class=\"py-5 mt-5\">\n      <div class=\"container\">\n        <router-outlet></router-outlet>\n      </div>\n    </section>\n  `\n})\nexport class MasterComponent implements OnInit {\n\tpublic loggedIn = false;\n\n\tconstructor(\n\t\tprivate readonly authService: AuthService,\n\t\tprivate readonly router: Router\n\t) {}\n\n\tngOnInit() {\n\t\tthis.loggedIn = !!this.authService.currentUserValue;\n\t}\n\n\tpublic logout(): void {\n\t\tthis.authService.logout();\n\t\tthis.router.navigate(['/login']);\n\t}\n}\n"
  },
  {
    "path": "todo-client/src/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "todo-client/src/environments/environment.prod.ts",
    "content": "export const environment = {\n  production: true\n};\n"
  },
  {
    "path": "todo-client/src/environments/environment.ts",
    "content": "// This file can be replaced during build by using the `fileReplacements` array.\n// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.\n// The list of file replacements can be found in `angular.json`.\n\nexport const environment = {\n  production: false\n};\n\n/*\n * For easier debugging in development mode, you can import the following file\n * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.\n *\n * This import should be commented out in production mode because it will have a negative impact\n * on performance if an error is thrown.\n */\n// import 'zone.js/dist/zone-error';  // Included with Angular CLI.\n"
  },
  {
    "path": "todo-client/src/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>TodoClient</title>\n    <base href=\"/\" />\n\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link\n      rel=\"stylesheet\"\n      href=\"https://use.fontawesome.com/releases/v5.7.0/css/all.css\"\n      integrity=\"sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ\"\n      crossorigin=\"anonymous\"\n    />\n\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n  </head>\n  <body>\n    <app-root></app-root>\n  </body>\n</html>\n"
  },
  {
    "path": "todo-client/src/main.ts",
    "content": "import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n  enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule)\n  .catch(err => console.error(err));\n"
  },
  {
    "path": "todo-client/src/polyfills.ts",
    "content": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfills to this file.\n *\n * This file is divided into 2 sections:\n *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\n *   2. Application imports. Files imported after ZoneJS that should be loaded before your main\n *      file.\n *\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\n * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),\n * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.\n *\n * Learn more in https://angular.io/guide/browser-support\n */\n\n/***************************************************************************************************\n * BROWSER POLYFILLS\n */\n\n/** IE10 and IE11 requires the following for NgClass support on SVG elements */\n// import 'classlist.js';  // Run `npm install --save classlist.js`.\n\n/**\n * Web Animations `@angular/platform-browser/animations`\n * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.\n * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).\n */\n// import 'web-animations-js';  // Run `npm install --save web-animations-js`.\n\n/**\n * By default, zone.js will patch all possible macroTask and DomEvents\n * user can disable parts of macroTask/DomEvents patch by setting following flags\n * because those flags need to be set before `zone.js` being loaded, and webpack\n * will put import in the top of bundle, so user need to create a separate file\n * in this directory (for example: zone-flags.ts), and put the following flags\n * into that file, and then add the following code before importing zone.js.\n * import './zone-flags.ts';\n *\n * The flags allowed in zone-flags.ts are listed here.\n *\n * The following flags will work for all browsers.\n *\n * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame\n * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick\n * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames\n *\n *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js\n *  with the following flag, it will bypass `zone.js` patch for IE/Edge\n *\n *  (window as any).__Zone_enable_cross_context_check = true;\n *\n */\n\n/***************************************************************************************************\n * Zone JS is required by default for Angular itself.\n */\nimport 'zone.js/dist/zone';  // Included with Angular CLI.\n\n\n/***************************************************************************************************\n * APPLICATION IMPORTS\n */\n"
  },
  {
    "path": "todo-client/src/styles.scss",
    "content": "/* You can add global styles to this file, and also import other style files */\n@import '~bootstrap/dist/css/bootstrap.min.css';"
  },
  {
    "path": "todo-client/src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/zone-testing';\nimport { getTestBed } from '@angular/core/testing';\nimport {\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting\n} from '@angular/platform-browser-dynamic/testing';\n\ndeclare const require: any;\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting()\n);\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n"
  },
  {
    "path": "todo-client/tsconfig.app.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/app\",\n    \"types\": []\n  },\n  \"include\": [\n    \"src/**/*.ts\"\n  ],\n  \"exclude\": [\n    \"src/test.ts\",\n    \"src/**/*.spec.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"baseUrl\": \"./\",\n    \"outDir\": \"./dist/out-tsc\",\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"downlevelIteration\": true,\n    \"experimentalDecorators\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"importHelpers\": true,\n    \"target\": \"es2015\",\n    \"typeRoots\": [\n      \"node_modules/@types\"\n    ],\n    \"lib\": [\n      \"es2018\",\n      \"dom\"\n    ],\n    \"paths\": {\n      \"auth\": [\n        \"dist/auth\"\n      ],\n      \"auth/*\": [\n        \"dist/auth/*\"\n      ],\n      \"common\": [\n        \"dist/common\",\n        \"dist/common\",\n        \"dist/common\"\n      ],\n      \"common/*\": [\n        \"dist/common/*\",\n        \"dist/common/*\",\n        \"dist/common/*\"\n      ],\n      \"app-common\": [\n        \"dist/app-common\"\n      ],\n      \"app-common/*\": [\n        \"dist/app-common/*\"\n      ],\n      \"todo\": [\n        \"dist/todo\"\n      ],\n      \"todo/*\": [\n        \"dist/todo/*\"\n      ]\n    }\n  },\n  \"angularCompilerOptions\": {\n    \"fullTemplateTypeCheck\": true,\n    \"strictInjectionParameters\": true\n  }\n}"
  },
  {
    "path": "todo-client/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/spec\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"src/test.ts\",\n    \"src/polyfills.ts\"\n  ],\n  \"include\": [\n    \"src/**/*.spec.ts\",\n    \"src/**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "todo-client/tslint.json",
    "content": "{\n  \"extends\": [\"tslint:recommended\"],\n  \"rules\": {\n    \"array-type\": false,\n    \"arrow-parens\": false,\n    \"deprecation\": {\n      \"severity\": \"warning\"\n    },\n    \"component-class-suffix\": true,\n    \"contextual-lifecycle\": true,\n    \"directive-class-suffix\": true,\n    \"directive-selector\": [true, \"attribute\", \"app\", \"camelCase\"],\n    \"component-selector\": [true, \"element\", \"app\", \"kebab-case\"],\n    \"import-blacklist\": [true, \"rxjs/Rx\"],\n    \"indent\": [true, \"tabs\", 2],\n    \"interface-name\": false,\n    \"max-classes-per-file\": false,\n    \"max-line-length\": [true, 120],\n    \"member-access\": false,\n    \"member-ordering\": [\n      true,\n      {\n        \"order\": [\n          \"static-field\",\n          \"instance-field\",\n          \"static-method\",\n          \"instance-method\"\n        ]\n      }\n    ],\n    \"no-consecutive-blank-lines\": false,\n    \"no-console\": [true, \"debug\", \"info\", \"time\", \"timeEnd\", \"trace\"],\n    \"no-empty\": false,\n    \"no-inferrable-types\": [true, \"ignore-params\"],\n    \"no-non-null-assertion\": true,\n    \"no-redundant-jsdoc\": true,\n    \"no-switch-case-fall-through\": true,\n    \"no-use-before-declare\": true,\n    \"no-var-requires\": false,\n    \"object-literal-key-quotes\": [true, \"as-needed\"],\n    \"object-literal-sort-keys\": false,\n    \"ordered-imports\": false,\n    \"quotemark\": [true, \"single\"],\n    \"trailing-comma\": false,\n    \"no-conflicting-lifecycle\": true,\n    \"no-host-metadata-property\": true,\n    \"no-input-rename\": true,\n    \"no-inputs-metadata-property\": true,\n    \"no-output-native\": true,\n    \"no-output-on-prefix\": true,\n    \"no-output-rename\": true,\n    \"no-outputs-metadata-property\": true,\n    \"template-banana-in-box\": true,\n    \"template-no-negated-async\": true,\n    \"use-lifecycle-interface\": true,\n    \"use-pipe-transform-interface\": true\n  },\n  \"rulesDirectory\": [\"codelyzer\"]\n}\n"
  }
]