├── .gitignore ├── README.md ├── index.ts ├── package.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | lib/ 3 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Node.js with MongoDB Example 2 | 3 | Swagger Page of that application 4 | 5 | ### Requirements 6 | 7 | - Node.js v10+ 8 | - MongoDB running on local instance 9 | 10 | #### Environment Variables 11 | 12 | - PORT: 3000 13 | - MONGO_URL: localhost:27017 14 | 15 | ### Running 16 | 17 | - Install dependencies - `npm i` 18 | - Build typescript - `npm run build` 19 | - Run project - `npm start` 20 | - Go to swagger page - `localhost:3000/` 21 | 22 | ### Development with Watch Compiler 23 | 24 | - Run once - `npm run dev` 25 | - Run and watch files - `npm run dev:watch` 26 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | // import * as Hapi from 'hapi'; 2 | import * as Joi from '@hapi/joi'; 3 | import * as Inert from '@hapi/inert'; 4 | import * as Vision from '@hapi/vision'; 5 | import * as Hapi from '@hapi/hapi'; 6 | 7 | import { MongoClient, ObjectId } from 'mongodb'; 8 | 9 | const HapiSwagger = require('hapi-swagger'); 10 | 11 | const port = process.env.PORT || 3000; 12 | const server = new Hapi.Server({ 13 | port, 14 | routes: { 15 | cors: { 16 | origin: ['*'], 17 | }, 18 | }, 19 | }); 20 | 21 | (async () => { 22 | const host = process.env.MONGO_URL || 'localhost'; 23 | const connectionString = `mongodb://${host}/heroes`; 24 | const connection = await MongoClient.connect(connectionString, { 25 | useNewUrlParser: true, 26 | }); 27 | console.log('mongo db is running'); 28 | 29 | const db = connection.db('heroes').collection('hero'); 30 | 31 | await server.register([ 32 | Inert, 33 | Vision, 34 | { 35 | plugin: HapiSwagger, 36 | options: { 37 | info: { 38 | title: 'Node.js with MongoDB Example - Erick Wendel', 39 | version: 'v1.0', 40 | }, 41 | }, 42 | }, 43 | ]); 44 | 45 | server.route([ 46 | { 47 | method: 'GET', 48 | path: '/', 49 | config: { 50 | handler: (r, reply) => reply.redirect('/documentation'), 51 | }, 52 | }, 53 | { 54 | method: 'GET', 55 | path: '/heroes', 56 | config: { 57 | handler: () => { 58 | return db.find().toArray(); 59 | }, 60 | description: 'List All heroes', 61 | notes: 'heroes from database', 62 | tags: ['api'], 63 | }, 64 | }, 65 | { 66 | method: 'POST', 67 | path: '/heroes', 68 | config: { 69 | handler: req => { 70 | const { payload } = req; 71 | return db.insert(payload); 72 | }, 73 | description: 'Create a hero', 74 | notes: 'create a hero', 75 | tags: ['api'], 76 | validate: { 77 | payload: { 78 | name: Joi.string().required(), 79 | power: Joi.string().required(), 80 | }, 81 | }, 82 | }, 83 | }, 84 | { 85 | method: 'PUT', 86 | path: '/heroes/{id}', 87 | config: { 88 | handler: req => { 89 | const { payload } = req; 90 | const { 91 | params: { id }, 92 | } = req; 93 | return db.updateOne({ _id: new ObjectId(id) }, { $set: payload }); 94 | }, 95 | description: 'Update a hero', 96 | notes: 'Update a hero', 97 | tags: ['api'], 98 | validate: { 99 | params: { 100 | id: Joi.string().required(), 101 | }, 102 | payload: { 103 | name: Joi.string(), 104 | power: Joi.string(), 105 | }, 106 | }, 107 | }, 108 | }, 109 | { 110 | method: 'DELETE', 111 | path: '/heroes/{id}', 112 | config: { 113 | handler: req => { 114 | return db.deleteOne({ _id: new ObjectId(req.params.id) }); 115 | }, 116 | description: 'Delete a hero', 117 | notes: 'Delete a hero', 118 | tags: ['api'], 119 | validate: { 120 | params: { 121 | id: Joi.string().required(), 122 | }, 123 | }, 124 | }, 125 | }, 126 | ]); 127 | 128 | await server.start(); 129 | console.log('server running at', port); 130 | })(); 131 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-with-mongodb-api-example", 3 | "version": "1.0.0", 4 | "description": "Swagger Page of that application", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "npx typescript", 8 | "build:watch": "npx typescript -w", 9 | "dev": "npx concurrently \"npm run build\" \"npm run dev:run\"", 10 | "dev:watch": "npx concurrently \"npm run build:watch\" \"npm run dev:run\"", 11 | "dev:run": "npx nodemon lib/index.js", 12 | "start": "node lib/index.js", 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/ErickWendel/nodejs-with-mongodb-api-example.git" 18 | }, 19 | "keywords": [], 20 | "author": "", 21 | "license": "ISC", 22 | "bugs": { 23 | "url": "https://github.com/ErickWendel/nodejs-with-mongodb-api-example/issues" 24 | }, 25 | "homepage": "https://github.com/ErickWendel/nodejs-with-mongodb-api-example#readme", 26 | "devDependencies": { 27 | "concurrently": "^4.1.1", 28 | "nodemon": "1.19.1", 29 | "typescript": "^3.7.3" 30 | }, 31 | "dependencies": { 32 | "@hapi/hapi": "18.3.1", 33 | "@hapi/inert": "5.2.1", 34 | "@hapi/joi": "15.1.0", 35 | "@hapi/vision": "5.5.2", 36 | "@types/mongodb": "3.1.32", 37 | "hapi-swagger": "10.0.2", 38 | "mongodb": "3.3.0-beta2" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": [ 7 | "es2019" 8 | ], /* Specify library files to be included in the compilation. */ 9 | // "allowJs": true, /* Allow javascript files to be compiled. */ 10 | // "checkJs": true, /* Report errors in .js files. */ 11 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 12 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 13 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 14 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 15 | // "outFile": "./", /* Concatenate and emit output to single file. */ 16 | "outDir": "./lib", /* Redirect output structure to the directory. */ 17 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 18 | // "composite": true, /* Enable project compilation */ 19 | // "incremental": true, /* Enable incremental compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | /* Strict Type-Checking Options */ 27 | "strict": false, /* Enable all strict type-checking options. */ 28 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 29 | // "strictNullChecks": true, /* Enable strict null checks. */ 30 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 31 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 32 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 33 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 34 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | /* Module Resolution Options */ 41 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 45 | // "typeRoots": [], /* List of folders to include type definitions from. */ 46 | // "types": [], /* Type declaration files to be included in compilation. */ 47 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 48 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 49 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | /* Experimental Options */ 56 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 57 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 58 | } 59 | } --------------------------------------------------------------------------------