├── .DS_Store
├── .editorconfig
├── .env
├── .env.test
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .prettierrc
├── README.md
├── index.ts
├── package.json
├── src
├── .DS_Store
├── helpers
│ ├── createSchema.ts
│ ├── getIDfromToken.ts
│ └── loadenv.ts
├── init
│ ├── db.ts
│ ├── locales
│ │ ├── ar
│ │ │ └── translation.json
│ │ ├── en
│ │ │ └── translation.json
│ │ └── index.ts
│ ├── localize.ts
│ ├── routes.ts
│ └── theApp.ts
├── interfaces
│ ├── controllers.interface.ts
│ ├── interface.ts
│ └── types.d.ts
└── mvc
│ ├── .DS_Store
│ ├── controllers
│ ├── auth.controller.ts
│ ├── index.ts
│ └── user.controller.ts
│ ├── middlewares
│ ├── auth
│ │ └── index.ts
│ ├── index.ts
│ └── userAuth
│ │ └── index.ts
│ ├── models
│ ├── index.ts
│ └── user.model.ts
│ └── routes
│ ├── auth.routes.ts
│ ├── index.ts
│ ├── routesStrings
│ └── index.ts
│ └── user.routes.ts
└── tsconfig.json
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/.DS_Store
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | DATABASE_URL = mongodb://localhost:27017/test
2 | JWT_KEY=secret
--------------------------------------------------------------------------------
/.env.test:
--------------------------------------------------------------------------------
1 | MORGAN_FORMAT=tiny
2 | SERVER_PORT=3000
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /dist
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "extends": ["prettier", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"],
4 | "parserOptions": {
5 | "ecmaVersion": 2018,
6 | "sourceType": "module"
7 | },
8 | "rules": {
9 | "@typescript-eslint/explicit-member-accessibility": 0,
10 | "@typescript-eslint/explicit-function-return-type": 0,
11 | "@typescript-eslint/no-parameter-properties": 0,
12 | "@typescript-eslint/interface-name-prefix": 0,
13 | "@typescript-eslint/explicit-module-boundary-types": 0,
14 | "@typescript-eslint/no-explicit-any": "off",
15 | "@typescript-eslint/ban-types": "off",
16 | "@typescript-eslint/no-var-requires": "off"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | # .env
73 | # .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # Package-lock json file
107 | package-lock.json
108 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 150,
3 | "tabWidth": 2,
4 | "singleQuote": true,
5 | "trailingComma": "all",
6 | "semi": true,
7 | "arrowParens": "avoid"
8 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # express-typescript-mongoose-boilerplate
2 | simple starter for newbies.
3 |
4 | My main goal with this project is a simple and easy starter for new learners. I like you to be focused on the correct learning path and not spending hours in choosing the right project structure.
5 |
6 | > Full Explanation available on Dev Community Post: [here](https://dev.to/nour_abdou/express-typescript-mongoose-boilerplate-2omp)
7 |
8 | ## Features
9 | - Beautiful Code as simple as possible.
10 | - Clear Structure inspired by MVC Model.
11 | - Localization implemention.
12 | - Authorization CRUD example.
13 |
14 |
15 | ## Scripts
16 |
17 | All script are defined in the package-scripts.js file, but the most important ones are listed here.
18 |
19 | ### Install
20 | Install node-ts `npm i -g node-ts`
21 | Install all dependencies with `npm i`
22 |
23 | ### Linting
24 | Run code quality analysis using `npm run lint` or `npm run lint:fix` to fix errors.
25 |
26 |
27 |
28 |
29 | ## Project Structure
30 |
31 | ```
32 | src\
33 | |--mvc
34 | |--models\ # Mongoose models (data layer)
35 | |--routes\ # Views routes
36 | |--controllers\ # Route controllers (controller layer)
37 | |--middlewares\ # Custom express middlewares
38 | |--helpers\ # Utility functions
39 | |--app.js # Express app
40 | |--init\ # Init Express app
41 | |--locales\ # translation maps
42 | |--db.ts # Init DB Connection
43 | |--localize.ts # Init localization
44 | |--routes.ts # Init Routes
45 | |--thApp.ts # Express app
46 | |--index.ts # App entry point
47 | ```
48 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | import express, { Express } from 'express';
2 | import dotenv from 'dotenv';
3 | import routes from './src/init/routes';
4 | import localize from './src/init/localize';
5 | import db from './src/init/db';
6 | import theApp from './src/init/theApp';
7 |
8 | dotenv.config();
9 | const app: Express = express();
10 |
11 | const cors = require('cors');
12 | const corsOptions = {
13 | origin: 'http://localhost:8081',
14 | };
15 |
16 | app.use(cors(corsOptions));
17 | theApp(app);
18 | localize(app);
19 | db();
20 | routes(app);
21 |
22 | app.listen(3000, () => {
23 | console.log(`⚡️ [server]: Server is running at https://localhost:${3000}`);
24 | });
25 | export default app;
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "small-business-backend",
3 | "version": "1.0.0",
4 | "main": "index.ts",
5 | "scripts": {
6 | "start": "npx nodemon",
7 | "dev": "npx nodemon --exec ts-node index.ts",
8 | "lint": "eslint --ignore-path .gitignore --ext .ts src/",
9 | "lint:fix": "npm run lint -- --fix",
10 | "in": "npm i --save",
11 | "ind": "npm i -D --save",
12 | "uin": "npm uninstall --save"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "git+https://github.com/NourAliAbdou/express-typescript-mongoose-boilerplate.git"
17 | },
18 | "keywords": [
19 | "node",
20 | "express",
21 | "mongodb",
22 | "typescript",
23 | "js",
24 | "ts"
25 | ],
26 | "author": "Nour Abdou",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/NourAliAbdou/express-typescript-mongoose-boilerplate/issues"
30 | },
31 | "homepage": "https://github.com/NourAliAbdou/express-typescript-mongoose-boilerplate#readme",
32 | "description": "",
33 | "dependencies": {
34 | "bcryptjs": "^2.4.3",
35 | "body-parser": "^1.20.1",
36 | "cookie-parser": "^1.4.6",
37 | "cors": "^2.8.5",
38 | "dotenv": "^16.0.3",
39 | "eslint": "^8.28.0",
40 | "eslint-config-prettier": "^8.5.0",
41 | "eslint-plugin-prettier": "^4.2.1",
42 | "express": "^4.18.2",
43 | "http-errors": "^2.0.0",
44 | "i18next": "^22.0.6",
45 | "i18next-http-middleware": "^3.2.1",
46 | "i18next-node-fs-backend": "^2.1.3",
47 | "jest": "^29.1.2",
48 | "jsonwebtoken": "^8.5.1",
49 | "jwt-decode": "^3.1.2",
50 | "module-resolver": "^1.0.0",
51 | "mongoose": "^6.6.5",
52 | "morgan": "^1.10.0",
53 | "prettier": "2.7.1",
54 | "source-map-support": "^0.5.21"
55 | },
56 | "devDependencies": {
57 | "@types/bcrypt": "^5.0.0",
58 | "@types/cookie-parser": "^1.4.3",
59 | "@types/cors": "^2.8.12",
60 | "@types/express": "^4.17.14",
61 | "@types/express-serve-static-core": "^4.17.31",
62 | "@types/i18n": "^0.13.5",
63 | "@types/mongoose": "^5.11.97",
64 | "@types/morgan": "^1.9.3",
65 | "@types/node": "^18.11.9",
66 | "@typescript-eslint/eslint-plugin": "^5.45.0",
67 | "@typescript-eslint/parser": "^5.45.0",
68 | "tsc-alias": "^1.8.1",
69 | "tsconfig-paths": "^4.1.1",
70 | "typescript": "^4.9.3"
71 | },
72 | "jest": {
73 | "setupFiles": [
74 | "./src/helpers/loadenv.ts"
75 | ],
76 | "testEnvironment": "node"
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/src/.DS_Store
--------------------------------------------------------------------------------
/src/helpers/createSchema.ts:
--------------------------------------------------------------------------------
1 | import mongoose from 'mongoose';
2 | import { ISchemaType } from '../interfaces/interface';
3 | const Schema: ISchemaType = mongoose.Schema;
4 |
5 | const CreateSchema = (schema: any) => {
6 | const schem: any = new Schema(schema, { timestamps: true });
7 | schem.method('toJSON', function () {
8 | const { _id, ...object } = this.toObject();
9 | object.id = _id;
10 | return object;
11 | });
12 |
13 | return schem;
14 | };
15 | export { CreateSchema };
16 |
--------------------------------------------------------------------------------
/src/helpers/getIDfromToken.ts:
--------------------------------------------------------------------------------
1 | const jwt_decode = require('jwt-decode');
2 |
3 | export const getIDfromToken = req => {
4 | const token = req.body.token;
5 | return jwt_decode(token).id;
6 | };
7 |
--------------------------------------------------------------------------------
/src/helpers/loadenv.ts:
--------------------------------------------------------------------------------
1 | import { config } from 'dotenv';
2 |
3 | const { NODE_ENV } = process.env;
4 | const path = `.env${NODE_ENV ? `.${NODE_ENV}` : ''}`;
5 |
6 | export default config({ path });
7 |
--------------------------------------------------------------------------------
/src/init/db.ts:
--------------------------------------------------------------------------------
1 | import mongoose from 'mongoose';
2 |
3 | export default () => {
4 | const mongoString = 'mongodb://localhost:27017/test';
5 |
6 | mongoose.connect(mongoString, {}, (error: any) => {
7 | if (error) {
8 | console.log(error);
9 | } else {
10 | console.log('Database Connected');
11 | }
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/src/init/locales/ar/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "responseMessages": {
3 | "successMessages": {
4 | "registeredsuccessfully": "تم تسجيل {{name}} بنجاح",
5 | "profile updated successfuly": "تم تحديث المعل،مات بنجاح."
6 | },
7 | "errorMessages": {
8 | "User already exists": "المستخدم موجود بالفعل."
9 | }
10 | },
11 | "home": {
12 | "title": "متجر",
13 | "total": "يوجد لدينا {{counter}} كتب في القائمة",
14 | "buttonText": "إعادة التحميل",
15 | "buttonHTML": ""
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/init/locales/en/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "responseMessages": {
3 | "successMessages": {
4 | "registeredsuccessfully": "{{name}} registered successfully",
5 | "profile updated successfuly": "Profile updated successfuly"
6 | },
7 | "errorMessages": {
8 | "User already exists": "User already exists"
9 | }
10 | },
11 | "home": {
12 | "title": "Book shop",
13 | "total": "There are {{counter}} books in the list",
14 | "buttonText": "Refresh button",
15 | "buttonHTML": ""
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/init/locales/index.ts:
--------------------------------------------------------------------------------
1 | export const transStrings = {
2 | registeredsuccessfully: 'responseMessages.successMessages.registeredsuccessfully',
3 | useralreadyexists: 'responseMessages.errorMessages.User already exists',
4 | profileupdatedsuccessfuly: 'responseMessages.successMessages.profile updated successfuly',
5 | };
6 |
--------------------------------------------------------------------------------
/src/init/localize.ts:
--------------------------------------------------------------------------------
1 | import { Express } from 'express';
2 | const i18next = require('i18next');
3 | const Backend = require('i18next-node-fs-backend');
4 | const i18nextMiddleware = require('i18next-http-middleware');
5 |
6 | export default function (app: Express) {
7 | i18next
8 | .use(Backend)
9 | .use(i18nextMiddleware.LanguageDetector)
10 | .init(
11 | {
12 | backend: {
13 | loadPath: __dirname + '/locales/{{lng}}/translation.json',
14 | addPath: __dirname + '/locales/ar/{{ns}}.json',
15 | },
16 | fallbackLng: 'ar',
17 | preload: ['en', 'ar'],
18 | supportedLngs: ['en', 'ar'],
19 | cleanCode: true,
20 | },
21 | (err, t) => {
22 | if (err) return console.log('something went wrong loading', err);
23 | console.log(t('home.title'));
24 | },
25 | );
26 |
27 | app.use(
28 | i18nextMiddleware.handle(i18next, {
29 | }),
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/src/init/routes.ts:
--------------------------------------------------------------------------------
1 | import { Express } from 'express';
2 |
3 | import { authRouter, userRouter } from '../mvc/routes';
4 | import { Routes } from '../mvc/routes/routesStrings';
5 |
6 | export default (app: Express) => {
7 | app.use('/', authRouter);
8 | app.use(Routes.user, userRouter);
9 | };
10 |
--------------------------------------------------------------------------------
/src/init/theApp.ts:
--------------------------------------------------------------------------------
1 | import express, { Express } from 'express';
2 | const logger = require('morgan');
3 | const cookieParser = require('cookie-parser');
4 | export default (app: Express) => {
5 | app.use(logger('dev'));
6 | app.use(cookieParser());
7 | app.use(express.json());
8 | app.use(express.urlencoded({ extended: true }));
9 | };
10 |
--------------------------------------------------------------------------------
/src/interfaces/controllers.interface.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express';
2 |
3 | interface IAuthControllerType {
4 | UserLogin: (req: Request, res: Response) => void;
5 | UserRegister: (req: Request, res: Response) => void;
6 | }
7 | interface IUserControllerType {
8 | UserProfile: (req: Request, res: Response) => void;
9 | UserUpdate: (req: Request, res: Response) => void;
10 | }
11 | export { IAuthControllerType, IUserControllerType };
12 |
--------------------------------------------------------------------------------
/src/interfaces/interface.ts:
--------------------------------------------------------------------------------
1 | import mongoose from 'mongoose';
2 |
3 | type IDBType = {};
4 | type ISchemaType = typeof mongoose.Schema;
5 |
6 | interface IUser {
7 | name: String;
8 | email: String;
9 | mobile: String;
10 | password: String;
11 | }
12 | export { IDBType, ISchemaType, IUser };
13 |
--------------------------------------------------------------------------------
/src/interfaces/types.d.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/src/interfaces/types.d.ts
--------------------------------------------------------------------------------
/src/mvc/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/src/mvc/.DS_Store
--------------------------------------------------------------------------------
/src/mvc/controllers/auth.controller.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express';
2 | import { transStrings } from '../../init/locales';
3 | import { User } from '../models';
4 | const jwt = require('jsonwebtoken');
5 | const bcrypt = require('bcryptjs');
6 |
7 | const UserLogin = (req: Request | any, res: Response) => {
8 | return User.findOne({
9 | email: req.body.mobile,
10 | }).then(function (user: any, err: any) {
11 | if (err) throw err;
12 |
13 | if (!user) {
14 | res.status(403).json({
15 | success: false,
16 | message: req.i18n.t('simpleStringWithVariable', {
17 | variable1: '3',
18 | variable2: '3',
19 | }),
20 | });
21 | } else if (user) {
22 |
23 | bcrypt.compare(req.body.password, user.password, function (err, compRes) {
24 | if (!compRes) {
25 | res.status(403).json({
26 | success: false,
27 | message: 'Ops! wrong Password!',
28 | });
29 | } else {
30 | const payload = {
31 | id: user._id,
32 | role: 'user',
33 | };
34 | const token = jwt.sign(payload, process.env.JWT_KEY);
35 | User.findById(user._id, function (err, result) {
36 | res.status(200).send({
37 | success: true,
38 | token: token,
39 | user: {
40 | id: result._id,
41 | name: result.name,
42 | email: result.email,
43 | mobile: result.mobile,
44 | },
45 | });
46 | });
47 | }
48 | });
49 | }
50 | });
51 | };
52 | const UserRegister = (req: Request | any, res: Response) => {
53 | const user = new User({
54 | name: req.body.name,
55 | email: req.body.email,
56 | mobile: req.body.mobile,
57 | password: req.body.password,
58 | created_at: new Date(),
59 | });
60 |
61 | return req.body?.name
62 | ? user
63 | .save()
64 | .then(() => {
65 | const payload = {
66 | id: user._id,
67 | roleL: 'user',
68 | };
69 |
70 | const signtoken = jwt.sign(payload, process.env.JWT_KEY);
71 | res.status(200).send({
72 | success: true,
73 | message: req.t(transStrings.registeredsuccessfully, {
74 | name: user.name,
75 | }),
76 | user: user,
77 | token: signtoken,
78 | });
79 | })
80 | .catch(err => {
81 | console.log(err);
82 | res.status(400).send({
83 | success: false,
84 | message: req.t(transStrings.useralreadyexists),
85 | error: err,
86 | });
87 | })
88 | : res.status(500).send({
89 | success: false,
90 | message: 'Check your data',
91 | error: {},
92 | });
93 | };
94 |
95 | export { UserLogin, UserRegister };
96 |
--------------------------------------------------------------------------------
/src/mvc/controllers/index.ts:
--------------------------------------------------------------------------------
1 | import * as userController from './user.controller';
2 | import * as authController from './auth.controller';
3 |
4 | export { userController, authController };
5 |
--------------------------------------------------------------------------------
/src/mvc/controllers/user.controller.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express';
2 | import { getIDfromToken } from '../../helpers/getIDfromToken';
3 | import { transStrings } from '../../init/locales';
4 | import { User } from '../models';
5 | const bcrypt = require('bcryptjs');
6 | const saltRounds = 10;
7 |
8 | const UserProfile = (req: Request | any, res: Response) => {
9 | const user_id = getIDfromToken(req);
10 | console.log('user_id', user_id);
11 | return User.findById(user_id, function (err, user) {
12 | if (err) throw err;
13 |
14 | if (!user) {
15 | res.status(403).json({
16 | success: false,
17 | message: req.i18n.t('simpleStringWithVariable', {
18 | variable1: '3',
19 | variable2: '3',
20 | }),
21 | });
22 | } else if (user) {
23 | res.status(200).send({
24 | success: true,
25 | user: {
26 | id: user._id,
27 | name: user.name,
28 | email: user.email,
29 | mobile: user.mobile,
30 | },
31 | });
32 | }
33 | });
34 | };
35 | const UserUpdate = async (req: Request | any, res: Response) => {
36 | const user_id = getIDfromToken(req);
37 | console.log('user_id', user_id);
38 | const { email, password, name } = req.body;
39 | if (email) delete req.body.email;
40 | if (name) req.body.name = name;
41 | if (password) {
42 | const newPassword = bcrypt.hashSync(password, saltRounds);
43 | req.body.password = newPassword;
44 | }
45 | const user = await User.findOneAndUpdate({ _id: user_id }, { $set: req.body }, { new: true });
46 |
47 | return res.status(200).send({
48 | success: true,
49 | message: req.t(transStrings.profileupdatedsuccessfuly),
50 | user: user,
51 | });
52 | };
53 | export { UserProfile, UserUpdate };
54 |
--------------------------------------------------------------------------------
/src/mvc/middlewares/auth/index.ts:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken');
2 |
3 | const auth = (req, res, next) => {
4 | const token = req.body.token;
5 |
6 | if (token) {
7 | req.token = token;
8 | jwt.verify(token, process.env.JWT_KEY, function (err, decoded) {
9 | if (err) {
10 | err.message = 'Please, Login.';
11 | return res.status(403).send({
12 | success: false,
13 | message: 'Please, Login.',
14 | });
15 | }
16 | req.user = decoded;
17 | console.log(decoded);
18 | next();
19 | });
20 | } else {
21 | return res.status(403).send({
22 | success: false,
23 | unAuthorized: true,
24 | message: 'Unauthorized',
25 | });
26 | }
27 | };
28 |
29 | export default auth;
30 |
--------------------------------------------------------------------------------
/src/mvc/middlewares/index.ts:
--------------------------------------------------------------------------------
1 | import auth from './auth';
2 | import userAuth from './userAuth';
3 |
4 | export { auth, userAuth };
5 |
--------------------------------------------------------------------------------
/src/mvc/middlewares/userAuth/index.ts:
--------------------------------------------------------------------------------
1 | import { User } from '../../models';
2 |
3 | const userAuth = async (req, res, next) => {
4 | const user = await User.findOne({
5 | _id: req.user.id,
6 | active: true,
7 | });
8 |
9 | if (!user)
10 | return res.status(403).send({
11 | success: false,
12 | unAuthorized: true,
13 | message: 'Unauthorized',
14 | });
15 | else {
16 | const data = user.toObject();
17 | data.role = 'user';
18 |
19 | req.user = data;
20 | next();
21 | }
22 | };
23 |
24 | export default userAuth;
25 |
--------------------------------------------------------------------------------
/src/mvc/models/index.ts:
--------------------------------------------------------------------------------
1 | const User = require('./user.model');
2 |
3 | export { User };
4 |
--------------------------------------------------------------------------------
/src/mvc/models/user.model.ts:
--------------------------------------------------------------------------------
1 | import mongoose from 'mongoose';
2 | import { ISchemaType } from '@/interfaces/interface';
3 | import { CreateSchema } from '../../helpers/createSchema';
4 |
5 | const bcrypt = require('bcryptjs');
6 | const saltRounds = 10;
7 |
8 | const schema = CreateSchema({
9 | name: { type: String },
10 | email: { type: String, unique: true, lowercase: true },
11 | mobile: { type: String, unique: true },
12 | password: { type: String },
13 | });
14 |
15 | schema.pre('save', function (next) {
16 | if (!this.isModified('password')) return next();
17 | if (this.password) {
18 | this.password = bcrypt.hashSync(this.password, saltRounds);
19 | next();
20 | } else {
21 | next();
22 | }
23 | });
24 |
25 | module.exports = mongoose.model('users', schema);
26 |
--------------------------------------------------------------------------------
/src/mvc/routes/auth.routes.ts:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import { authController } from '../controllers';
3 | import { Routes } from './routesStrings';
4 | const router = express.Router();
5 |
6 | router.post(Routes.login, authController.UserLogin);
7 | router.post(Routes.register, authController.UserRegister);
8 |
9 | export default router;
10 |
--------------------------------------------------------------------------------
/src/mvc/routes/index.ts:
--------------------------------------------------------------------------------
1 | import authRouter from './auth.routes';
2 | import userRouter from './user.routes';
3 |
4 | export { authRouter, userRouter };
5 |
--------------------------------------------------------------------------------
/src/mvc/routes/routesStrings/index.ts:
--------------------------------------------------------------------------------
1 | export const Routes = {
2 | user: '/user',
3 | login: '/login',
4 | register: '/register',
5 | profile: '/profile',
6 | update: '/update',
7 | };
8 |
--------------------------------------------------------------------------------
/src/mvc/routes/user.routes.ts:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import { userController } from '../controllers';
3 | import { auth, userAuth } from '../middlewares';
4 | import { Routes } from './routesStrings';
5 |
6 | const router = express.Router();
7 |
8 | router.get(Routes.profile, [auth, userAuth], userController.UserProfile);
9 | router.post(Routes.update, [auth, userAuth], userController.UserUpdate);
10 |
11 | export default router;
12 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "target": "es2017",
5 | "lib": [
6 | "es2017",
7 | "esnext.asynciterable",
8 | ],
9 | "typeRoots": [
10 | "node_modules/@types"
11 | ],
12 | "allowSyntheticDefaultImports": true,
13 | "experimentalDecorators": true,
14 | "emitDecoratorMetadata": true,
15 | "forceConsistentCasingInFileNames": true,
16 | "moduleResolution": "node",
17 | "module": "commonjs",
18 | "pretty": true,
19 | "sourceMap": true,
20 | "declaration": true,
21 | "outDir": "dist",
22 | "allowJs": true,
23 | "noEmit": false,
24 | "esModuleInterop": true,
25 | "resolveJsonModule": true,
26 | "importHelpers": true,
27 | "baseUrl": "./src",
28 | "paths": {
29 | "@/*": [
30 | "*"
31 | ],
32 | "@controllers/*": [
33 | "mvc/controllers"
34 | ],
35 | "@interfaces/*": [
36 | "interfaces/*"
37 | ],
38 | "@mvc/*": [
39 | "mvc/*"
40 | ],
41 | "@middlewares/*": [
42 | "middlewares/*"
43 | ],
44 | "@models/*": [
45 | "mvc/models"
46 | ],
47 | "@routes": [
48 | "mvc/routes/index.ts"
49 | ],
50 | "@routes/*": [
51 | "mvc/routes/*"
52 | ],
53 | "@services/*": [
54 | "services/*"
55 | ],
56 | "@helpers/*": [
57 | "helpers/*"
58 | ]
59 | }
60 | },
61 | "exclude": [
62 | "node_modules",
63 | "dist",
64 | ]
65 | }
--------------------------------------------------------------------------------