Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17,889 changes: 0 additions & 17,889 deletions package-lock.json

This file was deleted.

59 changes: 29 additions & 30 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,78 +1,77 @@
{
"name": "@nabadeep25/create-ts-node-app",
"version": "0.2.0",
"description": "",
"version": "0.3.0",
"description": "A boilerplate/starter project for quickly building RESTful APIs using Node.js,Typescript, Express, and Sequelize.",
"author": "Nabadeep Thakuria",
"bin": "bin/cli.js",
"homepage": "https://github.com/nabadeep25/typescript-node-sequelize-boilerplate",
"license": "MIT",
"keywords": ["typescript","node","express","sequelize","mysql","postgres","boilerplate","template","typescript node sequelize boilerplate","typescript node","typescript sequelize boilerplate"],
"keywords": [
"typescript",
"node",
"express",
"sequelize",
"mysql",
"postgres",
"boilerplate",
"template",
"typescript node sequelize boilerplate",
"typescript node",
"typescript sequelize boilerplate"
],
"scripts": {
"build-ts": "tsc",
"build": "npm run build-ts && npm run lint ",
"lint": "tsc --noEmit && eslint \"**/*.{js,ts}\" --quiet --fix",
"lint": "tsc --noEmit && eslint \"src/**/*.{js,ts}\" --quiet --fix",
"format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"",
"serve": "node dist/server.js",
"start": "npm run serve",
"watch-node": "nodemon dist/server.js",
"dev": "tsnd --respawn src/server.ts",
"watch-ts": "tsc -w",
"watch": "concurrently -k -p \"[{name}]\" -n \"TypeScript,Node\" -c \"cyan.bold,green.bold\" \"npm run watch-ts\" \"npm run watch-node\""
},
"dependencies": {
"@aws-sdk/client-s3": "^3.201.0",
"@aws-sdk/s3-request-presigner": "^3.202.0",
"@types/bcrypt": "^5.0.0",
"@types/cors": "^2.8.12",
"@types/joi": "^17.2.3",
"@types/jsonwebtoken": "^8.5.9",
"@types/morgan": "^1.9.3",
"async": "3.2.2",
"@types/node": "^20.8.4",
"bcrypt": "^5.1.0",
"cors": "^2.8.5",
"dotenv": "8.2.0",
"errorhandler": "1.5.1",
"express": "4.17.1",
"express": "^4.18.2",
"joi": "^17.6.4",
"jsonwebtoken": "^8.5.1",
"jsonwebtoken": "^9.0.2",
"lodash": "^4.17.21",
"mongoose": "^5.13.15",
"morgan": "^1.10.0",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
"mysql2": "^2.3.3",
"nodemailer": "^6.6.1",
"otplib": "^12.0.1",
"pg": "^8.11.3",
"sequelize": "^6.25.3",
"swagger-jsdoc": "^6.2.5",
"swagger-ui-express": "^4.6.0",
"winston": "3.3.3"
},
"devDependencies": {
"@types/async": "3.2.5",
"@types/bcrypt": "^5.0.0",
"@types/concurrently": "5.2.1",
"@types/cors": "^2.8.12",
"@types/errorhandler": "1.5.0",
"@types/eslint": "7.2.6",
"@types/express": "4.17.11",
"@types/jsonwebtoken": "^8.5.9",
"@types/lodash": "^4.14.170",
"@types/multer-s3": "^3.0.0",
"@types/node": "^14.18",
"@types/morgan": "^1.9.3",
"@types/nodemailer": "6.4.0",
"@types/request": "2.48.5",
"@types/request-promise": "4.1.47",
"@types/swagger-jsdoc": "^6.0.1",
"@types/swagger-ui-express": "^4.1.3",
"@types/winston": "2.4.4",
"@typescript-eslint/eslint-plugin": "4.14.2",
"@typescript-eslint/parser": "4.14.2",
"chai": "4.3.0",
"@typescript-eslint/eslint-plugin": "^6.7.5",
"@typescript-eslint/parser": "^6.7.5",
"concurrently": "6.0.2",
"eslint": "7.19.0",
"eslint-config-prettier": "^8.5.0",
"jest": "^27.0.6",
"nodemon": "^2.0.7",
"prettier": "^2.7.1",
"ts-node": "9.1.1",
"typescript": "4.1.3"
"ts-node-dev": "^2.0.0",
"typescript": "^5.2.2"
},
"engines": {
"node": ">=14.0.0"
Expand Down
32 changes: 31 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from "express";
import logger from "morgan";
import dbInit from "./model/init";
import dbInit from "./db/init";
import cors from "cors";
import { customRequest } from "./types/customDefinition";
import { deserializeUser } from "./middleware";
Expand Down Expand Up @@ -51,6 +51,36 @@ app.patch("/api/sync", async (req, res) => {
return res.status(400).json({ errorMsg: msg, error: true });
}
});

/**
* @swagger
* tags:
* name: Global
*
*/

/**
* @swagger
* /:
* get:
* summary: Get server status
* description: Logged in users can fetch only their own user information.
* tags: [Global]
* responses:
* "200":
* description: OK
*
* /sync:
* patch:
* summary: Sync database
* description: To sync database first time and after change in model.
* tags: [Global]
* responses:
* "200":
* description: OK
*
*/

// middleware to handle error
app.use(errorHandler);
export default app;
4 changes: 2 additions & 2 deletions src/config/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const swaggerOption = {
},
servers: [
{
url: `http://localhost:${process.env.PORT || 3000}/api/v1`,
url: `http://localhost:${process.env.PORT || 3000}/api`,
},
],
components: {
Expand All @@ -21,6 +21,6 @@ const swaggerOption = {
},
},

apis: ["src/routes/v1/*.ts"],
apis: ["src/routes/v1/*.ts", "src/app.ts"],
};
export { swaggerOption };
38 changes: 27 additions & 11 deletions src/controllers/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ import { sendOTP } from "../helpers/mailHelper";
import { ApiError } from "../util/ApiError";
const omitData = ["password"];

