├── frontend ├── .env ├── postcss.config.js ├── vercel.json ├── src │ ├── components │ │ ├── Loader.jsx │ │ ├── inputForm │ │ │ └── InputField.jsx │ │ ├── nav │ │ │ ├── UserMenu.jsx │ │ │ └── Header.jsx │ │ ├── ProductCard.jsx │ │ └── CartCard.jsx │ ├── pages │ │ ├── index.js │ │ ├── Hero.jsx │ │ ├── Login.jsx │ │ ├── Cart.jsx │ │ ├── Register.jsx │ │ └── DetailPage.jsx │ ├── main.jsx │ ├── App.jsx │ ├── layout │ │ └── Layout.jsx │ ├── hook │ │ └── useOuterClick.js │ ├── schema │ │ └── index.js │ ├── App.css │ ├── index.css │ ├── routes │ │ └── Router.jsx │ └── assets │ │ └── react.svg ├── vite.config.js ├── utils │ └── axios.js ├── tailwind.config.js ├── .gitignore ├── index.html ├── README.md ├── .eslintrc.cjs ├── package.json ├── public │ └── vite.svg └── store │ └── appStore.js ├── .gitignore ├── backend ├── .env ├── middleware │ ├── asyncHandler.js │ ├── checkAuth.js │ └── errorHandler.js ├── vercel.json ├── config │ └── db.js ├── utils │ └── jwt.js ├── package.json ├── server.js ├── routes │ └── userRoutes.js ├── model │ ├── cartModel.js │ └── userModel.js ├── controller │ └── userController.js ├── data │ └── products.json └── package-lock.json └── README.md /frontend/.env: -------------------------------------------------------------------------------- 1 | VITE_BASE_URL = http://localhost:2060 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | frontend/node_modules/ 2 | backend/node_modules/ 3 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /backend/.env: -------------------------------------------------------------------------------- 1 | PORT = 2060 2 | DB_URI = mongodb://127.0.0.1:27017/shopping-cart 3 | BASE_URL = http://localhost:5173 4 | SECRET_KEY= shopping-cart-1112 -------------------------------------------------------------------------------- /frontend/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "routes": [{ "src": "/[^.]+", "dest": "/", "status": 200 }], 3 | "github": { 4 | "silent": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/components/Loader.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Loader = () => { 4 | return ; 5 | }; 6 | 7 | export default Loader; 8 | -------------------------------------------------------------------------------- /backend/middleware/asyncHandler.js: -------------------------------------------------------------------------------- 1 | const asyncHandler = (fn) => (req, res, next) => { 2 | Promise.resolve(fn(req, res, next)).catch(next); 3 | }; 4 | 5 | module.exports = asyncHandler; 6 | -------------------------------------------------------------------------------- /frontend/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /frontend/utils/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | const BASE_URL = import.meta.env.VITE_BASE_URL; 4 | 5 | const API = axios.create({ baseURL: BASE_URL, withCredentials: true }); 6 | 7 | export default API; 8 | -------------------------------------------------------------------------------- /frontend/src/pages/index.js: -------------------------------------------------------------------------------- 1 | export { default as Login } from "./Login"; 2 | export { default as Register } from "./Register"; 3 | export { default as Cart } from "./Cart"; 4 | export { default as DetailPage } from "./DetailPage"; 5 | -------------------------------------------------------------------------------- /frontend/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /frontend/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App.jsx"; 4 | import "./index.css"; 5 | 6 | ReactDOM.createRoot(document.getElementById("root")).render(); 7 | -------------------------------------------------------------------------------- /frontend/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { RouterProvider } from "react-router-dom"; 3 | import routes from "./routes/Router"; 4 | 5 | const App = () => { 6 | return ; 7 | }; 8 | 9 | export default App; 10 | -------------------------------------------------------------------------------- /frontend/src/layout/Layout.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Layout = ({ children }) => { 4 | return ( 5 |
6 |
{children}
7 |
8 | ); 9 | }; 10 | 11 | export default Layout; 12 | -------------------------------------------------------------------------------- /backend/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "name": "backend", 4 | "builds": [ 5 | { 6 | "src": "server.js", 7 | "use": "@vercel/node" 8 | } 9 | ], 10 | "routes": [ 11 | { 12 | "src": "/(.*)", 13 | "dest": "/server.js" 14 | } 15 | ], 16 | "github": { 17 | "silent": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /backend/config/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const connectDB = async () => { 4 | try { 5 | const { connection } = await mongoose.connect(process.env.DB_URI); 6 | console.log(`connected with `, connection.host, connection.port); 7 | } catch (error) { 8 | console.log(error); 9 | } 10 | }; 11 | 12 | module.exports = connectDB; 13 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /backend/utils/jwt.js: -------------------------------------------------------------------------------- 1 | const sendToken = (user, res) => { 2 | const token = user.getJwtToken(); 3 | const options = { 4 | httpOnly: true, 5 | secure: true, 6 | sameSite: "none", 7 | maxAge: 72 * 60 * 60 * 1000, 8 | }; 9 | res 10 | .cookie("token", token, options) 11 | .status(200) 12 | .json({ success: true, token, user }); 13 | }; 14 | 15 | module.exports = sendToken; 16 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /frontend/src/hook/useOuterClick.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | const useOuterClick = (ref, callback) => { 4 | useEffect(() => { 5 | const close = (event) => { 6 | if (ref?.current && !ref?.current?.contains(event.target)) { 7 | callback(false); 8 | } 9 | }; 10 | document.addEventListener("mousedown", close); 11 | return () => { 12 | document.removeEventListener("mousedown", close); 13 | }; 14 | }, []); 15 | }; 16 | 17 | export default useOuterClick; 18 | -------------------------------------------------------------------------------- /frontend/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react-refresh/only-export-components': [ 16 | 'warn', 17 | { allowConstantExport: true }, 18 | ], 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /backend/middleware/checkAuth.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | const asyncHandler = require("./asyncHandler"); 3 | 4 | const checkAuth = asyncHandler(async (req, res, next) => { 5 | const { token } = req.cookies; 6 | 7 | if (token) { 8 | jwt.verify(token, process.env.SECRET_KEY, (err, user) => { 9 | if (err) { 10 | res.status(400); 11 | throw new Error("Invalid token"); 12 | } 13 | req.userId = user.id; 14 | next(); 15 | }); 16 | } else { 17 | return res.status(401).json({ success: false, message: "Unauthorized" }); 18 | } 19 | }); 20 | 21 | module.exports = checkAuth; 22 | -------------------------------------------------------------------------------- /frontend/src/schema/index.js: -------------------------------------------------------------------------------- 1 | import * as YUP from "yup"; 2 | 3 | export const loginSchema = YUP.object({ 4 | email: YUP.string().email("invalid mail").required("enter email"), 5 | password: YUP.string().required("enter password"), 6 | }); 7 | 8 | export const registerSchema = YUP.object({ 9 | name: YUP.string().min(3, "minimum 3 character").required("enter name"), 10 | email: YUP.string().email("invalid mail").required("enter email"), 11 | password: YUP.string().required("enter password"), 12 | confirmPassword: YUP.string() 13 | .oneOf([YUP.ref("password"), null], "password must be match") 14 | .required("enter password"), 15 | }); 16 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "dev": "nodemon server.js", 8 | "start": "node server.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "nodemon": "^3.0.1" 16 | }, 17 | "dependencies": { 18 | "bcrypt": "^5.1.1", 19 | "cookie-parser": "^1.4.6", 20 | "cors": "^2.8.5", 21 | "dotenv": "^16.3.1", 22 | "express": "^4.18.2", 23 | "jsonwebtoken": "^9.0.2", 24 | "mongoose": "^7.6.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /frontend/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /backend/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const cors = require("cors"); 3 | require("dotenv").config(); 4 | const connectDB = require("./config/db"); 5 | const userRoutes = require("./routes/userRoutes"); 6 | const cookieParser = require("cookie-parser"); 7 | const { notFound, errorHandler } = require("./middleware/errorHandler"); 8 | connectDB(); 9 | 10 | const app = express(); 11 | 12 | app.use( 13 | cors({ 14 | origin: process.env.BASE_URL, 15 | credentials: true, 16 | methods: "PUT,POST,GET,DELETE,PATCH,HEAD", 17 | }) 18 | ); 19 | 20 | app.use(express.json()); 21 | app.use(express.urlencoded({ extended: true })); 22 | app.use(cookieParser()); 23 | app.use("/api/user/", userRoutes); 24 | 25 | app.use(notFound); 26 | app.use(errorHandler); 27 | 28 | app.listen(process.env.PORT, () => { 29 | console.log(`Server running on port ${process.env.PORT}`); 30 | }); 31 | -------------------------------------------------------------------------------- /frontend/src/components/inputForm/InputField.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const InputField = ({ 4 | title, 5 | name, 6 | value, 7 | type, 8 | handleChange, 9 | errors, 10 | touched, 11 | handleBlur, 12 | }) => { 13 | return ( 14 |
15 | 19 | {errors[name] && touched[name] ? ( 20 | {errors[name]} 21 | ) : null} 22 | 32 |
33 | ); 34 | }; 35 | 36 | export default InputField; 37 | -------------------------------------------------------------------------------- /backend/routes/userRoutes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { 3 | login, 4 | register, 5 | logout, 6 | addCart, 7 | removeCart, 8 | decreaseCartQty, 9 | addCartQty, 10 | getUserCart, 11 | getCartNumber, 12 | } = require("../controller/userController"); 13 | const checkAuth = require("../middleware/checkAuth"); 14 | 15 | const userRoutes = express.Router(); 16 | 17 | userRoutes.post("/login", login); 18 | userRoutes.post("/register", register); 19 | userRoutes.post("/logout", checkAuth, logout); 20 | userRoutes.get("/get-user-cart-number", checkAuth, getCartNumber); 21 | userRoutes.get("/get-user-cart", checkAuth, getUserCart); 22 | userRoutes.post("/add-cart", checkAuth, addCart); 23 | userRoutes.delete("/remove-cart", checkAuth, removeCart); 24 | userRoutes.post("/add-qty", checkAuth, addCartQty); 25 | userRoutes.post("/decrease-qty", checkAuth, decreaseCartQty); 26 | 27 | module.exports = userRoutes; 28 | -------------------------------------------------------------------------------- /frontend/src/components/nav/UserMenu.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import { useAppStore } from "../../../store/appStore"; 3 | import { useNavigate } from "react-router-dom"; 4 | import useOuterClick from "../../hook/useOuterClick"; 5 | 6 | const UserMenu = ({ setShowMenu }) => { 7 | const userRef = useRef(null); 8 | useOuterClick(userRef, setShowMenu); 9 | const navigate = useNavigate(); 10 | const { logout, user } = useAppStore(); 11 | return ( 12 |
16 |

{user?.name}

17 |

logout(navigate, setShowMenu)} 20 | > 21 | Logout 22 |

23 |
24 | ); 25 | }; 26 | 27 | export default UserMenu; 28 | -------------------------------------------------------------------------------- /backend/model/cartModel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const cartSchema = mongoose.Schema( 4 | { 5 | cartItems: [ 6 | { 7 | product: { 8 | id: { type: Number, required: true }, 9 | title: { type: String, required: true }, 10 | price: Number, 11 | description: { type: String, required: true }, 12 | rating: { rate: { type: Number }, count: { type: Number } }, 13 | category: { type: String, required: true }, 14 | image: { type: String, required: true }, 15 | }, 16 | quantity: { type: Number, default: 1 }, 17 | }, 18 | ], 19 | user: { 20 | type: mongoose.Types.ObjectId, 21 | ref: "user", 22 | required: [true, "user id is required"], 23 | }, 24 | totalPrice: Number, 25 | }, 26 | { timestamp: true } 27 | ); 28 | 29 | const cartModel = mongoose.model("cart", cartSchema); 30 | 31 | module.exports = cartModel; 32 | -------------------------------------------------------------------------------- /frontend/src/pages/Hero.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Layout from "../layout/Layout"; 3 | import axios from "axios"; 4 | import ProductCard from "../components/ProductCard"; 5 | 6 | const Hero = () => { 7 | const [products, setProducts] = useState([]); 8 | const getAllProducts = async () => { 9 | try { 10 | const { data } = await axios( 11 | "https://ecommerce-backend-new.vercel.app/api/products" 12 | ); 13 | setProducts(data); 14 | } catch (error) { 15 | console.log(error); 16 | } 17 | }; 18 | useEffect(() => { 19 | getAllProducts(); 20 | }, []); 21 | return ( 22 | 23 |
24 | {products?.map((item, id) => ( 25 | 26 | ))} 27 |
28 |
29 | ); 30 | }; 31 | 32 | export default Hero; 33 | -------------------------------------------------------------------------------- /backend/model/userModel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const bcrypt = require("bcrypt"); 3 | const jwt = require("jsonwebtoken"); 4 | 5 | const userSchema = mongoose.Schema({ 6 | name: { type: "string", required: true }, 7 | email: { type: "string", required: true, unique: true }, 8 | password: { type: "string", required: true }, 9 | role: { type: "string", default: "user", enum: ["user", "admin"] }, 10 | }); 11 | 12 | userSchema.pre("save", async function (next) { 13 | if (!this.isModified("password")) { 14 | next(); 15 | } 16 | this.password = await bcrypt.hash(this.password, 10); 17 | next(); 18 | }); 19 | 20 | userSchema.methods.getJwtToken = function () { 21 | return jwt.sign({ id: this.id }, process.env.SECRET_KEY, { expiresIn: "2d" }); 22 | }; 23 | 24 | userSchema.methods.verifyPassword = async function (enteredPassword) { 25 | return bcrypt.compare(enteredPassword, this.password); 26 | }; 27 | 28 | const userModel = mongoose.model("user", userSchema); 29 | 30 | module.exports = userModel; 31 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "axios": "^1.5.1", 14 | "formik": "^2.4.5", 15 | "react": "^18.2.0", 16 | "react-dom": "^18.2.0", 17 | "react-icons": "^4.11.0", 18 | "react-router-dom": "^6.16.0", 19 | "react-toastify": "^9.1.3", 20 | "yup": "^1.3.2", 21 | "zustand": "^4.4.3" 22 | }, 23 | "devDependencies": { 24 | "@types/react": "^18.2.15", 25 | "@types/react-dom": "^18.2.7", 26 | "@vitejs/plugin-react": "^4.0.3", 27 | "autoprefixer": "^10.4.16", 28 | "eslint": "^8.45.0", 29 | "eslint-plugin-react": "^7.32.2", 30 | "eslint-plugin-react-hooks": "^4.6.0", 31 | "eslint-plugin-react-refresh": "^0.4.3", 32 | "postcss": "^8.4.31", 33 | "tailwindcss": "^3.3.3", 34 | "vite": "^4.4.5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /backend/middleware/errorHandler.js: -------------------------------------------------------------------------------- 1 | const notFound = (req, res, next) => { 2 | const error = new Error(`Not Found - ${req.originalUrl}`); 3 | res.status(404); 4 | next(error); 5 | }; 6 | 7 | const errorHandler = (err, req, res, next) => { 8 | let statusCode = res.statusCode === 200 ? 500 : res.statusCode; 9 | let message = err.message; 10 | 11 | if (err.name === "CastError" && err.kind === "ObjectId") { 12 | message = `Resource not found`; 13 | statusCode = 404; 14 | } 15 | 16 | if (err.name === "validationError") { 17 | message = Object.values(err.errors).map((value) => value.message); 18 | statusCode = 400; 19 | } 20 | 21 | if (err.code == 11000) { 22 | message = `Duplicate ${Object.keys(err.keyvalue)} entered`; 23 | } 24 | 25 | if (err.name === "JsonWebTokenError") { 26 | message = `Json web token is invalid`; 27 | statusCode = 400; 28 | } 29 | if (err.name === "TokenExpiredError") { 30 | message = `Json web token is expired`; 31 | statusCode = 400; 32 | } 33 | 34 | res.status(statusCode).json({ message }); 35 | }; 36 | 37 | module.exports = { notFound, errorHandler }; 38 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .loader { 6 | width: 48px; 7 | height: 48px; 8 | border-radius: 50%; 9 | z-index: 50; 10 | position: fixed; 11 | top: 50%; 12 | left: 50%; 13 | transform: translate(-50%, -50%); 14 | animation: rotate 1s linear infinite; 15 | } 16 | .loader::before, 17 | .loader::after { 18 | content: ""; 19 | box-sizing: border-box; 20 | position: absolute; 21 | inset: 0px; 22 | border-radius: 50%; 23 | border: 5px solid #fff; 24 | animation: prixClipFix 2s linear infinite; 25 | } 26 | .loader::after { 27 | border-color: #ff3d00; 28 | animation: prixClipFix 2s linear infinite, rotate 0.5s linear infinite reverse; 29 | inset: 6px; 30 | } 31 | 32 | @keyframes rotate { 33 | 0% { 34 | transform: rotate(0deg); 35 | } 36 | 100% { 37 | transform: rotate(360deg); 38 | } 39 | } 40 | 41 | @keyframes prixClipFix { 42 | 0% { 43 | clip-path: polygon(50% 50%, 0 0, 0 0, 0 0, 0 0, 0 0); 44 | } 45 | 25% { 46 | clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 0, 100% 0, 100% 0); 47 | } 48 | 50% { 49 | clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 100% 100%, 100% 100%); 50 | } 51 | 75% { 52 | clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 0 100%, 0 100%); 53 | } 54 | 100% { 55 | clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 0 100%, 0 0); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /frontend/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/routes/Router.jsx: -------------------------------------------------------------------------------- 1 | import { createBrowserRouter, useLocation } from "react-router-dom"; 2 | import Hero from "../pages/Hero"; 3 | import Header from "../components/nav/Header"; 4 | import { Outlet } from "react-router-dom"; 5 | import Login from "../pages/Login"; 6 | import Register from "./../pages/Register"; 7 | import Cart from "./../pages/Cart"; 8 | import { ToastContainer } from "react-toastify"; 9 | import "react-toastify/dist/ReactToastify.css"; 10 | import { useAppStore } from "../../store/appStore"; 11 | import { useEffect } from "react"; 12 | import { DetailPage } from "../pages"; 13 | import Loader from "../components/Loader"; 14 | 15 | const Layout = () => { 16 | const { pathname } = useLocation(); 17 | const { loading } = useAppStore(); 18 | useEffect(() => { 19 | window.scrollTo({ top: 0, left: 0, behavior: "smooth" }); 20 | }, [pathname]); 21 | return ( 22 | <> 23 | {loading && } 24 | 25 |
26 | 27 | 28 | ); 29 | }; 30 | 31 | const routes = createBrowserRouter([ 32 | { 33 | path: "/", 34 | element: , 35 | children: [ 36 | { 37 | path: "", 38 | element: , 39 | }, 40 | { 41 | path: "login", 42 | element: , 43 | }, 44 | { 45 | path: "register", 46 | element: , 47 | }, 48 | { 49 | path: "cart", 50 | element: , 51 | }, 52 | { 53 | path: "product/:id", 54 | element: , 55 | }, 56 | ], 57 | }, 58 | ]); 59 | 60 | export default routes; 61 | -------------------------------------------------------------------------------- /frontend/src/components/ProductCard.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { useAppStore } from "../../store/appStore"; 4 | 5 | const ProductCard = ({ item }) => { 6 | const { addCart } = useAppStore(); 7 | const navigate = useNavigate(); 8 | const productName = (name) => { 9 | if (name.length > 20) { 10 | return name.substring(0, 20) + "..."; 11 | } 12 | return name; 13 | }; 14 | return ( 15 |
16 |
17 | navigate(`/product/${item.id}`)} 20 | className="w-full h-full object-cover cursor-pointer" 21 | alt="" 22 | /> 23 |
24 |
25 |

navigate(`/product/${item.id}`)} 28 | > 29 | {productName(item.title)} 30 |

31 |

32 | {"₹ "} 33 | {Math.ceil(item.price * 81)} 34 |

35 |
36 |
37 | 43 |
44 | 45 |
46 | {item.rating.count} 47 |
48 |
49 | ); 50 | }; 51 | 52 | export default ProductCard; 53 | -------------------------------------------------------------------------------- /frontend/src/pages/Login.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import Layout from "../layout/Layout"; 3 | import { useFormik } from "formik"; 4 | import { loginSchema } from "../schema"; 5 | import InputField from "../components/inputForm/InputField"; 6 | import { Navigate, useNavigate } from "react-router-dom"; 7 | import { useAppStore } from "../../store/appStore"; 8 | 9 | const initialValues = { 10 | email: "", 11 | password: "", 12 | }; 13 | 14 | const Login = () => { 15 | const { loginUser, user } = useAppStore(); 16 | const navigate = useNavigate(); 17 | const { handleBlur, handleChange, handleSubmit, values, errors, touched } = 18 | useFormik({ 19 | initialValues, 20 | validationSchema: loginSchema, 21 | onSubmit: (values, action) => { 22 | loginUser(values, navigate); 23 | }, 24 | }); 25 | 26 | useEffect(() => { 27 | if (user) { 28 | navigate("/"); 29 | } 30 | }, [user]); 31 | 32 | return ( 33 | 34 |
35 |
39 |

Login

40 | 41 |

navigate("/register")} className="pt-6"> 42 | Don't have an account? 43 | 44 | Get Started 45 | 46 |

47 | 48 | 58 | 68 |

69 | forgot-password 70 |

71 | 77 | 78 |
79 |
80 | ); 81 | }; 82 | 83 | export default Login; 84 | -------------------------------------------------------------------------------- /frontend/src/pages/Cart.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import Layout from "./../layout/Layout"; 3 | import CartCard from "../components/CartCard"; 4 | import { useAppStore } from "../../store/appStore"; 5 | import { useNavigate } from "react-router-dom"; 6 | import { PiSmileySadFill } from "react-icons/pi"; 7 | 8 | const Cart = () => { 9 | const navigate = useNavigate(); 10 | const { cart, getUserCart, user } = useAppStore(); 11 | const displaycart = cart?.map((itemes, id) => { 12 | return ; 13 | }); 14 | 15 | useEffect(() => { 16 | if (!user) { 17 | navigate("/login"); 18 | } 19 | 20 | getUserCart(); 21 | }, []); 22 | 23 | let initialValue = 0; 24 | let total = Math.ceil( 25 | cart?.reduce( 26 | (acc, item) => acc + item.product.price * item.quantity, 27 | initialValue 28 | ) * 81 29 | ); 30 | 31 | return ( 32 | 33 |
34 |
35 |
36 |

Your Cart

37 |

Total Itemes : {cart?.length}

38 |
39 |
{displaycart}
40 | {!cart?.length && ( 41 |
42 |

cart is empty

{" "} 43 |
44 | 45 |
46 | )} 47 |
48 | {cart?.length ? ( 49 |
50 |
51 |
52 |

You Pay

53 |

Check Our order Policy

54 |
55 |
56 | You Can Pay .... on This Order 57 |
58 |
59 |

60 | Total Price {"₹"} {total} 61 |

62 |

63 | Distributor Price -20 64 |

65 |

Discount 40

66 |
67 |
68 |
69 | ) : null} 70 |
71 |
72 | ); 73 | }; 74 | 75 | export default Cart; 76 | -------------------------------------------------------------------------------- /frontend/src/pages/Register.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import Layout from "../layout/Layout"; 3 | import { useFormik } from "formik"; 4 | import { registerSchema } from "../schema"; 5 | import InputField from "../components/inputForm/InputField"; 6 | import { useNavigate } from "react-router-dom"; 7 | import { useAppStore } from "../../store/appStore"; 8 | 9 | const initialValues = { 10 | name: "", 11 | email: "", 12 | password: "", 13 | confirmPassword: "", 14 | }; 15 | 16 | const Register = () => { 17 | const { registerUser, user } = useAppStore(); 18 | const navigate = useNavigate(); 19 | const { handleBlur, handleChange, handleSubmit, values, errors, touched } = 20 | useFormik({ 21 | initialValues, 22 | validationSchema: registerSchema, 23 | onSubmit: (values, action) => { 24 | registerUser(values, navigate); 25 | }, 26 | }); 27 | 28 | const formValues = [ 29 | { name: "name", title: "Name ", type: "text", value: values.name }, 30 | { name: "email", title: "Email ", type: "email", value: values.email }, 31 | { 32 | name: "password", 33 | title: "Password ", 34 | type: "password", 35 | value: values.password, 36 | }, 37 | { 38 | name: "confirmPassword", 39 | title: "Confirm password ", 40 | type: "password", 41 | value: values.confirmPassword, 42 | }, 43 | ]; 44 | 45 | useEffect(() => { 46 | if (user) { 47 | navigate("/"); 48 | } 49 | }, [user]); 50 | 51 | return ( 52 | 53 |
54 |
58 |

59 | Get Started 60 |

61 | 62 |

63 | Already have an account? 64 | navigate("/login")} 66 | className="text-blue-500 underline cursor-pointer" 67 | > 68 | Login 69 | 70 |

71 | {formValues.map((item, id) => ( 72 | 83 | ))} 84 | 90 | 91 |
92 |
93 | ); 94 | }; 95 | 96 | export default Register; 97 | -------------------------------------------------------------------------------- /frontend/src/components/CartCard.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { HiPlus, HiMinus } from "react-icons/hi"; 4 | import { useAppStore } from "../../store/appStore"; 5 | 6 | const CartCard = ({ item }) => { 7 | const { removeCart, addCartQty, removeCartQty } = useAppStore(); 8 | const productName = (name) => { 9 | if (name.length > 20) { 10 | return name.substring(0, 20) + "..."; 11 | } 12 | return name; 13 | }; 14 | const navigate = useNavigate(); 15 | return ( 16 |
17 |
18 | navigate(`/product/${item.product.id}`)} 20 | src={item.product.image} 21 | className="h-full w-full cursor-pointer object-contain" 22 | alt="" 23 | /> 24 |
{" "} 25 |
26 |

navigate(`/product/${item.product.id}`)} 28 | className="cursor-pointer text-[16px] text-slate-600" 29 | > 30 | {productName(item.product.title)} 31 |

