Skip to content

Commit 222b017

Browse files
authored
Merge pull request #4 from nabadeep25/dev
refactor: ♻️ package update, wagger update, models refacored
2 parents 669cdf4 + b7ec41b commit 222b017

File tree

14 files changed

+144
-18000
lines changed

14 files changed

+144
-18000
lines changed

package-lock.json

Lines changed: 0 additions & 17889 deletions
This file was deleted.

package.json

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,77 @@
11
{
22
"name": "@nabadeep25/create-ts-node-app",
3-
"version": "0.2.0",
4-
"description": "",
3+
"version": "0.3.0",
4+
"description": "A boilerplate/starter project for quickly building RESTful APIs using Node.js,Typescript, Express, and Sequelize.",
55
"author": "Nabadeep Thakuria",
66
"bin": "bin/cli.js",
77
"homepage": "https://github.com/nabadeep25/typescript-node-sequelize-boilerplate",
88
"license": "MIT",
9-
"keywords": ["typescript","node","express","sequelize","mysql","postgres","boilerplate","template","typescript node sequelize boilerplate","typescript node","typescript sequelize boilerplate"],
9+
"keywords": [
10+
"typescript",
11+
"node",
12+
"express",
13+
"sequelize",
14+
"mysql",
15+
"postgres",
16+
"boilerplate",
17+
"template",
18+
"typescript node sequelize boilerplate",
19+
"typescript node",
20+
"typescript sequelize boilerplate"
21+
],
1022
"scripts": {
1123
"build-ts": "tsc",
1224
"build": "npm run build-ts && npm run lint ",
13-
"lint": "tsc --noEmit && eslint \"**/*.{js,ts}\" --quiet --fix",
25+
"lint": "tsc --noEmit && eslint \"src/**/*.{js,ts}\" --quiet --fix",
1426
"format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"",
1527
"serve": "node dist/server.js",
1628
"start": "npm run serve",
17-
"watch-node": "nodemon dist/server.js",
29+
"dev": "tsnd --respawn src/server.ts",
1830
"watch-ts": "tsc -w",
1931
"watch": "concurrently -k -p \"[{name}]\" -n \"TypeScript,Node\" -c \"cyan.bold,green.bold\" \"npm run watch-ts\" \"npm run watch-node\""
2032
},
2133
"dependencies": {
22-
"@aws-sdk/client-s3": "^3.201.0",
23-
"@aws-sdk/s3-request-presigner": "^3.202.0",
24-
"@types/bcrypt": "^5.0.0",
25-
"@types/cors": "^2.8.12",
26-
"@types/joi": "^17.2.3",
27-
"@types/jsonwebtoken": "^8.5.9",
28-
"@types/morgan": "^1.9.3",
29-
"async": "3.2.2",
34+
"@types/node": "^20.8.4",
3035
"bcrypt": "^5.1.0",
3136
"cors": "^2.8.5",
3237
"dotenv": "8.2.0",
3338
"errorhandler": "1.5.1",
34-
"express": "4.17.1",
39+
"express": "^4.18.2",
3540
"joi": "^17.6.4",
36-
"jsonwebtoken": "^8.5.1",
41+
"jsonwebtoken": "^9.0.2",
3742
"lodash": "^4.17.21",
38-
"mongoose": "^5.13.15",
3943
"morgan": "^1.10.0",
40-
"multer": "^1.4.5-lts.1",
41-
"multer-s3": "^3.0.1",
42-
"mysql2": "^2.3.3",
4344
"nodemailer": "^6.6.1",
4445
"otplib": "^12.0.1",
46+
"pg": "^8.11.3",
4547
"sequelize": "^6.25.3",
4648
"swagger-jsdoc": "^6.2.5",
4749
"swagger-ui-express": "^4.6.0",
4850
"winston": "3.3.3"
4951
},
5052
"devDependencies": {
51-
"@types/async": "3.2.5",
53+
"@types/bcrypt": "^5.0.0",
5254
"@types/concurrently": "5.2.1",
55+
"@types/cors": "^2.8.12",
5356
"@types/errorhandler": "1.5.0",
5457
"@types/eslint": "7.2.6",
5558
"@types/express": "4.17.11",
59+
"@types/jsonwebtoken": "^8.5.9",
5660
"@types/lodash": "^4.14.170",
57-
"@types/multer-s3": "^3.0.0",
58-
"@types/node": "^14.18",
61+
"@types/morgan": "^1.9.3",
5962
"@types/nodemailer": "6.4.0",
6063
"@types/request": "2.48.5",
6164
"@types/request-promise": "4.1.47",
6265
"@types/swagger-jsdoc": "^6.0.1",
6366
"@types/swagger-ui-express": "^4.1.3",
64-
"@types/winston": "2.4.4",
65-
"@typescript-eslint/eslint-plugin": "4.14.2",
66-
"@typescript-eslint/parser": "4.14.2",
67-
"chai": "4.3.0",
67+
"@typescript-eslint/eslint-plugin": "^6.7.5",
68+
"@typescript-eslint/parser": "^6.7.5",
6869
"concurrently": "6.0.2",
6970
"eslint": "7.19.0",
7071
"eslint-config-prettier": "^8.5.0",
71-
"jest": "^27.0.6",
72-
"nodemon": "^2.0.7",
7372
"prettier": "^2.7.1",
74-
"ts-node": "9.1.1",
75-
"typescript": "4.1.3"
73+
"ts-node-dev": "^2.0.0",
74+
"typescript": "^5.2.2"
7675
},
7776
"engines": {
7877
"node": ">=14.0.0"

src/app.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import express from "express";
22
import logger from "morgan";
3-
import dbInit from "./model/init";
3+
import dbInit from "./db/init";
44
import cors from "cors";
55
import { customRequest } from "./types/customDefinition";
66
import { deserializeUser } from "./middleware";
@@ -51,6 +51,36 @@ app.patch("/api/sync", async (req, res) => {
5151
return res.status(400).json({ errorMsg: msg, error: true });
5252
}
5353
});
54+
55+
/**
56+
* @swagger
57+
* tags:
58+
* name: Global
59+
*
60+
*/
61+
62+
/**
63+
* @swagger
64+
* /:
65+
* get:
66+
* summary: Get server status
67+
* description: Logged in users can fetch only their own user information.
68+
* tags: [Global]
69+
* responses:
70+
* "200":
71+
* description: OK
72+
*
73+
* /sync:
74+
* patch:
75+
* summary: Sync database
76+
* description: To sync database first time and after change in model.
77+
* tags: [Global]
78+
* responses:
79+
* "200":
80+
* description: OK
81+
*
82+
*/
83+
5484
// middleware to handle error
5585
app.use(errorHandler);
5686
export default app;

src/config/option.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const swaggerOption = {
77
},
88
servers: [
99
{
10-
url: `http://localhost:${process.env.PORT || 3000}/api/v1`,
10+
url: `http://localhost:${process.env.PORT || 3000}/api`,
1111
},
1212
],
1313
components: {
@@ -21,6 +21,6 @@ const swaggerOption = {
2121
},
2222
},
2323

24-
apis: ["src/routes/v1/*.ts"],
24+
apis: ["src/routes/v1/*.ts", "src/app.ts"],
2525
};
2626
export { swaggerOption };