export const registerUser = async (req: Request, res: Response,next:NextFunction) => {
export const registerUser = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
let user = req.body;
const userExist = await userExists({
email: user.email,
mobile: user.mobile,
});
if (userExist) {
throw new ApiError(400,"Email or Mobile is alredy used");
throw new ApiError(400, "Email or Mobile is alredy used");
}
user = await createUser(user);
const userData = omit(user?.toJSON(), omitData);
Expand All @@ -38,18 +42,22 @@ export const registerUser = async (req: Request, res: Response,next:NextFunction
}
};

export const loginUser = async (req: Request, res: Response,next:NextFunction) => {
export const loginUser = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
const { email, password } = req.body;

const user = await findOneUser({ email });
if (!user) {
throw new ApiError(400,"Email id is incorrect");
throw new ApiError(400, "Email id is incorrect");
}

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

export const forgotPassword = async (req: Request, res: Response,next:NextFunction) => {
export const forgotPassword = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
const { email } = req.body;

let user = await findOneUser({ email });
if (!user) {
throw new ApiError(400,"Email id is incorrect");
throw new ApiError(400, "Email id is incorrect");
}
user = user?.toJSON();
// generate otp
Expand All @@ -79,7 +91,7 @@ export const forgotPassword = async (req: Request, res: Response,next:NextFuncti
const send = await sendOTP(user.email, otp);
// send otp to email
if (!send) {
throw new ApiError(400,"Failed to send OTP");
throw new ApiError(400, "Failed to send OTP");
}

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

export const resetPassword = async (req: Request, res: Response,next:NextFunction) => {
export const resetPassword = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
const { email, otp, password } = req.body;

let user = await findOneUser({ email });
if (!user) {
throw new ApiError(400,"Email id is incorrect");
throw new ApiError(400, "Email id is incorrect");
}
user = user?.toJSON();
const isValid = verifyOTP(user.email, otp);
Expand All @@ -117,6 +133,6 @@ export const resetPassword = async (req: Request, res: Response,next:NextFunctio
error: false,
});
} catch (err) {
next(err);
next(err);
}
};
15 changes: 11 additions & 4 deletions src/controllers/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { omit } from "lodash";
import { customRequest } from "../types/customDefinition";
import { ApiError } from "../util/ApiError";
const omitData = ["password"];
export const updateUser = async (req: customRequest, res: Response,next:NextFunction) => {
export const updateUser = async (
req: customRequest,
res: Response,
next: NextFunction
) => {
try {
const { id: userId } = req.user;

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

if (!user) {
throw new ApiError(400,"User not found");
throw new ApiError(400, "User not found");
}

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

export const getUserData = async (req: customRequest, res: Response,next:NextFunction) => {
export const getUserData = async (
req: customRequest,
res: Response,
next: NextFunction
) => {
try {
return res.status(200).json({
data: req.user,
Expand All @@ -39,4 +47,3 @@ export const getUserData = async (req: customRequest, res: Response,next:NextFun
next(err);
}
};

File renamed without changes.
32 changes: 32 additions & 0 deletions src/db/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import sequelizeConnection from "./connection";

import { readdirSync } from "fs";
import path from "path";
import { Model } from "sequelize";

const isDev = process.env.NODE_ENV === "development";
const modelsFolder = path.join("src", "models");

const modelList: { [key: string]: Model } = {};

const importModel = async (file: string) => {
const model = await import(path.join("../models", file));
modelList[path.basename(file, ".ts")] = model.default;
};

const importModels = async () => {
const files = readdirSync(modelsFolder);
await Promise.all(files.map(importModel));
};
importModels();

const dbInit = async () => {
try {
await sequelizeConnection.sync({ alter: isDev });
return { success: true };
} catch (error) {
throw error;
}
};
export { modelList };
export default dbInit;
27 changes: 0 additions & 27 deletions src/model/init.ts

This file was deleted.

Loading