32 |
33 |
34 |
{ 36 | item.quantity === 1 37 | ? removeCart(item.product.id) 38 | : removeCartQty(item.product.id); 39 | }} 40 | className="flex relative bg-white md:h-[30px] md:w-[30px] h-[24px] w-[24px] items-center justify-center rounded-full border-[1px] p-[2px] text-center text-[35px] shadow-xl" 41 | > 42 | 43 | 44 | 45 |
46 |

{item?.quantity}

47 |
48 | 56 |
57 |
58 |
59 |

60 | {"₹ "} 61 | 62 | {Math.ceil(item.product.price * 81)} 63 | 64 |

65 |

removeCart(item.product.id)} 67 | className="cursor-pointer text-right text-red-500" 68 | > 69 | Remove 70 |

71 |
72 |
73 | ); 74 | }; 75 | 76 | export default CartCard; 77 | -------------------------------------------------------------------------------- /frontend/src/components/nav/Header.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { HiShoppingCart, HiUserCircle } from "react-icons/hi"; 3 | import { NavLink, useNavigate } from "react-router-dom"; 4 | import UserMenu from "./UserMenu"; 5 | import { useAppStore } from "../../../store/appStore"; 6 | import API from "../../../utils/axios"; 7 | 8 | const Header = () => { 9 | const { user, totalCart } = useAppStore(); 10 | const [showMenu, setShowMenu] = useState(false); 11 | const navigate = useNavigate(); 12 | 13 | const getCartNumber = async () => { 14 | try { 15 | const { data, status } = await API("/api/user/get-user-cart-number"); 16 | useAppStore.setState({ totalCart: data }); 17 | } catch (error) { 18 | console.log(error?.response?.data?.message); 19 | } 20 | }; 21 | 22 | useEffect(() => { 23 | if (user) { 24 | getCartNumber(); 25 | } 26 | }, [user]); 27 | 28 | return ( 29 |
30 |
31 |

navigate("/")} 33 | className="font-extrabold text-[26px] cursor-pointer tracking-wide sm:tracking-widest" 34 | > 35 | Shopping Cart 36 |

37 |
38 |
39 |
    40 |
  • 41 | (isActive ? "text-blue-400" : "")} 44 | > 45 | Home 46 | 47 |
  • 48 | {!user && ( 49 |
  • 50 | (isActive ? "text-blue-400" : "")} 53 | > 54 | Login 55 | 56 |
  • 57 | )} 58 |
