exp-node-server 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +180 -0
  2. package/bin/cli.js +41 -0
  3. package/package.json +32 -0
  4. package/src/createProject.js +58 -0
  5. package/src/generateModule.js +61 -0
  6. package/src/utils/controllerGenerator.js +70 -0
  7. package/src/utils/routeGenerator.js +27 -0
  8. package/src/utils/routeInjector.js +40 -0
  9. package/src/utils/schemaGenerator.js +11 -0
  10. package/src/utils/serviceGenerator.js +49 -0
  11. package/src/utils/swaggerGenerator.js +112 -0
  12. package/src/utils/swaggerInjector.js +52 -0
  13. package/src/utils/validateModuleName.js +17 -0
  14. package/src/utils/validateProjectName.js +15 -0
  15. package/src/utils/validationGenerator.js +13 -0
  16. package/src/utils.js +26 -0
  17. package/templates/mongoose/.env.example +23 -0
  18. package/templates/mongoose/package.json +45 -0
  19. package/templates/mongoose/readme.md +180 -0
  20. package/templates/mongoose/src/app/configs/index.ts +26 -0
  21. package/templates/mongoose/src/app/errors/castError.ts +23 -0
  22. package/templates/mongoose/src/app/errors/duplicateError.ts +26 -0
  23. package/templates/mongoose/src/app/errors/validationError.ts +25 -0
  24. package/templates/mongoose/src/app/errors/zodError.ts +20 -0
  25. package/templates/mongoose/src/app/middlewares/auth.ts +50 -0
  26. package/templates/mongoose/src/app/middlewares/global_error_handler.ts +69 -0
  27. package/templates/mongoose/src/app/middlewares/not_found_api.ts +10 -0
  28. package/templates/mongoose/src/app/middlewares/request_validator.ts +14 -0
  29. package/templates/mongoose/src/app/middlewares/uploader.ts +16 -0
  30. package/templates/mongoose/src/app/modules/auth/auth.controller.ts +125 -0
  31. package/templates/mongoose/src/app/modules/auth/auth.interface.ts +24 -0
  32. package/templates/mongoose/src/app/modules/auth/auth.route.ts +46 -0
  33. package/templates/mongoose/src/app/modules/auth/auth.schema.ts +19 -0
  34. package/templates/mongoose/src/app/modules/auth/auth.service.ts +306 -0
  35. package/templates/mongoose/src/app/modules/auth/auth.swagger.ts +214 -0
  36. package/templates/mongoose/src/app/modules/auth/auth.validation.ts +37 -0
  37. package/templates/mongoose/src/app/modules/user/user.controller.ts +17 -0
  38. package/templates/mongoose/src/app/modules/user/user.interface.ts +15 -0
  39. package/templates/mongoose/src/app/modules/user/user.route.ts +20 -0
  40. package/templates/mongoose/src/app/modules/user/user.schema.ts +22 -0
  41. package/templates/mongoose/src/app/modules/user/user.service.ts +22 -0
  42. package/templates/mongoose/src/app/modules/user/user.swagger.ts +75 -0
  43. package/templates/mongoose/src/app/modules/user/user.validation.ts +18 -0
  44. package/templates/mongoose/src/app/types/error.d.ts +10 -0
  45. package/templates/mongoose/src/app/types/index.d.ts +12 -0
  46. package/templates/mongoose/src/app/utils/JWT.ts +26 -0
  47. package/templates/mongoose/src/app/utils/app_error.ts +12 -0
  48. package/templates/mongoose/src/app/utils/catch_async.ts +13 -0
  49. package/templates/mongoose/src/app/utils/cloudinary.ts +66 -0
  50. package/templates/mongoose/src/app/utils/isAccountExist.ts +31 -0
  51. package/templates/mongoose/src/app/utils/mail_sender.ts +102 -0
  52. package/templates/mongoose/src/app/utils/manage_response.ts +24 -0
  53. package/templates/mongoose/src/app.ts +42 -0
  54. package/templates/mongoose/src/routes.ts +13 -0
  55. package/templates/mongoose/src/server.ts +18 -0
  56. package/templates/mongoose/src/swaggerOptions.ts +44 -0
  57. package/templates/mongoose/tsconfig.json +20 -0
