├── README.md ├── .gitignore ├── lib ├── server.ts ├── routes │ ├── common_routes.ts │ └── user_routes.ts ├── modules │ ├── users │ │ ├── model.ts │ │ ├── schema.ts │ │ └── service.ts │ └── common │ │ ├── model.ts │ │ └── service.ts ├── config │ └── app.ts ├── environment.ts └── controllers │ └── userController.ts ├── tsconfig.json └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # test-project -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /dist/ -------------------------------------------------------------------------------- /lib/server.ts: -------------------------------------------------------------------------------- 1 | import app from "./config/app"; 2 | import env from './environment' 3 | 4 | const PORT = env.getPort(); 5 | 6 | app.listen(PORT, () => { 7 | console.log('Express server listening on port ' + PORT); 8 | }); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "pretty": true, 6 | "target": "es6", 7 | "outDir": "./dist", 8 | "baseUrl": "./lib" 9 | }, 10 | "include": [ 11 | "lib/**/*.ts" 12 | ], 13 | "exclude": [ 14 | "node_modules" 15 | ] 16 | } -------------------------------------------------------------------------------- /lib/routes/common_routes.ts: -------------------------------------------------------------------------------- 1 | import { Application, Request, Response } from 'express'; 2 | 3 | export class CommonRoutes { 4 | public route(app: Application) { 5 | 6 | // Mismatch URL 7 | app.all('*', function (req: Request, res: Response) { 8 | res.status(404).send({ error: true, message: 'Check your URL please' }); 9 | }); 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/modules/users/model.ts: -------------------------------------------------------------------------------- 1 | import { ModificationNote } from "../common/model"; 2 | 3 | export interface IUser { 4 | _id?: String; 5 | name: { 6 | first_name: String; 7 | middle_name: String; 8 | last_name: String; 9 | }; 10 | email: String; 11 | phone_number: String; 12 | gender: String; 13 | is_deleted?: Boolean; 14 | modification_notes: ModificationNote[] 15 | } -------------------------------------------------------------------------------- /lib/modules/common/model.ts: -------------------------------------------------------------------------------- 1 | export interface ModificationNote { 2 | modified_on: Date; 3 | modified_by: String; 4 | modification_note: String; 5 | } 6 | 7 | export const ModificationNote = { 8 | modified_on: Date, 9 | modified_by: String, 10 | modification_note: String 11 | } 12 | 13 | export enum response_status_codes { 14 | success = 200, 15 | bad_request = 400, 16 | internal_server_error = 500 17 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-first-project", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "./dist/server.js", 6 | "scripts": { 7 | "test": "ts-node ./lib/server.ts", 8 | "dev": "tsc && nodemon ./dist/server.js", 9 | "prod": "tsc && nodemon ./dist/server.js" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@types/express": "^4.17.4", 15 | "body-parser": "^1.19.0", 16 | "express": "^4.17.1", 17 | "mongoose": "^5.9.7", 18 | "nodemon": "^2.0.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/modules/users/schema.ts: -------------------------------------------------------------------------------- 1 | import * as mongoose from 'mongoose'; 2 | import { ModificationNote } from '../common/model'; 3 | 4 | const Schema = mongoose.Schema; 5 | 6 | const schema = new Schema({ 7 | name: { 8 | type: { 9 | first_name: String, 10 | middle_name: String, 11 | last_name: String 12 | } 13 | }, 14 | email: String, 15 | phone_number: String, 16 | gender: String, 17 | is_deleted: { 18 | type: Boolean, 19 | default: false 20 | }, 21 | modification_notes: [ModificationNote] 22 | }); 23 | 24 | export default mongoose.model('users', schema); -------------------------------------------------------------------------------- /lib/modules/users/service.ts: -------------------------------------------------------------------------------- 1 | import { IUser } from './model'; 2 | import users from './schema'; 3 | 4 | export default class UserService { 5 | 6 | public createUser(user_params: IUser, callback: any) { 7 | const _session = new users(user_params); 8 | _session.save(callback); 9 | } 10 | 11 | public filterUser(query: any, callback: any) { 12 | users.findOne(query, callback); 13 | } 14 | 15 | public updateUser(user_params: IUser, callback: any) { 16 | const query = { _id: user_params._id }; 17 | users.findOneAndUpdate(query, user_params, callback); 18 | } 19 | 20 | public deleteUser(_id: String, callback: any) { 21 | const query = { _id: _id }; 22 | users.deleteOne(query, callback); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /lib/routes/user_routes.ts: -------------------------------------------------------------------------------- 1 | import { Application, Request, Response } from 'express'; 2 | import { UserController } from '../controllers/userController'; 3 | 4 | export class TestRoutes { 5 | 6 | private user_controller: UserController = new UserController(); 7 | 8 | public route(app: Application) { 9 | 10 | app.post('/api/user', (req: Request, res: Response) => { 11 | this.user_controller.create_user(req, res); 12 | }); 13 | 14 | app.get('/api/user/:id', (req: Request, res: Response) => { 15 | this.user_controller.get_user(req, res); 16 | }); 17 | 18 | app.put('/api/user/:id', (req: Request, res: Response) => { 19 | this.user_controller.update_user(req, res); 20 | }); 21 | 22 | app.delete('/api/user/:id', (req: Request, res: Response) => { 23 | this.user_controller.delete_user(req, res); 24 | }); 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /lib/modules/common/service.ts: -------------------------------------------------------------------------------- 1 | import { Response } from 'express'; 2 | import { response_status_codes } from './model'; 3 | 4 | export function successResponse(message: string, DATA: any, res: Response) { 5 | res.status(response_status_codes.success).json({ 6 | STATUS: 'SUCCESS', 7 | MESSAGE: message, 8 | DATA 9 | }); 10 | } 11 | 12 | export function failureResponse(message: string, DATA: any, res: Response) { 13 | res.status(response_status_codes.success).json({ 14 | STATUS: 'FAILURE', 15 | MESSAGE: message, 16 | DATA 17 | }); 18 | } 19 | 20 | export function insufficientParameters(res: Response) { 21 | res.status(response_status_codes.bad_request).json({ 22 | STATUS: 'FAILURE', 23 | MESSAGE: 'Insufficient parameters', 24 | DATA: {} 25 | }); 26 | } 27 | 28 | export function mongoError(err: any, res: Response) { 29 | res.status(response_status_codes.internal_server_error).json({ 30 | STATUS: 'FAILURE', 31 | MESSAGE: 'MongoDB error', 32 | DATA: err 33 | }); 34 | } -------------------------------------------------------------------------------- /lib/config/app.ts: -------------------------------------------------------------------------------- 1 | import * as express from "express"; 2 | import * as bodyParser from "body-parser"; 3 | import * as mongoose from 'mongoose'; 4 | import environment from "../environment"; 5 | import { TestRoutes } from "../routes/user_routes"; 6 | import { CommonRoutes } from "../routes/common_routes"; 7 | 8 | class App { 9 | 10 | public app: express.Application; 11 | public mongoUrl: string = 'mongodb://localhost/' + environment.getDBName(); 12 | 13 | private test_routes: TestRoutes = new TestRoutes(); 14 | private common_routes: CommonRoutes = new CommonRoutes(); 15 | 16 | constructor() { 17 | this.app = express(); 18 | this.config(); 19 | this.mongoSetup(); 20 | this.test_routes.route(this.app); 21 | this.common_routes.route(this.app); 22 | } 23 | 24 | private config(): void { 25 | // support application/json type post data 26 | this.app.use(bodyParser.json()); 27 | //support application/x-www-form-urlencoded post data 28 | this.app.use(bodyParser.urlencoded({ extended: false })); 29 | } 30 | 31 | private mongoSetup(): void { 32 | mongoose.connect(this.mongoUrl, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, useFindAndModify: false }); 33 | } 34 | 35 | } 36 | export default new App().app; -------------------------------------------------------------------------------- /lib/environment.ts: -------------------------------------------------------------------------------- 1 | enum Environments { 2 | local_environment = 'local', 3 | dev_environment = 'dev', 4 | prod_environment = 'prod', 5 | qa_environment = 'qa' 6 | } 7 | 8 | class Environment { 9 | private environment: String; 10 | 11 | constructor(environment: String) { 12 | this.environment = environment; 13 | } 14 | 15 | getPort(): Number { 16 | if (this.environment === Environments.prod_environment) { 17 | return 8081; 18 | } else if (this.environment === Environments.dev_environment) { 19 | return 8082; 20 | } else if (this.environment === Environments.qa_environment) { 21 | return 8083; 22 | } else { 23 | return 3000; 24 | } 25 | } 26 | 27 | getDBName(): String { 28 | if (this.environment === Environments.prod_environment) { 29 | return 'db_test_project_prod'; 30 | } else if (this.environment === Environments.dev_environment) { 31 | return 'db_test_project_dev'; 32 | } else if (this.environment === Environments.qa_environment) { 33 | return 'db_test_project_qa'; 34 | } else { 35 | return 'db_test_project_local'; 36 | } 37 | } 38 | } 39 | 40 | export default new Environment(Environments.local_environment); 41 | -------------------------------------------------------------------------------- /lib/controllers/userController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { insufficientParameters, mongoError, successResponse, failureResponse } from '../modules/common/service'; 3 | import { IUser } from '../modules/users/model'; 4 | import UserService from '../modules/users/service'; 5 | import e = require('express'); 6 | 7 | export class UserController { 8 | 9 | private user_service: UserService = new UserService(); 10 | 11 | public create_user(req: Request, res: Response) { 12 | // this check whether all the filds were send through the erquest or not 13 | if (req.body.name && req.body.name.first_name && req.body.name.middle_name && req.body.name.last_name && 14 | req.body.email && 15 | req.body.phone_number && 16 | req.body.gender) { 17 | const user_params: IUser = { 18 | name: { 19 | first_name: req.body.name.first_name, 20 | middle_name: req.body.name.middle_name, 21 | last_name: req.body.name.last_name 22 | }, 23 | email: req.body.email, 24 | phone_number: req.body.phone_number, 25 | gender: req.body.gender, 26 | modification_notes: [{ 27 | modified_on: new Date(Date.now()), 28 | modified_by: null, 29 | modification_note: 'New user created' 30 | }] 31 | }; 32 | this.user_service.createUser(user_params, (err: any, user_data: IUser) => { 33 | if (err) { 34 | mongoError(err, res); 35 | } else { 36 | successResponse('create user successfull', user_data, res); 37 | } 38 | }); 39 | } else { 40 | // error response if some fields are missing in request body 41 | insufficientParameters(res); 42 | } 43 | } 44 | 45 | public get_user(req: Request, res: Response) { 46 | if (req.params.id) { 47 | const user_filter = { _id: req.params.id }; 48 | this.user_service.filterUser(user_filter, (err: any, user_data: IUser) => { 49 | if (err) { 50 | mongoError(err, res); 51 | } else { 52 | successResponse('get user successfull', user_data, res); 53 | } 54 | }); 55 | } else { 56 | insufficientParameters(res); 57 | } 58 | } 59 | 60 | public update_user(req: Request, res: Response) { 61 | if (req.params.id && 62 | req.body.name || req.body.name.first_name || req.body.name.middle_name || req.body.name.last_name || 63 | req.body.email || 64 | req.body.phone_number || 65 | req.body.gender) { 66 | const user_filter = { _id: req.params.id }; 67 | this.user_service.filterUser(user_filter, (err: any, user_data: IUser) => { 68 | if (err) { 69 | mongoError(err, res); 70 | } else if (user_data) { 71 | user_data.modification_notes.push({ 72 | modified_on: new Date(Date.now()), 73 | modified_by: null, 74 | modification_note: 'User data updated' 75 | }); 76 | const user_params: IUser = { 77 | _id: req.params.id, 78 | name: req.body.name ? { 79 | first_name: req.body.name.first_name ? req.body.name.first_name : user_data.name.first_name, 80 | middle_name: req.body.name.first_name ? req.body.name.middle_name : user_data.name.middle_name, 81 | last_name: req.body.name.first_name ? req.body.name.last_name : user_data.name.last_name 82 | } : user_data.name, 83 | email: req.body.email ? req.body.email : user_data.email, 84 | phone_number: req.body.phone_number ? req.body.phone_number : user_data.phone_number, 85 | gender: req.body.gender ? req.body.gender : user_data.gender, 86 | is_deleted: req.body.is_deleted ? req.body.is_deleted : user_data.is_deleted, 87 | modification_notes: user_data.modification_notes 88 | }; 89 | this.user_service.updateUser(user_params, (err: any) => { 90 | if (err) { 91 | mongoError(err, res); 92 | } else { 93 | successResponse('update user successfull', null, res); 94 | } 95 | }); 96 | } else { 97 | failureResponse('invalid user', null, res); 98 | } 99 | }); 100 | } else { 101 | insufficientParameters(res); 102 | } 103 | } 104 | 105 | public delete_user(req: Request, res: Response) { 106 | if (req.params.id) { 107 | this.user_service.deleteUser(req.params.id, (err: any, delete_details) => { 108 | if (err) { 109 | mongoError(err, res); 110 | } else if (delete_details.deletedCount !== 0) { 111 | successResponse('delete user successfull', null, res); 112 | } else { 113 | failureResponse('invalid user', null, res); 114 | } 115 | }); 116 | } else { 117 | insufficientParameters(res); 118 | } 119 | } 120 | } --------------------------------------------------------------------------------