├── .prettierrc ├── nest-cli.json ├── nodemon.json ├── nodemon-debug.json ├── tsconfig.spec.json ├── src ├── app.service.ts ├── main.ts ├── app.controller.ts ├── main.hmr.ts ├── contacts │ ├── contact.entity.ts │ ├── contacts.module.ts │ ├── contacts.service.spec.ts │ ├── contacts │ │ ├── contacts.controller.spec.ts │ │ └── contacts.controller.ts │ └── contacts.service.ts ├── app.module.ts └── app.controller.spec.ts ├── test ├── jest-e2e.json └── app.e2e-spec.ts ├── tsconfig.json ├── .gitignore ├── webpack.config.js ├── tslint.json ├── package.json └── README.md /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "ts", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src" 5 | } 6 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "ts-node -r tsconfig-paths/register src/main.ts" 6 | } 7 | -------------------------------------------------------------------------------- /nodemon-debug.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "node --inspect-brk -r ts-node/register src/main.ts" 6 | } -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["jest", "node"] 5 | }, 6 | "include": ["**/*.spec.ts", "**/*.d.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | root(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | async function bootstrap() { 5 | const app = await NestFactory.create(AppModule); 6 | await app.listen(3000); 7 | } 8 | bootstrap(); 9 | -------------------------------------------------------------------------------- /src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Get, Controller } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller() 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get() 9 | root(): string { 10 | return this.appService.root(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main.hmr.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | declare const module: any; 5 | 6 | async function bootstrap() { 7 | const app = await NestFactory.create(AppModule); 8 | await app.listen(3000); 9 | 10 | if (module.hot) { 11 | module.hot.accept(); 12 | module.hot.dispose(() => app.close()); 13 | } 14 | } 15 | bootstrap(); 16 | -------------------------------------------------------------------------------- /src/contacts/contact.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; 2 | 3 | @Entity() 4 | export class Contact { 5 | @PrimaryGeneratedColumn() 6 | id: number; 7 | 8 | @Column() 9 | firstName: string; 10 | 11 | @Column() 12 | lastName: string; 13 | 14 | @Column() 15 | email: string; 16 | 17 | @Column() 18 | phone: string; 19 | 20 | @Column() 21 | city: string; 22 | 23 | @Column() 24 | country: string; 25 | } -------------------------------------------------------------------------------- /src/contacts/contacts.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ContactsService } from './contacts.service'; 3 | import { ContactsController } from './contacts/contacts.controller'; 4 | import { TypeOrmModule } from '@nestjs/typeorm'; 5 | import { Contact } from './contact.entity'; 6 | 7 | @Module({ 8 | imports: [ 9 | TypeOrmModule.forFeature([Contact]), 10 | ], 11 | providers: [ContactsService], 12 | controllers: [ContactsController] 13 | }) 14 | export class ContactsModule {} 15 | -------------------------------------------------------------------------------- /src/contacts/contacts.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ContactsService } from './contacts.service'; 3 | 4 | describe('ContactsService', () => { 5 | let service: ContactsService; 6 | beforeAll(async () => { 7 | const module: TestingModule = await Test.createTestingModule({ 8 | providers: [ContactsService], 9 | }).compile(); 10 | service = module.get(ContactsService); 11 | }); 12 | it('should be defined', () => { 13 | expect(service).toBeDefined(); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "noLib": false, 8 | "allowSyntheticDefaultImports": true, 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "target": "es6", 12 | "sourceMap": true, 13 | "outDir": "./dist", 14 | "baseUrl": "./src" 15 | }, 16 | "include": [ 17 | "src/**/*" 18 | ], 19 | "exclude": [ 20 | "node_modules", 21 | "**/*.spec.ts" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /src/contacts/contacts/contacts.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ContactsController } from './contacts.controller'; 3 | 4 | describe('Contacts Controller', () => { 5 | let module: TestingModule; 6 | beforeAll(async () => { 7 | module = await Test.createTestingModule({ 8 | controllers: [ContactsController], 9 | }).compile(); 10 | }); 11 | it('should be defined', () => { 12 | const controller: ContactsController = module.get(ContactsController); 13 | expect(controller).toBeDefined(); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | import { ContactsModule } from './contacts/contacts.module'; 5 | import { TypeOrmModule } from '@nestjs/typeorm'; 6 | 7 | @Module({ 8 | imports: [ContactsModule, 9 | TypeOrmModule.forRoot({ 10 | type: 'sqlite', 11 | database: 'db', 12 | entities: [__dirname + '/**/*.entity{.ts,.js}'], 13 | synchronize: true, 14 | }),], 15 | controllers: [AppController], 16 | providers: [AppService], 17 | }) 18 | export class AppModule {} 19 | -------------------------------------------------------------------------------- /test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { INestApplication } from '@nestjs/common'; 2 | import { Test } from '@nestjs/testing'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeAll(async () => { 10 | const moduleFixture = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | db 3 | package-lock.json 4 | # See http://help.github.com/ignore-files/ for more about ignoring files. 5 | 6 | # compiled output 7 | /dist 8 | /tmp 9 | /out-tsc 10 | 11 | # dependencies 12 | /node_modules 13 | 14 | # IDEs and editors 15 | /.idea 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # IDE - VSCode 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | 30 | # misc 31 | /.sass-cache 32 | /connect.lock 33 | /coverage 34 | /libpeerconnection.log 35 | npm-debug.log 36 | yarn-error.log 37 | testem.log 38 | /typings 39 | 40 | # System Files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import { AppController } from './app.controller'; 4 | import { AppService } from './app.service'; 5 | 6 | describe('AppController', () => { 7 | let app: TestingModule; 8 | 9 | beforeAll(async () => { 10 | app = await Test.createTestingModule({ 11 | controllers: [AppController], 12 | providers: [AppService], 13 | }).compile(); 14 | }); 15 | 16 | describe('root', () => { 17 | it('should return "Hello World!"', () => { 18 | const appController = app.get(AppController); 19 | expect(appController.root()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const nodeExternals = require('webpack-node-externals'); 4 | 5 | module.exports = { 6 | entry: ['webpack/hot/poll?1000', './src/main.hmr.ts'], 7 | watch: true, 8 | target: 'node', 9 | externals: [ 10 | nodeExternals({ 11 | whitelist: ['webpack/hot/poll?1000'], 12 | }), 13 | ], 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.tsx?$/, 18 | use: 'ts-loader', 19 | exclude: /node_modules/, 20 | }, 21 | ], 22 | }, 23 | mode: "development", 24 | resolve: { 25 | extensions: ['.tsx', '.ts', '.js'], 26 | }, 27 | plugins: [ 28 | new webpack.HotModuleReplacementPlugin(), 29 | ], 30 | output: { 31 | path: path.join(__dirname, 'dist'), 32 | filename: 'server.js', 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /src/contacts/contacts.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { Repository, UpdateResult, DeleteResult } from 'typeorm'; 3 | import { InjectRepository } from '@nestjs/typeorm'; 4 | import { Contact } from './contact.entity'; 5 | 6 | @Injectable() 7 | export class ContactsService { 8 | constructor( 9 | @InjectRepository(Contact) 10 | private contactRepository: Repository, 11 | ) { } 12 | async findAll(): Promise { 13 | return await this.contactRepository.find(); 14 | } 15 | 16 | async create(contact: Contact): Promise { 17 | return await this.contactRepository.save(contact); 18 | } 19 | 20 | async update(contact: Contact): Promise { 21 | 22 | return await this.contactRepository.update(contact.id,contact); 23 | } 24 | 25 | async delete(id): Promise { 26 | return await this.contactRepository.delete(id); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/contacts/contacts/contacts.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Post,Put, Delete, Body, Param } from '@nestjs/common'; 2 | import { Contact } from '../contact.entity'; 3 | import { ContactsService } from '../contacts.service'; 4 | 5 | @Controller('contacts') 6 | export class ContactsController { 7 | constructor(private contactsService: ContactsService){} 8 | 9 | @Get() 10 | index(): Promise { 11 | return this.contactsService.findAll(); 12 | } 13 | 14 | @Post('create') 15 | async create(@Body() contactData: Contact): Promise { 16 | return this.contactsService.create(contactData); 17 | } 18 | 19 | @Put(':id/update') 20 | async update(@Param('id') id, @Body() contactData: Contact): Promise { 21 | contactData.id = Number(id); 22 | console.log('Update #' + contactData.id) 23 | return this.contactsService.update(contactData); 24 | } 25 | 26 | @Delete(':id/delete') 27 | async delete(@Param('id') id): Promise { 28 | return this.contactsService.delete(id); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": { 7 | "no-unused-expression": true 8 | }, 9 | "rules": { 10 | "eofline": false, 11 | "quotemark": [ 12 | true, 13 | "single" 14 | ], 15 | "indent": false, 16 | "member-access": [ 17 | false 18 | ], 19 | "ordered-imports": [ 20 | false 21 | ], 22 | "max-line-length": [ 23 | true, 24 | 150 25 | ], 26 | "member-ordering": [ 27 | false 28 | ], 29 | "curly": false, 30 | "interface-name": [ 31 | false 32 | ], 33 | "array-type": [ 34 | false 35 | ], 36 | "no-empty-interface": false, 37 | "no-empty": false, 38 | "arrow-parens": false, 39 | "object-literal-sort-keys": false, 40 | "no-unused-expression": false, 41 | "max-classes-per-file": [ 42 | false 43 | ], 44 | "variable-name": [ 45 | false 46 | ], 47 | "one-line": [ 48 | false 49 | ], 50 | "one-variable-per-declaration": [ 51 | false 52 | ] 53 | }, 54 | "rulesDirectory": [] 55 | } 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crud-app", 3 | "version": "0.0.0", 4 | "description": "description", 5 | "author": "", 6 | "license": "MIT", 7 | "scripts": { 8 | "format": "prettier --write \"src/**/*.ts\"", 9 | "start": "ts-node -r tsconfig-paths/register src/main.ts", 10 | "start:dev": "nodemon", 11 | "start:debug": "nodemon --config nodemon-debug.json", 12 | "prestart:prod": "rimraf dist && tsc", 13 | "start:prod": "node dist/main.js", 14 | "start:hmr": "node dist/server", 15 | "lint": "tslint -p tsconfig.json -c tslint.json", 16 | "test": "jest", 17 | "test:watch": "jest --watch", 18 | "test:cov": "jest --coverage", 19 | "test:e2e": "jest --config ./test/jest-e2e.json", 20 | "webpack": "webpack --config webpack.config.js" 21 | }, 22 | "dependencies": { 23 | "@nestjs/common": "^5.1.0", 24 | "@nestjs/core": "^5.1.0", 25 | "@nestjs/typeorm": "^5.3.0", 26 | "reflect-metadata": "^0.1.12", 27 | "rxjs": "^6.2.2", 28 | "sqlite3": "^4.0.6", 29 | "typeorm": "^0.2.14", 30 | "typescript": "^3.0.1" 31 | }, 32 | "devDependencies": { 33 | "@nestjs/testing": "^5.1.0", 34 | "@types/express": "^4.16.0", 35 | "@types/jest": "^23.3.1", 36 | "@types/node": "^10.7.1", 37 | "@types/supertest": "^2.0.5", 38 | "jest": "^23.5.0", 39 | "nodemon": "^1.18.3", 40 | "prettier": "^1.14.2", 41 | "rimraf": "^2.6.2", 42 | "supertest": "^3.1.0", 43 | "ts-jest": "^23.1.3", 44 | "ts-loader": "^4.4.2", 45 | "ts-node": "^7.0.1", 46 | "tsconfig-paths": "^3.5.0", 47 | "tslint": "5.11.0", 48 | "webpack": "^4.16.5", 49 | "webpack-cli": "^3.1.0", 50 | "webpack-node-externals": "^1.7.2" 51 | }, 52 | "jest": { 53 | "moduleFileExtensions": [ 54 | "js", 55 | "json", 56 | "ts" 57 | ], 58 | "rootDir": "src", 59 | "testRegex": ".spec.ts$", 60 | "transform": { 61 | "^.+\\.(t|j)s$": "ts-jest" 62 | }, 63 | "coverageDirectory": "../coverage", 64 | "testEnvironment": "node" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master 6 | [travis-url]: https://travis-ci.org/nestjs/nest 7 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux 8 | [linux-url]: https://travis-ci.org/nestjs/nest 9 | 10 |

A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.

11 |

12 | NPM Version 13 | Package License 14 | NPM Downloads 15 | Travis 16 | Linux 17 | Coverage 18 | Gitter 19 | Backers on Open Collective 20 | Sponsors on Open Collective 21 | 22 | 23 |

24 | 26 | 27 | ## Description 28 | 29 | In this tutorial, you'll get introduced to Nest.js by building your first REST API CRUD application with this framework which is built on top of Node.js, Express.js and TypeScript and inspired by Angular. 30 | 31 | We'll be using TypeORM as the ORM to abtract away the differences between the various database management system. We'll be using SQLite because it doesn't need any special installation in but you can very much use any database supported by TypeORM like MySQL or Oracle. 32 | 33 | > Read [Nest.js Tutorial: Build your First REST API CRUD App with TypeORM](https://www.techiediaries.com/nestjs-tutorial-rest-api-crud) 34 | 35 | ```bash 36 | $ git clone https://github.com/techiediaries/nestjs-crud-rest-api.git 37 | ``` 38 | 39 | ## Installation 40 | 41 | ```bash 42 | $ cd nestjs-crud-rest-api 43 | $ npm install 44 | ``` 45 | 46 | ## Running the app 47 | 48 | ```bash 49 | # development 50 | $ npm run start 51 | 52 | # watch mode 53 | $ npm run start:dev 54 | 55 | # incremental rebuild (webpack) 56 | $ npm run webpack 57 | $ npm run start:hmr 58 | 59 | # production mode 60 | $ npm run start:prod 61 | ``` 62 | 63 | ## Test 64 | 65 | ```bash 66 | # unit tests 67 | $ npm run test 68 | 69 | # e2e tests 70 | $ npm run test:e2e 71 | 72 | # test coverage 73 | $ npm run test:cov 74 | ``` 75 | 76 | 77 | ## License 78 | 79 | Nest is [MIT licensed](LICENSE). 80 | --------------------------------------------------------------------------------