diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a94d12a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 160 + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..e37998f --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npm run test diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..3609f16 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "tabWidth": 2, + "useTabs": false, + "singleQuote": false, + "semi": true, + "bracketSpacing": true, + "arrowParens": "always", + "bracketSameLine": true, + "endOfLine": "auto" +} diff --git a/README.md b/README.md index 7e689e7..43d209b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # eagles-ec-be
+ Codecov GitHub Actions Workflow Status +Static Badge
diff --git a/__test__/home.test.ts b/__test__/home.test.ts index a2ddf99..03c4e86 100644 --- a/__test__/home.test.ts +++ b/__test__/home.test.ts @@ -10,11 +10,11 @@ describe("Testing Home route", () => { } catch (error) { sequelize.close(); } - }, 20000); + }, 40000); test("servr should return status code of 200 --> given'/'", async () => { const response = await request(app).get("/"); expect(response.status).toBe(200); - }, 20000); + }, 40000); }); diff --git a/__test__/user.test.ts b/__test__/user.test.ts index 32e9a70..b6ab8e4 100644 --- a/__test__/user.test.ts +++ b/__test__/user.test.ts @@ -5,74 +5,74 @@ import User from "../src/sequelize/models/users"; import * as userServices from "../src/services/user.service"; import sequelize, { connect } from "../src/config/dbConnection"; -const userData:any = { - name: 'yvanna', - username: 'testuser', - email: 'test1@gmail.com', - password:'test1234', - }; +const userData: any = { + name: "yvanna", + username: "testuser", + email: "test1@gmail.com", + password: "test1234", +}; - const loginData:any = { - email:'test1@gmail.com', - password:"test1234" - } -describe("Testing user Routes", () => { +const loginData: any = { + email: "test1@gmail.com", + password: "test1234", +}; +describe("Testing a user Routes", () => { beforeAll(async () => { try { await connect(); - await User.destroy({truncate:true}) + await User.destroy({ truncate: true }); } catch (error) { sequelize.close(); } - }, 20000); + }, 40000); - afterAll(async () => { + afterAll(async () => { await User.destroy({ truncate: true }); - await sequelize.close(); -}); -describe("Testing user authentication", () => { -test('should return 201 and create a new user when registering successfully', async () => { -const response = await request(app) -.post('/api/v1/users/register') -.send(userData); -expect(response.status).toBe(201); }, 20000); + await sequelize.close(); + }); + describe("Testing user authentication", () => { + test("should return 201 and create a new user when registering successfully", async () => { + const response = await request(app).post("/api/v1/users/register").send(userData); + expect(response.status).toBe(201); + }, 40000); + + test("should return 409 when registering with an existing email", async () => { + User.create(userData); + const response = await request(app).post("/api/v1/users/register").send(userData); + expect(response.status).toBe(409); + }, 40000); -test('should return 409 when registering with an existing email', async () => { - User.create(userData) - const response = await request(app) - .post('/api/v1/users/register') - .send(userData); - expect(response.status).toBe(409); }, 20000); + test("should return 400 when registering with an invalid credential", async () => { + const userData = { + email: "test@mail.com", + name: "", + username: "existinguser", + }; + const response = await request(app).post("/api/v1/users/register").send(userData); -test('should return 400 when registering with an invalid credential', async () => { - const userData = { - email: 'test@mail.com', name: "", username: 'existinguser', }; - const response = await request(app) - .post('/api/v1/users/register') - .send(userData); - - expect(response.status).toBe(400); }, 20000); }); + expect(response.status).toBe(400); + }, 40000); + }); +}); - test("should return all users in db --> given '/api/v1/users'", async () => { - const spy = jest.spyOn(User, "findAll"); - const spy2 = jest.spyOn(userServices, "getAllUsers"); - const response = await request(app).get("/api/v1/users"); - expect(spy).toHaveBeenCalled(); - expect(spy2).toHaveBeenCalled(); - }, 20000); - test("Should return status 401 to indicate Unauthorized user",async() =>{ - const loggedInUser ={ - email:userData.email, - password:"test", - }; - const spyonOne = jest.spyOn(User,"findOne").mockResolvedValueOnce({ - //@ts-ignore - email:userData.email, - password:loginData.password, - }); - const response = await request(app).post("/api/v1/users/login") - .send(loggedInUser) - expect(response.body.status).toBe(401); - spyonOne.mockRestore(); +test("should return all users in db --> given '/api/v1/users'", async () => { + const spy = jest.spyOn(User, "findAll"); + const spy2 = jest.spyOn(userServices, "getAllUsers"); + const response = await request(app).get("/api/v1/users"); + expect(spy).toHaveBeenCalled(); + expect(spy2).toHaveBeenCalled(); +}, 40000); +test("Should return status 401 to indicate Unauthorized user", async () => { + const loggedInUser = { + email: userData.email, + password: "test", + }; + const spyonOne = jest.spyOn(User, "findOne").mockResolvedValueOnce({ + //@ts-ignore + email: userData.email, + password: loginData.password, }); -}) + const response = await request(app).post("/api/v1/users/login").send(loggedInUser); + expect(response.body.status).toBe(401); + spyonOne.mockRestore(); +}); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..1a7d6f8 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,51 @@ +const eslint = require("@eslint/js"); +const tseslint = require("typescript-eslint"); + +module.exports = tseslint.config( + { + ignores: ["**/__test__", "**/*.json"], + }, + eslint.configs.recommended, + ...tseslint.configs.recommended, + { + languageOptions: { + parserOptions: { + project: true, + ecmaVersion: 2020, + }, + }, + }, + { + files: ["*.ts", "*.js"], + ...tseslint.configs.disableTypeChecked, + }, + { + files: ["*.test *.js"], + rules: { + "@typescript-eslint/no-unused-vars": 0, + "@typescript-eslint/no-unsafe-call": 0, + languageOptions: { + globals: { + it: "readonly", + describe: "readonly", + }, + }, + }, + }, + { + rules: { + semi: "error", + "@typescript-eslint/no-unused-vars": 2, + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/no-var-requires": 0, + "no-shadow": [2, { allow: ["req", "res", "err"] }], + "new-cap": 0, + "one-var-declaration-per-line": 0, + "consistent-return": 0, + "no-param-reassign": 0, + "comma-dangle": 0, + "no-undef": 0, + curly: ["error", "multi-line"], + }, + }, +); \ No newline at end of file diff --git a/hound.yml b/hound.yml new file mode 100644 index 0000000..4e976af --- /dev/null +++ b/hound.yml @@ -0,0 +1,9 @@ +eslint: + enabled: true + file_patterns: + - "*.js" + - "*.ts" + enabled_plugins: + - eslint-plugin-import + - eslint-plugin-prettier + - eslint-plugin:@typescript-eslint diff --git a/index.ts b/index.ts index aabd3d2..76a39d4 100644 --- a/index.ts +++ b/index.ts @@ -7,7 +7,7 @@ app.listen(env.port, async () => { await sequelize .sync() .then(() => { - console.log(` db synced and server is running on port ${env.port}`); + console.log(" db synced and server is running"); }) .catch((error: any) => { console.log(error.message); diff --git a/package.json b/package.json index e693874..adba14e 100644 --- a/package.json +++ b/package.json @@ -5,18 +5,39 @@ "main": "index.ts", "scripts": { "start": "", + "pre-commit": "prettier . --write && eslint .", + "lint": "eslint .", "dev": "nodemon index.ts", "build": "tsc", "migrate": "npx sequelize-cli db:migrate", "seed": "npx sequelize-cli db:seed:all", - "lint": "npx eslint .", "lint:fix": "npx eslint --fix .", - "test": "cross-env NODE_ENV=test jest --detectOpenHandles --coverage" + "test": "cross-env NODE_ENV=test jest --detectOpenHandles --coverage", + "prepare": "husky", + "prettier": "prettier . --write" + }, + "lint-staged": { + ".ts": [ + "npm run lint:fix" + ], + "**/*": "prettier --write" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest", + "prettier" + ] + }, + "husky": { + "hooks": { + "pre-commit": "npm run lint-staged && npm run test" + } }, "author": "atlp", "license": "MIT", "devDependencies": { - "@eslint/js": "^9.0.0", + "@eslint/js": "^9.1.1", "@types/bcryptjs": "^2.4.6", "@types/cors": "^2.8.17", "@types/dotenv": "^8.2.0", @@ -26,7 +47,7 @@ "@types/node": "^20.12.7", "@types/supertest": "^6.0.2", "@types/swagger-ui-express": "^4.1.6", - "@typescript-eslint/eslint-plugin": "^7.6.0", + "@typescript-eslint/eslint-plugin": "^7.7.1", "@typescript-eslint/parser": "^7.6.0", "eslint": "^8.57.0", "eslint-config-airbnb-base": "^15.0.0", @@ -36,6 +57,7 @@ "globals": "^15.0.0", "jest": "^29.7.0", "nodemon": "^3.1.0", + "pre-commit": "^1.2.2", "prettier": "^3.2.5", "sequelize-cli": "^6.6.2", "supertest": "^6.3.4", @@ -54,8 +76,10 @@ "dotenv": "^16.4.5", "email-validator": "^2.0.4", "express": "^4.19.2", - "joi": "^17.12.3", + "husky": "^9.0.11", + "joi": "^17.13.0", "jsonwebtoken": "^9.0.2", + "lint-staged": "^15.2.2", "path": "^0.12.7", "pg": "^8.11.5", "pg-hstore": "^2.3.4", diff --git a/src/config/dbConnection.ts b/src/config/dbConnection.ts index 8500c3d..c892b31 100644 --- a/src/config/dbConnection.ts +++ b/src/config/dbConnection.ts @@ -3,10 +3,9 @@ import { env } from "../utils/env"; const envT = process.env.NODE_ENV; -const sequelize = new Sequelize(envT === "test" ? env.test_db_url : env.db_url,{ - dialect: 'postgres', -}) - +const sequelize = new Sequelize(envT === "test" ? env.test_db_url : env.db_url, { + dialect: "postgres", +}); export const connect = async () => { try { diff --git a/src/controllers/userControllers.ts b/src/controllers/userControllers.ts index f3fed45..6152856 100644 --- a/src/controllers/userControllers.ts +++ b/src/controllers/userControllers.ts @@ -2,11 +2,13 @@ import { Request, Response } from "express"; import * as userService from "../services/user.service"; import { generateToken } from "../utils/jsonwebtoken"; import { comparePasswords } from "../helpers/comparePassword"; -import { loggedInUser} from "../services/user.service"; -import { createUserService, getUserByEmail } from "../services/user.service"; +import { loggedInUser } from "../services/user.service"; +import { createUserService } from "../services/user.service"; export const fetchAllUsers = async (req: Request, res: Response) => { try { + // const users = await userService.getAllUsers(); + const users = await userService.getAllUsers(); if (users.length <= 0) { @@ -28,53 +30,51 @@ export const fetchAllUsers = async (req: Request, res: Response) => { } }; -export const userLogin = async(req:Request,res:Response) =>{ - const {email, password} = req.body; +export const userLogin = async (req: Request, res: Response) => { + const { email, password } = req.body; const user = await loggedInUser(email); const accessToken = await generateToken(user); - if(!user){ + if (!user) { res.status(404).json({ - status:404, - message:'User Not Found ! Please Register new ancount' - }); - }else{ - const match = await comparePasswords(password,user.password); - if(!match){ - res.status(401).json({ - status:401, - message:' User email or password is incorrect!' - }); - }else{ - res.status(200).json({ - status:200, - message:"Logged in", - token:accessToken - }); - }; - }; + status: 404, + message: "User Not Found ! Please Register new ancount", + }); + } else { + const match = await comparePasswords(password, user.password); + if (!match) { + res.status(401).json({ + status: 401, + message: " User email or password is incorrect!", + }); + } else { + res.status(200).json({ + status: 200, + message: "Logged in", + token: accessToken, + }); + } + } }; - export const createUserController = async (req: Request, res: Response) => { - try { + try { const { name, email, username, password } = req.body; const user = await createUserService(name, email, username, password); - + if (!user) { - return res.status(409).json({ - status: 409, - message: 'Username or email already exists' + return res.status(409).json({ + status: 409, + message: "Username or email already exists", }); } - - res.status(201).json({ - status: 201, - message: "User successfully created." + + res.status(201).json({ + status: 201, + message: "User successfully created.", }); - } catch (err: any) { - if (err.name === 'UnauthorizedError' && err.message === 'User already exists') { - return res.status(409).json({ error: 'User already exists' }); + if (err.name === "UnauthorizedError" && err.message === "User already exists") { + return res.status(409).json({ error: "User already exists" }); } res.status(500).json({ error: err }); } diff --git a/src/docs/swagger.ts b/src/docs/swagger.ts index e7f82ec..f5fc119 100644 --- a/src/docs/swagger.ts +++ b/src/docs/swagger.ts @@ -1,68 +1,67 @@ import express from "express"; import { serve, setup } from "swagger-ui-express"; import { env } from "../utils/env"; -import { - createUsers, - getUsers, - loginAsUser, - userSchema, - loginSchema - } from "./users"; +import { createUsers, getUsers, loginAsUser, userSchema, loginSchema } from "./users"; const docRouter = express.Router(); const options = { - openapi: "3.0.1", - info: { - title: "Eagles E-commerce API", - version: "1.0.0", - description: "Documentation for Eagles E-commerce Backend", - }, + openapi: "3.0.1", + info: { + title: "Eagles E-commerce API", + version: "1.0.0", + description: "Documentation for Eagles E-commerce Backend", + }, - servers: [{ + servers: [ + { url: `http://localhost:${env.port}`, - description: 'Development server', - }, { - url: 'https://eagles-ec-be-development.onrender.com/', - description: 'Production server', - }], + description: "Development server", + }, + { + url: "https://eagles-ec-be-development.onrender.com/", + description: "Production server", + }, + ], - basePath: "/", + basePath: "/", - tags: [ - { name: "Users", description: "Endpoints related to users" } - ], + tags: [ + { + name: "Users", + description: "Endpoints related to users", + }, + ], - paths: { - "/api/v1/users": { - get: getUsers - }, - "/api/v1/users/register": { - post: createUsers - }, - "/api/v1/users/login": { - post: loginAsUser + paths: { + "/api/v1/users": { + get: getUsers, }, + "/api/v1/users/register": { + post: createUsers, }, + "/api/v1/users/login": { + post: loginAsUser, + }, + }, - components: { - schemas: { - User: userSchema, - Login:loginSchema, - }, - securitySchemes: { - bearerAuth: { - type: "http", - scheme: "bearer", - bearerFormat: "JWT", - in: "header", - name: "Authorization", - }, - }, - } - -} + components: { + schemas: { + User: userSchema, + Login: loginSchema, + }, + securitySchemes: { + bearerAuth: { + type: "http", + scheme: "bearer", + bearerFormat: "JWT", + in: "header", + name: "Authorization", + }, + }, + }, +}; docRouter.use("/", serve, setup(options)); -export default docRouter \ No newline at end of file +export default docRouter; diff --git a/src/docs/users.ts b/src/docs/users.ts index ca2f301..ae2c33c 100644 --- a/src/docs/users.ts +++ b/src/docs/users.ts @@ -1,26 +1,24 @@ -import { response } from "express" - export const userSchema = { - type: "object", - properties: { - name: { - type: "string", - }, - username: { - type: "string" - }, - email: { - type: "string", - format: "email", - }, - password: { - type: "string", - }, + type: "object", + properties: { + name: { + type: "string", + }, + username: { + type: "string", }, -} + email: { + type: "string", + format: "email", + }, + password: { + type: "string", + }, + }, +}; -export const loginSchema ={ - properties :{ +export const loginSchema = { + properties: { email: { type: "string", format: "email", @@ -28,77 +26,75 @@ export const loginSchema ={ password: { type: "string", }, - } -} + }, +}; export const getUsers = { - tags: ["Users"], - summary: "Get all users", - responses: { - 200: { - description: "OK", - content: { - "application/json": { - schema: { - type: "array", - items: { - $ref: "#/components/schemas/User", - }, + tags: ["Users"], + summary: "Get all users", + responses: { + 200: { + description: "OK", + content: { + "application/json": { + schema: { + type: "array", + items: { + $ref: "#/components/schemas/User", }, }, }, }, }, - } + }, +}; - export const createUsers = { - - tags: ["Users"], - summary: "Register a new user", - requestBody: { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/User", - }, - }, +export const createUsers = { + tags: ["Users"], + summary: "Register a new user", + requestBody: { + required: true, + content: { + "application/json": { + schema: { + $ref: "#/components/schemas/User", }, }, - responses: { - 201: { - description: "Created", - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/User", - }, - }, + }, + }, + responses: { + 201: { + description: "Created", + content: { + "application/json": { + schema: { + $ref: "#/components/schemas/User", }, }, - 400: { - description: "Bad request", - }, }, - } + }, + 400: { + description: "Bad request", + }, + }, +}; - export const loginAsUser ={ - tags: ["Users"], - summary: "Login as user", - requestBody: { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/Login" - } - } - } +export const loginAsUser = { + tags: ["Users"], + summary: "Login as user", + requestBody: { + required: true, + content: { + "application/json": { + schema: { + $ref: "#/components/schemas/Login", }, - responses: { - 200: { - description: "OK", - } - } - }; - \ No newline at end of file + }, + }, + }, + responses: { + 200: { + description: "OK", + }, + }, +}; diff --git a/src/helpers/comparePassword.ts b/src/helpers/comparePassword.ts index 79654ba..1552dec 100644 --- a/src/helpers/comparePassword.ts +++ b/src/helpers/comparePassword.ts @@ -1,4 +1,4 @@ -import bcrypt from 'bcrypt' -export const comparePasswords = async(plainPassword: string, hashedPassword: string): Promise => { - return await bcrypt.compare(plainPassword, hashedPassword); - } \ No newline at end of file +import bcrypt from "bcrypt"; +export const comparePasswords = async (plainPassword: string, hashedPassword: string): Promise => { + return await bcrypt.compare(plainPassword, hashedPassword); +}; diff --git a/src/middleware/validator.ts b/src/middleware/validator.ts index 93cc2b8..d52295c 100644 --- a/src/middleware/validator.ts +++ b/src/middleware/validator.ts @@ -1,6 +1,6 @@ -import { Request, Response, NextFunction } from 'express'; -import validator from 'email-validator'; -import { Schema } from 'joi'; +import { Request, Response, NextFunction } from "express"; +import validator from "email-validator"; +import { Schema } from "joi"; export const emailValidation = (req: Request, res: Response, next: NextFunction) => { const { email } = req.body; @@ -8,28 +8,27 @@ export const emailValidation = (req: Request, res: Response, next: NextFunction) if (!email) { return res.status(400).json({ status: 400, - message: "Email is required" + message: "Email is required", }); } const isValid = validator.validate(email); if (isValid) { - next(); + next(); } else { return res.status(400).json({ status: 400, - message: "Email is not valid." + message: "Email is not valid.", }); } }; - export const validateSchema = (schema: Schema) => { return (req: Request, res: Response, next: NextFunction) => { - const { error } = schema.validate(req.body); - if (error) { - return res.status(400).json({ message: error.details[0].message }); - } - next(); + const { error } = schema.validate(req.body); + if (error) { + return res.status(400).json({ message: error.details[0].message }); + } + next(); }; -}; \ No newline at end of file +}; diff --git a/src/routes/index.ts b/src/routes/index.ts index e7ddc3f..f65e84a 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,10 +1,8 @@ -import { Request, Response, Router } from "express"; +import { Router } from "express"; import userRoutes from "./userRoutes"; - const appROutes = Router(); appROutes.use("/users", userRoutes); - export default appROutes; diff --git a/src/routes/userRoutes.ts b/src/routes/userRoutes.ts index 23d9f47..5b4e507 100644 --- a/src/routes/userRoutes.ts +++ b/src/routes/userRoutes.ts @@ -1,24 +1,14 @@ import { Router } from "express"; -import { - fetchAllUsers, - createUserController, - userLogin } -from "../controllers/userControllers"; -import { - emailValidation, - validateSchema, - } from "../middleware/validator"; +import { fetchAllUsers, createUserController, userLogin } from "../controllers/userControllers"; +import { emailValidation, validateSchema } from "../middleware/validator"; import signUpSchema from "../schemas/signUpSchema"; const userRoutes = Router(); userRoutes.get("/", fetchAllUsers); -userRoutes.post('/login',userLogin); -userRoutes.post("/register", - emailValidation, - validateSchema(signUpSchema), - createUserController -) +userRoutes.post("/login", userLogin); +userRoutes.post("/register", emailValidation, validateSchema(signUpSchema), createUserController); +userRoutes.post("/register", createUserController); -export default userRoutes; +export default userRoutes; diff --git a/src/schemas/signUpSchema.ts b/src/schemas/signUpSchema.ts index 030fcd3..7d331d6 100644 --- a/src/schemas/signUpSchema.ts +++ b/src/schemas/signUpSchema.ts @@ -1,21 +1,10 @@ import Joi from "joi"; export const signUpSchema = Joi.object({ - name: Joi.string() - .min(5) - .max(40) - .required(), - username: Joi.string() - .min(4) - .required(), - email: Joi.string() - .min(6) - .required() - .email(), - password: Joi.string() - .min(6) - .max(20) - .required() + name: Joi.string().min(5).max(40).required(), + username: Joi.string().min(4).required(), + email: Joi.string().min(6).required().email(), + password: Joi.string().min(6).max(20).required(), }).options({ allowUnknown: false }); -export default signUpSchema \ No newline at end of file +export default signUpSchema; diff --git a/src/sequelize/config/config.js b/src/sequelize/config/config.js index 93850c4..c28f20f 100644 --- a/src/sequelize/config/config.js +++ b/src/sequelize/config/config.js @@ -20,5 +20,4 @@ module.exports = { }, }, }, - }; diff --git a/src/sequelize/migrations/20240416115110-create-user.js b/src/sequelize/migrations/20240416115110-create-user.js index ba6c2a3..5a452f2 100644 --- a/src/sequelize/migrations/20240416115110-create-user.js +++ b/src/sequelize/migrations/20240416115110-create-user.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ /** @type {import('sequelize-cli').Migration} */ module.exports = { async up(queryInterface, Sequelize) { @@ -41,4 +42,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.describeTable("users"); }, -}; \ No newline at end of file +}; diff --git a/src/sequelize/migrations/20240418083442-UserTests.js b/src/sequelize/migrations/20240418083442-UserTests.js index 1fac10a..a71e1c5 100644 --- a/src/sequelize/migrations/20240418083442-UserTests.js +++ b/src/sequelize/migrations/20240418083442-UserTests.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ /** @type {import('sequelize-cli').Migration} */ module.exports = { async up(queryInterface, Sequelize) { @@ -41,4 +42,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.describeTable("usersTests"); }, -}; \ No newline at end of file +}; diff --git a/src/sequelize/models/index.js b/src/sequelize/models/index.js index 7549577..916a184 100644 --- a/src/sequelize/models/index.js +++ b/src/sequelize/models/index.js @@ -13,28 +13,15 @@ let sequelize; if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config); } else { - sequelize = new Sequelize( - config.database, - config.username, - config.password, - config, - ); + sequelize = new Sequelize(config.database, config.username, config.password, config); } fs.readdirSync(__dirname) .filter((file) => { - return ( - file.indexOf(".") !== 0 && - file !== basename && - file.slice(-3) === ".js" && - file.indexOf(".test.js") === -1 - ); + return file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js" && file.indexOf(".test.js") === -1; }) .forEach((file) => { - const model = require(path.join(__dirname, file))( - sequelize, - Sequelize.DataTypes, - ); + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); db[model.name] = model; }); diff --git a/src/sequelize/models/users.ts b/src/sequelize/models/users.ts index 2bacede..b928163 100644 --- a/src/sequelize/models/users.ts +++ b/src/sequelize/models/users.ts @@ -1,17 +1,17 @@ -import {Model,DataTypes} from 'sequelize'; -import sequelize from '../../config/dbConnection'; +import { Model, DataTypes } from "sequelize"; +import sequelize from "../../config/dbConnection"; -export interface UserAttributes{ - id?:number, - name: string, - username: string, - email:string, - password:string, - createdAt?:Date, - updatedAt?:Date +export interface UserAttributes { + id?: number; + name: string; + username: string; + email: string; + password: string; + createdAt?: Date; + updatedAt?: Date; } -class User extends Model implements UserAttributes{ +class User extends Model implements UserAttributes { id!: number | undefined; name!: string; username!: string; @@ -21,7 +21,8 @@ class User extends Model implements UserAttributes{ updatedAt1: Date | undefined; } - User.init({ +User.init( + { id: { allowNull: false, autoIncrement: true, @@ -31,18 +32,18 @@ class User extends Model implements UserAttributes{ name: { type: DataTypes.STRING, allowNull: false, - }, + }, username: { - type: DataTypes.STRING, - allowNull: false, - }, - email:{ - allowNull:false, - type:DataTypes.STRING + type: DataTypes.STRING, + allowNull: false, + }, + email: { + allowNull: false, + type: DataTypes.STRING, }, password: { - allowNull:false, - type:DataTypes.STRING + allowNull: false, + type: DataTypes.STRING, }, createdAt: { allowNull: false, @@ -52,9 +53,11 @@ class User extends Model implements UserAttributes{ allowNull: false, type: DataTypes.DATE, }, - }, { - sequelize:sequelize, - modelName: 'users', - }); + }, + { + sequelize: sequelize, + modelName: "users", + }, +); - export default User; \ No newline at end of file +export default User; diff --git a/src/sequelize/models/usersTests.ts b/src/sequelize/models/usersTests.ts index 62cf9d1..a036b1c 100644 --- a/src/sequelize/models/usersTests.ts +++ b/src/sequelize/models/usersTests.ts @@ -1,28 +1,28 @@ -import {Model,DataTypes} from 'sequelize'; -import sequelize from '../../config/dbConnection'; +import { Model, DataTypes } from "sequelize"; +import sequelize from "../../config/dbConnection"; - -export interface UserAttributes{ - id?:number, - name: string, - username: string, - email:string, - password:string, - createdAt?:Date, - updatedAt?:Date +export interface UserAttributes { + id?: number; + name: string; + username: string; + email: string; + password: string; + createdAt?: Date; + updatedAt?: Date; } -class UserTest extends Model implements UserAttributes{ +class UserTest extends Model implements UserAttributes { id!: number | undefined; name!: string; username!: string; email!: string; password!: string; createdAt!: Date | undefined; - updatedAt1: Date | undefined; + updatedAt!: Date | undefined; // Corrected typo here } - UserTest.init({ +UserTest.init( + { id: { allowNull: false, autoIncrement: true, @@ -30,20 +30,20 @@ class UserTest extends Model implements UserAttributes{ type: DataTypes.NUMBER, }, name: { - type: DataTypes.STRING, - allowNull: false, - }, + type: DataTypes.STRING, + allowNull: false, + }, username: { - type: DataTypes.STRING, - allowNull: false, - }, - email:{ - allowNull:false, - type:DataTypes.STRING + type: DataTypes.STRING, + allowNull: false, + }, + email: { + allowNull: false, + type: DataTypes.STRING, }, password: { - allowNull:false, - type:DataTypes.STRING + allowNull: false, + type: DataTypes.STRING, }, createdAt: { allowNull: false, @@ -53,9 +53,11 @@ class UserTest extends Model implements UserAttributes{ allowNull: false, type: DataTypes.DATE, }, - }, { - sequelize:sequelize, - modelName: 'usersTests', - }); + }, + { + sequelize: sequelize, + modelName: "usersTests", + }, +); - export default UserTest; \ No newline at end of file +export default UserTest; diff --git a/src/sequelize/seeders/20240412144111-demo-user.js b/src/sequelize/seeders/20240412144111-demo-user.js index e460e81..4043e7f 100644 --- a/src/sequelize/seeders/20240412144111-demo-user.js +++ b/src/sequelize/seeders/20240412144111-demo-user.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ /** @type {import('sequelize-cli').Migration} */ module.exports = { up: (queryInterface, Sequelize) => { diff --git a/src/services/user.service.ts b/src/services/user.service.ts index dbdeae8..59c9fed 100644 --- a/src/services/user.service.ts +++ b/src/services/user.service.ts @@ -1,4 +1,3 @@ -import { errors } from "undici-types"; import User from "../sequelize/models/users"; import { hashedPassword } from "../utils/hashPassword"; import { Op } from "sequelize"; @@ -16,35 +15,43 @@ export const getAllUsers = async () => { } }; -export const loggedInUser = async(email:string) => { - try{ - const user:any = await User.findOne({ - where: { email: email } +export const loggedInUser = async (email: string) => { + try { + const user: any = await User.findOne({ + where: { email: email }, }); - if(!user){ - return false; - }else{ - return user; + if (!user) { + return false; + } else { + return user; } -}catch(err:any){ + } catch (err: any) { throw new Error(err.message); + } }; -}; + export const createUserService = async (name: string, email: string, username: string, password: string): Promise => { - const existingUser = await User.findOne({ - where: { - [Op.or]: [{ email }, { username }] - } + const existingUser = await User.findOne({ + where: { + [Op.or]: [{ email }, { username }], + }, }); if (existingUser) { - return null; + return null; } const hashPassword = await hashedPassword(password); - const user = await User.create({ name, email, username, password: hashPassword }); + const user = await User.create({ + name, + email, + username, + password: hashPassword, + }); return user; }; export const getUserByEmail = async (email: string): Promise => { - const user = await User.findOne({ where: { email } }); + const user = await User.findOne({ + where: { email }, + }); return user; }; diff --git a/src/utils/env.ts b/src/utils/env.ts index 5d15773..32b85e6 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -5,5 +5,5 @@ export const env = { port: process.env.PORT || 3000, db_url: process.env.DB_CONNECTION as string, test_db_url: process.env.TEST_DB as string, - jwt_secret:process.env.JWT_SECRET, + jwt_secret: process.env.JWT_SECRET, }; diff --git a/src/utils/hashPassword.ts b/src/utils/hashPassword.ts index 8da8382..f94d63a 100644 --- a/src/utils/hashPassword.ts +++ b/src/utils/hashPassword.ts @@ -1,6 +1,6 @@ -import bcrypt from 'bcryptjs' +import bcrypt from "bcryptjs"; -export const hashedPassword = async(password: string) => { - const hashpass = await bcrypt.hash(password, 10) - return hashpass; -} \ No newline at end of file +export const hashedPassword = async (password: string) => { + const hashpass = await bcrypt.hash(password, 10); + return hashpass; +}; diff --git a/src/utils/jsonwebtoken.ts b/src/utils/jsonwebtoken.ts index 53e9af0..6bea145 100644 --- a/src/utils/jsonwebtoken.ts +++ b/src/utils/jsonwebtoken.ts @@ -1,11 +1,15 @@ import { IUser } from "../types"; import { env } from "../utils/env"; -import { sign,verify } from "jsonwebtoken"; - -export const generateToken = async(user:IUser) =>{ - const accessToken = sign({email:user.email,password:user.password}, - `${env.jwt_secret}`,{expiresIn:'72h'} - ); - return accessToken; -} +import { sign } from "jsonwebtoken"; +export const generateToken = async (user: IUser) => { + const accessToken = sign( + { + email: user.email, + password: user.password, + }, + `${env.jwt_secret}`, + { expiresIn: "72h" }, + ); + return accessToken; +}; diff --git a/tsconfig.json b/tsconfig.json index b003173..1a28634 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,7 +31,7 @@ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - "typeRoots": ["node_modules/@types", "./typings"], /* Specify multiple folders that act like './node_modules/@types'. */ + "typeRoots": ["node_modules/@types", "./typings"] /* Specify multiple folders that act like './node_modules/@types'. */, // "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */