diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 0000000..186e9aa
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,2 @@
+npm run pre-commit
+npm run test
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..15319ae
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,5 @@
+{
+ "semi": true,
+ "tabWidth": 2,
+ "useTabs": true
+}
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
diff --git a/__test__/home.test.ts b/__test__/home.test.ts
index a2ddf99..0ccd376 100644
--- a/__test__/home.test.ts
+++ b/__test__/home.test.ts
@@ -4,17 +4,17 @@ import app from "../src/utils/server";
import sequelize, { connect } from "../src/config/dbConnection";
describe("Testing Home route", () => {
- beforeAll(async () => {
- try {
- await connect();
- } catch (error) {
- sequelize.close();
- }
- }, 20000);
+ beforeAll(async () => {
+ try {
+ await connect();
+ } catch (error) {
+ sequelize.close();
+ }
+ }, 20000);
- test("servr should return status code of 200 --> given'/'", async () => {
- const response = await request(app).get("/");
+ test("servr should return status code of 200 --> given'/'", async () => {
+ const response = await request(app).get("/");
- expect(response.status).toBe(200);
- }, 20000);
+ expect(response.status).toBe(200);
+ }, 20000);
});
diff --git a/__test__/user.test.ts b/__test__/user.test.ts
index 32e9a70..e4de66d 100644
--- a/__test__/user.test.ts
+++ b/__test__/user.test.ts
@@ -5,74 +5,82 @@ 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"
- }
+const loginData: any = {
+ email: "test1@gmail.com",
+ password: "test1234",
+};
describe("Testing user Routes", () => {
- beforeAll(async () => {
- try {
- await connect();
- await User.destroy({truncate:true})
- } catch (error) {
- sequelize.close();
- }
- }, 20000);
+ beforeAll(async () => {
+ try {
+ await connect();
+ await User.destroy({ truncate: true });
+ } catch (error) {
+ sequelize.close();
+ }
+ }, 20000);
- 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);
+ 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);
-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 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);
-
- expect(response.status).toBe(400); }, 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 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();
- });
-})
+ expect(response.status).toBe(400);
+ }, 20000);
+ });
+});
+
+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();
+});
diff --git a/eslint.config.cjs b/eslint.config.cjs
new file mode 100644
index 0000000..49f3638
--- /dev/null
+++ b/eslint.config.cjs
@@ -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"],
+ },
+ },
+);
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..328b27d 100644
--- a/index.ts
+++ b/index.ts
@@ -3,13 +3,13 @@ import { env } from "./src/utils/env";
import app from "./src/utils/server";
app.listen(env.port, async () => {
- await connect();
- await sequelize
- .sync()
- .then(() => {
- console.log(` db synced and server is running on port ${env.port}`);
- })
- .catch((error: any) => {
- console.log(error.message);
- });
+ await connect();
+ await sequelize
+ .sync()
+ .then(() => {
+ console.log(" db synced and server is running");
+ })
+ .catch((error: any) => {
+ console.log(error.message);
+ });
});
diff --git a/jest.config.js b/jest.config.js
index 36e4760..124cea1 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,11 +1,11 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
- preset: "ts-jest",
- testEnvironment: "node",
- testMatch: ["**/**/*.test.ts"],
- verbose: true,
- forceExit: true,
- clearMocks: true,
- resetMocks: true,
- restoreMocks: true,
+ preset: "ts-jest",
+ testEnvironment: "node",
+ testMatch: ["**/**/*.test.ts"],
+ verbose: true,
+ forceExit: true,
+ clearMocks: true,
+ resetMocks: true,
+ restoreMocks: true,
};
diff --git a/package.json b/package.json
index e693874..0b8461e 100644
--- a/package.json
+++ b/package.json
@@ -1,65 +1,89 @@
{
- "name": "eagles-ec-be",
- "version": "1.0.0",
- "description": "A platform providing a marketplace for buyers and sellers to meet",
- "main": "index.ts",
- "scripts": {
- "start": "",
- "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"
- },
- "author": "atlp",
- "license": "MIT",
- "devDependencies": {
- "@eslint/js": "^9.0.0",
- "@types/bcryptjs": "^2.4.6",
- "@types/cors": "^2.8.17",
- "@types/dotenv": "^8.2.0",
- "@types/express": "^4.17.21",
- "@types/jest": "^29.5.12",
- "@types/jsonwebtoken": "^9.0.6",
- "@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/parser": "^7.6.0",
- "eslint": "^8.57.0",
- "eslint-config-airbnb-base": "^15.0.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-import": "^2.29.1",
- "eslint-plugin-jest": "^28.2.0",
- "globals": "^15.0.0",
- "jest": "^29.7.0",
- "nodemon": "^3.1.0",
- "prettier": "^3.2.5",
- "sequelize-cli": "^6.6.2",
- "supertest": "^6.3.4",
- "ts-jest": "^29.1.2",
- "ts-node": "^10.9.2",
- "typescript": "^5.4.5",
- "typescript-eslint": "^7.7.0"
- },
- "dependencies": {
- "@types/bcrypt": "^5.0.2",
- "bcrypt": "^5.1.1",
- "bcryptjs": "^2.4.3",
- "cors": "^2.8.5",
- "cross-env": "^7.0.3",
- "cryptr": "^6.3.0",
- "dotenv": "^16.4.5",
- "email-validator": "^2.0.4",
- "express": "^4.19.2",
- "joi": "^17.12.3",
- "jsonwebtoken": "^9.0.2",
- "path": "^0.12.7",
- "pg": "^8.11.5",
- "pg-hstore": "^2.3.4",
- "sequelize": "^6.37.2",
- "swagger-ui-express": "^5.0.0"
- }
+ "name": "eagles-ec-be",
+ "version": "1.0.0",
+ "description": "A platform providing a marketplace for buyers and sellers to meet",
+ "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:fix": "npx eslint --fix .",
+ "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",
+ "@types/bcryptjs": "^2.4.6",
+ "@types/cors": "^2.8.17",
+ "@types/dotenv": "^8.2.0",
+ "@types/express": "^4.17.21",
+ "@types/jest": "^29.5.12",
+ "@types/jsonwebtoken": "^9.0.6",
+ "@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/parser": "^7.6.0",
+ "eslint": "^8.57.0",
+ "eslint-config-airbnb-base": "^15.0.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-jest": "^28.2.0",
+ "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",
+ "ts-jest": "^29.1.2",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.4.5",
+ "typescript-eslint": "^7.7.0"
+ },
+ "dependencies": {
+ "@types/bcrypt": "^5.0.2",
+ "bcrypt": "^5.1.1",
+ "bcryptjs": "^2.4.3",
+ "cors": "^2.8.5",
+ "cross-env": "^7.0.3",
+ "cryptr": "^6.3.0",
+ "dotenv": "^16.4.5",
+ "email-validator": "^2.0.4",
+ "express": "^4.19.2",
+ "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",
+ "sequelize": "^6.37.2",
+ "swagger-ui-express": "^5.0.0"
+ }
}
diff --git a/src/config/dbConnection.ts b/src/config/dbConnection.ts
index 8500c3d..5ebaef7 100644
--- a/src/config/dbConnection.ts
+++ b/src/config/dbConnection.ts
@@ -3,19 +3,21 @@ 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 {
- await sequelize.authenticate();
- console.log("successfuly connected's to db");
- } catch (error: any) {
- console.log("error: ", error.message);
- return;
- }
+ try {
+ await sequelize.authenticate();
+ console.log("successfuly connected's to db");
+ } catch (error: any) {
+ console.log("error: ", error.message);
+ return;
+ }
};
export default sequelize;
diff --git a/src/controllers/userControllers.ts b/src/controllers/userControllers.ts
index f3fed45..a1a276a 100644
--- a/src/controllers/userControllers.ts
+++ b/src/controllers/userControllers.ts
@@ -2,80 +2,83 @@ 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();
+ try {
+ // const users = await userService.getAllUsers();
- if (users.length <= 0) {
- return res.status(404).json({
- message: "No users found",
- });
- } else {
- res.status(200).json({
- message: "Users fetched successfully",
- count: users.length,
- users: users,
- });
- }
- } catch (error: any) {
- res.status(500).json({
- message: "Internal server error",
- error: error.message,
- });
- }
-};
+ const users = await userService.getAllUsers();
-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){
- 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
- });
- };
- };
+ if (users.length <= 0) {
+ return res.status(404).json({
+ message: "No users found",
+ });
+ } else {
+ res.status(200).json({
+ message: "Users fetched successfully",
+ count: users.length,
+ users: users,
+ });
+ }
+ } catch (error: any) {
+ res.status(500).json({
+ message: "Internal server error",
+ error: error.message,
+ });
+ }
};
+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) {
+ 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,
+ });
+ }
+ }
+};
export const createUserController = async (req: Request, res: Response) => {
- 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'
- });
- }
-
- 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' });
- }
- res.status(500).json({ error: err });
- }
+ 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",
+ });
+ }
+
+ 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" });
+ }
+ res.status(500).json({ error: err });
+ }
};
diff --git a/src/docs/swagger.ts b/src/docs/swagger.ts
index e7f82ec..46caa6c 100644
--- a/src/docs/swagger.ts
+++ b/src/docs/swagger.ts
@@ -1,68 +1,73 @@
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: [{
- url: `http://localhost:${env.port}`,
- description: 'Development server',
- }, {
- url: 'https://eagles-ec-be-development.onrender.com/',
- description: 'Production server',
- }],
+ servers: [
+ {
+ url: `http://localhost:${env.port}`,
+ 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..a120523 100644
--- a/src/docs/users.ts
+++ b/src/docs/users.ts
@@ -1,104 +1,100 @@
-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 :{
- email: {
- type: "string",
- format: "email",
- },
- password: {
- type: "string",
- },
- }
-}
+export const loginSchema = {
+ properties: {
+ email: {
+ type: "string",
+ format: "email",
+ },
+ 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",
- },
- },
- },
- },
- responses: {
- 201: {
- description: "Created",
- content: {
- "application/json": {
- schema: {
- $ref: "#/components/schemas/User",
- },
- },
- },
- },
- 400: {
- description: "Bad request",
- },
- },
- }
+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",
+ },
+ },
+ },
+ },
+ 400: {
+ description: "Bad request",
+ },
+ },
+};
- 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
+export const loginAsUser = {
+ tags: ["Users"],
+ summary: "Login as user",
+ requestBody: {
+ required: true,
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/Login",
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: "OK",
+ },
+ },
+};
diff --git a/src/helpers/comparePassword.ts b/src/helpers/comparePassword.ts
index 79654ba..27434ee 100644
--- a/src/helpers/comparePassword.ts
+++ b/src/helpers/comparePassword.ts
@@ -1,4 +1,7 @@
-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..660fdbb 100644
--- a/src/middleware/validator.ts
+++ b/src/middleware/validator.ts
@@ -1,35 +1,38 @@
-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;
+export const emailValidation = (
+ req: Request,
+ res: Response,
+ next: NextFunction,
+) => {
+ const { email } = req.body;
- if (!email) {
- return res.status(400).json({
- status: 400,
- message: "Email is required"
- });
- }
+ if (!email) {
+ return res.status(400).json({
+ status: 400,
+ message: "Email is required",
+ });
+ }
- const isValid = validator.validate(email);
- if (isValid) {
- next();
- } else {
- return res.status(400).json({
- status: 400,
- message: "Email is not valid."
- });
- }
+ const isValid = validator.validate(email);
+ if (isValid) {
+ next();
+ } else {
+ return res.status(400).json({
+ status: 400,
+ 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();
- };
-};
\ No newline at end of file
+ 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();
+ };
+};
diff --git a/src/routes/homeRoutes.ts b/src/routes/homeRoutes.ts
index b26f96b..884800e 100644
--- a/src/routes/homeRoutes.ts
+++ b/src/routes/homeRoutes.ts
@@ -3,16 +3,16 @@ import { Request, Response, Router } from "express";
const homeRoute = Router();
homeRoute.get("/", (req: Request, res: Response) => {
- try {
- res.status(200).json({
- message: "Api is working 😎",
- });
- } catch (error: any) {
- res.status(500).json({
- message: "Internal server error",
- error: error.message,
- });
- }
+ try {
+ res.status(200).json({
+ message: "Api is working 😎",
+ });
+ } catch (error: any) {
+ res.status(500).json({
+ message: "Internal server error",
+ error: error.message,
+ });
+ }
});
export default homeRoute;
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..c62efad 100644
--- a/src/routes/userRoutes.ts
+++ b/src/routes/userRoutes.ts
@@ -1,24 +1,23 @@
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..88d3ff0 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..a730b16 100644
--- a/src/sequelize/config/config.js
+++ b/src/sequelize/config/config.js
@@ -2,23 +2,22 @@ const dotenv = require("dotenv");
dotenv.config();
module.exports = {
- development: {
- url: process.env.DB_CONNECTION,
- dialect: "postgres",
- },
- test: {
- url: process.env.TEST_DB,
- dialect: "postgres",
- },
- production: {
- url: process.env.DB_CONNECTION,
- dialect: "postgres",
- dialectOptions: {
- ssl: {
- require: true,
- rejectUnauthorized: false,
- },
- },
- },
-
+ development: {
+ url: process.env.DB_CONNECTION,
+ dialect: "postgres",
+ },
+ test: {
+ url: process.env.TEST_DB,
+ dialect: "postgres",
+ },
+ production: {
+ url: process.env.DB_CONNECTION,
+ dialect: "postgres",
+ dialectOptions: {
+ ssl: {
+ require: true,
+ rejectUnauthorized: false,
+ },
+ },
+ },
};
diff --git a/src/sequelize/migrations/20240416115110-create-user.js b/src/sequelize/migrations/20240416115110-create-user.js
index ba6c2a3..80aecab 100644
--- a/src/sequelize/migrations/20240416115110-create-user.js
+++ b/src/sequelize/migrations/20240416115110-create-user.js
@@ -1,44 +1,45 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
/** @type {import('sequelize-cli').Migration} */
module.exports = {
- async up(queryInterface, Sequelize) {
- await queryInterface.createTable("users", {
- id: {
- allowNull: false,
- autoIncrement: true,
- primaryKey: true,
- type: Sequelize.INTEGER,
- },
- name: {
- type: Sequelize.STRING,
- allowNull: false,
- },
- username: {
- type: Sequelize.STRING,
- allowNull: false,
- },
- email: {
- type: Sequelize.STRING,
- allowNull: false,
- validate: {
- isEmail: true,
- },
- },
- password: {
- type: Sequelize.STRING,
- allowNull: false,
- },
- createdAt: {
- allowNull: false,
- type: Sequelize.DATE,
- },
- updatedAt: {
- allowNull: false,
- type: Sequelize.DATE,
- },
- });
- },
+ async up(queryInterface, Sequelize) {
+ await queryInterface.createTable("users", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER,
+ },
+ name: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+ username: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+ email: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ validate: {
+ isEmail: true,
+ },
+ },
+ password: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ },
+ });
+ },
- async down(queryInterface, Sequelize) {
- await queryInterface.describeTable("users");
- },
-};
\ No newline at end of file
+ async down(queryInterface, Sequelize) {
+ await queryInterface.describeTable("users");
+ },
+};
diff --git a/src/sequelize/migrations/20240418083442-UserTests.js b/src/sequelize/migrations/20240418083442-UserTests.js
index 1fac10a..871d9c4 100644
--- a/src/sequelize/migrations/20240418083442-UserTests.js
+++ b/src/sequelize/migrations/20240418083442-UserTests.js
@@ -1,44 +1,45 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
/** @type {import('sequelize-cli').Migration} */
module.exports = {
- async up(queryInterface, Sequelize) {
- await queryInterface.createTable("usersTests", {
- id: {
- allowNull: false,
- autoIncrement: true,
- primaryKey: true,
- type: Sequelize.INTEGER,
- },
- name: {
- type: Sequelize.STRING,
- allowNull: false,
- },
- username: {
- type: Sequelize.STRING,
- allowNull: false,
- },
- email: {
- type: Sequelize.STRING,
- allowNull: false,
- validate: {
- isEmail: true,
- },
- },
- password: {
- type: Sequelize.STRING,
- allowNull: false,
- },
- createdAt: {
- allowNull: false,
- type: Sequelize.DATE,
- },
- updatedAt: {
- allowNull: false,
- type: Sequelize.DATE,
- },
- });
- },
+ async up(queryInterface, Sequelize) {
+ await queryInterface.createTable("usersTests", {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER,
+ },
+ name: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+ username: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+ email: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ validate: {
+ isEmail: true,
+ },
+ },
+ password: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE,
+ },
+ });
+ },
- async down(queryInterface, Sequelize) {
- await queryInterface.describeTable("usersTests");
- },
-};
\ No newline at end of file
+ async down(queryInterface, Sequelize) {
+ await queryInterface.describeTable("usersTests");
+ },
+};
diff --git a/src/sequelize/models/index.js b/src/sequelize/models/index.js
index 7549577..bfd6219 100644
--- a/src/sequelize/models/index.js
+++ b/src/sequelize/models/index.js
@@ -11,37 +11,37 @@ const db = {};
let sequelize;
if (config.use_env_variable) {
- sequelize = new Sequelize(process.env[config.use_env_variable], config);
+ 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
- );
- })
- .forEach((file) => {
- const model = require(path.join(__dirname, file))(
- sequelize,
- Sequelize.DataTypes,
- );
- db[model.name] = model;
- });
+ .filter((file) => {
+ 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,
+ );
+ db[model.name] = model;
+ });
Object.keys(db).forEach((modelName) => {
- if (db[modelName].associate) {
- db[modelName].associate(db);
- }
+ if (db[modelName].associate) {
+ db[modelName].associate(db);
+ }
});
db.sequelize = sequelize;
diff --git a/src/sequelize/models/users.ts b/src/sequelize/models/users.ts
index 2bacede..fdc585f 100644
--- a/src/sequelize/models/users.ts
+++ b/src/sequelize/models/users.ts
@@ -1,60 +1,63 @@
-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{
- id!: number | undefined;
- name!: string;
- username!: string;
- email!: string;
- password!: string;
- createdAt!: Date | undefined;
- updatedAt1: Date | undefined;
+class User extends Model implements UserAttributes {
+ id!: number | undefined;
+ name!: string;
+ username!: string;
+ email!: string;
+ password!: string;
+ createdAt!: Date | undefined;
+ updatedAt1: Date | undefined;
}
- User.init({
- id: {
- allowNull: false,
- autoIncrement: true,
- primaryKey: true,
- type: DataTypes.NUMBER,
- },
- name: {
- type: DataTypes.STRING,
- allowNull: false,
- },
- username: {
- type: DataTypes.STRING,
- allowNull: false,
- },
- email:{
- allowNull:false,
- type:DataTypes.STRING
- },
- password: {
- allowNull:false,
- type:DataTypes.STRING
- },
- createdAt: {
- allowNull: false,
- type: DataTypes.DATE,
- },
- updatedAt: {
- allowNull: false,
- type: DataTypes.DATE,
- },
- }, {
- sequelize:sequelize,
- modelName: 'users',
- });
+User.init(
+ {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: DataTypes.NUMBER,
+ },
+ name: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ },
+ username: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ },
+ email: {
+ allowNull: false,
+ type: DataTypes.STRING,
+ },
+ password: {
+ allowNull: false,
+ type: DataTypes.STRING,
+ },
+ createdAt: {
+ allowNull: false,
+ type: DataTypes.DATE,
+ },
+ updatedAt: {
+ allowNull: false,
+ type: DataTypes.DATE,
+ },
+ },
+ {
+ 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..fcfe567 100644
--- a/src/sequelize/models/usersTests.ts
+++ b/src/sequelize/models/usersTests.ts
@@ -1,61 +1,63 @@
-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{
- id!: number | undefined;
- name!: string;
- username!: string;
- email!: string;
- password!: string;
- createdAt!: Date | undefined;
- updatedAt1: Date | undefined;
+class UserTest extends Model implements UserAttributes {
+ id!: number | undefined;
+ name!: string;
+ username!: string;
+ email!: string;
+ password!: string;
+ createdAt!: Date | undefined;
+ updatedAt!: Date | undefined; // Corrected typo here
}
- UserTest.init({
- id: {
- allowNull: false,
- autoIncrement: true,
- primaryKey: true,
- type: DataTypes.NUMBER,
- },
- name: {
- type: DataTypes.STRING,
- allowNull: false,
- },
- username: {
- type: DataTypes.STRING,
- allowNull: false,
- },
- email:{
- allowNull:false,
- type:DataTypes.STRING
- },
- password: {
- allowNull:false,
- type:DataTypes.STRING
- },
- createdAt: {
- allowNull: false,
- type: DataTypes.DATE,
- },
- updatedAt: {
- allowNull: false,
- type: DataTypes.DATE,
- },
- }, {
- sequelize:sequelize,
- modelName: 'usersTests',
- });
+UserTest.init(
+ {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: DataTypes.NUMBER,
+ },
+ name: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ },
+ username: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ },
+ email: {
+ allowNull: false,
+ type: DataTypes.STRING,
+ },
+ password: {
+ allowNull: false,
+ type: DataTypes.STRING,
+ },
+ createdAt: {
+ allowNull: false,
+ type: DataTypes.DATE,
+ },
+ updatedAt: {
+ allowNull: false,
+ type: DataTypes.DATE,
+ },
+ },
+ {
+ 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..2fdad7e 100644
--- a/src/sequelize/seeders/20240412144111-demo-user.js
+++ b/src/sequelize/seeders/20240412144111-demo-user.js
@@ -1,26 +1,27 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
/** @type {import('sequelize-cli').Migration} */
module.exports = {
- up: (queryInterface, Sequelize) => {
- return queryInterface.bulkInsert("Users", [
- {
- name: "Rukundo Soleil",
- username: "soleil00",
- email: "soleil@soleil00.com",
- password: "soleil00",
- createdAt: new Date(),
- updatedAt: new Date(),
- },
- {
- name: "test user",
- username: "yes",
- email: "soleil@soleil0w.com",
- password: "soleil0w0",
- createdAt: new Date(),
- updatedAt: new Date(),
- },
- ]);
- },
- down: (queryInterface, Sequelize) => {
- return queryInterface.bulkDelete("Users", null, {});
- },
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.bulkInsert("Users", [
+ {
+ name: "Rukundo Soleil",
+ username: "soleil00",
+ email: "soleil@soleil00.com",
+ password: "soleil00",
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ },
+ {
+ name: "test user",
+ username: "yes",
+ email: "soleil@soleil0w.com",
+ password: "soleil0w0",
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ },
+ ]);
+ },
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.bulkDelete("Users", null, {});
+ },
};
diff --git a/src/services/user.service.ts b/src/services/user.service.ts
index dbdeae8..f957347 100644
--- a/src/services/user.service.ts
+++ b/src/services/user.service.ts
@@ -1,50 +1,62 @@
-import { errors } from "undici-types";
import User from "../sequelize/models/users";
import { hashedPassword } from "../utils/hashPassword";
import { Op } from "sequelize";
export const getAllUsers = async () => {
- try {
- const users = await User.findAll();
- if (users.length === 0) {
- console.log("no user");
- }
- return users;
- } catch (error: any) {
- console.log(error.message);
- throw new Error(error.message);
- }
+ try {
+ const users = await User.findAll();
+ if (users.length === 0) {
+ console.log("no user");
+ }
+ return users;
+ } catch (error: any) {
+ console.log(error.message);
+ throw new Error(error.message);
+ }
};
-export const loggedInUser = async(email:string) => {
- try{
- const user:any = await User.findOne({
- where: { email: email }
- });
- if(!user){
- return false;
- }else{
- return user;
- }
-}catch(err:any){
- throw new Error(err.message);
+export const loggedInUser = async (email: string) => {
+ try {
+ const user: any = await User.findOne({
+ where: { email: email },
+ });
+ if (!user) {
+ return false;
+ } else {
+ return user;
+ }
+ } 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 }]
- }
- });
- if (existingUser) {
- return null;
- }
- const hashPassword = await hashedPassword(password);
- const user = await User.create({ name, email, username, password: hashPassword });
- return user;
+
+export const createUserService = async (
+ name: string,
+ email: string,
+ username: string,
+ password: string,
+): Promise => {
+ const existingUser = await User.findOne({
+ where: {
+ [Op.or]: [{ email }, { username }],
+ },
+ });
+ if (existingUser) {
+ return null;
+ }
+ const hashPassword = await hashedPassword(password);
+ 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 } });
- return user;
+ const user = await User.findOne({
+ where: { email },
+ });
+ return user;
};
diff --git a/src/types.ts b/src/types.ts
index 3fdbbd9..ee1753d 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,10 +1,10 @@
export interface IUser {
- id?: number;
- name: string;
- username: string;
- email: string;
- password: string;
- isMerchant?: boolean;
- createdAt: Date;
- updatedAt: Date;
+ id?: number;
+ name: string;
+ username: string;
+ email: string;
+ password: string;
+ isMerchant?: boolean;
+ createdAt: Date;
+ updatedAt: Date;
}
diff --git a/src/utils/env.ts b/src/utils/env.ts
index 5d15773..d066db0 100644
--- a/src/utils/env.ts
+++ b/src/utils/env.ts
@@ -2,8 +2,8 @@ import dotenv from "dotenv";
dotenv.config();
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,
+ 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,
};
diff --git a/src/utils/hashPassword.ts b/src/utils/hashPassword.ts
index 8da8382..18729fd 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..9c0178e 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..70e032a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,109 +1,112 @@
{
- "compilerOptions": {
- /* Visit https://aka.ms/tsconfig to read more about this file */
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig to read more about this file */
- /* Projects */
- // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
- // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
- // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
- // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
- // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
- // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+ /* Projects */
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
- /* Language and Environment */
- "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
- // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
- // "jsx": "preserve", /* Specify what JSX code is generated. */
- // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
- // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
- // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
- // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
- // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
- // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
- // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
- // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
- // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
+ /* Language and Environment */
+ "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
+ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
- /* Modules */
- "module": "commonjs" /* Specify what module code is generated. */,
- // "rootDir": "./", /* Specify the root folder within your source files. */
- // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
- // "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'. */
- // "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. */
- // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
- // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
- // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
- // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
- // "resolveJsonModule": true, /* Enable importing .json files. */
- // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
- // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
+ /* Modules */
+ "module": "commonjs" /* Specify what module code is generated. */,
+ // "rootDir": "./", /* Specify the root folder within your source files. */
+ // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
+ // "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'. */,
+ // "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. */
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
+ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
+ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
+ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
+ // "resolveJsonModule": true, /* Enable importing .json files. */
+ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
+ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
- /* JavaScript Support */
- // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
- // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
- // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+ /* JavaScript Support */
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
- /* Emit */
- // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
- // "declarationMap": true, /* Create sourcemaps for d.ts files. */
- // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
- // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
- // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
- // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
- "outDir": "./dist" /* Specify an output folder for all emitted files. */,
- // "removeComments": true, /* Disable emitting comments. */
- // "noEmit": true, /* Disable emitting files from a compilation. */
- // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
- // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
- // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
- // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
- // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
- // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
- // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
- // "newLine": "crlf", /* Set the newline character for emitting files. */
- // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
- // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
- // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
- // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
- // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
- // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+ /* Emit */
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+ "outDir": "./dist" /* Specify an output folder for all emitted files. */,
+ // "removeComments": true, /* Disable emitting comments. */
+ // "noEmit": true, /* Disable emitting files from a compilation. */
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
- /* Interop Constraints */
- // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
- // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
- // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
- "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
- // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
- "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
+ /* Interop Constraints */
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
+ // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
- /* Type Checking */
- "strict": true /* Enable all strict type-checking options. */,
- // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
- // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
- // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
- // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
- // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
- // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
- // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
- // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
- // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
- // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
- // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
- // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
- // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
- // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
- // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
- // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
- // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
- // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+ /* Type Checking */
+ "strict": true /* Enable all strict type-checking options. */,
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
- /* Completeness */
- // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
- "skipLibCheck": true /* Skip type checking all .d.ts files. */
- }
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
+ }
}