@@ -0,0 +1,52 @@
1
+ import chalk from "chalk";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ export function injectSwagger(name) {
6
+
7
+ const swaggerFile = path.join(process.cwd(), "src/swaggerOptions.ts");
8
+
9
+ if (!fs.existsSync(swaggerFile)) {
10
+ console.log(chalk.yellow("⚠️ swaggerOptions.ts not found"));
11
+ return;
12
+ }
13
+
14
+ let content = fs.readFileSync(swaggerFile, "utf-8");
15
+
16
+ const importLine = `import { ${name}SwaggerDocs } from "./app/modules/${name}/${name}.swagger";`;
17
+ const spreadLine = ` ...${name}SwaggerDocs,`;
18
+
19
+
20
+ if (!content.includes(importLine)) {
21
+
22
+ const lastImportIndex = content.lastIndexOf("import ");
23
+ const nextLine = content.indexOf("\n", lastImportIndex);
24
+
25
+ content =
26
+ content.slice(0, nextLine + 1) +
27
+ importLine +
28
+ "\n" +
29
+ content.slice(nextLine + 1);
30
+ }
31
+
32
+ if (!content.includes(spreadLine)) {
33
+
34
+ const match = content.match(/paths:\s*{([\s\S]*?)}/);
35
+
36
+ if (match) {
37
+
38
+ const pathsBlock = match[0];
39
+
40
+ const updatedBlock = pathsBlock.replace(
41
+ /}$/,
42
+ `${spreadLine}\n }`
43
+ );
44
+
45
+ content = content.replace(pathsBlock, updatedBlock);
46
+ }
47
+ }
48
+
49
+ fs.writeFileSync(swaggerFile, content);
50
+
51
+ console.log(chalk.green(`✔ Swagger registered for ${name}`));
52
+ }
@@ -0,0 +1,17 @@
1
+ export function validateModuleName(name) {
2
+
3
+ if (!name) return null;
4
+
5
+ // convert space / dash → underscore
6
+ const normalized = name
7
+ .trim()
8
+ .toLowerCase()
9
+ .replace(/[-\s]+/g, "_");
10
+
11
+ // allow only a-z and underscore
12
+ const isValid = /^[a-z_]+$/.test(normalized);
13
+
14
+ if (!isValid) return null;
15
+
16
+ return normalized;
17
+ }
@@ -0,0 +1,15 @@
1
+ export function validateProjectName(name) {
2
+
3
+ if (!name) return null;
4
+
5
+ const normalized = name
6
+ .trim()
7
+ .toLowerCase()
8
+ .replace(/\s+/g, "-");
9
+
10
+ const isValid = /^[a-z0-9-]+$/.test(normalized);
11
+
12
+ if (!isValid) return null;
13
+
14
+ return normalized;
15
+ }
@@ -0,0 +1,13 @@
1
+ export const validationGenerator = (name) => {
2
+ return `
3
+ import { z } from "zod";
4
+
5
+ const create_${name} = z.object({});
6
+ const update_${name} = z.object({});
7
+
8
+ export const ${name}_validations = {
9
+ create_${name},
10
+ update_${name},
11
+ };
12
+ `
13
+ }
package/src/utils.js ADDED
@@ -0,0 +1,26 @@
1
+ import fs from "fs";
2
+ import ora from "ora";
3
+ import path from "path";
4
+
5
+ export const createDir = (dir) => {
6
+ if (!fs.existsSync(dir)) {
7
+ fs.mkdirSync(dir, { recursive: true });
8
+ }
9
+ };
10
+
11
+ export const createFile = (file, content) => {
12
+ const spinner = ora(`Creating ${path.basename(file)}...`).start();
13
+
14
+ try {
15
+ fs.writeFileSync(file, content);
16
+ spinner.succeed(`${path.basename(file)} created`);
17
+ } catch {
18
+ spinner.fail(`${path.basename(file)} failed`);
19
+ }
20
+ };
21
+
22
+ export const toSnakeCase = (str) =>
23
+ str.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
24
+
25
+ export const toPascalCase = (str) =>
26
+ str.charAt(0).toUpperCase() + str.slice(1);
@@ -0,0 +1,23 @@
1
+ NODE_ENV=development
2
+ DATABASE_URL=
3
+ PORT=5000
4
+
5
+
6
+ # JWT Configuration
7
+ ACCESS_TOKEN=
8
+ REFRESH_TOKEN=
9
+ ACCESS_EXPIRES=
10
+ REFRESH_EXPIRES=
11
+ RESET_SECRET=
12
+ RESET_EXPIRES=
13
+ VERIFIED_TOKEN=
14
+ FRONT_END_URL=
15
+
16
+ # Email Configuration
17
+ APP_USER_EMAIL=
18
+ APP_PASSWORD=
19
+
20
+ # Cloudinary Configuration
21
+ CLOUD_NAME=
22
+ CLOUD_API_KEY=
23
+ CLOUD_API_SECRET=
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "server",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "dev": "ts-node-dev --respawn --transpile-only src/server.ts",
9
+ "build": "tsc"
10
+ },
11
+ "keywords": [],
12
+ "author": "",
13
+ "license": "ISC",
14
+ "type": "commonjs",
15
+ "dependencies": {
16
+ "bcrypt": "^6.0.0",
17
+ "cloudinary": "^2.7.0",
18
+ "cookie-parser": "^1.4.7",
19
+ "cors": "^2.8.5",
20
+ "dotenv": "^17.2.3",
21
+ "express": "^5.1.0",
22
+ "jsonwebtoken": "^9.0.2",
23
+ "multer": "^2.0.2",
24
+ "nodemailer": "^7.0.9",
25
+ "pg": "^8.17.2",
26
+ "swagger-jsdoc": "^6.2.8",
27
+ "swagger-ui-express": "^5.0.1",
28
+ "ts-node-dev": "^2.0.0",
29
+ "zod": "^4.1.12"
30
+ },
31
+ "devDependencies": {
32
+ "@types/bcrypt": "^6.0.0",
33
+ "@types/cookie-parser": "^1.4.9",
34
+ "@types/cors": "^2.8.19",
35
+ "@types/express": "^5.0.3",
36
+ "@types/jsonwebtoken": "^9.0.10",
37
+ "@types/mongoose": "^5.11.96",
38
+ "@types/multer": "^2.0.0",
39
+ "@types/node": "^24.10.9",
40
+ "@types/nodemailer": "^7.0.2",
41
+ "@types/pg": "^8.16.0",
42
+ "@types/swagger-jsdoc": "^6.0.4",
43
+ "@types/swagger-ui-express": "^4.1.8"
44
+ }
45
+ }
@@ -0,0 +1,180 @@
1
+ # ⚡ Express + Mongoose + TypeScript Module Generator
2
+
3
+ [![npm version](https://img.shields.io/npm/v/exp-cli-gen.svg)](https://www.npmjs.com/package/exp-cli-gen)
4
+ [![npm downloads](https://img.shields.io/npm/dw/exp-cli-gen.svg)](https://www.npmjs.com/package/exp-cli-gen)
5
+ [![npm total downloads](https://img.shields.io/npm/dt/exp-cli-gen.svg)](https://www.npmjs.com/package/exp-cli-gen)
6
+ [![GitHub stars](https://img.shields.io/github/stars/abumahid/mongo-server-stater-pack.svg)](https://github.com/abumahid/mongo-server-stater-pack/stargazers)
7
+ [![GitHub issues](https://img.shields.io/github/issues/abumahid/mongo-server-stater-pack.svg)](https://github.com/abumahid/mongo-server-stater-pack/issues)
8
+ [![License](https://img.shields.io/github/license/abumahid/mongo-server-stater-pack.svg)](https://github.com/abumahid/mongo-server-stater-pack/blob/main/LICENSE)
9
+ [![GitHub last commit](https://img.shields.io/github/last-commit/abumahid/mongo-server-stater-pack.svg)](https://github.com/abumahid/mongo-server-stater-pack/commits/main)
10
+ [![Made with TypeScript](https://img.shields.io/badge/Made%20with-TypeScript-blue.svg)](https://www.typescriptlang.org/)
11
+ [![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
12
+
13
+ ---
14
+
15
+ ## 🚀 Overview
16
+
17
+ **exp-cli-gen** is a powerful **Express + TypeScript module generator** that uses **Mongoose** for database interaction.
18
+ It automatically creates a complete module structure — including **models, controllers, services, routes, Zod validations, and Swagger documentation** — all in one command.
19
+
20
+ Ideal for developers who want to quickly scaffold modular Express APIs with clean architecture and ready-to-use integrations.
21
+
22
+ ---
23
+
24
+ ## ✨ Features
25
+
26
+ - ⚙️ Generates full-featured Express + TypeScript modules
27
+ - 🧩 Automatically integrates Mongoose models and Zod validations
28
+ - 📘 Adds Swagger documentation automatically
29
+ - 🚀 Clones and sets up a ready-to-run Express starter project
30
+ - 🔁 Can add new modules anytime with a single command
31
+ - 🧠 Skips redundant setup if the starter pack already exists
32
+ - 💪 Built for scalability and maintainability
33
+
34
+ ---
35
+
36
+ ## 📦 Installation
37
+
38
+ Install globally:
39
+
40
+ ```bash
41
+ npm install -g exp-cli-gen
42
+ ```
43
+ Or run directly using npx (recommended):
44
+
45
+ ```bash
46
+ npx exp-cli-gen <module-name>
47
+ ```
48
+ ## Usage
49
+ 🏗️ Generate your first module
50
+
51
+ Run:
52
+
53
+ ```bash
54
+ npx exp-cli-gen test
55
+ ```
56
+ First run example:
57
+
58
+ ```bash
59
+ Need to install the following packages:
60
+ exp-cli-gen@1.0.1
61
+ Ok to proceed? (y)
62
+
63
+ ⠋ No Express project found. Cloning starter pack...
64
+ ✔ Starter project cloned!
65
+
66
+ ✔ Git logs removed!
67
+
68
+ 📦 Installing dependencies...
69
+
70
+ 🚀 Project setup complete.
71
+ 🧩 Generating module: test...
72
+ ✔ test.interface.ts created
73
+ ✔ test.schema.ts created
74
+ ✔ test.validation.ts created
75
+ ✔ test.route.ts created
76
+ ✔ test.controller.ts created
77
+ ✔ test.service.ts created
78
+ ✔ test.swagger.ts created
79
+
80
+ 🔗 Route added to src/app/routes.ts
81
+ 📘 Swagger doc added to src/swaggerOptions.ts
82
+ ✨ Module 'test' created successfully!
83
+
84
+ ```
85
+
86
+ ## 📁 Generated Module Structure
87
+
88
+ Each generated module will contain the following files:
89
+
90
+ ```pgsql
91
+ src/app/modules/<module-name>/
92
+ ├── <module-name>.interface.ts
93
+ ├── <module-name>.schema.ts
94
+ ├── <module-name>.validation.ts
95
+ ├── <module-name>.route.ts
96
+ ├── <module-name>.controller.ts
97
+ ├── <module-name>.service.ts
98
+ └── <module-name>.swagger.ts
99
+ ```
100
+
101
+ ## 🔄 Add More Modules
102
+
103
+ Need another module? Just run:
104
+
105
+ ```bash
106
+ npx exp-cli-gen products
107
+ ```
108
+
109
+ If the starter project already exists, it will skip cloning and directly add the new module.
110
+
111
+ Example output:
112
+ ```bash
113
+ ℹ 📦 Starter folder already exists. Skipping clone.
114
+ 📦 Dependencies already installed. Skipping npm install.
115
+ 🧩 Generating module: products...
116
+ ✔ products files created
117
+ ✨ Module 'products' created successfully!
118
+
119
+ src/app/modules/products/
120
+ ├── products.interface.ts
121
+ ├── products.schema.ts
122
+ ├── products.validation.ts
123
+ ├── products.route.ts
124
+ ├── products.controller.ts
125
+ ├── products.service.ts
126
+ └── products.swagger.ts
127
+ ```
128
+
129
+ Then, refresh your Swagger docs at:
130
+ ```bash
131
+ http://localhost:5000/docs
132
+ ```
133
+
134
+ You’ll see your new routes automatically added.
135
+
136
+ ---
137
+
138
+ ## ⚙️ Configuration
139
+
140
+ After setup, update your .env file following the .env.example file in the starter project.
141
+
142
+ To start the server:
143
+ ```bash
144
+ npm run dev
145
+ ```
146
+ Open Swagger documentation at:
147
+ ```bash
148
+ http://localhost:5000/docs
149
+ ```
150
+
151
+ ---
152
+ ## 🧠 Tech Stack
153
+
154
+ - Express.js — Backend framework
155
+ - TypeScript — Strongly typed JavaScript
156
+ - Mongoose — MongoDB ORM
157
+ - Zod — Runtime schema validation
158
+ - Swagger — API documentation
159
+ - CLI (Node.js) — Command-line automation
160
+
161
+ ---
162
+ ## 🧩 Starter Pack Repository
163
+
164
+ This CLI uses the following base project as a starter:
165
+
166
+ 👉 [mongo-server-stater-pack](https://github.com/abumahid/mongo-server-stater-pack.git)
167
+
168
+ ---
169
+ ## 💬 Author
170
+
171
+ Abu Mahid
172
+
173
+ 🧠 [GitHub Profile](https://github.com/abumahid)
174
+
175
+ 💼 [npm Profile](https://www.npmjs.com/~dev_abumahid)
176
+
177
+ ---
178
+ ### ⭐ Star this project
179
+
180
+ If you like this CLI, please give it a ⭐ on GitHub — it helps others discover it too! Thank you!
@@ -0,0 +1,26 @@
1
+ import "dotenv/config";
2
+
3
+ export const configs = {
4
+ port: process.env.PORT,
5
+ env: process.env.NODE_ENV,
6
+ db_url: process.env.DATABASE_URL,
7
+ jwt: {
8
+ access_token: process.env.ACCESS_TOKEN,
9
+ refresh_token: process.env.REFRESH_TOKEN,
10
+ access_expires: process.env.ACCESS_EXPIRES,
11
+ refresh_expires: process.env.REFRESH_EXPIRES,
12
+ reset_secret: process.env.RESET_SECRET,
13
+ reset_expires: process.env.RESET_EXPIRES,
14
+ front_end_url: process.env.FRONT_END_URL,
15
+ verified_token: process.env.VERIFIED_TOKEN,
16
+ },
17
+ email: {
18
+ app_email: process.env.APP_USER_EMAIL,
19
+ app_password: process.env.APP_PASSWORD,
20
+ },
21
+ cloudinary: {
22
+ cloud_name: process.env.CLOUD_NAME,
23
+ cloud_api_key: process.env.CLOUD_API_KEY,
24
+ cloud_api_secret: process.env.CLOUD_API_SECRET,
25
+ },
26
+ };
@@ -0,0 +1,23 @@
1
+ import mongoose from 'mongoose'
2
+ import { TErrorSources, TGenericErrorResponse } from '../types/error'
3
+
4
+ const handleCastError = (
5
+ err: mongoose.Error.CastError
6
+ ): TGenericErrorResponse => {
7
+ const errorSources: TErrorSources= [
8
+ {
9
+ path: err.path,
10
+ message: err.message
11
+ }
12
+ ]
13
+
14
+ const statusCode = 400
15
+
16
+ return {
17
+ statusCode,
18
+ message: 'Invalid ID',
19
+ errorSources
20
+ }
21
+ }
22
+
23
+ export default handleCastError
@@ -0,0 +1,26 @@
1
+ import { TErrorSources, TGenericErrorResponse } from '../types/error'
2
+
3
+ const handleDuplicateError = (err: any): TGenericErrorResponse => {
4
+ // Extract value within double quotes using regex
5
+ const match = err.message.match(/"([^"]*)"/)
6
+
7
+ // The extracted value will be in the first capturing group
8
+ const extractedMessage = match && match[1]
9
+
10
+ const errorSources: TErrorSources = [
11
+ {
12
+ path: '',
13
+ message: `${extractedMessage} is already exists`
14
+ }
15
+ ]
16
+
17
+ const statusCode = 400
18
+
19
+ return {
20
+ statusCode,
21
+ message: 'Invalid ID',
22
+ errorSources
23
+ }
24
+ }
25
+
26
+ export default handleDuplicateError
@@ -0,0 +1,25 @@
1
+ import mongoose from 'mongoose'
2
+ import { TErrorSources, TGenericErrorResponse } from '../types/error'
3
+
4
+ const handleValidationError = (
5
+ err: mongoose.Error.ValidationError
6
+ ): TGenericErrorResponse => {
7
+ const errorSources: TErrorSources = Object.values(err.errors).map(
8
+ (val: mongoose.Error.ValidatorError | mongoose.Error.CastError) => {
9
+ return {
10
+ path: val?.path,
11
+ message: val?.message
12
+ }
13
+ }
14
+ )
15
+
16
+ const statusCode = 400
17
+
18
+ return {
19
+ statusCode,
20
+ message: 'Validation Error',
21
+ errorSources
22
+ }
23
+ }
24
+
25
+ export default handleValidationError
@@ -0,0 +1,20 @@
1
+ import { ZodError, ZodIssue } from 'zod'
2
+ import { TErrorSources, TGenericErrorResponse } from '../types/error'
3
+
4
+ const handleZodError = (err: ZodError): TGenericErrorResponse => {
5
+ const errorSources: TErrorSources = err.issues.map((issue: ZodIssue) => {
6
+ return {
7
+ path: issue?.path[issue.path.length - 1] as string,
8
+ message: issue.message
9
+ }
10
+ })
11
+
12
+ const statusCode = 400
13
+ return {
14
+ statusCode,
15
+ message: 'Validation Error',
16
+ errorSources
17
+ }
18
+ }
19
+
20
+ export default handleZodError
@@ -0,0 +1,50 @@
1
+ import { NextFunction, Request, Response } from 'express';
2
+ import { AppError } from '../utils/app_error';
3
+ import { configs } from '../configs';
4
+ import { jwtHelpers, JwtPayloadType } from '../utils/JWT';
5
+ import { Account_Model } from '../modules/auth/auth.schema';
6
+
7
+
8
+ type Role = "ADMIN" | "USER"
9
+
10
+
11
+ const auth = (...roles: Role[]) => {
12
+ return async (req: Request, res: Response, next: NextFunction) => {
13
+ try {
14
+ const token = req.headers.authorization;
15
+ if (!token) {
16
+ throw new AppError('You are not authorize!!', 401);
17
+ }
18
+ const verifiedUser = jwtHelpers.verifyToken(
19
+ token,
20
+ configs.jwt.access_token as string,
21
+ );
22
+ if (!roles.length || !roles.includes(verifiedUser.role)) {
23
+ throw new AppError('You are not authorize!!', 401);
24
+ }
25
+ // check user
26
+ const isUserExist = await Account_Model.findOne({ email: verifiedUser?.email }).lean()
27
+ if (!isUserExist) {
28
+ throw new AppError("Account not found !", 404)
29
+ }
30
+ if (isUserExist?.accountStatus == "SUSPENDED") {
31
+ throw new AppError("This Account is suspended !", 401)
32
+ }
33
+ if (isUserExist?.accountStatus == "INACTIVE") {
34
+ throw new AppError("This Account is inactive !", 401)
35
+ }
36
+ if (isUserExist?.isDeleted) {
37
+ throw new AppError("This account is deleted", 401)
38
+ }
39
+ if (!isUserExist?.isVerified) {
40
+ throw new AppError("This account is not verified ", 401)
41
+ }
42
+ req.user = verifiedUser as JwtPayloadType;
43
+ next();
44
+ } catch (err) {
45
+ next(err);
46
+ }
47
+ };
48
+ };
49
+
50
+ export default auth;
@@ -0,0 +1,69 @@
1
+ import { Request, Response, NextFunction, ErrorRequestHandler } from 'express'
2
+ import { ZodError } from 'zod'
3
+ import handleZodError from '../errors/zodError'
4
+ import handleValidationError from '../errors/validationError'
5
+ import handleCastError from '../errors/castError'
6
+ import { TErrorSources } from '../types/error'
7
+ import handleDuplicateError from '../errors/duplicateError'
8
+ import { AppError } from '../utils/app_error'
9
+ import { configs } from '../configs'
10
+
11
+ const globalErrorHandler: ErrorRequestHandler = (err, req, res, next) => {
12
+ let statusCode = 500
13
+ let message = 'Something went wrong!'
14
+ let errorSources: TErrorSources = [
15
+ {
16
+ path: '',
17
+ message: 'Something went wrong'
18
+ }
19
+ ]
20
+
21
+ if (err instanceof ZodError) {
22
+ const simplifiedError = handleZodError(err)
23
+ statusCode = simplifiedError?.statusCode
24
+ message = simplifiedError?.message
25
+ errorSources = simplifiedError?.errorSources
26
+ } else if (err?.name === 'ValidationError') {
27
+ const simplifiedError = handleValidationError(err)
28
+ statusCode = simplifiedError?.statusCode
29
+ message = simplifiedError?.message
30
+ errorSources = simplifiedError?.errorSources
31
+ } else if (err?.name === 'CastError') {
32
+ const simplifiedError = handleCastError(err)
33
+ statusCode = simplifiedError?.statusCode
34
+ message = simplifiedError?.message
35
+ errorSources = simplifiedError?.errorSources
36
+ } else if (err?.code === 11000) {
37
+ const simplifiedError = handleDuplicateError(err)
38
+ statusCode = simplifiedError?.statusCode
39
+ message = simplifiedError?.message
40
+ errorSources = simplifiedError?.errorSources
41
+ } else if (err instanceof AppError) {
42
+ statusCode = err?.statusCode
43
+ message = err.message
44
+ errorSources = [
45
+ {
46
+ path: '',
47
+ message: err?.message
48
+ }
49
+ ]
50
+ } else if (err instanceof Error) {
51
+ message = err.message
52
+ errorSources = [
53
+ {
54
+ path: '',
55
+ message: err?.message
56
+ }
57
+ ]
58
+ }
59
+
60
+ res.status(statusCode).json({
61
+ success: false,
62
+ message,
63
+ errorSources,
64
+ err,
65
+ stack: configs.env === 'development' ? err?.stack : null
66
+ })
67
+ }
68
+
69
+ export default globalErrorHandler
@@ -0,0 +1,10 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const notFound = (req: Request, res: Response, next: NextFunction) => {
4
+ res.status(404).json({
5
+ message: 'Sorry Route is not found!! 😴😴😴',
6
+ success: false,
7
+ error: '',
8
+ });
9
+ };
10
+ export default notFound;
@@ -0,0 +1,14 @@
1
+ import { NextFunction, Request, Response } from 'express';
2
+
3
+ const RequestValidator = (schema: any) => {
4
+ return async (req: Request, res: Response, next: NextFunction) => {
5
+ try {
6
+ await schema.parseAsync(req.body);
7
+ next();
8
+ } catch (err) {
9
+ next(err);
10
+ }
11
+ };
12
+ };
13
+
14
+ export default RequestValidator;
@@ -0,0 +1,16 @@
1
+ import multer from "multer";
2
+ import path from "path";
3
+
4
+ const storage = multer.diskStorage({
5
+ destination: function (req, file, cb) {
6
+ cb(null, path.join(process.cwd(), "uploads"))
7
+ },
8
+ filename: function (req, file, cb) {
9
+
10
+ cb(null, file.originalname)
11
+ }
12
+ })
13
+
14
+ const uploader = multer({ storage: storage })
15
+
16
+ export default uploader;