├── .gitignore ├── .vscode └── launch.json ├── README.md ├── build └── api.bundle.js ├── package.json ├── src ├── app.module.ts ├── book │ ├── addBook.dto.ts │ ├── book.controller.ts │ ├── book.module.ts │ ├── book.providers.ts │ ├── book.schema.ts │ ├── book.service.ts │ └── getBook.middleware.ts ├── dbConfig │ ├── dbConfig.module.ts │ └── dbConfig.providers.ts └── index.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /package-lock.json -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "attach", 7 | "name": "Attach by Process ID", 8 | "processId": "${command:PickProcess}" 9 | }, 10 | { 11 | "type": "node", 12 | "request": "launch", 13 | "name": "Launch Program", 14 | "program": "${file}", 15 | "outFiles": [ 16 | "${workspaceRoot}/out/**/*.js" 17 | ] 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Books Library API 2 | A book store restful api built with nestjs, nodejs , express , monogoodb , mongoose 3 | 4 |

5 | Nest Logo 6 |

7 | 8 | 9 |

A progressive Node.js framework for building efficient and scalable web applications.

10 |

11 |

12 | 14 | 15 | ## Description 16 | 17 | [Nest](https://github.com/nestjs/nest) framework **TypeScript** starter repository. 18 | 19 | ## Installation 20 | 21 | ```bash 22 | $ npm install 23 | ``` 24 | 25 | ## Start 26 | 27 | ``` 28 | $ npm run start 29 | ``` 30 | 31 | ## People 32 | 33 | - Author - [Abdallah Khalil](https://abdallah-khalil.github.io) 34 | 35 | 36 | -------------------------------------------------------------------------------- /build/api.bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { 40 | /******/ configurable: false, 41 | /******/ enumerable: true, 42 | /******/ get: getter 43 | /******/ }); 44 | /******/ } 45 | /******/ }; 46 | /******/ 47 | /******/ // getDefaultExport function for compatibility with non-harmony modules 48 | /******/ __webpack_require__.n = function(module) { 49 | /******/ var getter = module && module.__esModule ? 50 | /******/ function getDefault() { return module['default']; } : 51 | /******/ function getModuleExports() { return module; }; 52 | /******/ __webpack_require__.d(getter, 'a', getter); 53 | /******/ return getter; 54 | /******/ }; 55 | /******/ 56 | /******/ // Object.prototype.hasOwnProperty.call 57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 | /******/ 59 | /******/ // __webpack_public_path__ 60 | /******/ __webpack_require__.p = ""; 61 | /******/ 62 | /******/ // Load entry module and return exports 63 | /******/ return __webpack_require__(__webpack_require__.s = 3); 64 | /******/ }) 65 | /************************************************************************/ 66 | /******/ ([ 67 | /* 0 */ 68 | /***/ (function(module, exports) { 69 | 70 | module.exports = require("@nestjs/common"); 71 | 72 | /***/ }), 73 | /* 1 */ 74 | /***/ (function(module, exports) { 75 | 76 | module.exports = require("mongoose"); 77 | 78 | /***/ }), 79 | /* 2 */ 80 | /***/ (function(module, exports, __webpack_require__) { 81 | 82 | "use strict"; 83 | 84 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 85 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 86 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 87 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 88 | return c > 3 && r && Object.defineProperty(target, key, r), r; 89 | }; 90 | var __metadata = (this && this.__metadata) || function (k, v) { 91 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 92 | }; 93 | var __param = (this && this.__param) || function (paramIndex, decorator) { 94 | return function (target, key) { decorator(target, key, paramIndex); } 95 | }; 96 | Object.defineProperty(exports, "__esModule", { value: true }); 97 | const mongoose_1 = __webpack_require__(1); 98 | const common_1 = __webpack_require__(0); 99 | let BookService = class BookService { 100 | constructor(BookModel) { 101 | this.BookModel = BookModel; 102 | } 103 | async findAll(reqQuery) { 104 | let query = {}; 105 | if (reqQuery.genre) { 106 | query.genre = reqQuery.genre; 107 | } 108 | return await this.BookModel.find(query).exec(); 109 | } 110 | async findBook(bookId) { 111 | return await this.BookModel.findById(bookId); 112 | } 113 | async addBook(addDookDTO) { 114 | const createdBook = new this.BookModel(addDookDTO); 115 | return await createdBook.save(); 116 | } 117 | async editBook(addBookDTO, book) { 118 | const editedBook = book; 119 | editedBook.title = addBookDTO.title; 120 | editedBook.genre = addBookDTO.genre; 121 | editedBook.author = addBookDTO.author; 122 | editedBook.read = addBookDTO.read; 123 | return await editedBook.save(); 124 | } 125 | async deleteBook(book) { 126 | await book.remove(); 127 | return "Deleted Successfully"; 128 | } 129 | }; 130 | BookService = __decorate([ 131 | common_1.Component(), 132 | __param(0, common_1.Inject('bookModelToken')), 133 | __metadata("design:paramtypes", [mongoose_1.Model]) 134 | ], BookService); 135 | exports.BookService = BookService; 136 | 137 | 138 | /***/ }), 139 | /* 3 */ 140 | /***/ (function(module, exports, __webpack_require__) { 141 | 142 | "use strict"; 143 | 144 | Object.defineProperty(exports, "__esModule", { value: true }); 145 | const bodyParser = __webpack_require__(4); 146 | const core_1 = __webpack_require__(5); 147 | const app_module_1 = __webpack_require__(6); 148 | async function bootstrap() { 149 | const app = await core_1.NestFactory.create(app_module_1.ApplicationModule); 150 | app.use(bodyParser.json()); 151 | await app.listen(3001); 152 | } 153 | bootstrap(); 154 | 155 | 156 | /***/ }), 157 | /* 4 */ 158 | /***/ (function(module, exports) { 159 | 160 | module.exports = require("body-parser"); 161 | 162 | /***/ }), 163 | /* 5 */ 164 | /***/ (function(module, exports) { 165 | 166 | module.exports = require("@nestjs/core"); 167 | 168 | /***/ }), 169 | /* 6 */ 170 | /***/ (function(module, exports, __webpack_require__) { 171 | 172 | "use strict"; 173 | 174 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 175 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 176 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 177 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 178 | return c > 3 && r && Object.defineProperty(target, key, r), r; 179 | }; 180 | Object.defineProperty(exports, "__esModule", { value: true }); 181 | const common_1 = __webpack_require__(0); 182 | const book_module_1 = __webpack_require__(7); 183 | let ApplicationModule = class ApplicationModule { 184 | }; 185 | ApplicationModule = __decorate([ 186 | common_1.Module({ 187 | modules: [book_module_1.BookModule] 188 | }) 189 | ], ApplicationModule); 190 | exports.ApplicationModule = ApplicationModule; 191 | 192 | 193 | /***/ }), 194 | /* 7 */ 195 | /***/ (function(module, exports, __webpack_require__) { 196 | 197 | "use strict"; 198 | 199 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 200 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 201 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 202 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 203 | return c > 3 && r && Object.defineProperty(target, key, r), r; 204 | }; 205 | Object.defineProperty(exports, "__esModule", { value: true }); 206 | const common_1 = __webpack_require__(0); 207 | const dbConfig_module_1 = __webpack_require__(8); 208 | const book_providers_1 = __webpack_require__(10); 209 | const book_service_1 = __webpack_require__(2); 210 | const book_controller_1 = __webpack_require__(12); 211 | const getBook_middleware_1 = __webpack_require__(14); 212 | let BookModule = class BookModule { 213 | configure(consumer) { 214 | consumer.apply(getBook_middleware_1.GetBookMiddleware).forRoutes({ path: 'api/book/:bookId', method: common_1.RequestMethod.GET }, { path: 'api/book/:bookId', method: common_1.RequestMethod.PUT }, { path: 'api/book/:bookId', method: common_1.RequestMethod.PATCH }, { path: 'api/book/:bookId', method: common_1.RequestMethod.DELETE }); 215 | } 216 | }; 217 | BookModule = __decorate([ 218 | common_1.Module({ 219 | modules: [dbConfig_module_1.dbConfigModule], 220 | components: [ 221 | book_service_1.BookService, 222 | ...book_providers_1.BookProviders 223 | ], 224 | controllers: [book_controller_1.BookController] 225 | }) 226 | ], BookModule); 227 | exports.BookModule = BookModule; 228 | 229 | 230 | /***/ }), 231 | /* 8 */ 232 | /***/ (function(module, exports, __webpack_require__) { 233 | 234 | "use strict"; 235 | 236 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 237 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 238 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 239 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 240 | return c > 3 && r && Object.defineProperty(target, key, r), r; 241 | }; 242 | Object.defineProperty(exports, "__esModule", { value: true }); 243 | const common_1 = __webpack_require__(0); 244 | const dbConfig_providers_1 = __webpack_require__(9); 245 | let dbConfigModule = class dbConfigModule { 246 | }; 247 | dbConfigModule = __decorate([ 248 | common_1.Module({ 249 | components: [...dbConfig_providers_1.dbConfigProviders], 250 | exports: [...dbConfig_providers_1.dbConfigProviders] 251 | }) 252 | ], dbConfigModule); 253 | exports.dbConfigModule = dbConfigModule; 254 | 255 | 256 | /***/ }), 257 | /* 9 */ 258 | /***/ (function(module, exports, __webpack_require__) { 259 | 260 | "use strict"; 261 | 262 | Object.defineProperty(exports, "__esModule", { value: true }); 263 | const mongoose = __webpack_require__(1); 264 | exports.dbConfigProviders = [ 265 | { 266 | provide: 'DbConToken', 267 | useFactory: async () => { 268 | mongoose.Promise = global.Promise; 269 | return await mongoose.connect('mongodb://localhost:27017/libraryApp', { 270 | useMongoClient: true, 271 | }); 272 | }, 273 | }, 274 | ]; 275 | 276 | 277 | /***/ }), 278 | /* 10 */ 279 | /***/ (function(module, exports, __webpack_require__) { 280 | 281 | "use strict"; 282 | 283 | Object.defineProperty(exports, "__esModule", { value: true }); 284 | const book_schema_1 = __webpack_require__(11); 285 | exports.BookProviders = [ 286 | { 287 | provide: 'bookModelToken', 288 | useFactory: async (connection) => connection.model('Book', book_schema_1.BookSchema), 289 | inject: ['DbConToken'] 290 | } 291 | ]; 292 | 293 | 294 | /***/ }), 295 | /* 11 */ 296 | /***/ (function(module, exports, __webpack_require__) { 297 | 298 | "use strict"; 299 | 300 | Object.defineProperty(exports, "__esModule", { value: true }); 301 | const mongoose_1 = __webpack_require__(1); 302 | exports.BookSchema = new mongoose_1.Schema({ 303 | title: { 304 | type: String 305 | }, 306 | author: { 307 | type: String 308 | }, 309 | genre: { 310 | type: String 311 | }, 312 | read: { 313 | type: Boolean, 314 | default: false 315 | } 316 | }); 317 | 318 | 319 | /***/ }), 320 | /* 12 */ 321 | /***/ (function(module, exports, __webpack_require__) { 322 | 323 | "use strict"; 324 | 325 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 326 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 327 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 328 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 329 | return c > 3 && r && Object.defineProperty(target, key, r), r; 330 | }; 331 | var __metadata = (this && this.__metadata) || function (k, v) { 332 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 333 | }; 334 | var __param = (this && this.__param) || function (paramIndex, decorator) { 335 | return function (target, key) { decorator(target, key, paramIndex); } 336 | }; 337 | Object.defineProperty(exports, "__esModule", { value: true }); 338 | const common_1 = __webpack_require__(0); 339 | const book_service_1 = __webpack_require__(2); 340 | const addBook_dto_1 = __webpack_require__(13); 341 | let BookController = class BookController { 342 | constructor(bookService) { 343 | this.bookService = bookService; 344 | } 345 | async findAll(reqQuery) { 346 | return await this.bookService.findAll(reqQuery); 347 | } 348 | async addBook(addBookDTO) { 349 | return this.bookService.addBook(addBookDTO); 350 | } 351 | async findBook(request) { 352 | return request.book; 353 | } 354 | async editBook(request) { 355 | return this.bookService.editBook(request.body, request.book); 356 | } 357 | async patchBook(request) { 358 | if (request.body._id) { 359 | delete request.body._id; 360 | } 361 | return this.bookService.editBook(request.body, request.book); 362 | } 363 | async deleteBook(request) { 364 | return this.bookService.deleteBook(request.book); 365 | } 366 | }; 367 | __decorate([ 368 | common_1.Get(), 369 | __param(0, common_1.Query()), 370 | __metadata("design:type", Function), 371 | __metadata("design:paramtypes", [Object]), 372 | __metadata("design:returntype", Promise) 373 | ], BookController.prototype, "findAll", null); 374 | __decorate([ 375 | common_1.Post(), 376 | __param(0, common_1.Body()), 377 | __metadata("design:type", Function), 378 | __metadata("design:paramtypes", [addBook_dto_1.AddBookDTO]), 379 | __metadata("design:returntype", Promise) 380 | ], BookController.prototype, "addBook", null); 381 | __decorate([ 382 | common_1.Get("/:bookId"), 383 | __param(0, common_1.Req()), 384 | __metadata("design:type", Function), 385 | __metadata("design:paramtypes", [Object]), 386 | __metadata("design:returntype", Promise) 387 | ], BookController.prototype, "findBook", null); 388 | __decorate([ 389 | common_1.Put("/:bookId"), 390 | __param(0, common_1.Req()), 391 | __metadata("design:type", Function), 392 | __metadata("design:paramtypes", [Object]), 393 | __metadata("design:returntype", Promise) 394 | ], BookController.prototype, "editBook", null); 395 | __decorate([ 396 | common_1.Patch("/:bookId"), 397 | __param(0, common_1.Req()), 398 | __metadata("design:type", Function), 399 | __metadata("design:paramtypes", [Object]), 400 | __metadata("design:returntype", Promise) 401 | ], BookController.prototype, "patchBook", null); 402 | __decorate([ 403 | common_1.Delete("/:bookId"), 404 | __param(0, common_1.Req()), 405 | __metadata("design:type", Function), 406 | __metadata("design:paramtypes", [Object]), 407 | __metadata("design:returntype", Promise) 408 | ], BookController.prototype, "deleteBook", null); 409 | BookController = __decorate([ 410 | common_1.Controller('api/book'), 411 | __metadata("design:paramtypes", [book_service_1.BookService]) 412 | ], BookController); 413 | exports.BookController = BookController; 414 | 415 | 416 | /***/ }), 417 | /* 13 */ 418 | /***/ (function(module, exports, __webpack_require__) { 419 | 420 | "use strict"; 421 | 422 | Object.defineProperty(exports, "__esModule", { value: true }); 423 | class AddBookDTO { 424 | } 425 | exports.AddBookDTO = AddBookDTO; 426 | 427 | 428 | /***/ }), 429 | /* 14 */ 430 | /***/ (function(module, exports, __webpack_require__) { 431 | 432 | "use strict"; 433 | 434 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 435 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 436 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 437 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 438 | return c > 3 && r && Object.defineProperty(target, key, r), r; 439 | }; 440 | var __metadata = (this && this.__metadata) || function (k, v) { 441 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 442 | }; 443 | Object.defineProperty(exports, "__esModule", { value: true }); 444 | const common_1 = __webpack_require__(0); 445 | const book_service_1 = __webpack_require__(2); 446 | let GetBookMiddleware = class GetBookMiddleware { 447 | constructor(bookService) { 448 | this.bookService = bookService; 449 | } 450 | async resolve(...args) { 451 | return async (req, res, next) => { 452 | await this.bookService.findBook(req.params.bookId).then((book) => { 453 | req.book = book; 454 | next(); 455 | }); 456 | }; 457 | } 458 | }; 459 | GetBookMiddleware = __decorate([ 460 | common_1.Middleware(), 461 | __metadata("design:paramtypes", [book_service_1.BookService]) 462 | ], GetBookMiddleware); 463 | exports.GetBookMiddleware = GetBookMiddleware; 464 | 465 | 466 | /***/ }) 467 | /******/ ]); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejsexpresswebservice", 3 | "version": "1.0.0", 4 | "description": "nodejs , expressjs , typescript , webpack for building a restfull services", 5 | "main": "index.ts", 6 | "repository": { 7 | "url": "https://github.com/Abdallah-khalil/RestfullServices.git" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1", 11 | "start": "nodemon --watch ./src --exec ts-node ./src/index.ts" 12 | }, 13 | "keywords": [ 14 | "nodejs", 15 | "expressjs", 16 | "webpack", 17 | "restfull", 18 | "webservices", 19 | "typescript", 20 | "monogodb", 21 | "mongoose" 22 | ], 23 | "author": "abdallah khalil", 24 | "license": "ISC", 25 | "dependencies": { 26 | "@nestjs/common": "^4.0.1", 27 | "@nestjs/core": "^4.0.1", 28 | "@nestjs/microservices": "^4.0.1", 29 | "@nestjs/testing": "^4.0.1", 30 | "@nestjs/websockets": "^4.0.1", 31 | "body-parser": "^1.17.2", 32 | "cors": "^2.8.4", 33 | "debug": "^3.0.1", 34 | "express": "^4.15.4", 35 | "http": "0.0.0", 36 | "mongoose": "^4.11.12", 37 | "redis": "^2.7.1", 38 | "reflect-metadata": "^0.1.10", 39 | "rxjs": "^5.4.3" 40 | }, 41 | "devDependencies": { 42 | "@types/body-parser": "^1.16.5", 43 | "@types/cors": "^2.8.1", 44 | "@types/debug": "0.0.30", 45 | "@types/express": "^4.0.37", 46 | "@types/mongodb": "^2.2.11", 47 | "@types/mongoose": "^4.7.23", 48 | "@types/node": "^8.0.30", 49 | "nodemon": "^1.12.1", 50 | "ts-loader": "^2.3.7", 51 | "ts-node": "^3.3.0", 52 | "typescript": "^2.5.2" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { BookModule } from './book/book.module'; 3 | 4 | 5 | @Module({ 6 | modules: [BookModule] 7 | }) 8 | export class ApplicationModule { } 9 | -------------------------------------------------------------------------------- /src/book/addBook.dto.ts: -------------------------------------------------------------------------------- 1 | export class AddBookDTO { 2 | readonly title: string; 3 | readonly author: string; 4 | readonly genre: string; 5 | readonly read: boolean; 6 | } -------------------------------------------------------------------------------- /src/book/book.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Post, Put, Patch, Delete, Query, Body, Param, Req } from '@nestjs/common'; 2 | import { BookService } from './book.service'; 3 | import { Book } from './book.schema'; 4 | import { AddBookDTO } from './addBook.dto'; 5 | 6 | 7 | @Controller('api/book') 8 | export class BookController { 9 | constructor(private readonly bookService: BookService) { } 10 | 11 | @Get() 12 | async findAll( @Query() reqQuery): Promise { 13 | return await this.bookService.findAll(reqQuery); 14 | } 15 | 16 | @Post() 17 | async addBook( @Body() addBookDTO: AddBookDTO): Promise { 18 | return this.bookService.addBook(addBookDTO); 19 | } 20 | 21 | @Get("/:bookId") 22 | async findBook( @Req() request): Promise { 23 | return request.book; 24 | } 25 | 26 | @Put("/:bookId") 27 | async editBook( @Req() request): Promise { 28 | return this.bookService.editBook(request.body, request.book); 29 | } 30 | 31 | @Patch("/:bookId") 32 | async patchBook( @Req() request): Promise { 33 | if (request.body._id) { 34 | delete request.body._id; 35 | } 36 | return this.bookService.editBook(request.body, request.book); 37 | } 38 | 39 | @Delete("/:bookId") 40 | async deleteBook( @Req() request): Promise { 41 | return this.bookService.deleteBook(request.book); 42 | } 43 | } -------------------------------------------------------------------------------- /src/book/book.module.ts: -------------------------------------------------------------------------------- 1 | import { Module, NestModule, MiddlewaresConsumer, RequestMethod } from '@nestjs/common'; 2 | import { dbConfigModule } from '../dbConfig/dbConfig.module'; 3 | import { BookProviders } from './book.providers'; 4 | import { BookService } from './book.service'; 5 | import { BookController } from './book.controller'; 6 | import { GetBookMiddleware } from './getBook.middleware'; 7 | @Module({ 8 | modules: [dbConfigModule], 9 | components: [ 10 | BookService, 11 | ...BookProviders 12 | ], 13 | controllers: [BookController] 14 | }) 15 | export class BookModule implements NestModule { 16 | 17 | configure(consumer: MiddlewaresConsumer): void { 18 | consumer.apply(GetBookMiddleware).forRoutes( 19 | { path: 'api/book/:bookId', method: RequestMethod.GET }, 20 | { path: 'api/book/:bookId', method: RequestMethod.PUT }, 21 | { path: 'api/book/:bookId', method: RequestMethod.PATCH }, 22 | { path: 'api/book/:bookId', method: RequestMethod.DELETE } 23 | ) 24 | } 25 | } -------------------------------------------------------------------------------- /src/book/book.providers.ts: -------------------------------------------------------------------------------- 1 | import { Connection } from 'mongoose'; 2 | import { BookSchema } from './book.schema'; 3 | 4 | export const BookProviders = [ 5 | { 6 | provide: 'bookModelToken', 7 | useFactory: async (connection: Connection) => connection.model('Book', BookSchema), 8 | inject: ['DbConToken'] 9 | } 10 | ] -------------------------------------------------------------------------------- /src/book/book.schema.ts: -------------------------------------------------------------------------------- 1 | import { Document, Schema } from 'mongoose'; 2 | 3 | export interface Book extends Document { 4 | title: string, 5 | author: string, 6 | genre: string, 7 | read: boolean 8 | } 9 | 10 | export const BookSchema = new Schema({ 11 | title: { 12 | type: String 13 | }, 14 | author: { 15 | type: String 16 | }, 17 | genre: { 18 | type: String 19 | }, 20 | read: { 21 | type: Boolean, 22 | default: false 23 | } 24 | }); -------------------------------------------------------------------------------- /src/book/book.service.ts: -------------------------------------------------------------------------------- 1 | import { Model } from 'mongoose'; 2 | import { Component, Inject } from '@nestjs/common'; 3 | import { Book } from './book.schema'; 4 | import { AddBookDTO } from './addBook.dto'; 5 | @Component() 6 | export class BookService { 7 | constructor( 8 | @Inject('bookModelToken') private readonly BookModel: Model 9 | ) { } 10 | 11 | 12 | async findAll(reqQuery): Promise { 13 | let query: { [key: string]: string } = {}; 14 | if (reqQuery.genre) { 15 | query.genre = reqQuery.genre; 16 | } 17 | return await this.BookModel.find(query).exec(); 18 | } 19 | 20 | async findBook(bookId: number): Promise { 21 | return await this.BookModel.findById(bookId); 22 | } 23 | 24 | async addBook(addDookDTO: AddBookDTO): Promise { 25 | const createdBook = new this.BookModel(addDookDTO); 26 | return await createdBook.save(); 27 | } 28 | 29 | async editBook(addBookDTO: AddBookDTO, book: Book): Promise { 30 | const editedBook = book; 31 | editedBook.title = addBookDTO.title; 32 | editedBook.genre = addBookDTO.genre; 33 | editedBook.author = addBookDTO.author; 34 | editedBook.read = addBookDTO.read; 35 | return await editedBook.save(); 36 | } 37 | 38 | async deleteBook(book: Book): Promise { 39 | await book.remove(); 40 | return "Deleted Successfully"; 41 | } 42 | } -------------------------------------------------------------------------------- /src/book/getBook.middleware.ts: -------------------------------------------------------------------------------- 1 | import { Middleware, NestMiddleware, ExpressMiddleware } from '@nestjs/common'; 2 | import { Request, Response, NextFunction } from 'express'; 3 | import { Book } from './book.schema'; 4 | import { BookService } from './book.service'; 5 | 6 | export interface CustomRequest extends Request { 7 | book: Book 8 | } 9 | 10 | @Middleware() 11 | export class GetBookMiddleware implements NestMiddleware { 12 | constructor( 13 | private readonly bookService: BookService 14 | ) { } 15 | 16 | async resolve(...args: any[]): Promise { 17 | return async (req: CustomRequest, res: Response, next: NextFunction) => { 18 | await this.bookService.findBook(req.params.bookId).then((book) => { 19 | req.book = book; 20 | next(); 21 | }); 22 | 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/dbConfig/dbConfig.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | import { dbConfigProviders } from './dbConfig.providers'; 4 | 5 | @Module({ 6 | components: [...dbConfigProviders], 7 | exports: [...dbConfigProviders] 8 | }) 9 | export class dbConfigModule { } -------------------------------------------------------------------------------- /src/dbConfig/dbConfig.providers.ts: -------------------------------------------------------------------------------- 1 | import * as mongoose from 'mongoose'; 2 | 3 | export const dbConfigProviders = [ 4 | { 5 | provide: 'DbConToken', 6 | useFactory: async (): Promise => { 7 | (mongoose as any).Promise = global.Promise; 8 | return await mongoose.connect('mongodb://localhost:27017/libraryApp', { 9 | useMongoClient: true, 10 | }); 11 | }, 12 | }, 13 | ]; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as bodyParser from 'body-parser'; 2 | import { NestFactory } from '@nestjs/core'; 3 | import { ApplicationModule } from './app.module'; 4 | import * as cors from 'cors'; 5 | async function bootstrap() { 6 | const app = await NestFactory.create(ApplicationModule); 7 | app.use(cors()); 8 | app.use(bodyParser.json()); 9 | await app.listen(3001); 10 | } 11 | bootstrap(); 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": false, 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "noLib": false, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "target": "es2017", 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "lib": [ 14 | "es2017", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ], 21 | "exclude": [ 22 | "node_modules", 23 | "**/*.spec.ts" 24 | ] 25 | } --------------------------------------------------------------------------------