├── .gitignore ├── src ├── book │ ├── addBook.dto.ts │ ├── book.providers.ts │ ├── book.schema.ts │ ├── getBook.middleware.ts │ ├── book.module.ts │ ├── book.controller.ts │ └── book.service.ts ├── app.module.ts ├── dbConfig │ ├── dbConfig.module.ts │ └── dbConfig.providers.ts └── index.ts ├── tsconfig.json ├── .vscode └── launch.json ├── README.md └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /package-lock.json -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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 | }); -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /.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 | } -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.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 | } -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------