59 |
60 |
61 | (isActive ? "text-blue-400" : "")} 64 | > 65 | 66 | {user && ( 67 | 72 | )} 73 | 74 | {user ? ( 75 | setShowMenu((pre) => !pre)} 79 | /> 80 | ) : ( 81 | (isActive ? "text-blue-400" : "")} 84 | > 85 | 86 | 87 | )} 88 | 89 | {showMenu && } 90 |
91 |
92 | ); 93 | }; 94 | 95 | export default Header; 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MERN eCommerce Shopping Cart 2 | 3 | This is a MERN (MongoDB, Express.js, React, Node.js) eCommerce shopping cart project that allows users to browse products online. It includes features like user authentication, cart management. 4 | 5 | ![pc1](https://github.com/Ajith101/shopping-cart/assets/41799543/ff550e22-8891-4246-a429-8102421c3ead) 6 | ![pc6](https://github.com/Ajith101/shopping-cart/assets/41799543/9720fe8d-4f46-421f-86db-ead81f525b2f) 7 | 8 | ## Table of Contents 9 | 10 | 1. [Demo](#demo) 11 | 2. [Features](#features) 12 | 3. [Technologies Used](#technologies-used) 13 | 4. [Installation](#installation) 14 | 5. [Screenshot](#screenshot) 15 | 16 | ## Demo 17 | 18 | You can check out a live demo of this project [here](https://shopping-cart-new-one.vercel.app). 19 | 20 | ## Features 21 | 22 | - User authentication (signup, login, logout). 23 | - Form validation using 24 | - Add products to the shopping cart. 25 | - Manage the shopping cart (add, remove, update items). 26 | - Product detail page. 27 | 28 | ## Technologies Used 29 | 30 | - Frontend: 31 | 32 | - React: A JavaScript library for building user interfaces. 33 | - Zustand: A state management library for managing application state with simplicity. 34 | - Tailwind: A CSS framework for responsive and modern UI design. 35 | - Axios: A popular JavaScript library for making HTTP requests. 36 | - Formik - For handling forms and form validation. 37 | - Yup - For schema validation with Formik. 38 | - React-Toastify - For displaying toast notifications in the application. 39 | - React-Icons - For including icons in the user interface. 40 | 41 | - Backend: 42 | - Node.js: A server-side JavaScript runtime environment. 43 | - Express: A web application framework for Node.js. 44 | - Cors: A middleware for enabling Cross-Origin Resource Sharing. 45 | - Dotenv: A module for loading environment variables from a .env file. 46 | - nodemon - For automatically restarting the server during development. 47 | - bcrypt - For hashing and securing passwords. 48 | - cookie-parser - For parsing cookies in HTTP requests. 49 | - cors - For handling Cross-Origin Resource Sharing. 50 | - jsonwebtoken - For generating and verifying JSON Web Tokens for user authentication. 51 | 52 | ## Installation 53 | 54 | - Clone the repository from GitHub. 55 | - Install Node.js and MongoDB on your system if you haven't already. 56 | - Run 57 | 58 | ``` 59 | npm install 60 | ``` 61 | 62 | in the root directory to install the required dependencies. 63 | 64 | - Configure the MongoDB connection string in the server configuration file. 65 | - Run 66 | 67 | ``` 68 | npm run dev 69 | ``` 70 | 71 | start to start the development server. 72 | 73 | ## Screenshot 74 | 75 | ![pc2](https://github.com/Ajith101/shopping-cart/assets/41799543/cfa92732-dc88-4646-93a1-31a3588bd94d) 76 | ![pc3](https://github.com/Ajith101/shopping-cart/assets/41799543/9cee429a-8ceb-460d-80fb-10eed6e276ea) 77 | ![pc4](https://github.com/Ajith101/shopping-cart/assets/41799543/efe9bfca-f628-4fb1-8044-6294e978e71b) 78 | ![pc5](https://github.com/Ajith101/shopping-cart/assets/41799543/c222d6af-3307-4518-a88f-52f834c43965) 79 | ![pc7](https://github.com/Ajith101/shopping-cart/assets/41799543/fb0f94f9-608a-40cd-9794-e8aaf63fcbf1) 80 | ![pc8](https://github.com/Ajith101/shopping-cart/assets/41799543/f8becfd8-2208-44a2-ae62-cebf36b5dce4) 81 | ![mobile (4)](https://github.com/Ajith101/shopping-cart/assets/41799543/77ae0083-eb70-49f6-891c-062cee2d9e6b) 82 | ![mobile (5)](https://github.com/Ajith101/shopping-cart/assets/41799543/4ca4e416-139c-4e33-acf4-a6129f2d8857) 83 | ![mobile (6)](https://github.com/Ajith101/shopping-cart/assets/41799543/912d6aee-50b1-46de-b5c9-3f453b154b52) 84 | ![mobile (7)](https://github.com/Ajith101/shopping-cart/assets/41799543/d5c513f9-efdd-48e6-aaf1-0c2363e227d5) 85 | -------------------------------------------------------------------------------- /frontend/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/pages/DetailPage.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Layout from "../layout/Layout"; 3 | import { useNavigate, useParams } from "react-router-dom"; 4 | import axios from "axios"; 5 | import { useAppStore } from "../../store/appStore"; 6 | 7 | const DetailPage = () => { 8 | const navigate = useNavigate(); 9 | const { addCart } = useAppStore(); 10 | const [singleProduct, setSingleProduct] = useState(null); 11 | const { id } = useParams(); 12 | 13 | const getSingleProduct = async () => { 14 | try { 15 | const { data, status } = await axios( 16 | `https://ecommerce-backend-new.vercel.app/api/products/${id}` 17 | ); 18 | setSingleProduct(data); 19 | } catch (error) { 20 | console.log(error); 21 | } 22 | }; 23 | 24 | useEffect(() => { 25 | if (id) { 26 | getSingleProduct(); 27 | } 28 | }, [id]); 29 | 30 | return ( 31 | 32 |
33 |
34 | <> 35 | {singleProduct ? ( 36 | <> 37 |
38 | 43 |
44 |
45 |
46 |

47 | {singleProduct?.category} 48 |

49 |

50 | {singleProduct?.title} 51 |

52 |
53 |
54 |

55 | {"₹ "} 56 | 57 | {Math.ceil(singleProduct?.price * 81)} 58 | 59 |

60 |

61 | Rating {": "} 62 | 63 | {singleProduct?.rating?.rate} 64 | 65 |

66 |
67 |

68 | {singleProduct?.description} 69 |

70 |

71 | Quantity :{" "} 72 | 73 | {singleProduct?.rating?.count} nos 74 | 75 |

76 |
77 | 80 | 86 |
87 |
88 | 89 | ) : ( 90 |
91 | No Itemes Found 92 |
93 | )} 94 | 95 |
96 |
97 |
98 | ); 99 | }; 100 | 101 | export default DetailPage; 102 | -------------------------------------------------------------------------------- /backend/controller/userController.js: -------------------------------------------------------------------------------- 1 | const asyncHandler = require("../middleware/asyncHandler"); 2 | const userModel = require("../model/userModel"); 3 | const cartModel = require("../model/cartModel"); 4 | const bcrypt = require("bcrypt"); 5 | const sendToken = require("../utils/jwt"); 6 | 7 | // /api/user/login 8 | const login = asyncHandler(async (req, res) => { 9 | const { email, password } = req.body; 10 | if (!email || !password) { 11 | res.status(401).json({ success: false, message: "Invalid Credential" }); 12 | } else { 13 | const isExist = await userModel.findOne({ email }); 14 | if (!isExist) { 15 | res.status(401).json({ success: false, message: "Invalid Credential" }); 16 | } 17 | const checkPassword = isExist.verifyPassword; 18 | if (checkPassword) { 19 | sendToken(isExist, res); 20 | } else { 21 | res.status(400).json({ success: false, message: "Invalid Credential" }); 22 | } 23 | } 24 | }); 25 | 26 | const register = asyncHandler(async (req, res) => { 27 | const { email, password, name } = req.body; 28 | if (!email || !password || !name) { 29 | res.status(401).json({ success: false, message: "Invalid credential" }); 30 | } 31 | const isExist = await userModel.findOne({ email }); 32 | if (!isExist) { 33 | const newUser = await userModel.create(req.body); 34 | sendToken(newUser, res); 35 | } else { 36 | res.status(400).json({ success: false, message: "Mail already exists" }); 37 | } 38 | }); 39 | 40 | const logout = asyncHandler(async (req, res) => { 41 | res.cookie("token", "", { httpOnly: true, expires: new Date(0) }); 42 | res.status(200).json({ message: "Logout successfully" }); 43 | }); 44 | 45 | const addCart = asyncHandler(async (req, res) => { 46 | const { userId } = req; 47 | const { id } = req.body.product; 48 | const cart = await cartModel.findOne({ user: userId }); 49 | if (cart) { 50 | const productExist = cart.cartItems.findIndex( 51 | (item) => item.product.id == id 52 | ); 53 | if (productExist !== -1) { 54 | await cartModel.findOneAndUpdate( 55 | { user: userId, "cartItems.product.id": id }, 56 | { $inc: { "cartItems.$.quantity": 1 } }, 57 | { new: true } 58 | ); 59 | const updatedProduct = await cartModel.findOne({ user: userId }); 60 | res.status(200).json({ 61 | message: "Added Cart", 62 | total: updatedProduct?.cartItems?.length, 63 | }); 64 | } else { 65 | const addNewProduct = await cartModel.findOneAndUpdate( 66 | { user: userId }, 67 | { $push: { cartItems: { product: { ...req.body.product } } } }, 68 | { new: true } 69 | ); 70 | res.status(200).json({ 71 | message: "Added Cart", 72 | total: addNewProduct?.cartItems?.length, 73 | }); 74 | } 75 | } else { 76 | const product = await cartModel.create({ 77 | user: userId, 78 | cartItems: [{ product: { ...req.body.product } }], 79 | }); 80 | res.status(200).json({ 81 | message: "Added Cart", 82 | total: product?.cartItems?.length, 83 | }); 84 | } 85 | }); 86 | 87 | const removeCart = asyncHandler(async (req, res) => { 88 | const { userId } = req; 89 | const { id } = req.body; 90 | const cart = await cartModel.findOne({ 91 | user: userId, 92 | "cartItems.product.id": id, 93 | }); 94 | if (cart) { 95 | const response = await cartModel.findOneAndUpdate( 96 | { 97 | user: userId, 98 | "cartItems.product.id": id, 99 | }, 100 | { $pull: { cartItems: { "product.id": id } } }, 101 | { new: true } 102 | ); 103 | res.status(200).json({ 104 | message: "Item removed from cart", 105 | total: response?.cartItems?.length, 106 | }); 107 | } else { 108 | res.status(404); 109 | throw new Error("item not found"); 110 | } 111 | }); 112 | 113 | const addCartQty = asyncHandler(async (req, res) => { 114 | const { userId } = req; 115 | const { productId } = req.body; 116 | const cart = await cartModel.findOne({ 117 | user: userId, 118 | "cartItems.product.id": productId, 119 | }); 120 | if (cart) { 121 | await cartModel.findOneAndUpdate( 122 | { "cartItems.product.id": productId }, 123 | { $inc: { "cartItems.$.quantity": 1 } }, 124 | { new: true } 125 | ); 126 | res.status(200).json({ message: "Added qty" }); 127 | } else { 128 | res.status(404); 129 | throw new Error("Item not found"); 130 | } 131 | }); 132 | 133 | const decreaseCartQty = asyncHandler(async (req, res) => { 134 | const { userId } = req; 135 | const { productId } = req.body; 136 | const cart = await cartModel.findOne({ 137 | user: userId, 138 | "cartItems.product.id": productId, 139 | }); 140 | if (cart) { 141 | await cartModel.findOneAndUpdate( 142 | { "cartItems.product.id": productId }, 143 | { $inc: { "cartItems.$.quantity": -1 } }, 144 | { new: true } 145 | ); 146 | res.status(200).json({ message: "Decreased qty" }); 147 | } else { 148 | res.status(404); 149 | throw new Error("Item not found"); 150 | } 151 | }); 152 | 153 | const getUserCart = asyncHandler(async (req, res) => { 154 | const { userId } = req; 155 | const cart = await cartModel.findOne({ user: userId }); 156 | if (!cart) { 157 | res.status(404); 158 | throw new Error("Item not found"); 159 | } else { 160 | res.status(200).json(cart); 161 | } 162 | }); 163 | 164 | const getCartNumber = asyncHandler(async (req, res) => { 165 | const { userId } = req; 166 | // console.log(userId); 167 | const resPonse = await cartModel.findOne({ user: userId }); 168 | if (resPonse) { 169 | res.status(200).json(resPonse?.cartItems.length); 170 | } else res.status(200).json(0); 171 | }); 172 | 173 | module.exports = { 174 | login, 175 | register, 176 | logout, 177 | addCart, 178 | removeCart, 179 | decreaseCartQty, 180 | addCartQty, 181 | getUserCart, 182 | getCartNumber, 183 | }; 184 | -------------------------------------------------------------------------------- /frontend/store/appStore.js: -------------------------------------------------------------------------------- 1 | import { create } from "zustand"; 2 | import API from "./../utils/axios"; 3 | import { toast } from "react-toastify"; 4 | 5 | const user = localStorage.getItem("user") 6 | ? JSON.parse(localStorage.getItem("user")) 7 | : null; 8 | 9 | export const useAppStore = create((set, get) => ({ 10 | user: user, 11 | loading: false, 12 | cart: null, 13 | totalCart: null, 14 | loginUser: async (details, navigate) => { 15 | try { 16 | set((state) => ({ loading: true })); 17 | const { data, status } = await API("/api/user/login", { 18 | method: "POST", 19 | data: { ...details }, 20 | }); 21 | if (status === 200) { 22 | toast.success("Login successfully"); 23 | set((state) => ({ loading: false, user: data.user })); 24 | localStorage.setItem("user", JSON.stringify(data.user)); 25 | navigate("/"); 26 | } 27 | } catch (error) { 28 | set((state) => ({ loading: false })); 29 | toast, error(error?.response?.data?.message); 30 | console.log(error); 31 | } 32 | }, 33 | registerUser: async (details, navigate) => { 34 | try { 35 | set(() => ({ loading: true })); 36 | const { data, status } = await API("/api/user/register", { 37 | method: "POST", 38 | data: { ...details }, 39 | }); 40 | 41 | if (status === 200) { 42 | set(() => ({ loading: false, user: data.user })); 43 | localStorage.setItem("user", JSON.stringify(data.user)); 44 | navigate("/"); 45 | toast.success("Register successfully"); 46 | } 47 | } catch (error) { 48 | set((state) => ({ loading: false })); 49 | toast, error(error?.response?.data?.message); 50 | console.log(error); 51 | } 52 | }, 53 | 54 | addCart: async (product, navigate) => { 55 | try { 56 | set((state) => ({ loading: true })); 57 | const { data, status } = await API("/api/user/add-cart", { 58 | method: "POST", 59 | data: { 60 | product: { ...product }, 61 | }, 62 | }); 63 | if (status === 200) { 64 | toast.success("Added to cart successfully"); 65 | set((state) => ({ 66 | loading: false, 67 | totalCart: data.total, 68 | })); 69 | } 70 | } catch (error) { 71 | set((state) => ({ loading: false })); 72 | if (error?.response?.status === 401) { 73 | navigate("/login"); 74 | } 75 | toast.error(error?.response?.data?.message); 76 | console.log(error); 77 | } 78 | }, 79 | 80 | addCartQty: async (id) => { 81 | try { 82 | set((state) => ({ loading: true })); 83 | const { data, status } = await API("/api/user/add-qty", { 84 | method: "POST", 85 | data: { productId: id }, 86 | }); 87 | if (status === 200) { 88 | toast.success("Added to cart successfully"); 89 | let cart = get().cart; 90 | const updatedCart = cart.map((item) => 91 | item.product.id === id 92 | ? { ...item, quantity: item.quantity + 1 } 93 | : item 94 | ); 95 | set((state) => ({ 96 | loading: false, 97 | cart: updatedCart, 98 | })); 99 | // set((state) => ({ loading: false, cart: [...state.cart.] })); 100 | } 101 | } catch (error) { 102 | set((state) => ({ loading: false })); 103 | toast.error(error?.response?.data?.message); 104 | console.log(error); 105 | } 106 | }, 107 | removeCartQty: async (id) => { 108 | try { 109 | set((state) => ({ loading: true })); 110 | const { data, status } = await API("/api/user/decrease-qty", { 111 | method: "POST", 112 | data: { productId: id }, 113 | }); 114 | if (status === 200) { 115 | toast.success("Added to cart successfully"); 116 | let cart = get().cart; 117 | const updatedCart = cart.map((item) => 118 | item.product.id === id 119 | ? { ...item, quantity: item.quantity - 1 } 120 | : item 121 | ); 122 | set((state) => ({ 123 | loading: false, 124 | cart: updatedCart, 125 | })); 126 | // set((state) => ({ loading: false, cart: [...state.cart.] })); 127 | } 128 | } catch (error) { 129 | toast.error(error?.response?.data?.message); 130 | console.log(error); 131 | set((state) => ({ loading: false })); 132 | } 133 | }, 134 | 135 | getUserCart: async () => { 136 | try { 137 | set((state) => ({ loading: true })); 138 | const { data, status } = await API("/api/user/get-user-cart"); 139 | if (status === 200) { 140 | set((state) => ({ cart: data.cartItems, loading: false })); 141 | } 142 | } catch (error) { 143 | set((state) => ({ loading: false })); 144 | toast.error(error?.response?.data?.message); 145 | console.log(error); 146 | } 147 | }, 148 | // getUserCart: async () => { 149 | // try { 150 | // set((state) => ({ loading: true })); 151 | // const { data, status } = await API("/api/user/get-user-cart"); 152 | // if (status === 200) { 153 | // set((state) => ({ cart: data.cartItems, loading: false })); 154 | // } 155 | // } catch (error) { 156 | // set((state) => ({ loading: false })); 157 | // toast.error(error?.response?.data?.message); 158 | // console.log(error); 159 | // } 160 | // }, 161 | 162 | removeCart: async (id) => { 163 | try { 164 | set((state) => ({ loading: true })); 165 | const { data, status } = await API("/api/user/remove-cart", { 166 | method: "DELETE", 167 | data: { id }, 168 | }); 169 | if (status === 200) { 170 | toast.success("Item removed successfully"); 171 | let cart = get().cart; 172 | const updatedCart = cart.filter((item) => item.product.id !== id); 173 | set((state) => ({ 174 | loading: false, 175 | cart: updatedCart, 176 | totalCart: data.total, 177 | })); 178 | } 179 | } catch (error) { 180 | set((state) => ({ loading: false })); 181 | toast.error(error?.response?.data?.message); 182 | console.log(error); 183 | } 184 | }, 185 | 186 | logout: async (navigate, setShowMenu) => { 187 | try { 188 | set(() => ({ loading: true })); 189 | const { status } = await API("/api/user/logout", { 190 | method: "POST", 191 | }); 192 | 193 | if (status === 200) { 194 | setShowMenu(false); 195 | set(() => ({ loading: false, user: null })); 196 | localStorage.clear(); 197 | navigate("/"); 198 | toast.success("Logged out successfully"); 199 | } 200 | } catch (error) { 201 | set((state) => ({ loading: false })); 202 | toast, error(error?.response?.data?.message); 203 | console.log(error); 204 | } 205 | }, 206 | })); 207 | -------------------------------------------------------------------------------- /backend/data/products.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "title": "iPhone 9", 5 | "description": "An apple mobile which is nothing like apple", 6 | "price": 549, 7 | "discountPercentage": 12.96, 8 | "rating": 4.69, 9 | "stock": 94, 10 | "brand": "Apple", 11 | "category": "smartphones", 12 | "thumbnail": "https://i.dummyjson.com/data/products/1/thumbnail.jpg", 13 | "images": [ 14 | "https://i.dummyjson.com/data/products/1/1.jpg", 15 | "https://i.dummyjson.com/data/products/1/2.jpg", 16 | "https://i.dummyjson.com/data/products/1/3.jpg", 17 | "https://i.dummyjson.com/data/products/1/4.jpg", 18 | "https://i.dummyjson.com/data/products/1/thumbnail.jpg" 19 | ] 20 | }, 21 | { 22 | "id": 2, 23 | "title": "iPhone X", 24 | "description": "SIM-Free, Model A19211 6.5-inch Super Retina HD display with OLED technology A12 Bionic chip with ...", 25 | "price": 899, 26 | "discountPercentage": 17.94, 27 | "rating": 4.44, 28 | "stock": 34, 29 | "brand": "Apple", 30 | "category": "smartphones", 31 | "thumbnail": "https://i.dummyjson.com/data/products/2/thumbnail.jpg", 32 | "images": [ 33 | "https://i.dummyjson.com/data/products/2/1.jpg", 34 | "https://i.dummyjson.com/data/products/2/2.jpg", 35 | "https://i.dummyjson.com/data/products/2/3.jpg", 36 | "https://i.dummyjson.com/data/products/2/thumbnail.jpg" 37 | ] 38 | }, 39 | { 40 | "id": 3, 41 | "title": "Samsung Universe 9", 42 | "description": "Samsung's new variant which goes beyond Galaxy to the Universe", 43 | "price": 1249, 44 | "discountPercentage": 15.46, 45 | "rating": 4.09, 46 | "stock": 36, 47 | "brand": "Samsung", 48 | "category": "smartphones", 49 | "thumbnail": "https://i.dummyjson.com/data/products/3/thumbnail.jpg", 50 | "images": ["https://i.dummyjson.com/data/products/3/1.jpg"] 51 | }, 52 | { 53 | "id": 4, 54 | "title": "OPPOF19", 55 | "description": "OPPO F19 is officially announced on April 2021.", 56 | "price": 280, 57 | "discountPercentage": 17.91, 58 | "rating": 4.3, 59 | "stock": 123, 60 | "brand": "OPPO", 61 | "category": "smartphones", 62 | "thumbnail": "https://i.dummyjson.com/data/products/4/thumbnail.jpg", 63 | "images": [ 64 | "https://i.dummyjson.com/data/products/4/1.jpg", 65 | "https://i.dummyjson.com/data/products/4/2.jpg", 66 | "https://i.dummyjson.com/data/products/4/3.jpg", 67 | "https://i.dummyjson.com/data/products/4/4.jpg", 68 | "https://i.dummyjson.com/data/products/4/thumbnail.jpg" 69 | ] 70 | }, 71 | { 72 | "id": 5, 73 | "title": "Huawei P30", 74 | "description": "Huawei’s re-badged P30 Pro New Edition was officially unveiled yesterday in Germany and now the device has made its way to the UK.", 75 | "price": 499, 76 | "discountPercentage": 10.58, 77 | "rating": 4.09, 78 | "stock": 32, 79 | "brand": "Huawei", 80 | "category": "smartphones", 81 | "thumbnail": "https://i.dummyjson.com/data/products/5/thumbnail.jpg", 82 | "images": [ 83 | "https://i.dummyjson.com/data/products/5/1.jpg", 84 | "https://i.dummyjson.com/data/products/5/2.jpg", 85 | "https://i.dummyjson.com/data/products/5/3.jpg" 86 | ] 87 | }, 88 | { 89 | "id": 6, 90 | "title": "MacBook Pro", 91 | "description": "MacBook Pro 2021 with mini-LED display may launch between September, November", 92 | "price": 1749, 93 | "discountPercentage": 11.02, 94 | "rating": 4.57, 95 | "stock": 83, 96 | "brand": "Apple", 97 | "category": "laptops", 98 | "thumbnail": "https://i.dummyjson.com/data/products/6/thumbnail.png", 99 | "images": [ 100 | "https://i.dummyjson.com/data/products/6/1.png", 101 | "https://i.dummyjson.com/data/products/6/2.jpg", 102 | "https://i.dummyjson.com/data/products/6/3.png", 103 | "https://i.dummyjson.com/data/products/6/4.jpg" 104 | ] 105 | }, 106 | { 107 | "id": 7, 108 | "title": "Samsung Galaxy Book", 109 | "description": "Samsung Galaxy Book S (2020) Laptop With Intel Lakefield Chip, 8GB of RAM Launched", 110 | "price": 1499, 111 | "discountPercentage": 4.15, 112 | "rating": 4.25, 113 | "stock": 50, 114 | "brand": "Samsung", 115 | "category": "laptops", 116 | "thumbnail": "https://i.dummyjson.com/data/products/7/thumbnail.jpg", 117 | "images": [ 118 | "https://i.dummyjson.com/data/products/7/1.jpg", 119 | "https://i.dummyjson.com/data/products/7/2.jpg", 120 | "https://i.dummyjson.com/data/products/7/3.jpg", 121 | "https://i.dummyjson.com/data/products/7/thumbnail.jpg" 122 | ] 123 | }, 124 | { 125 | "id": 8, 126 | "title": "Microsoft Surface Laptop 4", 127 | "description": "Style and speed. Stand out on HD video calls backed by Studio Mics. Capture ideas on the vibrant touchscreen.", 128 | "price": 1499, 129 | "discountPercentage": 10.23, 130 | "rating": 4.43, 131 | "stock": 68, 132 | "brand": "Microsoft Surface", 133 | "category": "laptops", 134 | "thumbnail": "https://i.dummyjson.com/data/products/8/thumbnail.jpg", 135 | "images": [ 136 | "https://i.dummyjson.com/data/products/8/1.jpg", 137 | "https://i.dummyjson.com/data/products/8/2.jpg", 138 | "https://i.dummyjson.com/data/products/8/3.jpg", 139 | "https://i.dummyjson.com/data/products/8/4.jpg", 140 | "https://i.dummyjson.com/data/products/8/thumbnail.jpg" 141 | ] 142 | }, 143 | { 144 | "id": 9, 145 | "title": "Infinix INBOOK", 146 | "description": "Infinix Inbook X1 Ci3 10th 8GB 256GB 14 Win10 Grey – 1 Year Warranty", 147 | "price": 1099, 148 | "discountPercentage": 11.83, 149 | "rating": 4.54, 150 | "stock": 96, 151 | "brand": "Infinix", 152 | "category": "laptops", 153 | "thumbnail": "https://i.dummyjson.com/data/products/9/thumbnail.jpg", 154 | "images": [ 155 | "https://i.dummyjson.com/data/products/9/1.jpg", 156 | "https://i.dummyjson.com/data/products/9/2.png", 157 | "https://i.dummyjson.com/data/products/9/3.png", 158 | "https://i.dummyjson.com/data/products/9/4.jpg", 159 | "https://i.dummyjson.com/data/products/9/thumbnail.jpg" 160 | ] 161 | }, 162 | { 163 | "id": 10, 164 | "title": "HP Pavilion 15-DK1056WM", 165 | "description": "HP Pavilion 15-DK1056WM Gaming Laptop 10th Gen Core i5, 8GB, 256GB SSD, GTX 1650 4GB, Windows 10", 166 | "price": 1099, 167 | "discountPercentage": 6.18, 168 | "rating": 4.43, 169 | "stock": 89, 170 | "brand": "HP Pavilion", 171 | "category": "laptops", 172 | "thumbnail": "https://i.dummyjson.com/data/products/10/thumbnail.jpeg", 173 | "images": [ 174 | "https://i.dummyjson.com/data/products/10/1.jpg", 175 | "https://i.dummyjson.com/data/products/10/2.jpg", 176 | "https://i.dummyjson.com/data/products/10/3.jpg", 177 | "https://i.dummyjson.com/data/products/10/thumbnail.jpeg" 178 | ] 179 | }, 180 | { 181 | "id": 11, 182 | "title": "perfume Oil", 183 | "description": "Mega Discount, Impression of Acqua Di Gio by GiorgioArmani concentrated attar perfume Oil", 184 | "price": 13, 185 | "discountPercentage": 8.4, 186 | "rating": 4.26, 187 | "stock": 65, 188 | "brand": "Impression of Acqua Di Gio", 189 | "category": "fragrances", 190 | "thumbnail": "https://i.dummyjson.com/data/products/11/thumbnail.jpg", 191 | "images": [ 192 | "https://i.dummyjson.com/data/products/11/1.jpg", 193 | "https://i.dummyjson.com/data/products/11/2.jpg", 194 | "https://i.dummyjson.com/data/products/11/3.jpg", 195 | "https://i.dummyjson.com/data/products/11/thumbnail.jpg" 196 | ] 197 | }, 198 | { 199 | "id": 12, 200 | "title": "Brown Perfume", 201 | "description": "Royal_Mirage Sport Brown Perfume for Men & Women - 120ml", 202 | "price": 40, 203 | "discountPercentage": 15.66, 204 | "rating": 4, 205 | "stock": 52, 206 | "brand": "Royal_Mirage", 207 | "category": "fragrances", 208 | "thumbnail": "https://i.dummyjson.com/data/products/12/thumbnail.jpg", 209 | "images": [ 210 | "https://i.dummyjson.com/data/products/12/1.jpg", 211 | "https://i.dummyjson.com/data/products/12/2.jpg", 212 | "https://i.dummyjson.com/data/products/12/3.png", 213 | "https://i.dummyjson.com/data/products/12/4.jpg", 214 | "https://i.dummyjson.com/data/products/12/thumbnail.jpg" 215 | ] 216 | }, 217 | { 218 | "id": 13, 219 | "title": "Fog Scent Xpressio Perfume", 220 | "description": "Product details of Best Fog Scent Xpressio Perfume 100ml For Men cool long lasting perfumes for Men", 221 | "price": 13, 222 | "discountPercentage": 8.14, 223 | "rating": 4.59, 224 | "stock": 61, 225 | "brand": "Fog Scent Xpressio", 226 | "category": "fragrances", 227 | "thumbnail": "https://i.dummyjson.com/data/products/13/thumbnail.webp", 228 | "images": [ 229 | "https://i.dummyjson.com/data/products/13/1.jpg", 230 | "https://i.dummyjson.com/data/products/13/2.png", 231 | "https://i.dummyjson.com/data/products/13/3.jpg", 232 | "https://i.dummyjson.com/data/products/13/4.jpg", 233 | "https://i.dummyjson.com/data/products/13/thumbnail.webp" 234 | ] 235 | }, 236 | { 237 | "id": 14, 238 | "title": "Non-Alcoholic Concentrated Perfume Oil", 239 | "description": "Original Al Munakh® by Mahal Al Musk | Our Impression of Climate | 6ml Non-Alcoholic Concentrated Perfume Oil", 240 | "price": 120, 241 | "discountPercentage": 15.6, 242 | "rating": 4.21, 243 | "stock": 114, 244 | "brand": "Al Munakh", 245 | "category": "fragrances", 246 | "thumbnail": "https://i.dummyjson.com/data/products/14/thumbnail.jpg", 247 | "images": [ 248 | "https://i.dummyjson.com/data/products/14/1.jpg", 249 | "https://i.dummyjson.com/data/products/14/2.jpg", 250 | "https://i.dummyjson.com/data/products/14/3.jpg", 251 | "https://i.dummyjson.com/data/products/14/thumbnail.jpg" 252 | ] 253 | }, 254 | { 255 | "id": 15, 256 | "title": "Eau De Perfume Spray", 257 | "description": "Genuine Al-Rehab spray perfume from UAE/Saudi Arabia/Yemen High Quality", 258 | "price": 30, 259 | "discountPercentage": 10.99, 260 | "rating": 4.7, 261 | "stock": 105, 262 | "brand": "Lord - Al-Rehab", 263 | "category": "fragrances", 264 | "thumbnail": "https://i.dummyjson.com/data/products/15/thumbnail.jpg", 265 | "images": [ 266 | "https://i.dummyjson.com/data/products/15/1.jpg", 267 | "https://i.dummyjson.com/data/products/15/2.jpg", 268 | "https://i.dummyjson.com/data/products/15/3.jpg", 269 | "https://i.dummyjson.com/data/products/15/4.jpg", 270 | "https://i.dummyjson.com/data/products/15/thumbnail.jpg" 271 | ] 272 | }, 273 | { 274 | "id": 16, 275 | "title": "Hyaluronic Acid Serum", 276 | "description": "L'Oréal Paris introduces Hyaluron Expert Replumping Serum formulated with 1.5% Hyaluronic Acid", 277 | "price": 19, 278 | "discountPercentage": 13.31, 279 | "rating": 4.83, 280 | "stock": 110, 281 | "brand": "L'Oreal Paris", 282 | "category": "skincare", 283 | "thumbnail": "https://i.dummyjson.com/data/products/16/thumbnail.jpg", 284 | "images": [ 285 | "https://i.dummyjson.com/data/products/16/1.png", 286 | "https://i.dummyjson.com/data/products/16/2.webp", 287 | "https://i.dummyjson.com/data/products/16/3.jpg", 288 | "https://i.dummyjson.com/data/products/16/4.jpg", 289 | "https://i.dummyjson.com/data/products/16/thumbnail.jpg" 290 | ] 291 | }, 292 | { 293 | "id": 17, 294 | "title": "Tree Oil 30ml", 295 | "description": "Tea tree oil contains a number of compounds, including terpinen-4-ol, that have been shown to kill certain bacteria,", 296 | "price": 12, 297 | "discountPercentage": 4.09, 298 | "rating": 4.52, 299 | "stock": 78, 300 | "brand": "Hemani Tea", 301 | "category": "skincare", 302 | "thumbnail": "https://i.dummyjson.com/data/products/17/thumbnail.jpg", 303 | "images": [ 304 | "https://i.dummyjson.com/data/products/17/1.jpg", 305 | "https://i.dummyjson.com/data/products/17/2.jpg", 306 | "https://i.dummyjson.com/data/products/17/3.jpg", 307 | "https://i.dummyjson.com/data/products/17/thumbnail.jpg" 308 | ] 309 | }, 310 | { 311 | "id": 18, 312 | "title": "Oil Free Moisturizer 100ml", 313 | "description": "Dermive Oil Free Moisturizer with SPF 20 is specifically formulated with ceramides, hyaluronic acid & sunscreen.", 314 | "price": 40, 315 | "discountPercentage": 13.1, 316 | "rating": 4.56, 317 | "stock": 88, 318 | "brand": "Dermive", 319 | "category": "skincare", 320 | "thumbnail": "https://i.dummyjson.com/data/products/18/thumbnail.jpg", 321 | "images": [ 322 | "https://i.dummyjson.com/data/products/18/1.jpg", 323 | "https://i.dummyjson.com/data/products/18/2.jpg", 324 | "https://i.dummyjson.com/data/products/18/3.jpg", 325 | "https://i.dummyjson.com/data/products/18/4.jpg", 326 | "https://i.dummyjson.com/data/products/18/thumbnail.jpg" 327 | ] 328 | }, 329 | { 330 | "id": 19, 331 | "title": "Skin Beauty Serum.", 332 | "description": "Product name: rorec collagen hyaluronic acid white face serum riceNet weight: 15 m", 333 | "price": 46, 334 | "discountPercentage": 10.68, 335 | "rating": 4.42, 336 | "stock": 54, 337 | "brand": "ROREC White Rice", 338 | "category": "skincare", 339 | "thumbnail": "https://i.dummyjson.com/data/products/19/thumbnail.jpg", 340 | "images": [ 341 | "https://i.dummyjson.com/data/products/19/1.jpg", 342 | "https://i.dummyjson.com/data/products/19/2.jpg", 343 | "https://i.dummyjson.com/data/products/19/3.png", 344 | "https://i.dummyjson.com/data/products/19/thumbnail.jpg" 345 | ] 346 | }, 347 | { 348 | "id": 20, 349 | "title": "Freckle Treatment Cream- 15gm", 350 | "description": "Fair & Clear is Pakistan's only pure Freckle cream which helpsfade Freckles, Darkspots and pigments. Mercury level is 0%, so there are no side effects.", 351 | "price": 70, 352 | "discountPercentage": 16.99, 353 | "rating": 4.06, 354 | "stock": 140, 355 | "brand": "Fair & Clear", 356 | "category": "skincare", 357 | "thumbnail": "https://i.dummyjson.com/data/products/20/thumbnail.jpg", 358 | "images": [ 359 | "https://i.dummyjson.com/data/products/20/1.jpg", 360 | "https://i.dummyjson.com/data/products/20/2.jpg", 361 | "https://i.dummyjson.com/data/products/20/3.jpg", 362 | "https://i.dummyjson.com/data/products/20/4.jpg", 363 | "https://i.dummyjson.com/data/products/20/thumbnail.jpg" 364 | ] 365 | }, 366 | { 367 | "id": 21, 368 | "title": "- Daal Masoor 500 grams", 369 | "description": "Fine quality Branded Product Keep in a cool and dry place", 370 | "price": 20, 371 | "discountPercentage": 4.81, 372 | "rating": 4.44, 373 | "stock": 133, 374 | "brand": "Saaf & Khaas", 375 | "category": "groceries", 376 | "thumbnail": "https://i.dummyjson.com/data/products/21/thumbnail.png", 377 | "images": [ 378 | "https://i.dummyjson.com/data/products/21/1.png", 379 | "https://i.dummyjson.com/data/products/21/2.jpg", 380 | "https://i.dummyjson.com/data/products/21/3.jpg" 381 | ] 382 | }, 383 | { 384 | "id": 22, 385 | "title": "Elbow Macaroni - 400 gm", 386 | "description": "Product details of Bake Parlor Big Elbow Macaroni - 400 gm", 387 | "price": 14, 388 | "discountPercentage": 15.58, 389 | "rating": 4.57, 390 | "stock": 146, 391 | "brand": "Bake Parlor Big", 392 | "category": "groceries", 393 | "thumbnail": "https://i.dummyjson.com/data/products/22/thumbnail.jpg", 394 | "images": [ 395 | "https://i.dummyjson.com/data/products/22/1.jpg", 396 | "https://i.dummyjson.com/data/products/22/2.jpg", 397 | "https://i.dummyjson.com/data/products/22/3.jpg" 398 | ] 399 | }, 400 | { 401 | "id": 23, 402 | "title": "Orange Essence Food Flavou", 403 | "description": "Specifications of Orange Essence Food Flavour For Cakes and Baking Food Item", 404 | "price": 14, 405 | "discountPercentage": 8.04, 406 | "rating": 4.85, 407 | "stock": 26, 408 | "brand": "Baking Food Items", 409 | "category": "groceries", 410 | "thumbnail": "https://i.dummyjson.com/data/products/23/thumbnail.jpg", 411 | "images": [ 412 | "https://i.dummyjson.com/data/products/23/1.jpg", 413 | "https://i.dummyjson.com/data/products/23/2.jpg", 414 | "https://i.dummyjson.com/data/products/23/3.jpg", 415 | "https://i.dummyjson.com/data/products/23/4.jpg", 416 | "https://i.dummyjson.com/data/products/23/thumbnail.jpg" 417 | ] 418 | }, 419 | { 420 | "id": 24, 421 | "title": "cereals muesli fruit nuts", 422 | "description": "original fauji cereal muesli 250gm box pack original fauji cereals muesli fruit nuts flakes breakfast cereal break fast faujicereals cerels cerel foji fouji", 423 | "price": 46, 424 | "discountPercentage": 16.8, 425 | "rating": 4.94, 426 | "stock": 113, 427 | "brand": "fauji", 428 | "category": "groceries", 429 | "thumbnail": "https://i.dummyjson.com/data/products/24/thumbnail.jpg", 430 | "images": [ 431 | "https://i.dummyjson.com/data/products/24/1.jpg", 432 | "https://i.dummyjson.com/data/products/24/2.jpg", 433 | "https://i.dummyjson.com/data/products/24/3.jpg", 434 | "https://i.dummyjson.com/data/products/24/4.jpg", 435 | "https://i.dummyjson.com/data/products/24/thumbnail.jpg" 436 | ] 437 | }, 438 | { 439 | "id": 25, 440 | "title": "Gulab Powder 50 Gram", 441 | "description": "Dry Rose Flower Powder Gulab Powder 50 Gram • Treats Wounds", 442 | "price": 70, 443 | "discountPercentage": 13.58, 444 | "rating": 4.87, 445 | "stock": 47, 446 | "brand": "Dry Rose", 447 | "category": "groceries", 448 | "thumbnail": "https://i.dummyjson.com/data/products/25/thumbnail.jpg", 449 | "images": [ 450 | "https://i.dummyjson.com/data/products/25/1.png", 451 | "https://i.dummyjson.com/data/products/25/2.jpg", 452 | "https://i.dummyjson.com/data/products/25/3.png", 453 | "https://i.dummyjson.com/data/products/25/4.jpg", 454 | "https://i.dummyjson.com/data/products/25/thumbnail.jpg" 455 | ] 456 | }, 457 | { 458 | "id": 26, 459 | "title": "Plant Hanger For Home", 460 | "description": "Boho Decor Plant Hanger For Home Wall Decoration Macrame Wall Hanging Shelf", 461 | "price": 41, 462 | "discountPercentage": 17.86, 463 | "rating": 4.08, 464 | "stock": 131, 465 | "brand": "Boho Decor", 466 | "category": "home-decoration", 467 | "thumbnail": "https://i.dummyjson.com/data/products/26/thumbnail.jpg", 468 | "images": [ 469 | "https://i.dummyjson.com/data/products/26/1.jpg", 470 | "https://i.dummyjson.com/data/products/26/2.jpg", 471 | "https://i.dummyjson.com/data/products/26/3.jpg", 472 | "https://i.dummyjson.com/data/products/26/4.jpg", 473 | "https://i.dummyjson.com/data/products/26/5.jpg", 474 | "https://i.dummyjson.com/data/products/26/thumbnail.jpg" 475 | ] 476 | }, 477 | { 478 | "id": 27, 479 | "title": "Flying Wooden Bird", 480 | "description": "Package Include 6 Birds with Adhesive Tape Shape: 3D Shaped Wooden Birds Material: Wooden MDF, Laminated 3.5mm", 481 | "price": 51, 482 | "discountPercentage": 15.58, 483 | "rating": 4.41, 484 | "stock": 17, 485 | "brand": "Flying Wooden", 486 | "category": "home-decoration", 487 | "thumbnail": "https://i.dummyjson.com/data/products/27/thumbnail.webp", 488 | "images": [ 489 | "https://i.dummyjson.com/data/products/27/1.jpg", 490 | "https://i.dummyjson.com/data/products/27/2.jpg", 491 | "https://i.dummyjson.com/data/products/27/3.jpg", 492 | "https://i.dummyjson.com/data/products/27/4.jpg", 493 | "https://i.dummyjson.com/data/products/27/thumbnail.webp" 494 | ] 495 | }, 496 | { 497 | "id": 28, 498 | "title": "3D Embellishment Art Lamp", 499 | "description": "3D led lamp sticker Wall sticker 3d wall art light on/off button cell operated (included)", 500 | "price": 20, 501 | "discountPercentage": 16.49, 502 | "rating": 4.82, 503 | "stock": 54, 504 | "brand": "LED Lights", 505 | "category": "home-decoration", 506 | "thumbnail": "https://i.dummyjson.com/data/products/28/thumbnail.jpg", 507 | "images": [ 508 | "https://i.dummyjson.com/data/products/28/1.jpg", 509 | "https://i.dummyjson.com/data/products/28/2.jpg", 510 | "https://i.dummyjson.com/data/products/28/3.png", 511 | "https://i.dummyjson.com/data/products/28/4.jpg", 512 | "https://i.dummyjson.com/data/products/28/thumbnail.jpg" 513 | ] 514 | }, 515 | { 516 | "id": 29, 517 | "title": "Handcraft Chinese style", 518 | "description": "Handcraft Chinese style art luxury palace hotel villa mansion home decor ceramic vase with brass fruit plate", 519 | "price": 60, 520 | "discountPercentage": 15.34, 521 | "rating": 4.44, 522 | "stock": 7, 523 | "brand": "luxury palace", 524 | "category": "home-decoration", 525 | "thumbnail": "https://i.dummyjson.com/data/products/29/thumbnail.webp", 526 | "images": [ 527 | "https://i.dummyjson.com/data/products/29/1.jpg", 528 | "https://i.dummyjson.com/data/products/29/2.jpg", 529 | "https://i.dummyjson.com/data/products/29/3.webp", 530 | "https://i.dummyjson.com/data/products/29/4.webp", 531 | "https://i.dummyjson.com/data/products/29/thumbnail.webp" 532 | ] 533 | }, 534 | { 535 | "id": 30, 536 | "title": "Key Holder", 537 | "description": "Attractive DesignMetallic materialFour key hooksReliable & DurablePremium Quality", 538 | "price": 30, 539 | "discountPercentage": 2.92, 540 | "rating": 4.92, 541 | "stock": 54, 542 | "brand": "Golden", 543 | "category": "home-decoration", 544 | "thumbnail": "https://i.dummyjson.com/data/products/30/thumbnail.jpg", 545 | "images": [ 546 | "https://i.dummyjson.com/data/products/30/1.jpg", 547 | "https://i.dummyjson.com/data/products/30/2.jpg", 548 | "https://i.dummyjson.com/data/products/30/3.jpg", 549 | "https://i.dummyjson.com/data/products/30/thumbnail.jpg" 550 | ] 551 | }, 552 | { 553 | "id": 31, 554 | "title": "Mornadi Velvet Bed", 555 | "description": "Mornadi Velvet Bed Base with Headboard Slats Support Classic Style Bedroom Furniture Bed Set", 556 | "price": 40, 557 | "discountPercentage": 17, 558 | "rating": 4.16, 559 | "stock": 140, 560 | "brand": "Furniture Bed Set", 561 | "category": "furniture", 562 | "thumbnail": "https://i.dummyjson.com/data/products/31/thumbnail.jpg", 563 | "images": [ 564 | "https://i.dummyjson.com/data/products/31/1.jpg", 565 | "https://i.dummyjson.com/data/products/31/2.jpg", 566 | "https://i.dummyjson.com/data/products/31/3.jpg", 567 | "https://i.dummyjson.com/data/products/31/4.jpg", 568 | "https://i.dummyjson.com/data/products/31/thumbnail.jpg" 569 | ] 570 | }, 571 | { 572 | "id": 32, 573 | "title": "Sofa for Coffe Cafe", 574 | "description": "Ratttan Outdoor furniture Set Waterproof Rattan Sofa for Coffe Cafe", 575 | "price": 50, 576 | "discountPercentage": 15.59, 577 | "rating": 4.74, 578 | "stock": 30, 579 | "brand": "Ratttan Outdoor", 580 | "category": "furniture", 581 | "thumbnail": "https://i.dummyjson.com/data/products/32/thumbnail.jpg", 582 | "images": [ 583 | "https://i.dummyjson.com/data/products/32/1.jpg", 584 | "https://i.dummyjson.com/data/products/32/2.jpg", 585 | "https://i.dummyjson.com/data/products/32/3.jpg", 586 | "https://i.dummyjson.com/data/products/32/thumbnail.jpg" 587 | ] 588 | }, 589 | { 590 | "id": 33, 591 | "title": "3 Tier Corner Shelves", 592 | "description": "3 Tier Corner Shelves | 3 PCs Wall Mount Kitchen Shelf | Floating Bedroom Shelf", 593 | "price": 700, 594 | "discountPercentage": 17, 595 | "rating": 4.31, 596 | "stock": 106, 597 | "brand": "Kitchen Shelf", 598 | "category": "furniture", 599 | "thumbnail": "https://i.dummyjson.com/data/products/33/thumbnail.jpg", 600 | "images": [ 601 | "https://i.dummyjson.com/data/products/33/1.jpg", 602 | "https://i.dummyjson.com/data/products/33/2.jpg", 603 | "https://i.dummyjson.com/data/products/33/3.jpg", 604 | "https://i.dummyjson.com/data/products/33/4.jpg", 605 | "https://i.dummyjson.com/data/products/33/thumbnail.jpg" 606 | ] 607 | }, 608 | { 609 | "id": 34, 610 | "title": "Plastic Table", 611 | "description": "Very good quality plastic table for multi purpose now in reasonable price", 612 | "price": 50, 613 | "discountPercentage": 4, 614 | "rating": 4.01, 615 | "stock": 136, 616 | "brand": "Multi Purpose", 617 | "category": "furniture", 618 | "thumbnail": "https://i.dummyjson.com/data/products/34/thumbnail.jpg", 619 | "images": [ 620 | "https://i.dummyjson.com/data/products/34/1.jpg", 621 | "https://i.dummyjson.com/data/products/34/2.jpg", 622 | "https://i.dummyjson.com/data/products/34/3.jpg", 623 | "https://i.dummyjson.com/data/products/34/4.jpg", 624 | "https://i.dummyjson.com/data/products/34/thumbnail.jpg" 625 | ] 626 | }, 627 | { 628 | "id": 35, 629 | "title": "3 DOOR PORTABLE", 630 | "description": "Material: Stainless Steel and Fabric Item Size: 110 cm x 45 cm x 175 cm Package Contents: 1 Storage Wardrobe", 631 | "price": 41, 632 | "discountPercentage": 7.98, 633 | "rating": 4.06, 634 | "stock": 68, 635 | "brand": "AmnaMart", 636 | "category": "furniture", 637 | "thumbnail": "https://i.dummyjson.com/data/products/35/thumbnail.jpg", 638 | "images": [ 639 | "https://i.dummyjson.com/data/products/35/1.jpg", 640 | "https://i.dummyjson.com/data/products/35/2.jpg", 641 | "https://i.dummyjson.com/data/products/35/3.jpg", 642 | "https://i.dummyjson.com/data/products/35/4.jpg", 643 | "https://i.dummyjson.com/data/products/35/thumbnail.jpg" 644 | ] 645 | }, 646 | { 647 | "id": 36, 648 | "title": "Sleeve Shirt Womens", 649 | "description": "Cotton Solid Color Professional Wear Sleeve Shirt Womens Work Blouses Wholesale Clothing Casual Plain Custom Top OEM Customized", 650 | "price": 90, 651 | "discountPercentage": 10.89, 652 | "rating": 4.26, 653 | "stock": 39, 654 | "brand": "Professional Wear", 655 | "category": "tops", 656 | "thumbnail": "https://i.dummyjson.com/data/products/36/thumbnail.jpg", 657 | "images": [ 658 | "https://i.dummyjson.com/data/products/36/1.jpg", 659 | "https://i.dummyjson.com/data/products/36/2.webp", 660 | "https://i.dummyjson.com/data/products/36/3.webp", 661 | "https://i.dummyjson.com/data/products/36/4.jpg", 662 | "https://i.dummyjson.com/data/products/36/thumbnail.jpg" 663 | ] 664 | }, 665 | { 666 | "id": 37, 667 | "title": "ank Tops for Womens/Girls", 668 | "description": "PACK OF 3 CAMISOLES ,VERY COMFORTABLE SOFT COTTON STUFF, COMFORTABLE IN ALL FOUR SEASONS", 669 | "price": 50, 670 | "discountPercentage": 12.05, 671 | "rating": 4.52, 672 | "stock": 107, 673 | "brand": "Soft Cotton", 674 | "category": "tops", 675 | "thumbnail": "https://i.dummyjson.com/data/products/37/thumbnail.jpg", 676 | "images": [ 677 | "https://i.dummyjson.com/data/products/37/1.jpg", 678 | "https://i.dummyjson.com/data/products/37/2.jpg", 679 | "https://i.dummyjson.com/data/products/37/3.jpg", 680 | "https://i.dummyjson.com/data/products/37/4.jpg", 681 | "https://i.dummyjson.com/data/products/37/thumbnail.jpg" 682 | ] 683 | }, 684 | { 685 | "id": 38, 686 | "title": "sublimation plain kids tank", 687 | "description": "sublimation plain kids tank tops wholesale", 688 | "price": 100, 689 | "discountPercentage": 11.12, 690 | "rating": 4.8, 691 | "stock": 20, 692 | "brand": "Soft Cotton", 693 | "category": "tops", 694 | "thumbnail": "https://i.dummyjson.com/data/products/38/thumbnail.jpg", 695 | "images": [ 696 | "https://i.dummyjson.com/data/products/38/1.png", 697 | "https://i.dummyjson.com/data/products/38/2.jpg", 698 | "https://i.dummyjson.com/data/products/38/3.jpg", 699 | "https://i.dummyjson.com/data/products/38/4.jpg" 700 | ] 701 | }, 702 | { 703 | "id": 39, 704 | "title": "Women Sweaters Wool", 705 | "description": "2021 Custom Winter Fall Zebra Knit Crop Top Women Sweaters Wool Mohair Cos Customize Crew Neck Women' S Crop Top Sweater", 706 | "price": 600, 707 | "discountPercentage": 17.2, 708 | "rating": 4.55, 709 | "stock": 55, 710 | "brand": "Top Sweater", 711 | "category": "tops", 712 | "thumbnail": "https://i.dummyjson.com/data/products/39/thumbnail.jpg", 713 | "images": [ 714 | "https://i.dummyjson.com/data/products/39/1.jpg", 715 | "https://i.dummyjson.com/data/products/39/2.jpg", 716 | "https://i.dummyjson.com/data/products/39/3.jpg", 717 | "https://i.dummyjson.com/data/products/39/4.jpg", 718 | "https://i.dummyjson.com/data/products/39/thumbnail.jpg" 719 | ] 720 | }, 721 | { 722 | "id": 40, 723 | "title": "women winter clothes", 724 | "description": "women winter clothes thick fleece hoodie top with sweat pantjogger women sweatsuit set joggers pants two piece pants set", 725 | "price": 57, 726 | "discountPercentage": 13.39, 727 | "rating": 4.91, 728 | "stock": 84, 729 | "brand": "Top Sweater", 730 | "category": "tops", 731 | "thumbnail": "https://i.dummyjson.com/data/products/40/thumbnail.jpg", 732 | "images": [ 733 | "https://i.dummyjson.com/data/products/40/1.jpg", 734 | "https://i.dummyjson.com/data/products/40/2.jpg" 735 | ] 736 | }, 737 | { 738 | "id": 41, 739 | "title": "NIGHT SUIT", 740 | "description": "NIGHT SUIT RED MICKY MOUSE.. For Girls. Fantastic Suits.", 741 | "price": 55, 742 | "discountPercentage": 15.05, 743 | "rating": 4.65, 744 | "stock": 21, 745 | "brand": "RED MICKY MOUSE..", 746 | "category": "womens-dresses", 747 | "thumbnail": "https://i.dummyjson.com/data/products/41/thumbnail.webp", 748 | "images": [ 749 | "https://i.dummyjson.com/data/products/41/1.jpg", 750 | "https://i.dummyjson.com/data/products/41/2.webp", 751 | "https://i.dummyjson.com/data/products/41/3.jpg", 752 | "https://i.dummyjson.com/data/products/41/4.jpg", 753 | "https://i.dummyjson.com/data/products/41/thumbnail.webp" 754 | ] 755 | }, 756 | { 757 | "id": 42, 758 | "title": "Stiched Kurta plus trouser", 759 | "description": "FABRIC: LILEIN CHEST: 21 LENGHT: 37 TROUSER: (38) :ARABIC LILEIN", 760 | "price": 80, 761 | "discountPercentage": 15.37, 762 | "rating": 4.05, 763 | "stock": 148, 764 | "brand": "Digital Printed", 765 | "category": "womens-dresses", 766 | "thumbnail": "https://i.dummyjson.com/data/products/42/thumbnail.jpg", 767 | "images": [ 768 | "https://i.dummyjson.com/data/products/42/1.png", 769 | "https://i.dummyjson.com/data/products/42/2.png", 770 | "https://i.dummyjson.com/data/products/42/3.png", 771 | "https://i.dummyjson.com/data/products/42/4.jpg", 772 | "https://i.dummyjson.com/data/products/42/thumbnail.jpg" 773 | ] 774 | }, 775 | { 776 | "id": 43, 777 | "title": "frock gold printed", 778 | "description": "Ghazi fabric long frock gold printed ready to wear stitched collection (G992)", 779 | "price": 600, 780 | "discountPercentage": 15.55, 781 | "rating": 4.31, 782 | "stock": 150, 783 | "brand": "Ghazi Fabric", 784 | "category": "womens-dresses", 785 | "thumbnail": "https://i.dummyjson.com/data/products/43/thumbnail.jpg", 786 | "images": [ 787 | "https://i.dummyjson.com/data/products/43/1.jpg", 788 | "https://i.dummyjson.com/data/products/43/2.jpg", 789 | "https://i.dummyjson.com/data/products/43/3.jpg", 790 | "https://i.dummyjson.com/data/products/43/4.jpg", 791 | "https://i.dummyjson.com/data/products/43/thumbnail.jpg" 792 | ] 793 | }, 794 | { 795 | "id": 44, 796 | "title": "Ladies Multicolored Dress", 797 | "description": "This classy shirt for women gives you a gorgeous look on everyday wear and specially for semi-casual wears.", 798 | "price": 79, 799 | "discountPercentage": 16.88, 800 | "rating": 4.03, 801 | "stock": 2, 802 | "brand": "Ghazi Fabric", 803 | "category": "womens-dresses", 804 | "thumbnail": "https://i.dummyjson.com/data/products/44/thumbnail.jpg", 805 | "images": [ 806 | "https://i.dummyjson.com/data/products/44/1.jpg", 807 | "https://i.dummyjson.com/data/products/44/2.jpg", 808 | "https://i.dummyjson.com/data/products/44/3.jpg", 809 | "https://i.dummyjson.com/data/products/44/4.jpg", 810 | "https://i.dummyjson.com/data/products/44/thumbnail.jpg" 811 | ] 812 | }, 813 | { 814 | "id": 45, 815 | "title": "Malai Maxi Dress", 816 | "description": "Ready to wear, Unique design according to modern standard fashion, Best fitting ,Imported stuff", 817 | "price": 50, 818 | "discountPercentage": 5.07, 819 | "rating": 4.67, 820 | "stock": 96, 821 | "brand": "IELGY", 822 | "category": "womens-dresses", 823 | "thumbnail": "https://i.dummyjson.com/data/products/45/thumbnail.jpg", 824 | "images": [ 825 | "https://i.dummyjson.com/data/products/45/1.jpg", 826 | "https://i.dummyjson.com/data/products/45/2.webp", 827 | "https://i.dummyjson.com/data/products/45/3.jpg", 828 | "https://i.dummyjson.com/data/products/45/4.jpg", 829 | "https://i.dummyjson.com/data/products/45/thumbnail.jpg" 830 | ] 831 | }, 832 | { 833 | "id": 46, 834 | "title": "women's shoes", 835 | "description": "Close: Lace, Style with bottom: Increased inside, Sole Material: Rubber", 836 | "price": 40, 837 | "discountPercentage": 16.96, 838 | "rating": 4.14, 839 | "stock": 72, 840 | "brand": "IELGY fashion", 841 | "category": "womens-shoes", 842 | "thumbnail": "https://i.dummyjson.com/data/products/46/thumbnail.jpg", 843 | "images": [ 844 | "https://i.dummyjson.com/data/products/46/1.webp", 845 | "https://i.dummyjson.com/data/products/46/2.jpg", 846 | "https://i.dummyjson.com/data/products/46/3.jpg", 847 | "https://i.dummyjson.com/data/products/46/4.jpg", 848 | "https://i.dummyjson.com/data/products/46/thumbnail.jpg" 849 | ] 850 | }, 851 | { 852 | "id": 47, 853 | "title": "Sneaker shoes", 854 | "description": "Synthetic Leather Casual Sneaker shoes for Women/girls Sneakers For Women", 855 | "price": 120, 856 | "discountPercentage": 10.37, 857 | "rating": 4.19, 858 | "stock": 50, 859 | "brand": "Synthetic Leather", 860 | "category": "womens-shoes", 861 | "thumbnail": "https://i.dummyjson.com/data/products/47/thumbnail.jpeg", 862 | "images": [ 863 | "https://i.dummyjson.com/data/products/47/1.jpg", 864 | "https://i.dummyjson.com/data/products/47/2.jpg", 865 | "https://i.dummyjson.com/data/products/47/3.jpg", 866 | "https://i.dummyjson.com/data/products/47/thumbnail.jpeg" 867 | ] 868 | }, 869 | { 870 | "id": 48, 871 | "title": "Women Strip Heel", 872 | "description": "Features: Flip-flops, Mid Heel, Comfortable, Striped Heel, Antiskid, Striped", 873 | "price": 40, 874 | "discountPercentage": 10.83, 875 | "rating": 4.02, 876 | "stock": 25, 877 | "brand": "Sandals Flip Flops", 878 | "category": "womens-shoes", 879 | "thumbnail": "https://i.dummyjson.com/data/products/48/thumbnail.jpg", 880 | "images": [ 881 | "https://i.dummyjson.com/data/products/48/1.jpg", 882 | "https://i.dummyjson.com/data/products/48/2.jpg", 883 | "https://i.dummyjson.com/data/products/48/3.jpg", 884 | "https://i.dummyjson.com/data/products/48/4.jpg", 885 | "https://i.dummyjson.com/data/products/48/thumbnail.jpg" 886 | ] 887 | }, 888 | { 889 | "id": 49, 890 | "title": "Chappals & Shoe Ladies Metallic", 891 | "description": "Womens Chappals & Shoe Ladies Metallic Tong Thong Sandal Flat Summer 2020 Maasai Sandals", 892 | "price": 23, 893 | "discountPercentage": 2.62, 894 | "rating": 4.72, 895 | "stock": 107, 896 | "brand": "Maasai Sandals", 897 | "category": "womens-shoes", 898 | "thumbnail": "https://i.dummyjson.com/data/products/49/thumbnail.jpg", 899 | "images": [ 900 | "https://i.dummyjson.com/data/products/49/1.jpg", 901 | "https://i.dummyjson.com/data/products/49/2.jpg", 902 | "https://i.dummyjson.com/data/products/49/3.webp", 903 | "https://i.dummyjson.com/data/products/49/thumbnail.jpg" 904 | ] 905 | }, 906 | { 907 | "id": 50, 908 | "title": "Women Shoes", 909 | "description": "2020 New Arrivals Genuine Leather Fashion Trend Platform Summer Women Shoes", 910 | "price": 36, 911 | "discountPercentage": 16.87, 912 | "rating": 4.33, 913 | "stock": 46, 914 | "brand": "Arrivals Genuine", 915 | "category": "womens-shoes", 916 | "thumbnail": "https://i.dummyjson.com/data/products/50/thumbnail.jpg", 917 | "images": [ 918 | "https://i.dummyjson.com/data/products/50/1.jpeg", 919 | "https://i.dummyjson.com/data/products/50/2.jpg", 920 | "https://i.dummyjson.com/data/products/50/3.jpg" 921 | ] 922 | }, 923 | { 924 | "id": 51, 925 | "title": "half sleeves T shirts", 926 | "description": "Many store is creating new designs and trend every month and every year. Daraz.pk have a beautiful range of men fashion brands", 927 | "price": 23, 928 | "discountPercentage": 12.76, 929 | "rating": 4.26, 930 | "stock": 132, 931 | "brand": "Vintage Apparel", 932 | "category": "mens-shirts", 933 | "thumbnail": "https://i.dummyjson.com/data/products/51/thumbnail.jpg", 934 | "images": [ 935 | "https://i.dummyjson.com/data/products/51/1.png", 936 | "https://i.dummyjson.com/data/products/51/2.jpg", 937 | "https://i.dummyjson.com/data/products/51/3.jpg", 938 | "https://i.dummyjson.com/data/products/51/thumbnail.jpg" 939 | ] 940 | }, 941 | { 942 | "id": 52, 943 | "title": "FREE FIRE T Shirt", 944 | "description": "quality and professional print - It doesn't just look high quality, it is high quality.", 945 | "price": 10, 946 | "discountPercentage": 14.72, 947 | "rating": 4.52, 948 | "stock": 128, 949 | "brand": "FREE FIRE", 950 | "category": "mens-shirts", 951 | "thumbnail": "https://i.dummyjson.com/data/products/52/thumbnail.jpg", 952 | "images": [ 953 | "https://i.dummyjson.com/data/products/52/1.png", 954 | "https://i.dummyjson.com/data/products/52/2.png", 955 | "https://i.dummyjson.com/data/products/52/3.jpg", 956 | "https://i.dummyjson.com/data/products/52/4.jpg", 957 | "https://i.dummyjson.com/data/products/52/thumbnail.jpg" 958 | ] 959 | }, 960 | { 961 | "id": 53, 962 | "title": "printed high quality T shirts", 963 | "description": "Brand: vintage Apparel ,Export quality", 964 | "price": 35, 965 | "discountPercentage": 7.54, 966 | "rating": 4.89, 967 | "stock": 6, 968 | "brand": "Vintage Apparel", 969 | "category": "mens-shirts", 970 | "thumbnail": "https://i.dummyjson.com/data/products/53/thumbnail.jpg", 971 | "images": [ 972 | "https://i.dummyjson.com/data/products/53/1.webp", 973 | "https://i.dummyjson.com/data/products/53/2.jpg", 974 | "https://i.dummyjson.com/data/products/53/3.jpg", 975 | "https://i.dummyjson.com/data/products/53/4.jpg", 976 | "https://i.dummyjson.com/data/products/53/thumbnail.jpg" 977 | ] 978 | }, 979 | { 980 | "id": 54, 981 | "title": "Pubg Printed Graphic T-Shirt", 982 | "description": "Product Description Features: 100% Ultra soft Polyester Jersey. Vibrant & colorful printing on front. Feels soft as cotton without ever cracking", 983 | "price": 46, 984 | "discountPercentage": 16.44, 985 | "rating": 4.62, 986 | "stock": 136, 987 | "brand": "The Warehouse", 988 | "category": "mens-shirts", 989 | "thumbnail": "https://i.dummyjson.com/data/products/54/thumbnail.jpg", 990 | "images": [ 991 | "https://i.dummyjson.com/data/products/54/1.jpg", 992 | "https://i.dummyjson.com/data/products/54/2.jpg", 993 | "https://i.dummyjson.com/data/products/54/3.jpg", 994 | "https://i.dummyjson.com/data/products/54/4.jpg", 995 | "https://i.dummyjson.com/data/products/54/thumbnail.jpg" 996 | ] 997 | }, 998 | { 999 | "id": 55, 1000 | "title": "Money Heist Printed Summer T Shirts", 1001 | "description": "Fabric Jercy, Size: M & L Wear Stylish Dual Stiched", 1002 | "price": 66, 1003 | "discountPercentage": 15.97, 1004 | "rating": 4.9, 1005 | "stock": 122, 1006 | "brand": "The Warehouse", 1007 | "category": "mens-shirts", 1008 | "thumbnail": "https://i.dummyjson.com/data/products/55/thumbnail.jpg", 1009 | "images": [ 1010 | "https://i.dummyjson.com/data/products/55/1.jpg", 1011 | "https://i.dummyjson.com/data/products/55/2.webp", 1012 | "https://i.dummyjson.com/data/products/55/3.jpg", 1013 | "https://i.dummyjson.com/data/products/55/4.jpg", 1014 | "https://i.dummyjson.com/data/products/55/thumbnail.jpg" 1015 | ] 1016 | }, 1017 | { 1018 | "id": 56, 1019 | "title": "Sneakers Joggers Shoes", 1020 | "description": "Gender: Men , Colors: Same as DisplayedCondition: 100% Brand New", 1021 | "price": 40, 1022 | "discountPercentage": 12.57, 1023 | "rating": 4.38, 1024 | "stock": 6, 1025 | "brand": "Sneakers", 1026 | "category": "mens-shoes", 1027 | "thumbnail": "https://i.dummyjson.com/data/products/56/thumbnail.jpg", 1028 | "images": [ 1029 | "https://i.dummyjson.com/data/products/56/1.jpg", 1030 | "https://i.dummyjson.com/data/products/56/2.jpg", 1031 | "https://i.dummyjson.com/data/products/56/3.jpg", 1032 | "https://i.dummyjson.com/data/products/56/4.jpg", 1033 | "https://i.dummyjson.com/data/products/56/5.jpg", 1034 | "https://i.dummyjson.com/data/products/56/thumbnail.jpg" 1035 | ] 1036 | }, 1037 | { 1038 | "id": 57, 1039 | "title": "Loafers for men", 1040 | "description": "Men Shoes - Loafers for men - Rubber Shoes - Nylon Shoes - Shoes for men - Moccassion - Pure Nylon (Rubber) Expot Quality.", 1041 | "price": 47, 1042 | "discountPercentage": 10.91, 1043 | "rating": 4.91, 1044 | "stock": 20, 1045 | "brand": "Rubber", 1046 | "category": "mens-shoes", 1047 | "thumbnail": "https://i.dummyjson.com/data/products/57/thumbnail.jpg", 1048 | "images": [ 1049 | "https://i.dummyjson.com/data/products/57/1.jpg", 1050 | "https://i.dummyjson.com/data/products/57/2.jpg", 1051 | "https://i.dummyjson.com/data/products/57/3.jpg", 1052 | "https://i.dummyjson.com/data/products/57/4.jpg", 1053 | "https://i.dummyjson.com/data/products/57/thumbnail.jpg" 1054 | ] 1055 | }, 1056 | { 1057 | "id": 58, 1058 | "title": "formal offices shoes", 1059 | "description": "Pattern Type: Solid, Material: PU, Toe Shape: Pointed Toe ,Outsole Material: Rubber", 1060 | "price": 57, 1061 | "discountPercentage": 12, 1062 | "rating": 4.41, 1063 | "stock": 68, 1064 | "brand": "The Warehouse", 1065 | "category": "mens-shoes", 1066 | "thumbnail": "https://i.dummyjson.com/data/products/58/thumbnail.jpg", 1067 | "images": [ 1068 | "https://i.dummyjson.com/data/products/58/1.jpg", 1069 | "https://i.dummyjson.com/data/products/58/2.jpg", 1070 | "https://i.dummyjson.com/data/products/58/3.jpg", 1071 | "https://i.dummyjson.com/data/products/58/4.jpg", 1072 | "https://i.dummyjson.com/data/products/58/thumbnail.jpg" 1073 | ] 1074 | }, 1075 | { 1076 | "id": 59, 1077 | "title": "Spring and summershoes", 1078 | "description": "Comfortable stretch cloth, lightweight body; ,rubber sole, anti-skid wear;", 1079 | "price": 20, 1080 | "discountPercentage": 8.71, 1081 | "rating": 4.33, 1082 | "stock": 137, 1083 | "brand": "Sneakers", 1084 | "category": "mens-shoes", 1085 | "thumbnail": "https://i.dummyjson.com/data/products/59/thumbnail.jpg", 1086 | "images": [ 1087 | "https://i.dummyjson.com/data/products/59/1.jpg", 1088 | "https://i.dummyjson.com/data/products/59/2.jpg", 1089 | "https://i.dummyjson.com/data/products/59/3.jpg", 1090 | "https://i.dummyjson.com/data/products/59/4.jpg", 1091 | "https://i.dummyjson.com/data/products/59/thumbnail.jpg" 1092 | ] 1093 | }, 1094 | { 1095 | "id": 60, 1096 | "title": "Stylish Casual Jeans Shoes", 1097 | "description": "High Quality ,Stylish design ,Comfortable wear ,FAshion ,Durable", 1098 | "price": 58, 1099 | "discountPercentage": 7.55, 1100 | "rating": 4.55, 1101 | "stock": 129, 1102 | "brand": "Sneakers", 1103 | "category": "mens-shoes", 1104 | "thumbnail": "https://i.dummyjson.com/data/products/60/thumbnail.jpg", 1105 | "images": [ 1106 | "https://i.dummyjson.com/data/products/60/1.jpg", 1107 | "https://i.dummyjson.com/data/products/60/2.jpg", 1108 | "https://i.dummyjson.com/data/products/60/3.jpg", 1109 | "https://i.dummyjson.com/data/products/60/thumbnail.jpg" 1110 | ] 1111 | }, 1112 | { 1113 | "id": 61, 1114 | "title": "Leather Straps Wristwatch", 1115 | "description": "Style:Sport ,Clasp:Buckles ,Water Resistance Depth:3Bar", 1116 | "price": 120, 1117 | "discountPercentage": 7.14, 1118 | "rating": 4.63, 1119 | "stock": 91, 1120 | "brand": "Naviforce", 1121 | "category": "mens-watches", 1122 | "thumbnail": "https://i.dummyjson.com/data/products/61/thumbnail.jpg", 1123 | "images": [ 1124 | "https://i.dummyjson.com/data/products/61/1.jpg", 1125 | "https://i.dummyjson.com/data/products/61/2.png", 1126 | "https://i.dummyjson.com/data/products/61/3.jpg" 1127 | ] 1128 | }, 1129 | { 1130 | "id": 62, 1131 | "title": "Waterproof Leather Brand Watch", 1132 | "description": "Watch Crown With Environmental IPS Bronze Electroplating; Display system of 12 hours", 1133 | "price": 46, 1134 | "discountPercentage": 3.15, 1135 | "rating": 4.05, 1136 | "stock": 95, 1137 | "brand": "SKMEI 9117", 1138 | "category": "mens-watches", 1139 | "thumbnail": "https://i.dummyjson.com/data/products/62/thumbnail.jpg", 1140 | "images": [ 1141 | "https://i.dummyjson.com/data/products/62/1.jpg", 1142 | "https://i.dummyjson.com/data/products/62/2.jpg" 1143 | ] 1144 | }, 1145 | { 1146 | "id": 63, 1147 | "title": "Royal Blue Premium Watch", 1148 | "description": "Men Silver Chain Royal Blue Premium Watch Latest Analog Watch", 1149 | "price": 50, 1150 | "discountPercentage": 2.56, 1151 | "rating": 4.89, 1152 | "stock": 142, 1153 | "brand": "SKMEI 9117", 1154 | "category": "mens-watches", 1155 | "thumbnail": "https://i.dummyjson.com/data/products/63/thumbnail.webp", 1156 | "images": [ 1157 | "https://i.dummyjson.com/data/products/63/1.jpg", 1158 | "https://i.dummyjson.com/data/products/63/2.jpg", 1159 | "https://i.dummyjson.com/data/products/63/3.png", 1160 | "https://i.dummyjson.com/data/products/63/4.jpeg" 1161 | ] 1162 | }, 1163 | { 1164 | "id": 64, 1165 | "title": "Leather Strap Skeleton Watch", 1166 | "description": "Leather Strap Skeleton Watch for Men - Stylish and Latest Design", 1167 | "price": 46, 1168 | "discountPercentage": 10.2, 1169 | "rating": 4.98, 1170 | "stock": 61, 1171 | "brand": "Strap Skeleton", 1172 | "category": "mens-watches", 1173 | "thumbnail": "https://i.dummyjson.com/data/products/64/thumbnail.jpg", 1174 | "images": [ 1175 | "https://i.dummyjson.com/data/products/64/1.jpg", 1176 | "https://i.dummyjson.com/data/products/64/2.webp", 1177 | "https://i.dummyjson.com/data/products/64/3.jpg", 1178 | "https://i.dummyjson.com/data/products/64/thumbnail.jpg" 1179 | ] 1180 | }, 1181 | { 1182 | "id": 65, 1183 | "title": "Stainless Steel Wrist Watch", 1184 | "description": "Stylish Watch For Man (Luxury) Classy Men's Stainless Steel Wrist Watch - Box Packed", 1185 | "price": 47, 1186 | "discountPercentage": 17.79, 1187 | "rating": 4.79, 1188 | "stock": 94, 1189 | "brand": "Stainless", 1190 | "category": "mens-watches", 1191 | "thumbnail": "https://i.dummyjson.com/data/products/65/thumbnail.webp", 1192 | "images": [ 1193 | "https://i.dummyjson.com/data/products/65/1.jpg", 1194 | "https://i.dummyjson.com/data/products/65/2.webp", 1195 | "https://i.dummyjson.com/data/products/65/3.jpg", 1196 | "https://i.dummyjson.com/data/products/65/4.webp", 1197 | "https://i.dummyjson.com/data/products/65/thumbnail.webp" 1198 | ] 1199 | }, 1200 | { 1201 | "id": 66, 1202 | "title": "Steel Analog Couple Watches", 1203 | "description": "Elegant design, Stylish ,Unique & Trendy,Comfortable wear", 1204 | "price": 35, 1205 | "discountPercentage": 3.23, 1206 | "rating": 4.79, 1207 | "stock": 24, 1208 | "brand": "Eastern Watches", 1209 | "category": "womens-watches", 1210 | "thumbnail": "https://i.dummyjson.com/data/products/66/thumbnail.jpg", 1211 | "images": [ 1212 | "https://i.dummyjson.com/data/products/66/1.jpg", 1213 | "https://i.dummyjson.com/data/products/66/2.jpg", 1214 | "https://i.dummyjson.com/data/products/66/3.jpg", 1215 | "https://i.dummyjson.com/data/products/66/4.JPG", 1216 | "https://i.dummyjson.com/data/products/66/thumbnail.jpg" 1217 | ] 1218 | }, 1219 | { 1220 | "id": 67, 1221 | "title": "Fashion Magnetic Wrist Watch", 1222 | "description": "Buy this awesome The product is originally manufactured by the company and it's a top selling product with a very reasonable", 1223 | "price": 60, 1224 | "discountPercentage": 16.69, 1225 | "rating": 4.03, 1226 | "stock": 46, 1227 | "brand": "Eastern Watches", 1228 | "category": "womens-watches", 1229 | "thumbnail": "https://i.dummyjson.com/data/products/67/thumbnail.jpg", 1230 | "images": [ 1231 | "https://i.dummyjson.com/data/products/67/1.jpg", 1232 | "https://i.dummyjson.com/data/products/67/2.jpg", 1233 | "https://i.dummyjson.com/data/products/67/3.jpg", 1234 | "https://i.dummyjson.com/data/products/67/4.jpg", 1235 | "https://i.dummyjson.com/data/products/67/thumbnail.jpg" 1236 | ] 1237 | }, 1238 | { 1239 | "id": 68, 1240 | "title": "Stylish Luxury Digital Watch", 1241 | "description": "Stylish Luxury Digital Watch For Girls / Women - Led Smart Ladies Watches For Girls", 1242 | "price": 57, 1243 | "discountPercentage": 9.03, 1244 | "rating": 4.55, 1245 | "stock": 77, 1246 | "brand": "Luxury Digital", 1247 | "category": "womens-watches", 1248 | "thumbnail": "https://i.dummyjson.com/data/products/68/thumbnail.webp", 1249 | "images": [ 1250 | "https://i.dummyjson.com/data/products/68/1.jpg", 1251 | "https://i.dummyjson.com/data/products/68/2.jpg" 1252 | ] 1253 | }, 1254 | { 1255 | "id": 69, 1256 | "title": "Golden Watch Pearls Bracelet Watch", 1257 | "description": "Product details of Golden Watch Pearls Bracelet Watch For Girls - Golden Chain Ladies Bracelate Watch for Women", 1258 | "price": 47, 1259 | "discountPercentage": 17.55, 1260 | "rating": 4.77, 1261 | "stock": 89, 1262 | "brand": "Watch Pearls", 1263 | "category": "womens-watches", 1264 | "thumbnail": "https://i.dummyjson.com/data/products/69/thumbnail.jpg", 1265 | "images": [ 1266 | "https://i.dummyjson.com/data/products/69/1.jpg", 1267 | "https://i.dummyjson.com/data/products/69/2.jpg", 1268 | "https://i.dummyjson.com/data/products/69/3.webp", 1269 | "https://i.dummyjson.com/data/products/69/4.jpg", 1270 | "https://i.dummyjson.com/data/products/69/thumbnail.jpg" 1271 | ] 1272 | }, 1273 | { 1274 | "id": 70, 1275 | "title": "Stainless Steel Women", 1276 | "description": "Fashion Skmei 1830 Shell Dial Stainless Steel Women Wrist Watch Lady Bracelet Watch Quartz Watches Ladies", 1277 | "price": 35, 1278 | "discountPercentage": 8.98, 1279 | "rating": 4.08, 1280 | "stock": 111, 1281 | "brand": "Bracelet", 1282 | "category": "womens-watches", 1283 | "thumbnail": "https://i.dummyjson.com/data/products/70/thumbnail.jpg", 1284 | "images": [ 1285 | "https://i.dummyjson.com/data/products/70/1.jpg", 1286 | "https://i.dummyjson.com/data/products/70/2.jpg", 1287 | "https://i.dummyjson.com/data/products/70/thumbnail.jpg" 1288 | ] 1289 | }, 1290 | { 1291 | "id": 71, 1292 | "title": "Women Shoulder Bags", 1293 | "description": "LouisWill Women Shoulder Bags Long Clutches Cross Body Bags Phone Bags PU Leather Hand Bags Large Capacity Card Holders Zipper Coin Purses Fashion Crossbody Bags for Girls Ladies", 1294 | "price": 46, 1295 | "discountPercentage": 14.65, 1296 | "rating": 4.71, 1297 | "stock": 17, 1298 | "brand": "LouisWill", 1299 | "category": "womens-bags", 1300 | "thumbnail": "https://i.dummyjson.com/data/products/71/thumbnail.jpg", 1301 | "images": [ 1302 | "https://i.dummyjson.com/data/products/71/1.jpg", 1303 | "https://i.dummyjson.com/data/products/71/2.jpg", 1304 | "https://i.dummyjson.com/data/products/71/3.webp", 1305 | "https://i.dummyjson.com/data/products/71/thumbnail.jpg" 1306 | ] 1307 | }, 1308 | { 1309 | "id": 72, 1310 | "title": "Handbag For Girls", 1311 | "description": "This fashion is designed to add a charming effect to your casual outfit. This Bag is made of synthetic leather.", 1312 | "price": 23, 1313 | "discountPercentage": 17.5, 1314 | "rating": 4.91, 1315 | "stock": 27, 1316 | "brand": "LouisWill", 1317 | "category": "womens-bags", 1318 | "thumbnail": "https://i.dummyjson.com/data/products/72/thumbnail.webp", 1319 | "images": [ 1320 | "https://i.dummyjson.com/data/products/72/1.jpg", 1321 | "https://i.dummyjson.com/data/products/72/2.png", 1322 | "https://i.dummyjson.com/data/products/72/3.webp", 1323 | "https://i.dummyjson.com/data/products/72/4.jpg", 1324 | "https://i.dummyjson.com/data/products/72/thumbnail.webp" 1325 | ] 1326 | }, 1327 | { 1328 | "id": 73, 1329 | "title": "Fancy hand clutch", 1330 | "description": "This fashion is designed to add a charming effect to your casual outfit. This Bag is made of synthetic leather.", 1331 | "price": 44, 1332 | "discountPercentage": 10.39, 1333 | "rating": 4.18, 1334 | "stock": 101, 1335 | "brand": "Bracelet", 1336 | "category": "womens-bags", 1337 | "thumbnail": "https://i.dummyjson.com/data/products/73/thumbnail.jpg", 1338 | "images": [ 1339 | "https://i.dummyjson.com/data/products/73/1.jpg", 1340 | "https://i.dummyjson.com/data/products/73/2.webp", 1341 | "https://i.dummyjson.com/data/products/73/3.jpg", 1342 | "https://i.dummyjson.com/data/products/73/thumbnail.jpg" 1343 | ] 1344 | }, 1345 | { 1346 | "id": 74, 1347 | "title": "Leather Hand Bag", 1348 | "description": "It features an attractive design that makes it a must have accessory in your collection. We sell different kind of bags for boys, kids, women, girls and also for unisex.", 1349 | "price": 57, 1350 | "discountPercentage": 11.19, 1351 | "rating": 4.01, 1352 | "stock": 43, 1353 | "brand": "Copenhagen Luxe", 1354 | "category": "womens-bags", 1355 | "thumbnail": "https://i.dummyjson.com/data/products/74/thumbnail.jpg", 1356 | "images": [ 1357 | "https://i.dummyjson.com/data/products/74/1.jpg", 1358 | "https://i.dummyjson.com/data/products/74/2.jpg", 1359 | "https://i.dummyjson.com/data/products/74/3.jpg", 1360 | "https://i.dummyjson.com/data/products/74/4.jpg", 1361 | "https://i.dummyjson.com/data/products/74/thumbnail.jpg" 1362 | ] 1363 | }, 1364 | { 1365 | "id": 75, 1366 | "title": "Seven Pocket Women Bag", 1367 | "description": "Seven Pocket Women Bag Handbags Lady Shoulder Crossbody Bag Female Purse Seven Pocket Bag", 1368 | "price": 68, 1369 | "discountPercentage": 14.87, 1370 | "rating": 4.93, 1371 | "stock": 13, 1372 | "brand": "Steal Frame", 1373 | "category": "womens-bags", 1374 | "thumbnail": "https://i.dummyjson.com/data/products/75/thumbnail.jpg", 1375 | "images": [ 1376 | "https://i.dummyjson.com/data/products/75/1.jpg", 1377 | "https://i.dummyjson.com/data/products/75/2.jpg", 1378 | "https://i.dummyjson.com/data/products/75/3.jpg", 1379 | "https://i.dummyjson.com/data/products/75/thumbnail.jpg" 1380 | ] 1381 | }, 1382 | { 1383 | "id": 76, 1384 | "title": "Silver Ring Set Women", 1385 | "description": "Jewelry Type:RingsCertificate Type:NonePlating:Silver PlatedShapeattern:noneStyle:CLASSICReligious", 1386 | "price": 70, 1387 | "discountPercentage": 13.57, 1388 | "rating": 4.61, 1389 | "stock": 51, 1390 | "brand": "Darojay", 1391 | "category": "womens-jewellery", 1392 | "thumbnail": "https://i.dummyjson.com/data/products/76/thumbnail.jpg", 1393 | "images": [ 1394 | "https://i.dummyjson.com/data/products/76/1.jpg", 1395 | "https://i.dummyjson.com/data/products/76/2.jpg", 1396 | "https://i.dummyjson.com/data/products/76/thumbnail.jpg" 1397 | ] 1398 | }, 1399 | { 1400 | "id": 77, 1401 | "title": "Rose Ring", 1402 | "description": "Brand: The Greetings Flower Colour: RedRing Colour: GoldenSize: Adjustable", 1403 | "price": 100, 1404 | "discountPercentage": 3.22, 1405 | "rating": 4.21, 1406 | "stock": 149, 1407 | "brand": "Copenhagen Luxe", 1408 | "category": "womens-jewellery", 1409 | "thumbnail": "https://i.dummyjson.com/data/products/77/thumbnail.jpg", 1410 | "images": [ 1411 | "https://i.dummyjson.com/data/products/77/1.jpg", 1412 | "https://i.dummyjson.com/data/products/77/2.jpg", 1413 | "https://i.dummyjson.com/data/products/77/3.jpg", 1414 | "https://i.dummyjson.com/data/products/77/thumbnail.jpg" 1415 | ] 1416 | }, 1417 | { 1418 | "id": 78, 1419 | "title": "Rhinestone Korean Style Open Rings", 1420 | "description": "Fashion Jewellery 3Pcs Adjustable Pearl Rhinestone Korean Style Open Rings For Women", 1421 | "price": 30, 1422 | "discountPercentage": 8.02, 1423 | "rating": 4.69, 1424 | "stock": 9, 1425 | "brand": "Fashion Jewellery", 1426 | "category": "womens-jewellery", 1427 | "thumbnail": "https://i.dummyjson.com/data/products/78/thumbnail.jpg", 1428 | "images": ["https://i.dummyjson.com/data/products/78/thumbnail.jpg"] 1429 | }, 1430 | { 1431 | "id": 79, 1432 | "title": "Elegant Female Pearl Earrings", 1433 | "description": "Elegant Female Pearl Earrings Set Zircon Pearl Earings Women Party Accessories 9 Pairs/Set", 1434 | "price": 30, 1435 | "discountPercentage": 12.8, 1436 | "rating": 4.74, 1437 | "stock": 16, 1438 | "brand": "Fashion Jewellery", 1439 | "category": "womens-jewellery", 1440 | "thumbnail": "https://i.dummyjson.com/data/products/79/thumbnail.jpg", 1441 | "images": ["https://i.dummyjson.com/data/products/79/1.jpg"] 1442 | }, 1443 | { 1444 | "id": 80, 1445 | "title": "Chain Pin Tassel Earrings", 1446 | "description": "Pair Of Ear Cuff Butterfly Long Chain Pin Tassel Earrings - Silver ( Long Life Quality Product)", 1447 | "price": 45, 1448 | "discountPercentage": 17.75, 1449 | "rating": 4.59, 1450 | "stock": 9, 1451 | "brand": "Cuff Butterfly", 1452 | "category": "womens-jewellery", 1453 | "thumbnail": "https://i.dummyjson.com/data/products/80/thumbnail.jpg", 1454 | "images": [ 1455 | "https://i.dummyjson.com/data/products/80/1.jpg", 1456 | "https://i.dummyjson.com/data/products/80/2.jpg", 1457 | "https://i.dummyjson.com/data/products/80/3.png", 1458 | "https://i.dummyjson.com/data/products/80/4.jpg", 1459 | "https://i.dummyjson.com/data/products/80/thumbnail.jpg" 1460 | ] 1461 | }, 1462 | { 1463 | "id": 81, 1464 | "title": "Round Silver Frame Sun Glasses", 1465 | "description": "A pair of sunglasses can protect your eyes from being hurt. For car driving, vacation travel, outdoor activities, social gatherings,", 1466 | "price": 19, 1467 | "discountPercentage": 10.1, 1468 | "rating": 4.94, 1469 | "stock": 78, 1470 | "brand": "Designer Sun Glasses", 1471 | "category": "sunglasses", 1472 | "thumbnail": "https://i.dummyjson.com/data/products/81/thumbnail.jpg", 1473 | "images": [ 1474 | "https://i.dummyjson.com/data/products/81/1.jpg", 1475 | "https://i.dummyjson.com/data/products/81/2.jpg", 1476 | "https://i.dummyjson.com/data/products/81/3.jpg", 1477 | "https://i.dummyjson.com/data/products/81/4.webp", 1478 | "https://i.dummyjson.com/data/products/81/thumbnail.jpg" 1479 | ] 1480 | }, 1481 | { 1482 | "id": 82, 1483 | "title": "Kabir Singh Square Sunglass", 1484 | "description": "Orignal Metal Kabir Singh design 2020 Sunglasses Men Brand Designer Sun Glasses Kabir Singh Square Sunglass", 1485 | "price": 50, 1486 | "discountPercentage": 15.6, 1487 | "rating": 4.62, 1488 | "stock": 78, 1489 | "brand": "Designer Sun Glasses", 1490 | "category": "sunglasses", 1491 | "thumbnail": "https://i.dummyjson.com/data/products/82/thumbnail.jpg", 1492 | "images": [ 1493 | "https://i.dummyjson.com/data/products/82/1.jpg", 1494 | "https://i.dummyjson.com/data/products/82/2.webp", 1495 | "https://i.dummyjson.com/data/products/82/3.jpg", 1496 | "https://i.dummyjson.com/data/products/82/4.jpg", 1497 | "https://i.dummyjson.com/data/products/82/thumbnail.jpg" 1498 | ] 1499 | }, 1500 | { 1501 | "id": 83, 1502 | "title": "Wiley X Night Vision Yellow Glasses", 1503 | "description": "Wiley X Night Vision Yellow Glasses for Riders - Night Vision Anti Fog Driving Glasses - Free Night Glass Cover - Shield Eyes From Dust and Virus- For Night Sport Matches", 1504 | "price": 30, 1505 | "discountPercentage": 6.33, 1506 | "rating": 4.97, 1507 | "stock": 115, 1508 | "brand": "mastar watch", 1509 | "category": "sunglasses", 1510 | "thumbnail": "https://i.dummyjson.com/data/products/83/thumbnail.jpg", 1511 | "images": [ 1512 | "https://i.dummyjson.com/data/products/83/1.jpg", 1513 | "https://i.dummyjson.com/data/products/83/2.jpg", 1514 | "https://i.dummyjson.com/data/products/83/3.jpg", 1515 | "https://i.dummyjson.com/data/products/83/4.jpg", 1516 | "https://i.dummyjson.com/data/products/83/thumbnail.jpg" 1517 | ] 1518 | }, 1519 | { 1520 | "id": 84, 1521 | "title": "Square Sunglasses", 1522 | "description": "Fashion Oversized Square Sunglasses Retro Gradient Big Frame Sunglasses For Women One Piece Gafas Shade Mirror Clear Lens 17059", 1523 | "price": 28, 1524 | "discountPercentage": 13.89, 1525 | "rating": 4.64, 1526 | "stock": 64, 1527 | "brand": "mastar watch", 1528 | "category": "sunglasses", 1529 | "thumbnail": "https://i.dummyjson.com/data/products/84/thumbnail.jpg", 1530 | "images": [ 1531 | "https://i.dummyjson.com/data/products/84/1.jpg", 1532 | "https://i.dummyjson.com/data/products/84/2.jpg", 1533 | "https://i.dummyjson.com/data/products/84/thumbnail.jpg" 1534 | ] 1535 | }, 1536 | { 1537 | "id": 85, 1538 | "title": "LouisWill Men Sunglasses", 1539 | "description": "LouisWill Men Sunglasses Polarized Sunglasses UV400 Sunglasses Day Night Dual Use Safety Driving Night Vision Eyewear AL-MG Frame Sun Glasses with Free Box for Drivers", 1540 | "price": 50, 1541 | "discountPercentage": 11.27, 1542 | "rating": 4.98, 1543 | "stock": 92, 1544 | "brand": "LouisWill", 1545 | "category": "sunglasses", 1546 | "thumbnail": "https://i.dummyjson.com/data/products/85/thumbnail.jpg", 1547 | "images": [ 1548 | "https://i.dummyjson.com/data/products/85/1.jpg", 1549 | "https://i.dummyjson.com/data/products/85/2.jpg", 1550 | "https://i.dummyjson.com/data/products/85/thumbnail.jpg" 1551 | ] 1552 | }, 1553 | { 1554 | "id": 86, 1555 | "title": "Bluetooth Aux", 1556 | "description": "Bluetooth Aux Bluetooth Car Aux Car Bluetooth Transmitter Aux Audio Receiver Handfree Car Bluetooth Music Receiver Universal 3.5mm Streaming A2DP Wireless Auto AUX Audio Adapter With Mic For Phone MP3", 1557 | "price": 25, 1558 | "discountPercentage": 10.56, 1559 | "rating": 4.57, 1560 | "stock": 22, 1561 | "brand": "Car Aux", 1562 | "category": "automotive", 1563 | "thumbnail": "https://i.dummyjson.com/data/products/86/thumbnail.jpg", 1564 | "images": [ 1565 | "https://i.dummyjson.com/data/products/86/1.jpg", 1566 | "https://i.dummyjson.com/data/products/86/2.webp", 1567 | "https://i.dummyjson.com/data/products/86/3.jpg", 1568 | "https://i.dummyjson.com/data/products/86/4.jpg", 1569 | "https://i.dummyjson.com/data/products/86/thumbnail.jpg" 1570 | ] 1571 | }, 1572 | { 1573 | "id": 87, 1574 | "title": "t Temperature Controller Incubator Controller", 1575 | "description": "Both Heat and Cool Purpose, Temperature control range; -50 to +110, Temperature measurement accuracy; 0.1, Control accuracy; 0.1", 1576 | "price": 40, 1577 | "discountPercentage": 11.3, 1578 | "rating": 4.54, 1579 | "stock": 37, 1580 | "brand": "W1209 DC12V", 1581 | "category": "automotive", 1582 | "thumbnail": "https://i.dummyjson.com/data/products/87/thumbnail.jpg", 1583 | "images": [ 1584 | "https://i.dummyjson.com/data/products/87/1.jpg", 1585 | "https://i.dummyjson.com/data/products/87/2.jpg", 1586 | "https://i.dummyjson.com/data/products/87/3.jpg", 1587 | "https://i.dummyjson.com/data/products/87/4.jpg", 1588 | "https://i.dummyjson.com/data/products/87/thumbnail.jpg" 1589 | ] 1590 | }, 1591 | { 1592 | "id": 88, 1593 | "title": "TC Reusable Silicone Magic Washing Gloves", 1594 | "description": "TC Reusable Silicone Magic Washing Gloves with Scrubber, Cleaning Brush Scrubber Gloves Heat Resistant Pair for Cleaning of Kitchen, Dishes, Vegetables and Fruits, Bathroom, Car Wash, Pet Care and Multipurpose", 1595 | "price": 29, 1596 | "discountPercentage": 3.19, 1597 | "rating": 4.98, 1598 | "stock": 42, 1599 | "brand": "TC Reusable", 1600 | "category": "automotive", 1601 | "thumbnail": "https://i.dummyjson.com/data/products/88/thumbnail.jpg", 1602 | "images": [ 1603 | "https://i.dummyjson.com/data/products/88/1.jpg", 1604 | "https://i.dummyjson.com/data/products/88/2.jpg", 1605 | "https://i.dummyjson.com/data/products/88/3.jpg", 1606 | "https://i.dummyjson.com/data/products/88/4.webp", 1607 | "https://i.dummyjson.com/data/products/88/thumbnail.jpg" 1608 | ] 1609 | }, 1610 | { 1611 | "id": 89, 1612 | "title": "Qualcomm original Car Charger", 1613 | "description": "best Quality CHarger , Highly Recommended to all best Quality CHarger , Highly Recommended to all", 1614 | "price": 40, 1615 | "discountPercentage": 17.53, 1616 | "rating": 4.2, 1617 | "stock": 79, 1618 | "brand": "TC Reusable", 1619 | "category": "automotive", 1620 | "thumbnail": "https://i.dummyjson.com/data/products/89/thumbnail.jpg", 1621 | "images": [ 1622 | "https://i.dummyjson.com/data/products/89/1.jpg", 1623 | "https://i.dummyjson.com/data/products/89/2.jpg", 1624 | "https://i.dummyjson.com/data/products/89/3.jpg", 1625 | "https://i.dummyjson.com/data/products/89/4.jpg", 1626 | "https://i.dummyjson.com/data/products/89/thumbnail.jpg" 1627 | ] 1628 | }, 1629 | { 1630 | "id": 90, 1631 | "title": "Cycle Bike Glow", 1632 | "description": "Universal fitment and easy to install no special wires, can be easily installed and removed. Fits most standard tyre air stem valves of road, mountain bicycles, motocycles and cars.Bright led will turn on w", 1633 | "price": 35, 1634 | "discountPercentage": 11.08, 1635 | "rating": 4.1, 1636 | "stock": 63, 1637 | "brand": "Neon LED Light", 1638 | "category": "automotive", 1639 | "thumbnail": "https://i.dummyjson.com/data/products/90/thumbnail.jpg", 1640 | "images": [ 1641 | "https://i.dummyjson.com/data/products/90/1.jpg", 1642 | "https://i.dummyjson.com/data/products/90/2.jpg", 1643 | "https://i.dummyjson.com/data/products/90/3.jpg", 1644 | "https://i.dummyjson.com/data/products/90/4.jpg", 1645 | "https://i.dummyjson.com/data/products/90/thumbnail.jpg" 1646 | ] 1647 | }, 1648 | { 1649 | "id": 91, 1650 | "title": "Black Motorbike", 1651 | "description": "Engine Type:Wet sump, Single Cylinder, Four Stroke, Two Valves, Air Cooled with SOHC (Single Over Head Cam) Chain Drive Bore & Stroke:47.0 x 49.5 MM", 1652 | "price": 569, 1653 | "discountPercentage": 13.63, 1654 | "rating": 4.04, 1655 | "stock": 115, 1656 | "brand": "METRO 70cc Motorcycle - MR70", 1657 | "category": "motorcycle", 1658 | "thumbnail": "https://i.dummyjson.com/data/products/91/thumbnail.jpg", 1659 | "images": [ 1660 | "https://i.dummyjson.com/data/products/91/1.jpg", 1661 | "https://i.dummyjson.com/data/products/91/2.jpg", 1662 | "https://i.dummyjson.com/data/products/91/3.jpg", 1663 | "https://i.dummyjson.com/data/products/91/4.jpg", 1664 | "https://i.dummyjson.com/data/products/91/thumbnail.jpg" 1665 | ] 1666 | }, 1667 | { 1668 | "id": 92, 1669 | "title": "HOT SALE IN EUROPE electric racing motorcycle", 1670 | "description": "HOT SALE IN EUROPE electric racing motorcycle electric motorcycle for sale adult electric motorcycles", 1671 | "price": 920, 1672 | "discountPercentage": 14.4, 1673 | "rating": 4.19, 1674 | "stock": 22, 1675 | "brand": "BRAVE BULL", 1676 | "category": "motorcycle", 1677 | "thumbnail": "https://i.dummyjson.com/data/products/92/thumbnail.jpg", 1678 | "images": [ 1679 | "https://i.dummyjson.com/data/products/92/1.jpg", 1680 | "https://i.dummyjson.com/data/products/92/2.jpg", 1681 | "https://i.dummyjson.com/data/products/92/3.jpg", 1682 | "https://i.dummyjson.com/data/products/92/4.jpg" 1683 | ] 1684 | }, 1685 | { 1686 | "id": 93, 1687 | "title": "Automatic Motor Gas Motorcycles", 1688 | "description": "150cc 4-Stroke Motorcycle Automatic Motor Gas Motorcycles Scooter motorcycles 150cc scooter", 1689 | "price": 1050, 1690 | "discountPercentage": 3.34, 1691 | "rating": 4.84, 1692 | "stock": 127, 1693 | "brand": "shock absorber", 1694 | "category": "motorcycle", 1695 | "thumbnail": "https://i.dummyjson.com/data/products/93/thumbnail.jpg", 1696 | "images": [ 1697 | "https://i.dummyjson.com/data/products/93/1.jpg", 1698 | "https://i.dummyjson.com/data/products/93/2.jpg", 1699 | "https://i.dummyjson.com/data/products/93/3.jpg", 1700 | "https://i.dummyjson.com/data/products/93/4.jpg", 1701 | "https://i.dummyjson.com/data/products/93/thumbnail.jpg" 1702 | ] 1703 | }, 1704 | { 1705 | "id": 94, 1706 | "title": "new arrivals Fashion motocross goggles", 1707 | "description": "new arrivals Fashion motocross goggles motorcycle motocross racing motorcycle", 1708 | "price": 900, 1709 | "discountPercentage": 3.85, 1710 | "rating": 4.06, 1711 | "stock": 109, 1712 | "brand": "JIEPOLLY", 1713 | "category": "motorcycle", 1714 | "thumbnail": "https://i.dummyjson.com/data/products/94/thumbnail.webp", 1715 | "images": [ 1716 | "https://i.dummyjson.com/data/products/94/1.webp", 1717 | "https://i.dummyjson.com/data/products/94/2.jpg", 1718 | "https://i.dummyjson.com/data/products/94/3.jpg", 1719 | "https://i.dummyjson.com/data/products/94/thumbnail.webp" 1720 | ] 1721 | }, 1722 | { 1723 | "id": 95, 1724 | "title": "Wholesale cargo lashing Belt", 1725 | "description": "Wholesale cargo lashing Belt Tie Down end Ratchet strap customized strap 25mm motorcycle 1500kgs with rubber handle", 1726 | "price": 930, 1727 | "discountPercentage": 17.67, 1728 | "rating": 4.21, 1729 | "stock": 144, 1730 | "brand": "Xiangle", 1731 | "category": "motorcycle", 1732 | "thumbnail": "https://i.dummyjson.com/data/products/95/thumbnail.jpg", 1733 | "images": [ 1734 | "https://i.dummyjson.com/data/products/95/1.jpg", 1735 | "https://i.dummyjson.com/data/products/95/2.jpg", 1736 | "https://i.dummyjson.com/data/products/95/3.jpg", 1737 | "https://i.dummyjson.com/data/products/95/4.jpg", 1738 | "https://i.dummyjson.com/data/products/95/thumbnail.jpg" 1739 | ] 1740 | }, 1741 | { 1742 | "id": 96, 1743 | "title": "lighting ceiling kitchen", 1744 | "description": "Wholesale slim hanging decorative kid room lighting ceiling kitchen chandeliers pendant light modern", 1745 | "price": 30, 1746 | "discountPercentage": 14.89, 1747 | "rating": 4.83, 1748 | "stock": 96, 1749 | "brand": "lightingbrilliance", 1750 | "category": "lighting", 1751 | "thumbnail": "https://i.dummyjson.com/data/products/96/thumbnail.jpg", 1752 | "images": [ 1753 | "https://i.dummyjson.com/data/products/96/1.jpg", 1754 | "https://i.dummyjson.com/data/products/96/2.jpg", 1755 | "https://i.dummyjson.com/data/products/96/3.jpg", 1756 | "https://i.dummyjson.com/data/products/96/4.jpg", 1757 | "https://i.dummyjson.com/data/products/96/thumbnail.jpg" 1758 | ] 1759 | }, 1760 | { 1761 | "id": 97, 1762 | "title": "Metal Ceramic Flower", 1763 | "description": "Metal Ceramic Flower Chandelier Home Lighting American Vintage Hanging Lighting Pendant Lamp", 1764 | "price": 35, 1765 | "discountPercentage": 10.94, 1766 | "rating": 4.93, 1767 | "stock": 146, 1768 | "brand": "Ifei Home", 1769 | "category": "lighting", 1770 | "thumbnail": "https://i.dummyjson.com/data/products/97/thumbnail.jpg", 1771 | "images": [ 1772 | "https://i.dummyjson.com/data/products/97/1.jpg", 1773 | "https://i.dummyjson.com/data/products/97/2.jpg", 1774 | "https://i.dummyjson.com/data/products/97/3.jpg", 1775 | "https://i.dummyjson.com/data/products/97/4.webp", 1776 | "https://i.dummyjson.com/data/products/97/thumbnail.jpg" 1777 | ] 1778 | }, 1779 | { 1780 | "id": 98, 1781 | "title": "3 lights lndenpant kitchen islang", 1782 | "description": "3 lights lndenpant kitchen islang dining room pendant rice paper chandelier contemporary led pendant light modern chandelier", 1783 | "price": 34, 1784 | "discountPercentage": 5.92, 1785 | "rating": 4.99, 1786 | "stock": 44, 1787 | "brand": "DADAWU", 1788 | "category": "lighting", 1789 | "thumbnail": "https://i.dummyjson.com/data/products/98/thumbnail.jpg", 1790 | "images": [ 1791 | "https://i.dummyjson.com/data/products/98/1.jpg", 1792 | "https://i.dummyjson.com/data/products/98/2.jpg", 1793 | "https://i.dummyjson.com/data/products/98/3.jpg", 1794 | "https://i.dummyjson.com/data/products/98/4.jpg", 1795 | "https://i.dummyjson.com/data/products/98/thumbnail.jpg" 1796 | ] 1797 | }, 1798 | { 1799 | "id": 99, 1800 | "title": "American Vintage Wood Pendant Light", 1801 | "description": "American Vintage Wood Pendant Light Farmhouse Antique Hanging Lamp Lampara Colgante", 1802 | "price": 46, 1803 | "discountPercentage": 8.84, 1804 | "rating": 4.32, 1805 | "stock": 138, 1806 | "brand": "Ifei Home", 1807 | "category": "lighting", 1808 | "thumbnail": "https://i.dummyjson.com/data/products/99/thumbnail.jpg", 1809 | "images": [ 1810 | "https://i.dummyjson.com/data/products/99/1.jpg", 1811 | "https://i.dummyjson.com/data/products/99/2.jpg", 1812 | "https://i.dummyjson.com/data/products/99/3.jpg", 1813 | "https://i.dummyjson.com/data/products/99/4.jpg", 1814 | "https://i.dummyjson.com/data/products/99/thumbnail.jpg" 1815 | ] 1816 | }, 1817 | { 1818 | "id": 100, 1819 | "title": "Crystal chandelier maria theresa for 12 light", 1820 | "description": "Crystal chandelier maria theresa for 12 light", 1821 | "price": 47, 1822 | "discountPercentage": 16, 1823 | "rating": 4.74, 1824 | "stock": 133, 1825 | "brand": "YIOSI", 1826 | "category": "lighting", 1827 | "thumbnail": "https://i.dummyjson.com/data/products/100/thumbnail.jpg", 1828 | "images": [ 1829 | "https://i.dummyjson.com/data/products/100/1.jpg", 1830 | "https://i.dummyjson.com/data/products/100/2.jpg", 1831 | "https://i.dummyjson.com/data/products/100/3.jpg", 1832 | "https://i.dummyjson.com/data/products/100/thumbnail.jpg" 1833 | ] 1834 | } 1835 | ] 1836 | -------------------------------------------------------------------------------- /backend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "backend", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "bcrypt": "^5.1.1", 13 | "cookie-parser": "^1.4.6", 14 | "cors": "^2.8.5", 15 | "dotenv": "^16.3.1", 16 | "express": "^4.18.2", 17 | "jsonwebtoken": "^9.0.2", 18 | "mongoose": "^7.6.2" 19 | }, 20 | "devDependencies": { 21 | "nodemon": "^3.0.1" 22 | } 23 | }, 24 | "node_modules/@mapbox/node-pre-gyp": { 25 | "version": "1.0.11", 26 | "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", 27 | "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", 28 | "dependencies": { 29 | "detect-libc": "^2.0.0", 30 | "https-proxy-agent": "^5.0.0", 31 | "make-dir": "^3.1.0", 32 | "node-fetch": "^2.6.7", 33 | "nopt": "^5.0.0", 34 | "npmlog": "^5.0.1", 35 | "rimraf": "^3.0.2", 36 | "semver": "^7.3.5", 37 | "tar": "^6.1.11" 38 | }, 39 | "bin": { 40 | "node-pre-gyp": "bin/node-pre-gyp" 41 | } 42 | }, 43 | "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { 44 | "version": "5.0.0", 45 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", 46 | "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", 47 | "dependencies": { 48 | "abbrev": "1" 49 | }, 50 | "bin": { 51 | "nopt": "bin/nopt.js" 52 | }, 53 | "engines": { 54 | "node": ">=6" 55 | } 56 | }, 57 | "node_modules/@mongodb-js/saslprep": { 58 | "version": "1.1.0", 59 | "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", 60 | "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", 61 | "optional": true, 62 | "dependencies": { 63 | "sparse-bitfield": "^3.0.3" 64 | } 65 | }, 66 | "node_modules/@types/node": { 67 | "version": "20.8.6", 68 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", 69 | "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", 70 | "dependencies": { 71 | "undici-types": "~5.25.1" 72 | } 73 | }, 74 | "node_modules/@types/webidl-conversions": { 75 | "version": "7.0.1", 76 | "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.1.tgz", 77 | "integrity": "sha512-8hKOnOan+Uu+NgMaCouhg3cT9x5fFZ92Jwf+uDLXLu/MFRbXxlWwGeQY7KVHkeSft6RvY+tdxklUBuyY9eIEKg==" 78 | }, 79 | "node_modules/@types/whatwg-url": { 80 | "version": "8.2.2", 81 | "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", 82 | "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", 83 | "dependencies": { 84 | "@types/node": "*", 85 | "@types/webidl-conversions": "*" 86 | } 87 | }, 88 | "node_modules/abbrev": { 89 | "version": "1.1.1", 90 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 91 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 92 | }, 93 | "node_modules/accepts": { 94 | "version": "1.3.8", 95 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 96 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 97 | "dependencies": { 98 | "mime-types": "~2.1.34", 99 | "negotiator": "0.6.3" 100 | }, 101 | "engines": { 102 | "node": ">= 0.6" 103 | } 104 | }, 105 | "node_modules/agent-base": { 106 | "version": "6.0.2", 107 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 108 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 109 | "dependencies": { 110 | "debug": "4" 111 | }, 112 | "engines": { 113 | "node": ">= 6.0.0" 114 | } 115 | }, 116 | "node_modules/agent-base/node_modules/debug": { 117 | "version": "4.3.4", 118 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 119 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 120 | "dependencies": { 121 | "ms": "2.1.2" 122 | }, 123 | "engines": { 124 | "node": ">=6.0" 125 | }, 126 | "peerDependenciesMeta": { 127 | "supports-color": { 128 | "optional": true 129 | } 130 | } 131 | }, 132 | "node_modules/agent-base/node_modules/ms": { 133 | "version": "2.1.2", 134 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 135 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 136 | }, 137 | "node_modules/ansi-regex": { 138 | "version": "5.0.1", 139 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 140 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 141 | "engines": { 142 | "node": ">=8" 143 | } 144 | }, 145 | "node_modules/anymatch": { 146 | "version": "3.1.3", 147 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 148 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 149 | "dev": true, 150 | "dependencies": { 151 | "normalize-path": "^3.0.0", 152 | "picomatch": "^2.0.4" 153 | }, 154 | "engines": { 155 | "node": ">= 8" 156 | } 157 | }, 158 | "node_modules/aproba": { 159 | "version": "2.0.0", 160 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", 161 | "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" 162 | }, 163 | "node_modules/are-we-there-yet": { 164 | "version": "2.0.0", 165 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", 166 | "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", 167 | "dependencies": { 168 | "delegates": "^1.0.0", 169 | "readable-stream": "^3.6.0" 170 | }, 171 | "engines": { 172 | "node": ">=10" 173 | } 174 | }, 175 | "node_modules/array-flatten": { 176 | "version": "1.1.1", 177 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 178 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 179 | }, 180 | "node_modules/balanced-match": { 181 | "version": "1.0.2", 182 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 183 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 184 | }, 185 | "node_modules/bcrypt": { 186 | "version": "5.1.1", 187 | "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", 188 | "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", 189 | "hasInstallScript": true, 190 | "dependencies": { 191 | "@mapbox/node-pre-gyp": "^1.0.11", 192 | "node-addon-api": "^5.0.0" 193 | }, 194 | "engines": { 195 | "node": ">= 10.0.0" 196 | } 197 | }, 198 | "node_modules/binary-extensions": { 199 | "version": "2.2.0", 200 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 201 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 202 | "dev": true, 203 | "engines": { 204 | "node": ">=8" 205 | } 206 | }, 207 | "node_modules/body-parser": { 208 | "version": "1.20.1", 209 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 210 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 211 | "dependencies": { 212 | "bytes": "3.1.2", 213 | "content-type": "~1.0.4", 214 | "debug": "2.6.9", 215 | "depd": "2.0.0", 216 | "destroy": "1.2.0", 217 | "http-errors": "2.0.0", 218 | "iconv-lite": "0.4.24", 219 | "on-finished": "2.4.1", 220 | "qs": "6.11.0", 221 | "raw-body": "2.5.1", 222 | "type-is": "~1.6.18", 223 | "unpipe": "1.0.0" 224 | }, 225 | "engines": { 226 | "node": ">= 0.8", 227 | "npm": "1.2.8000 || >= 1.4.16" 228 | } 229 | }, 230 | "node_modules/body-parser/node_modules/debug": { 231 | "version": "2.6.9", 232 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 233 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 234 | "dependencies": { 235 | "ms": "2.0.0" 236 | } 237 | }, 238 | "node_modules/body-parser/node_modules/ms": { 239 | "version": "2.0.0", 240 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 241 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 242 | }, 243 | "node_modules/brace-expansion": { 244 | "version": "1.1.11", 245 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 246 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 247 | "dependencies": { 248 | "balanced-match": "^1.0.0", 249 | "concat-map": "0.0.1" 250 | } 251 | }, 252 | "node_modules/braces": { 253 | "version": "3.0.2", 254 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 255 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 256 | "dev": true, 257 | "dependencies": { 258 | "fill-range": "^7.0.1" 259 | }, 260 | "engines": { 261 | "node": ">=8" 262 | } 263 | }, 264 | "node_modules/bson": { 265 | "version": "5.5.0", 266 | "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.0.tgz", 267 | "integrity": "sha512-B+QB4YmDx9RStKv8LLSl/aVIEV3nYJc3cJNNTK2Cd1TL+7P+cNpw9mAPeCgc5K+j01Dv6sxUzcITXDx7ZU3F0w==", 268 | "engines": { 269 | "node": ">=14.20.1" 270 | } 271 | }, 272 | "node_modules/buffer-equal-constant-time": { 273 | "version": "1.0.1", 274 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 275 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" 276 | }, 277 | "node_modules/bytes": { 278 | "version": "3.1.2", 279 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 280 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 281 | "engines": { 282 | "node": ">= 0.8" 283 | } 284 | }, 285 | "node_modules/call-bind": { 286 | "version": "1.0.2", 287 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 288 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 289 | "dependencies": { 290 | "function-bind": "^1.1.1", 291 | "get-intrinsic": "^1.0.2" 292 | }, 293 | "funding": { 294 | "url": "https://github.com/sponsors/ljharb" 295 | } 296 | }, 297 | "node_modules/chokidar": { 298 | "version": "3.5.3", 299 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 300 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 301 | "dev": true, 302 | "funding": [ 303 | { 304 | "type": "individual", 305 | "url": "https://paulmillr.com/funding/" 306 | } 307 | ], 308 | "dependencies": { 309 | "anymatch": "~3.1.2", 310 | "braces": "~3.0.2", 311 | "glob-parent": "~5.1.2", 312 | "is-binary-path": "~2.1.0", 313 | "is-glob": "~4.0.1", 314 | "normalize-path": "~3.0.0", 315 | "readdirp": "~3.6.0" 316 | }, 317 | "engines": { 318 | "node": ">= 8.10.0" 319 | }, 320 | "optionalDependencies": { 321 | "fsevents": "~2.3.2" 322 | } 323 | }, 324 | "node_modules/chownr": { 325 | "version": "2.0.0", 326 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", 327 | "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", 328 | "engines": { 329 | "node": ">=10" 330 | } 331 | }, 332 | "node_modules/color-support": { 333 | "version": "1.1.3", 334 | "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", 335 | "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", 336 | "bin": { 337 | "color-support": "bin.js" 338 | } 339 | }, 340 | "node_modules/concat-map": { 341 | "version": "0.0.1", 342 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 343 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 344 | }, 345 | "node_modules/console-control-strings": { 346 | "version": "1.1.0", 347 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 348 | "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" 349 | }, 350 | "node_modules/content-disposition": { 351 | "version": "0.5.4", 352 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 353 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 354 | "dependencies": { 355 | "safe-buffer": "5.2.1" 356 | }, 357 | "engines": { 358 | "node": ">= 0.6" 359 | } 360 | }, 361 | "node_modules/content-type": { 362 | "version": "1.0.5", 363 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 364 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 365 | "engines": { 366 | "node": ">= 0.6" 367 | } 368 | }, 369 | "node_modules/cookie": { 370 | "version": "0.5.0", 371 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 372 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 373 | "engines": { 374 | "node": ">= 0.6" 375 | } 376 | }, 377 | "node_modules/cookie-parser": { 378 | "version": "1.4.6", 379 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", 380 | "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", 381 | "dependencies": { 382 | "cookie": "0.4.1", 383 | "cookie-signature": "1.0.6" 384 | }, 385 | "engines": { 386 | "node": ">= 0.8.0" 387 | } 388 | }, 389 | "node_modules/cookie-parser/node_modules/cookie": { 390 | "version": "0.4.1", 391 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 392 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", 393 | "engines": { 394 | "node": ">= 0.6" 395 | } 396 | }, 397 | "node_modules/cookie-signature": { 398 | "version": "1.0.6", 399 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 400 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 401 | }, 402 | "node_modules/cors": { 403 | "version": "2.8.5", 404 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 405 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 406 | "dependencies": { 407 | "object-assign": "^4", 408 | "vary": "^1" 409 | }, 410 | "engines": { 411 | "node": ">= 0.10" 412 | } 413 | }, 414 | "node_modules/debug": { 415 | "version": "3.2.7", 416 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 417 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 418 | "dev": true, 419 | "dependencies": { 420 | "ms": "^2.1.1" 421 | } 422 | }, 423 | "node_modules/delegates": { 424 | "version": "1.0.0", 425 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", 426 | "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" 427 | }, 428 | "node_modules/depd": { 429 | "version": "2.0.0", 430 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 431 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 432 | "engines": { 433 | "node": ">= 0.8" 434 | } 435 | }, 436 | "node_modules/destroy": { 437 | "version": "1.2.0", 438 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 439 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 440 | "engines": { 441 | "node": ">= 0.8", 442 | "npm": "1.2.8000 || >= 1.4.16" 443 | } 444 | }, 445 | "node_modules/detect-libc": { 446 | "version": "2.0.2", 447 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", 448 | "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", 449 | "engines": { 450 | "node": ">=8" 451 | } 452 | }, 453 | "node_modules/dotenv": { 454 | "version": "16.3.1", 455 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", 456 | "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", 457 | "engines": { 458 | "node": ">=12" 459 | }, 460 | "funding": { 461 | "url": "https://github.com/motdotla/dotenv?sponsor=1" 462 | } 463 | }, 464 | "node_modules/ecdsa-sig-formatter": { 465 | "version": "1.0.11", 466 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 467 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 468 | "dependencies": { 469 | "safe-buffer": "^5.0.1" 470 | } 471 | }, 472 | "node_modules/ee-first": { 473 | "version": "1.1.1", 474 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 475 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 476 | }, 477 | "node_modules/emoji-regex": { 478 | "version": "8.0.0", 479 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 480 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 481 | }, 482 | "node_modules/encodeurl": { 483 | "version": "1.0.2", 484 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 485 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 486 | "engines": { 487 | "node": ">= 0.8" 488 | } 489 | }, 490 | "node_modules/escape-html": { 491 | "version": "1.0.3", 492 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 493 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 494 | }, 495 | "node_modules/etag": { 496 | "version": "1.8.1", 497 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 498 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 499 | "engines": { 500 | "node": ">= 0.6" 501 | } 502 | }, 503 | "node_modules/express": { 504 | "version": "4.18.2", 505 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 506 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 507 | "dependencies": { 508 | "accepts": "~1.3.8", 509 | "array-flatten": "1.1.1", 510 | "body-parser": "1.20.1", 511 | "content-disposition": "0.5.4", 512 | "content-type": "~1.0.4", 513 | "cookie": "0.5.0", 514 | "cookie-signature": "1.0.6", 515 | "debug": "2.6.9", 516 | "depd": "2.0.0", 517 | "encodeurl": "~1.0.2", 518 | "escape-html": "~1.0.3", 519 | "etag": "~1.8.1", 520 | "finalhandler": "1.2.0", 521 | "fresh": "0.5.2", 522 | "http-errors": "2.0.0", 523 | "merge-descriptors": "1.0.1", 524 | "methods": "~1.1.2", 525 | "on-finished": "2.4.1", 526 | "parseurl": "~1.3.3", 527 | "path-to-regexp": "0.1.7", 528 | "proxy-addr": "~2.0.7", 529 | "qs": "6.11.0", 530 | "range-parser": "~1.2.1", 531 | "safe-buffer": "5.2.1", 532 | "send": "0.18.0", 533 | "serve-static": "1.15.0", 534 | "setprototypeof": "1.2.0", 535 | "statuses": "2.0.1", 536 | "type-is": "~1.6.18", 537 | "utils-merge": "1.0.1", 538 | "vary": "~1.1.2" 539 | }, 540 | "engines": { 541 | "node": ">= 0.10.0" 542 | } 543 | }, 544 | "node_modules/express/node_modules/debug": { 545 | "version": "2.6.9", 546 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 547 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 548 | "dependencies": { 549 | "ms": "2.0.0" 550 | } 551 | }, 552 | "node_modules/express/node_modules/ms": { 553 | "version": "2.0.0", 554 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 555 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 556 | }, 557 | "node_modules/fill-range": { 558 | "version": "7.0.1", 559 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 560 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 561 | "dev": true, 562 | "dependencies": { 563 | "to-regex-range": "^5.0.1" 564 | }, 565 | "engines": { 566 | "node": ">=8" 567 | } 568 | }, 569 | "node_modules/finalhandler": { 570 | "version": "1.2.0", 571 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 572 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 573 | "dependencies": { 574 | "debug": "2.6.9", 575 | "encodeurl": "~1.0.2", 576 | "escape-html": "~1.0.3", 577 | "on-finished": "2.4.1", 578 | "parseurl": "~1.3.3", 579 | "statuses": "2.0.1", 580 | "unpipe": "~1.0.0" 581 | }, 582 | "engines": { 583 | "node": ">= 0.8" 584 | } 585 | }, 586 | "node_modules/finalhandler/node_modules/debug": { 587 | "version": "2.6.9", 588 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 589 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 590 | "dependencies": { 591 | "ms": "2.0.0" 592 | } 593 | }, 594 | "node_modules/finalhandler/node_modules/ms": { 595 | "version": "2.0.0", 596 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 597 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 598 | }, 599 | "node_modules/forwarded": { 600 | "version": "0.2.0", 601 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 602 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 603 | "engines": { 604 | "node": ">= 0.6" 605 | } 606 | }, 607 | "node_modules/fresh": { 608 | "version": "0.5.2", 609 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 610 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 611 | "engines": { 612 | "node": ">= 0.6" 613 | } 614 | }, 615 | "node_modules/fs-minipass": { 616 | "version": "2.1.0", 617 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", 618 | "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", 619 | "dependencies": { 620 | "minipass": "^3.0.0" 621 | }, 622 | "engines": { 623 | "node": ">= 8" 624 | } 625 | }, 626 | "node_modules/fs-minipass/node_modules/minipass": { 627 | "version": "3.3.6", 628 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 629 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 630 | "dependencies": { 631 | "yallist": "^4.0.0" 632 | }, 633 | "engines": { 634 | "node": ">=8" 635 | } 636 | }, 637 | "node_modules/fs.realpath": { 638 | "version": "1.0.0", 639 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 640 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 641 | }, 642 | "node_modules/fsevents": { 643 | "version": "2.3.3", 644 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 645 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 646 | "dev": true, 647 | "hasInstallScript": true, 648 | "optional": true, 649 | "os": [ 650 | "darwin" 651 | ], 652 | "engines": { 653 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 654 | } 655 | }, 656 | "node_modules/function-bind": { 657 | "version": "1.1.2", 658 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 659 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 660 | "funding": { 661 | "url": "https://github.com/sponsors/ljharb" 662 | } 663 | }, 664 | "node_modules/gauge": { 665 | "version": "3.0.2", 666 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", 667 | "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", 668 | "dependencies": { 669 | "aproba": "^1.0.3 || ^2.0.0", 670 | "color-support": "^1.1.2", 671 | "console-control-strings": "^1.0.0", 672 | "has-unicode": "^2.0.1", 673 | "object-assign": "^4.1.1", 674 | "signal-exit": "^3.0.0", 675 | "string-width": "^4.2.3", 676 | "strip-ansi": "^6.0.1", 677 | "wide-align": "^1.1.2" 678 | }, 679 | "engines": { 680 | "node": ">=10" 681 | } 682 | }, 683 | "node_modules/get-intrinsic": { 684 | "version": "1.2.1", 685 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", 686 | "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", 687 | "dependencies": { 688 | "function-bind": "^1.1.1", 689 | "has": "^1.0.3", 690 | "has-proto": "^1.0.1", 691 | "has-symbols": "^1.0.3" 692 | }, 693 | "funding": { 694 | "url": "https://github.com/sponsors/ljharb" 695 | } 696 | }, 697 | "node_modules/glob": { 698 | "version": "7.2.3", 699 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 700 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 701 | "dependencies": { 702 | "fs.realpath": "^1.0.0", 703 | "inflight": "^1.0.4", 704 | "inherits": "2", 705 | "minimatch": "^3.1.1", 706 | "once": "^1.3.0", 707 | "path-is-absolute": "^1.0.0" 708 | }, 709 | "engines": { 710 | "node": "*" 711 | }, 712 | "funding": { 713 | "url": "https://github.com/sponsors/isaacs" 714 | } 715 | }, 716 | "node_modules/glob-parent": { 717 | "version": "5.1.2", 718 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 719 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 720 | "dev": true, 721 | "dependencies": { 722 | "is-glob": "^4.0.1" 723 | }, 724 | "engines": { 725 | "node": ">= 6" 726 | } 727 | }, 728 | "node_modules/has": { 729 | "version": "1.0.4", 730 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", 731 | "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", 732 | "engines": { 733 | "node": ">= 0.4.0" 734 | } 735 | }, 736 | "node_modules/has-flag": { 737 | "version": "3.0.0", 738 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 739 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 740 | "dev": true, 741 | "engines": { 742 | "node": ">=4" 743 | } 744 | }, 745 | "node_modules/has-proto": { 746 | "version": "1.0.1", 747 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 748 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 749 | "engines": { 750 | "node": ">= 0.4" 751 | }, 752 | "funding": { 753 | "url": "https://github.com/sponsors/ljharb" 754 | } 755 | }, 756 | "node_modules/has-symbols": { 757 | "version": "1.0.3", 758 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 759 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 760 | "engines": { 761 | "node": ">= 0.4" 762 | }, 763 | "funding": { 764 | "url": "https://github.com/sponsors/ljharb" 765 | } 766 | }, 767 | "node_modules/has-unicode": { 768 | "version": "2.0.1", 769 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 770 | "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" 771 | }, 772 | "node_modules/http-errors": { 773 | "version": "2.0.0", 774 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 775 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 776 | "dependencies": { 777 | "depd": "2.0.0", 778 | "inherits": "2.0.4", 779 | "setprototypeof": "1.2.0", 780 | "statuses": "2.0.1", 781 | "toidentifier": "1.0.1" 782 | }, 783 | "engines": { 784 | "node": ">= 0.8" 785 | } 786 | }, 787 | "node_modules/https-proxy-agent": { 788 | "version": "5.0.1", 789 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 790 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 791 | "dependencies": { 792 | "agent-base": "6", 793 | "debug": "4" 794 | }, 795 | "engines": { 796 | "node": ">= 6" 797 | } 798 | }, 799 | "node_modules/https-proxy-agent/node_modules/debug": { 800 | "version": "4.3.4", 801 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 802 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 803 | "dependencies": { 804 | "ms": "2.1.2" 805 | }, 806 | "engines": { 807 | "node": ">=6.0" 808 | }, 809 | "peerDependenciesMeta": { 810 | "supports-color": { 811 | "optional": true 812 | } 813 | } 814 | }, 815 | "node_modules/https-proxy-agent/node_modules/ms": { 816 | "version": "2.1.2", 817 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 818 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 819 | }, 820 | "node_modules/iconv-lite": { 821 | "version": "0.4.24", 822 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 823 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 824 | "dependencies": { 825 | "safer-buffer": ">= 2.1.2 < 3" 826 | }, 827 | "engines": { 828 | "node": ">=0.10.0" 829 | } 830 | }, 831 | "node_modules/ignore-by-default": { 832 | "version": "1.0.1", 833 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 834 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", 835 | "dev": true 836 | }, 837 | "node_modules/inflight": { 838 | "version": "1.0.6", 839 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 840 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 841 | "dependencies": { 842 | "once": "^1.3.0", 843 | "wrappy": "1" 844 | } 845 | }, 846 | "node_modules/inherits": { 847 | "version": "2.0.4", 848 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 849 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 850 | }, 851 | "node_modules/ip": { 852 | "version": "2.0.0", 853 | "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", 854 | "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" 855 | }, 856 | "node_modules/ipaddr.js": { 857 | "version": "1.9.1", 858 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 859 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 860 | "engines": { 861 | "node": ">= 0.10" 862 | } 863 | }, 864 | "node_modules/is-binary-path": { 865 | "version": "2.1.0", 866 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 867 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 868 | "dev": true, 869 | "dependencies": { 870 | "binary-extensions": "^2.0.0" 871 | }, 872 | "engines": { 873 | "node": ">=8" 874 | } 875 | }, 876 | "node_modules/is-extglob": { 877 | "version": "2.1.1", 878 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 879 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 880 | "dev": true, 881 | "engines": { 882 | "node": ">=0.10.0" 883 | } 884 | }, 885 | "node_modules/is-fullwidth-code-point": { 886 | "version": "3.0.0", 887 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 888 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 889 | "engines": { 890 | "node": ">=8" 891 | } 892 | }, 893 | "node_modules/is-glob": { 894 | "version": "4.0.3", 895 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 896 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 897 | "dev": true, 898 | "dependencies": { 899 | "is-extglob": "^2.1.1" 900 | }, 901 | "engines": { 902 | "node": ">=0.10.0" 903 | } 904 | }, 905 | "node_modules/is-number": { 906 | "version": "7.0.0", 907 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 908 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 909 | "dev": true, 910 | "engines": { 911 | "node": ">=0.12.0" 912 | } 913 | }, 914 | "node_modules/jsonwebtoken": { 915 | "version": "9.0.2", 916 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", 917 | "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", 918 | "dependencies": { 919 | "jws": "^3.2.2", 920 | "lodash.includes": "^4.3.0", 921 | "lodash.isboolean": "^3.0.3", 922 | "lodash.isinteger": "^4.0.4", 923 | "lodash.isnumber": "^3.0.3", 924 | "lodash.isplainobject": "^4.0.6", 925 | "lodash.isstring": "^4.0.1", 926 | "lodash.once": "^4.0.0", 927 | "ms": "^2.1.1", 928 | "semver": "^7.5.4" 929 | }, 930 | "engines": { 931 | "node": ">=12", 932 | "npm": ">=6" 933 | } 934 | }, 935 | "node_modules/jwa": { 936 | "version": "1.4.1", 937 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 938 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 939 | "dependencies": { 940 | "buffer-equal-constant-time": "1.0.1", 941 | "ecdsa-sig-formatter": "1.0.11", 942 | "safe-buffer": "^5.0.1" 943 | } 944 | }, 945 | "node_modules/jws": { 946 | "version": "3.2.2", 947 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 948 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 949 | "dependencies": { 950 | "jwa": "^1.4.1", 951 | "safe-buffer": "^5.0.1" 952 | } 953 | }, 954 | "node_modules/kareem": { 955 | "version": "2.5.1", 956 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", 957 | "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", 958 | "engines": { 959 | "node": ">=12.0.0" 960 | } 961 | }, 962 | "node_modules/lodash.includes": { 963 | "version": "4.3.0", 964 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 965 | "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" 966 | }, 967 | "node_modules/lodash.isboolean": { 968 | "version": "3.0.3", 969 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 970 | "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" 971 | }, 972 | "node_modules/lodash.isinteger": { 973 | "version": "4.0.4", 974 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 975 | "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" 976 | }, 977 | "node_modules/lodash.isnumber": { 978 | "version": "3.0.3", 979 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 980 | "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" 981 | }, 982 | "node_modules/lodash.isplainobject": { 983 | "version": "4.0.6", 984 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 985 | "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" 986 | }, 987 | "node_modules/lodash.isstring": { 988 | "version": "4.0.1", 989 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 990 | "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" 991 | }, 992 | "node_modules/lodash.once": { 993 | "version": "4.1.1", 994 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 995 | "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" 996 | }, 997 | "node_modules/lru-cache": { 998 | "version": "6.0.0", 999 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1000 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1001 | "dependencies": { 1002 | "yallist": "^4.0.0" 1003 | }, 1004 | "engines": { 1005 | "node": ">=10" 1006 | } 1007 | }, 1008 | "node_modules/make-dir": { 1009 | "version": "3.1.0", 1010 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 1011 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 1012 | "dependencies": { 1013 | "semver": "^6.0.0" 1014 | }, 1015 | "engines": { 1016 | "node": ">=8" 1017 | }, 1018 | "funding": { 1019 | "url": "https://github.com/sponsors/sindresorhus" 1020 | } 1021 | }, 1022 | "node_modules/make-dir/node_modules/semver": { 1023 | "version": "6.3.1", 1024 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 1025 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 1026 | "bin": { 1027 | "semver": "bin/semver.js" 1028 | } 1029 | }, 1030 | "node_modules/media-typer": { 1031 | "version": "0.3.0", 1032 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1033 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 1034 | "engines": { 1035 | "node": ">= 0.6" 1036 | } 1037 | }, 1038 | "node_modules/memory-pager": { 1039 | "version": "1.5.0", 1040 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 1041 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 1042 | "optional": true 1043 | }, 1044 | "node_modules/merge-descriptors": { 1045 | "version": "1.0.1", 1046 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1047 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 1048 | }, 1049 | "node_modules/methods": { 1050 | "version": "1.1.2", 1051 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1052 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 1053 | "engines": { 1054 | "node": ">= 0.6" 1055 | } 1056 | }, 1057 | "node_modules/mime": { 1058 | "version": "1.6.0", 1059 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1060 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 1061 | "bin": { 1062 | "mime": "cli.js" 1063 | }, 1064 | "engines": { 1065 | "node": ">=4" 1066 | } 1067 | }, 1068 | "node_modules/mime-db": { 1069 | "version": "1.52.0", 1070 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1071 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1072 | "engines": { 1073 | "node": ">= 0.6" 1074 | } 1075 | }, 1076 | "node_modules/mime-types": { 1077 | "version": "2.1.35", 1078 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1079 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1080 | "dependencies": { 1081 | "mime-db": "1.52.0" 1082 | }, 1083 | "engines": { 1084 | "node": ">= 0.6" 1085 | } 1086 | }, 1087 | "node_modules/minimatch": { 1088 | "version": "3.1.2", 1089 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1090 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1091 | "dependencies": { 1092 | "brace-expansion": "^1.1.7" 1093 | }, 1094 | "engines": { 1095 | "node": "*" 1096 | } 1097 | }, 1098 | "node_modules/minipass": { 1099 | "version": "5.0.0", 1100 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 1101 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 1102 | "engines": { 1103 | "node": ">=8" 1104 | } 1105 | }, 1106 | "node_modules/minizlib": { 1107 | "version": "2.1.2", 1108 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", 1109 | "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", 1110 | "dependencies": { 1111 | "minipass": "^3.0.0", 1112 | "yallist": "^4.0.0" 1113 | }, 1114 | "engines": { 1115 | "node": ">= 8" 1116 | } 1117 | }, 1118 | "node_modules/minizlib/node_modules/minipass": { 1119 | "version": "3.3.6", 1120 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 1121 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 1122 | "dependencies": { 1123 | "yallist": "^4.0.0" 1124 | }, 1125 | "engines": { 1126 | "node": ">=8" 1127 | } 1128 | }, 1129 | "node_modules/mkdirp": { 1130 | "version": "1.0.4", 1131 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 1132 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", 1133 | "bin": { 1134 | "mkdirp": "bin/cmd.js" 1135 | }, 1136 | "engines": { 1137 | "node": ">=10" 1138 | } 1139 | }, 1140 | "node_modules/mongodb": { 1141 | "version": "5.9.0", 1142 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", 1143 | "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", 1144 | "dependencies": { 1145 | "bson": "^5.5.0", 1146 | "mongodb-connection-string-url": "^2.6.0", 1147 | "socks": "^2.7.1" 1148 | }, 1149 | "engines": { 1150 | "node": ">=14.20.1" 1151 | }, 1152 | "optionalDependencies": { 1153 | "@mongodb-js/saslprep": "^1.1.0" 1154 | }, 1155 | "peerDependencies": { 1156 | "@aws-sdk/credential-providers": "^3.188.0", 1157 | "@mongodb-js/zstd": "^1.0.0", 1158 | "kerberos": "^1.0.0 || ^2.0.0", 1159 | "mongodb-client-encryption": ">=2.3.0 <3", 1160 | "snappy": "^7.2.2" 1161 | }, 1162 | "peerDependenciesMeta": { 1163 | "@aws-sdk/credential-providers": { 1164 | "optional": true 1165 | }, 1166 | "@mongodb-js/zstd": { 1167 | "optional": true 1168 | }, 1169 | "kerberos": { 1170 | "optional": true 1171 | }, 1172 | "mongodb-client-encryption": { 1173 | "optional": true 1174 | }, 1175 | "snappy": { 1176 | "optional": true 1177 | } 1178 | } 1179 | }, 1180 | "node_modules/mongodb-connection-string-url": { 1181 | "version": "2.6.0", 1182 | "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", 1183 | "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", 1184 | "dependencies": { 1185 | "@types/whatwg-url": "^8.2.1", 1186 | "whatwg-url": "^11.0.0" 1187 | } 1188 | }, 1189 | "node_modules/mongodb-connection-string-url/node_modules/tr46": { 1190 | "version": "3.0.0", 1191 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", 1192 | "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", 1193 | "dependencies": { 1194 | "punycode": "^2.1.1" 1195 | }, 1196 | "engines": { 1197 | "node": ">=12" 1198 | } 1199 | }, 1200 | "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { 1201 | "version": "7.0.0", 1202 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 1203 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", 1204 | "engines": { 1205 | "node": ">=12" 1206 | } 1207 | }, 1208 | "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { 1209 | "version": "11.0.0", 1210 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", 1211 | "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", 1212 | "dependencies": { 1213 | "tr46": "^3.0.0", 1214 | "webidl-conversions": "^7.0.0" 1215 | }, 1216 | "engines": { 1217 | "node": ">=12" 1218 | } 1219 | }, 1220 | "node_modules/mongoose": { 1221 | "version": "7.6.2", 1222 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.2.tgz", 1223 | "integrity": "sha512-OVx6RWbfNOzBbfTvXoOkgZmaizdXDU/B/KbBjietXQoInSg/OSULjOavXJzL51XWFkbefqkOvbeE07DfvW6FkQ==", 1224 | "dependencies": { 1225 | "bson": "^5.5.0", 1226 | "kareem": "2.5.1", 1227 | "mongodb": "5.9.0", 1228 | "mpath": "0.9.0", 1229 | "mquery": "5.0.0", 1230 | "ms": "2.1.3", 1231 | "sift": "16.0.1" 1232 | }, 1233 | "engines": { 1234 | "node": ">=14.20.1" 1235 | }, 1236 | "funding": { 1237 | "type": "opencollective", 1238 | "url": "https://opencollective.com/mongoose" 1239 | } 1240 | }, 1241 | "node_modules/mpath": { 1242 | "version": "0.9.0", 1243 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", 1244 | "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", 1245 | "engines": { 1246 | "node": ">=4.0.0" 1247 | } 1248 | }, 1249 | "node_modules/mquery": { 1250 | "version": "5.0.0", 1251 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", 1252 | "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", 1253 | "dependencies": { 1254 | "debug": "4.x" 1255 | }, 1256 | "engines": { 1257 | "node": ">=14.0.0" 1258 | } 1259 | }, 1260 | "node_modules/mquery/node_modules/debug": { 1261 | "version": "4.3.4", 1262 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1263 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1264 | "dependencies": { 1265 | "ms": "2.1.2" 1266 | }, 1267 | "engines": { 1268 | "node": ">=6.0" 1269 | }, 1270 | "peerDependenciesMeta": { 1271 | "supports-color": { 1272 | "optional": true 1273 | } 1274 | } 1275 | }, 1276 | "node_modules/mquery/node_modules/ms": { 1277 | "version": "2.1.2", 1278 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1279 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1280 | }, 1281 | "node_modules/ms": { 1282 | "version": "2.1.3", 1283 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1284 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1285 | }, 1286 | "node_modules/negotiator": { 1287 | "version": "0.6.3", 1288 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1289 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 1290 | "engines": { 1291 | "node": ">= 0.6" 1292 | } 1293 | }, 1294 | "node_modules/node-addon-api": { 1295 | "version": "5.1.0", 1296 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", 1297 | "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" 1298 | }, 1299 | "node_modules/node-fetch": { 1300 | "version": "2.7.0", 1301 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 1302 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 1303 | "dependencies": { 1304 | "whatwg-url": "^5.0.0" 1305 | }, 1306 | "engines": { 1307 | "node": "4.x || >=6.0.0" 1308 | }, 1309 | "peerDependencies": { 1310 | "encoding": "^0.1.0" 1311 | }, 1312 | "peerDependenciesMeta": { 1313 | "encoding": { 1314 | "optional": true 1315 | } 1316 | } 1317 | }, 1318 | "node_modules/nodemon": { 1319 | "version": "3.0.1", 1320 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz", 1321 | "integrity": "sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==", 1322 | "dev": true, 1323 | "dependencies": { 1324 | "chokidar": "^3.5.2", 1325 | "debug": "^3.2.7", 1326 | "ignore-by-default": "^1.0.1", 1327 | "minimatch": "^3.1.2", 1328 | "pstree.remy": "^1.1.8", 1329 | "semver": "^7.5.3", 1330 | "simple-update-notifier": "^2.0.0", 1331 | "supports-color": "^5.5.0", 1332 | "touch": "^3.1.0", 1333 | "undefsafe": "^2.0.5" 1334 | }, 1335 | "bin": { 1336 | "nodemon": "bin/nodemon.js" 1337 | }, 1338 | "engines": { 1339 | "node": ">=10" 1340 | }, 1341 | "funding": { 1342 | "type": "opencollective", 1343 | "url": "https://opencollective.com/nodemon" 1344 | } 1345 | }, 1346 | "node_modules/nopt": { 1347 | "version": "1.0.10", 1348 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 1349 | "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", 1350 | "dev": true, 1351 | "dependencies": { 1352 | "abbrev": "1" 1353 | }, 1354 | "bin": { 1355 | "nopt": "bin/nopt.js" 1356 | }, 1357 | "engines": { 1358 | "node": "*" 1359 | } 1360 | }, 1361 | "node_modules/normalize-path": { 1362 | "version": "3.0.0", 1363 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1364 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1365 | "dev": true, 1366 | "engines": { 1367 | "node": ">=0.10.0" 1368 | } 1369 | }, 1370 | "node_modules/npmlog": { 1371 | "version": "5.0.1", 1372 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", 1373 | "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", 1374 | "dependencies": { 1375 | "are-we-there-yet": "^2.0.0", 1376 | "console-control-strings": "^1.1.0", 1377 | "gauge": "^3.0.0", 1378 | "set-blocking": "^2.0.0" 1379 | } 1380 | }, 1381 | "node_modules/object-assign": { 1382 | "version": "4.1.1", 1383 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1384 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1385 | "engines": { 1386 | "node": ">=0.10.0" 1387 | } 1388 | }, 1389 | "node_modules/object-inspect": { 1390 | "version": "1.13.0", 1391 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", 1392 | "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", 1393 | "funding": { 1394 | "url": "https://github.com/sponsors/ljharb" 1395 | } 1396 | }, 1397 | "node_modules/on-finished": { 1398 | "version": "2.4.1", 1399 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1400 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1401 | "dependencies": { 1402 | "ee-first": "1.1.1" 1403 | }, 1404 | "engines": { 1405 | "node": ">= 0.8" 1406 | } 1407 | }, 1408 | "node_modules/once": { 1409 | "version": "1.4.0", 1410 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1411 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1412 | "dependencies": { 1413 | "wrappy": "1" 1414 | } 1415 | }, 1416 | "node_modules/parseurl": { 1417 | "version": "1.3.3", 1418 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1419 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1420 | "engines": { 1421 | "node": ">= 0.8" 1422 | } 1423 | }, 1424 | "node_modules/path-is-absolute": { 1425 | "version": "1.0.1", 1426 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1427 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1428 | "engines": { 1429 | "node": ">=0.10.0" 1430 | } 1431 | }, 1432 | "node_modules/path-to-regexp": { 1433 | "version": "0.1.7", 1434 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1435 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 1436 | }, 1437 | "node_modules/picomatch": { 1438 | "version": "2.3.1", 1439 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1440 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1441 | "dev": true, 1442 | "engines": { 1443 | "node": ">=8.6" 1444 | }, 1445 | "funding": { 1446 | "url": "https://github.com/sponsors/jonschlinkert" 1447 | } 1448 | }, 1449 | "node_modules/proxy-addr": { 1450 | "version": "2.0.7", 1451 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1452 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1453 | "dependencies": { 1454 | "forwarded": "0.2.0", 1455 | "ipaddr.js": "1.9.1" 1456 | }, 1457 | "engines": { 1458 | "node": ">= 0.10" 1459 | } 1460 | }, 1461 | "node_modules/pstree.remy": { 1462 | "version": "1.1.8", 1463 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 1464 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 1465 | "dev": true 1466 | }, 1467 | "node_modules/punycode": { 1468 | "version": "2.3.0", 1469 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 1470 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 1471 | "engines": { 1472 | "node": ">=6" 1473 | } 1474 | }, 1475 | "node_modules/qs": { 1476 | "version": "6.11.0", 1477 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 1478 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 1479 | "dependencies": { 1480 | "side-channel": "^1.0.4" 1481 | }, 1482 | "engines": { 1483 | "node": ">=0.6" 1484 | }, 1485 | "funding": { 1486 | "url": "https://github.com/sponsors/ljharb" 1487 | } 1488 | }, 1489 | "node_modules/range-parser": { 1490 | "version": "1.2.1", 1491 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1492 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1493 | "engines": { 1494 | "node": ">= 0.6" 1495 | } 1496 | }, 1497 | "node_modules/raw-body": { 1498 | "version": "2.5.1", 1499 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1500 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1501 | "dependencies": { 1502 | "bytes": "3.1.2", 1503 | "http-errors": "2.0.0", 1504 | "iconv-lite": "0.4.24", 1505 | "unpipe": "1.0.0" 1506 | }, 1507 | "engines": { 1508 | "node": ">= 0.8" 1509 | } 1510 | }, 1511 | "node_modules/readable-stream": { 1512 | "version": "3.6.2", 1513 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1514 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1515 | "dependencies": { 1516 | "inherits": "^2.0.3", 1517 | "string_decoder": "^1.1.1", 1518 | "util-deprecate": "^1.0.1" 1519 | }, 1520 | "engines": { 1521 | "node": ">= 6" 1522 | } 1523 | }, 1524 | "node_modules/readdirp": { 1525 | "version": "3.6.0", 1526 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1527 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1528 | "dev": true, 1529 | "dependencies": { 1530 | "picomatch": "^2.2.1" 1531 | }, 1532 | "engines": { 1533 | "node": ">=8.10.0" 1534 | } 1535 | }, 1536 | "node_modules/rimraf": { 1537 | "version": "3.0.2", 1538 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1539 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1540 | "dependencies": { 1541 | "glob": "^7.1.3" 1542 | }, 1543 | "bin": { 1544 | "rimraf": "bin.js" 1545 | }, 1546 | "funding": { 1547 | "url": "https://github.com/sponsors/isaacs" 1548 | } 1549 | }, 1550 | "node_modules/safe-buffer": { 1551 | "version": "5.2.1", 1552 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1553 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1554 | "funding": [ 1555 | { 1556 | "type": "github", 1557 | "url": "https://github.com/sponsors/feross" 1558 | }, 1559 | { 1560 | "type": "patreon", 1561 | "url": "https://www.patreon.com/feross" 1562 | }, 1563 | { 1564 | "type": "consulting", 1565 | "url": "https://feross.org/support" 1566 | } 1567 | ] 1568 | }, 1569 | "node_modules/safer-buffer": { 1570 | "version": "2.1.2", 1571 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1572 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1573 | }, 1574 | "node_modules/semver": { 1575 | "version": "7.5.4", 1576 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", 1577 | "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", 1578 | "dependencies": { 1579 | "lru-cache": "^6.0.0" 1580 | }, 1581 | "bin": { 1582 | "semver": "bin/semver.js" 1583 | }, 1584 | "engines": { 1585 | "node": ">=10" 1586 | } 1587 | }, 1588 | "node_modules/send": { 1589 | "version": "0.18.0", 1590 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1591 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1592 | "dependencies": { 1593 | "debug": "2.6.9", 1594 | "depd": "2.0.0", 1595 | "destroy": "1.2.0", 1596 | "encodeurl": "~1.0.2", 1597 | "escape-html": "~1.0.3", 1598 | "etag": "~1.8.1", 1599 | "fresh": "0.5.2", 1600 | "http-errors": "2.0.0", 1601 | "mime": "1.6.0", 1602 | "ms": "2.1.3", 1603 | "on-finished": "2.4.1", 1604 | "range-parser": "~1.2.1", 1605 | "statuses": "2.0.1" 1606 | }, 1607 | "engines": { 1608 | "node": ">= 0.8.0" 1609 | } 1610 | }, 1611 | "node_modules/send/node_modules/debug": { 1612 | "version": "2.6.9", 1613 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1614 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1615 | "dependencies": { 1616 | "ms": "2.0.0" 1617 | } 1618 | }, 1619 | "node_modules/send/node_modules/debug/node_modules/ms": { 1620 | "version": "2.0.0", 1621 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1622 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1623 | }, 1624 | "node_modules/serve-static": { 1625 | "version": "1.15.0", 1626 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1627 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1628 | "dependencies": { 1629 | "encodeurl": "~1.0.2", 1630 | "escape-html": "~1.0.3", 1631 | "parseurl": "~1.3.3", 1632 | "send": "0.18.0" 1633 | }, 1634 | "engines": { 1635 | "node": ">= 0.8.0" 1636 | } 1637 | }, 1638 | "node_modules/set-blocking": { 1639 | "version": "2.0.0", 1640 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1641 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" 1642 | }, 1643 | "node_modules/setprototypeof": { 1644 | "version": "1.2.0", 1645 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1646 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1647 | }, 1648 | "node_modules/side-channel": { 1649 | "version": "1.0.4", 1650 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1651 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1652 | "dependencies": { 1653 | "call-bind": "^1.0.0", 1654 | "get-intrinsic": "^1.0.2", 1655 | "object-inspect": "^1.9.0" 1656 | }, 1657 | "funding": { 1658 | "url": "https://github.com/sponsors/ljharb" 1659 | } 1660 | }, 1661 | "node_modules/sift": { 1662 | "version": "16.0.1", 1663 | "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", 1664 | "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" 1665 | }, 1666 | "node_modules/signal-exit": { 1667 | "version": "3.0.7", 1668 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 1669 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 1670 | }, 1671 | "node_modules/simple-update-notifier": { 1672 | "version": "2.0.0", 1673 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 1674 | "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 1675 | "dev": true, 1676 | "dependencies": { 1677 | "semver": "^7.5.3" 1678 | }, 1679 | "engines": { 1680 | "node": ">=10" 1681 | } 1682 | }, 1683 | "node_modules/smart-buffer": { 1684 | "version": "4.2.0", 1685 | "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", 1686 | "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", 1687 | "engines": { 1688 | "node": ">= 6.0.0", 1689 | "npm": ">= 3.0.0" 1690 | } 1691 | }, 1692 | "node_modules/socks": { 1693 | "version": "2.7.1", 1694 | "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", 1695 | "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", 1696 | "dependencies": { 1697 | "ip": "^2.0.0", 1698 | "smart-buffer": "^4.2.0" 1699 | }, 1700 | "engines": { 1701 | "node": ">= 10.13.0", 1702 | "npm": ">= 3.0.0" 1703 | } 1704 | }, 1705 | "node_modules/sparse-bitfield": { 1706 | "version": "3.0.3", 1707 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 1708 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", 1709 | "optional": true, 1710 | "dependencies": { 1711 | "memory-pager": "^1.0.2" 1712 | } 1713 | }, 1714 | "node_modules/statuses": { 1715 | "version": "2.0.1", 1716 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1717 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1718 | "engines": { 1719 | "node": ">= 0.8" 1720 | } 1721 | }, 1722 | "node_modules/string_decoder": { 1723 | "version": "1.3.0", 1724 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1725 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1726 | "dependencies": { 1727 | "safe-buffer": "~5.2.0" 1728 | } 1729 | }, 1730 | "node_modules/string-width": { 1731 | "version": "4.2.3", 1732 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1733 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1734 | "dependencies": { 1735 | "emoji-regex": "^8.0.0", 1736 | "is-fullwidth-code-point": "^3.0.0", 1737 | "strip-ansi": "^6.0.1" 1738 | }, 1739 | "engines": { 1740 | "node": ">=8" 1741 | } 1742 | }, 1743 | "node_modules/strip-ansi": { 1744 | "version": "6.0.1", 1745 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1746 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1747 | "dependencies": { 1748 | "ansi-regex": "^5.0.1" 1749 | }, 1750 | "engines": { 1751 | "node": ">=8" 1752 | } 1753 | }, 1754 | "node_modules/supports-color": { 1755 | "version": "5.5.0", 1756 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1757 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1758 | "dev": true, 1759 | "dependencies": { 1760 | "has-flag": "^3.0.0" 1761 | }, 1762 | "engines": { 1763 | "node": ">=4" 1764 | } 1765 | }, 1766 | "node_modules/tar": { 1767 | "version": "6.2.0", 1768 | "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", 1769 | "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", 1770 | "dependencies": { 1771 | "chownr": "^2.0.0", 1772 | "fs-minipass": "^2.0.0", 1773 | "minipass": "^5.0.0", 1774 | "minizlib": "^2.1.1", 1775 | "mkdirp": "^1.0.3", 1776 | "yallist": "^4.0.0" 1777 | }, 1778 | "engines": { 1779 | "node": ">=10" 1780 | } 1781 | }, 1782 | "node_modules/to-regex-range": { 1783 | "version": "5.0.1", 1784 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1785 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1786 | "dev": true, 1787 | "dependencies": { 1788 | "is-number": "^7.0.0" 1789 | }, 1790 | "engines": { 1791 | "node": ">=8.0" 1792 | } 1793 | }, 1794 | "node_modules/toidentifier": { 1795 | "version": "1.0.1", 1796 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1797 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1798 | "engines": { 1799 | "node": ">=0.6" 1800 | } 1801 | }, 1802 | "node_modules/touch": { 1803 | "version": "3.1.0", 1804 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 1805 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 1806 | "dev": true, 1807 | "dependencies": { 1808 | "nopt": "~1.0.10" 1809 | }, 1810 | "bin": { 1811 | "nodetouch": "bin/nodetouch.js" 1812 | } 1813 | }, 1814 | "node_modules/tr46": { 1815 | "version": "0.0.3", 1816 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1817 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 1818 | }, 1819 | "node_modules/type-is": { 1820 | "version": "1.6.18", 1821 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1822 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1823 | "dependencies": { 1824 | "media-typer": "0.3.0", 1825 | "mime-types": "~2.1.24" 1826 | }, 1827 | "engines": { 1828 | "node": ">= 0.6" 1829 | } 1830 | }, 1831 | "node_modules/undefsafe": { 1832 | "version": "2.0.5", 1833 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1834 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 1835 | "dev": true 1836 | }, 1837 | "node_modules/undici-types": { 1838 | "version": "5.25.3", 1839 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", 1840 | "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" 1841 | }, 1842 | "node_modules/unpipe": { 1843 | "version": "1.0.0", 1844 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1845 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1846 | "engines": { 1847 | "node": ">= 0.8" 1848 | } 1849 | }, 1850 | "node_modules/util-deprecate": { 1851 | "version": "1.0.2", 1852 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1853 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1854 | }, 1855 | "node_modules/utils-merge": { 1856 | "version": "1.0.1", 1857 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1858 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 1859 | "engines": { 1860 | "node": ">= 0.4.0" 1861 | } 1862 | }, 1863 | "node_modules/vary": { 1864 | "version": "1.1.2", 1865 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1866 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1867 | "engines": { 1868 | "node": ">= 0.8" 1869 | } 1870 | }, 1871 | "node_modules/webidl-conversions": { 1872 | "version": "3.0.1", 1873 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1874 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 1875 | }, 1876 | "node_modules/whatwg-url": { 1877 | "version": "5.0.0", 1878 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 1879 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 1880 | "dependencies": { 1881 | "tr46": "~0.0.3", 1882 | "webidl-conversions": "^3.0.0" 1883 | } 1884 | }, 1885 | "node_modules/wide-align": { 1886 | "version": "1.1.5", 1887 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", 1888 | "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", 1889 | "dependencies": { 1890 | "string-width": "^1.0.2 || 2 || 3 || 4" 1891 | } 1892 | }, 1893 | "node_modules/wrappy": { 1894 | "version": "1.0.2", 1895 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1896 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1897 | }, 1898 | "node_modules/yallist": { 1899 | "version": "4.0.0", 1900 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1901 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1902 | } 1903 | } 1904 | } 1905 | --------------------------------------------------------------------------------