src/controllers/auth.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@ import { sendOTP } from "../helpers/mailHelper";
1313
import { ApiError } from "../util/ApiError";
1414
const omitData = ["password"];
1515

16-
export const registerUser = async (req: Request, res: Response,next:NextFunction) => {
16+
export const registerUser = async (
17+
req: Request,
18+
res: Response,
19+
next: NextFunction
20+
) => {
1721
try {
1822
let user = req.body;
1923
const userExist = await userExists({
2024
email: user.email,
2125
mobile: user.mobile,
2226
});
2327
if (userExist) {
24-
throw new ApiError(400,"Email or Mobile is alredy used");
28+
throw new ApiError(400, "Email or Mobile is alredy used");
2529
}
2630
user = await createUser(user);
2731
const userData = omit(user?.toJSON(), omitData);
@@ -38,18 +42,22 @@ export const registerUser = async (req: Request, res: Response,next:NextFunction
3842
}
3943
};
4044

41-
export const loginUser = async (req: Request, res: Response,next:NextFunction) => {
45+
export const loginUser = async (
46+
req: Request,
47+
res: Response,
48+
next: NextFunction
49+
) => {
4250
try {
4351
const { email, password } = req.body;
4452

4553
const user = await findOneUser({ email });
4654
if (!user) {
47-
throw new ApiError(400,"Email id is incorrect");
55+
throw new ApiError(400, "Email id is incorrect");
4856
}
4957

5058
const validPassword = await validatePassword(user.email, password);
5159
if (!validPassword) {
52-
throw new ApiError(400,"Password is incorrect");
60+
throw new ApiError(400, "Password is incorrect");
5361
}
5462
const userData = omit(user?.toJSON(), omitData);
5563
const accessToken = sign({ ...userData });
@@ -64,13 +72,17 @@ export const loginUser = async (req: Request, res: Response,next:NextFunction) =
6472
}
6573
};
6674

67-
export const forgotPassword = async (req: Request, res: Response,next:NextFunction) => {
75+
export const forgotPassword = async (
76+
req: Request,
77+
res: Response,
78+
next: NextFunction
79+
) => {
6880
try {
6981
const { email } = req.body;
7082

7183
let user = await findOneUser({ email });
7284
if (!user) {
73-
throw new ApiError(400,"Email id is incorrect");
85+
throw new ApiError(400, "Email id is incorrect");
7486
}
7587
user = user?.toJSON();
7688
// generate otp
@@ -79,7 +91,7 @@ export const forgotPassword = async (req: Request, res: Response,next:NextFuncti
7991
const send = await sendOTP(user.email, otp);
8092
// send otp to email
8193
if (!send) {
82-
throw new ApiError(400,"Failed to send OTP");
94+
throw new ApiError(400, "Failed to send OTP");
8395
}
8496

8597
return res.status(200).json({
@@ -91,13 +103,17 @@ export const forgotPassword = async (req: Request, res: Response,next:NextFuncti
91103
}
92104
};
93105

94-
export const resetPassword = async (req: Request, res: Response,next:NextFunction) => {
106+
export const resetPassword = async (
107+
req: Request,
108+
res: Response,
109+
next: NextFunction
110+
) => {
95111
try {
96112
const { email, otp, password } = req.body;
97113

98114
let user = await findOneUser({ email });
99115
if (!user) {
100-
throw new ApiError(400,"Email id is incorrect");
116+
throw new ApiError(400, "Email id is incorrect");
101117
}
102118
user = user?.toJSON();
103119
const isValid = verifyOTP(user.email, otp);
@@ -117,6 +133,6 @@ export const resetPassword = async (req: Request, res: Response,next:NextFunctio
117133
error: false,
118134
});
119135
} catch (err) {
120-
next(err);
136+
next(err);
121137
}
122138
};

src/controllers/user.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import { omit } from "lodash";
44
import { customRequest } from "../types/customDefinition";
55
import { ApiError } from "../util/ApiError";
66
const omitData = ["password"];
7-
export const updateUser = async (req: customRequest, res: Response,next:NextFunction) => {
7+
export const updateUser = async (
8+
req: customRequest,
9+
res: Response,
10+
next: NextFunction
11+
) => {
812
try {
913
const { id: userId } = req.user;
1014

@@ -14,7 +18,7 @@ export const updateUser = async (req: customRequest, res: Response,next:NextFunc
1418
const user = await findOneUser({ id: userId });
1519

1620
if (!user) {
17-
throw new ApiError(400,"User not found");
21+
throw new ApiError(400, "User not found");
1822
}
1923

2024
const updated = await updateUserById(body, parseInt(userId, 10));
@@ -29,7 +33,11 @@ export const updateUser = async (req: customRequest, res: Response,next:NextFunc
2933
}
3034
};
3135

32-
export const getUserData = async (req: customRequest, res: Response,next:NextFunction) => {
36+
export const getUserData = async (
37+
req: customRequest,
38+
res: Response,
39+
next: NextFunction
40+
) => {
3341
try {
3442
return res.status(200).json({
3543
data: req.user,
@@ -39,4 +47,3 @@ export const getUserData = async (req: customRequest, res: Response,next:NextFun
3947
next(err);
4048
}
4149
};
42-
File renamed without changes.

src/db/init.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import sequelizeConnection from "./connection";
2+
3+
import { readdirSync } from "fs";
4+
import path from "path";
5+
import { Model } from "sequelize";
6+
7+
const isDev = process.env.NODE_ENV === "development";
8+
const modelsFolder = path.join("src", "models");
9+
10+
const modelList: { [key: string]: Model } = {};
11+
12+
const importModel = async (file: string) => {
13+
const model = await import(path.join("../models", file));
14+
modelList[path.basename(file, ".ts")] = model.default;
15+
};
16+
17+
const importModels = async () => {
18+
const files = readdirSync(modelsFolder);
19+
await Promise.all(files.map(importModel));
20+
};
21+
importModels();
22+
23+
const dbInit = async () => {
24+
try {
25+
await sequelizeConnection.sync({ alter: isDev });
26+
return { success: true };
27+
} catch (error) {
28+
throw error;
29+
}
30+
};
31+
export { modelList };
32+
export default dbInit;

src/model/init.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)