├── backend
├── .gitignore
├── middlewares
│ ├── catchAsyncErrors.js
│ ├── auth.js
│ └── errorMiddleware.js
├── router
│ ├── messageRouter.js
│ ├── appointmentRouter.js
│ └── userRouter.js
├── server.js
├── database
│ └── dbConnection.js
├── config
│ └── config.env
├── utils
│ └── jwtToken.js
├── package.json
├── controller
│ ├── messageController.js
│ ├── appointmentController.js
│ └── userController.js
├── models
│ ├── messageSchema.js
│ ├── appointmentSchema.js
│ └── userScheme.js
├── app.js
└── package-lock.json
├── README.md
├── frontend
├── vite.config.js
├── .gitignore
├── src
│ ├── App.jsx
│ ├── main.jsx
│ └── App.css
├── index.html
├── README.md
├── package.json
├── eslint.config.js
└── public
│ └── vite.svg
└── LICENSE
/backend/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MERN-Hosptal-Management-System
--------------------------------------------------------------------------------
/backend/middlewares/catchAsyncErrors.js:
--------------------------------------------------------------------------------
1 | export const catchAsyncErrors = (theFunction) => {
2 | return (req,res,next) => {
3 | Promise.resolve(theFunction(req,res,next)).catch(next);
4 | };
5 | }
--------------------------------------------------------------------------------
/frontend/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vite.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/frontend/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import './App.css';
3 | import {BrowserRouter as Router, Routes,Route} from 'react-router-dom'
4 |
5 |
6 | const App = () => {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | )
16 | }
17 |
18 | export default App
19 |
--------------------------------------------------------------------------------
/backend/router/messageRouter.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import { getAllMessages, sendMessage } from "../controller/messageController.js";
3 | import { isAdminAuthenticated } from "../middlewares/auth.js";
4 |
5 | const router = express.Router();
6 |
7 | //sending message
8 | router.post("/send",sendMessage);
9 | router.get("/getall",isAdminAuthenticated,getAllMessages);
10 |
11 | export default router;
--------------------------------------------------------------------------------
/backend/server.js:
--------------------------------------------------------------------------------
1 | import app from "./app.js";
2 | import cloudinary from "cloudinary"
3 |
4 | cloudinary.v2.config({
5 | cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
6 | api_key: process.env.CLOUDINARY_API_KEY,
7 | api_secret: process.env.CLOUDINARY_API_SECRET,
8 |
9 | })
10 |
11 |
12 | app.listen(process.env.PORT, () => {
13 | console.log(`server listening on port ${process.env.PORT}`);
14 | });
15 |
--------------------------------------------------------------------------------
/backend/database/dbConnection.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 | //db connection
3 |
4 | export const dbConnection = () => {
5 | mongoose.connect(process.env.MONGO_URI,{
6 | dbName: "Hospital-Management-System",
7 | }).then(() => {
8 | console.log("Connected to database")
9 | }).catch((err) => {
10 | console.log(`some error occured while connecting to database: ${err}`)
11 | })
12 | }
--------------------------------------------------------------------------------
/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/backend/config/config.env:
--------------------------------------------------------------------------------
1 | PORT = 4000
2 |
3 | MONGO_URI=mongodb+srv://hirun:hirun@cluster0.5wlbz.mongodb.net/?retryWrites=true
4 |
5 | FRONTEND_URL=http://localhost:5173
6 |
7 | DASHBOARD_URL=http://localhost:5174
8 |
9 | JWT_SECRET_KEY=vgvgvjvkjvjfuukfkhghkj
10 |
11 | JWT_EXPIRES=7d
12 |
13 | COOKIE_EXPIRE=7
14 |
15 | CLOUDINARY_CLOUD_NAME=dvcvgmi80
16 |
17 | CLOUDINARY_API_SECRET=UZIvScqCP_LhvdrHBy1cbaVwYjI
18 |
19 | CLOUDINARY_API_KEY=758751253881523
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/backend/utils/jwtToken.js:
--------------------------------------------------------------------------------
1 | export const generateToken=( user,message,statusCode,res) => {
2 | const token = user.generateJsonWebToken();
3 | const cookieName= user.role === "Admin" ? "adminToken" : "patientToken";
4 | res
5 | .status(statusCode)
6 | .cookie(cookieName, token, {
7 | expires: new Date(
8 | Date.now() + process.env.COOKIE_EXPIRE * 24 * 60 * 60 * 1000
9 | ),
10 | })
11 | .json({
12 | success: true,
13 | message,
14 | user,
15 | token,
16 | });
17 | }
--------------------------------------------------------------------------------
/backend/router/appointmentRouter.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import { deleteAppointment, getAllAppointments, postAppointment, updateAppointmentStatus } from '../controller/appointmentController.js';
3 | import {isAdminAuthenticated,isPatientAuthenticated} from '../middlewares/auth.js'
4 |
5 | const router = express.Router();
6 |
7 | router.post("/post",isPatientAuthenticated,postAppointment)
8 | router.get("/getall",isAdminAuthenticated,getAllAppointments)
9 | router.put("/update/:id",isAdminAuthenticated,updateAppointmentStatus)
10 | router.delete("/delete/:id",isAdminAuthenticated,deleteAppointment)
11 |
12 | export default router;
--------------------------------------------------------------------------------
/backend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backend",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "type": "module",
6 | "scripts": {
7 | "start": "node server.js",
8 | "dev": "nodemon server.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "description": "",
13 | "dependencies": {
14 | "bcrypt": "^5.1.1",
15 | "cloudinary": "^2.5.1",
16 | "cookie-parser": "^1.4.7",
17 | "cors": "^2.8.5",
18 | "dotenv": "^16.4.5",
19 | "express": "^4.21.1",
20 | "express-fileupload": "^1.5.1",
21 | "jsonwebtoken": "^9.0.2",
22 | "mongoose": "^8.7.2",
23 | "validator": "^13.12.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/frontend/src/main.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 |
4 | import App from './App.jsx'
5 |
6 | export const Context = createContext({isAuthenticated: false});
7 |
8 | const AppWrapper = () =>{
9 | const [isAuthenticated, setIsAuthenticated] = useState(false);
10 | const[user,setUser] = useState({});
11 |
12 | return(
13 |
14 |
15 |
16 | )
17 |
18 |
19 | }
20 |
21 |
22 |
23 | createRoot(document.getElementById('root')).render(
24 |
25 |
26 | ,
27 | )
28 |
--------------------------------------------------------------------------------
/backend/router/userRouter.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import { login, patientRegister,addNewAdmin, getAllDoctors, getUserDetails, logoutAdmin, logoutPatient, addNewDoctor } from '../controller/userController.js';
3 | import { isAdminAuthenticated,isPatientAuthenticated } from "../middlewares/auth.js"
4 |
5 | const router = express.Router();
6 |
7 | router.post("/patient/register" ,patientRegister);
8 | router.post("/login" ,login);
9 | router.post("/admin/addnew",isAdminAuthenticated, addNewAdmin);
10 | router.get("/doctors",getAllDoctors);
11 | router.get("/admin/me",isAdminAuthenticated,getUserDetails);
12 | router.get("/patient/me", isPatientAuthenticated,getUserDetails);
13 | router.get("/admin/logout", isAdminAuthenticated,logoutAdmin);
14 | router.get("/patient/logout", isPatientAuthenticated,logoutPatient);
15 | router.post("/doctor/addnew", isAdminAuthenticated,addNewDoctor);
16 |
17 | export default router;
--------------------------------------------------------------------------------
/backend/controller/messageController.js:
--------------------------------------------------------------------------------
1 | import {catchAsyncErrors} from '../middlewares/catchAsyncErrors.js'
2 | import { Message } from "../models/messageSchema.js";
3 | import ErrorHandler from "../middlewares/errorMiddleware.js";
4 |
5 | export const sendMessage = catchAsyncErrors(async(req,res,next) => {
6 | const {firstName,lastName,email,phone,message} = req.body;
7 | if(!firstName || !lastName || !email || !phone || !message){
8 | return next(new ErrorHandler("please fill full form!",400))
9 | }
10 | await Message.create({firstName,lastName,email,phone,message});
11 | res.status(200).json({
12 | success: true,
13 | message: "Message send successfully",
14 | });
15 | })
16 | //finish send message
17 |
18 | export const getAllMessages = catchAsyncErrors(async (req,res,next) => {
19 | const messages= await Message.find();
20 | res.status(200).json({
21 | success: true,
22 | messages,
23 | })
24 | })
--------------------------------------------------------------------------------
/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 .",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "axios": "^1.7.7",
14 | "react": "^18.3.1",
15 | "react-dom": "^18.3.1",
16 | "react-icons": "^5.3.0",
17 | "react-multi-carousel": "^2.8.5",
18 | "react-router-dom": "^6.28.0",
19 | "react-toastify": "^10.0.6"
20 | },
21 | "devDependencies": {
22 | "@eslint/js": "^9.13.0",
23 | "@types/react": "^18.3.12",
24 | "@types/react-dom": "^18.3.1",
25 | "@vitejs/plugin-react": "^4.3.3",
26 | "eslint": "^9.13.0",
27 | "eslint-plugin-react": "^7.37.2",
28 | "eslint-plugin-react-hooks": "^5.0.0",
29 | "eslint-plugin-react-refresh": "^0.4.14",
30 | "globals": "^15.11.0",
31 | "vite": "^5.4.10"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/backend/models/messageSchema.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose"
2 | import validator from "validator"
3 |
4 | const messageSchema = new mongoose.Schema({
5 | firstName:{
6 | type:String,
7 | required: true,
8 | minLength: [3, "First name must contain at least 3 characters"]
9 | },
10 | lastName:{
11 | type:String,
12 | required: true,
13 | minLength: [3, "Last name must contain at least 3 characters"]
14 | },
15 | email:{
16 | type: String,
17 | required: true,
18 | validate: [validator.isEmail, "Please provide a valid email"]
19 | },
20 | phone:{
21 | type:String,
22 | required: true,
23 | minLength: [10, "phone number must contain 10"],
24 | maxLength: [10, "phone number must contain 10"]
25 | },
26 | message:{
27 | type:String,
28 | required: true,
29 | minLength: [10, "message must contain at least 10 characters"],
30 |
31 | },
32 |
33 |
34 | });
35 |
36 | export const Message = mongoose.model("Message", messageSchema);
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Hirun
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/frontend/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import react from 'eslint-plugin-react'
4 | import reactHooks from 'eslint-plugin-react-hooks'
5 | import reactRefresh from 'eslint-plugin-react-refresh'
6 |
7 | export default [
8 | { ignores: ['dist'] },
9 | {
10 | files: ['**/*.{js,jsx}'],
11 | languageOptions: {
12 | ecmaVersion: 2020,
13 | globals: globals.browser,
14 | parserOptions: {
15 | ecmaVersion: 'latest',
16 | ecmaFeatures: { jsx: true },
17 | sourceType: 'module',
18 | },
19 | },
20 | settings: { react: { version: '18.3' } },
21 | plugins: {
22 | react,
23 | 'react-hooks': reactHooks,
24 | 'react-refresh': reactRefresh,
25 | },
26 | rules: {
27 | ...js.configs.recommended.rules,
28 | ...react.configs.recommended.rules,
29 | ...react.configs['jsx-runtime'].rules,
30 | ...reactHooks.configs.recommended.rules,
31 | 'react/jsx-no-target-blank': 'off',
32 | 'react-refresh/only-export-components': [
33 | 'warn',
34 | { allowConstantExport: true },
35 | ],
36 | },
37 | },
38 | ]
39 |
--------------------------------------------------------------------------------
/backend/app.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import {config} from "dotenv";
3 | import cors from "cors";
4 | import cookieParser from "cookie-parser";
5 | import fileUpload from "express-fileupload";
6 | import { dbConnection } from "./database/dbConnection.js";
7 | import messageRouter from "./router/messageRouter.js"
8 | import {errorMiddleware} from "./middlewares/errorMiddleware.js"
9 | import userRouter from "./router/userRouter.js"
10 | import appointmentRouter from "./router/appointmentRouter.js"
11 |
12 | const app= express();
13 |
14 | config( {path: "./config/config.env"})
15 |
16 | app.use(cors({
17 | origin: [process.env.FRONTEND_URL,process.env.DASHBOARD_URL],
18 | methods: ["GET","POST","PUT","DELETE"],
19 | credentials: true,
20 | }));
21 |
22 | app.use(cookieParser());
23 | app.use(express.json());
24 | app.use(express.urlencoded({ extended: true}));
25 |
26 | app.use(
27 | fileUpload({
28 | useTempFiles: true,
29 | tempFileDir: "/tmp/",
30 | })
31 | );
32 |
33 | app.use("/api/v1/message" ,messageRouter);
34 | app.use("/api/v1/user" ,userRouter);
35 | app.use("/api/v1/appointment" ,appointmentRouter);
36 |
37 |
38 | dbConnection();
39 |
40 | app.use(errorMiddleware);
41 |
42 |
43 | export default app;
44 |
45 | //backend finished
--------------------------------------------------------------------------------
/backend/middlewares/auth.js:
--------------------------------------------------------------------------------
1 | import { catchAsyncErrors } from "./catchAsyncErrors.js";
2 | import ErrorHandler from "./errorMiddleware.js";
3 | import jwt from "jsonwebtoken"
4 | import { User } from "../models/userScheme.js";
5 |
6 | export const isAdminAuthenticated = catchAsyncErrors(async(req,res,next) =>{
7 | const token = req.cookies.adminToken;
8 |
9 | if (!token) {
10 | return next(new ErrorHandler("Admin not Authenticated!", 400))
11 | }
12 | const decoded = jwt.verify(token, process.env.JWT_SECRET_KEY);
13 | req.user = await User.findById(decoded.id);
14 | if(req.user.role !== "Admin"){
15 | return next(new ErrorHandler(`${req.user.role} not authorized for this resources!`,403))
16 | }
17 | next();
18 | })
19 |
20 | export const isPatientAuthenticated = catchAsyncErrors(async(req,res,next) =>{
21 | const token = req.cookies.patientToken;
22 |
23 | if (!token) {
24 | return next(new ErrorHandler("Patient not Authenticated!", 400))
25 | }
26 | const decoded = jwt.verify(token, process.env.JWT_SECRET_KEY);
27 | req.user = await User.findById(decoded.id);
28 | if(req.user.role !== "Patient"){
29 | return next(new ErrorHandler(`${req.user.role} not authorized for this resources!`,403))
30 | }
31 | next();
32 | })
--------------------------------------------------------------------------------
/backend/middlewares/errorMiddleware.js:
--------------------------------------------------------------------------------
1 | class ErrorHandler extends Error{
2 | constructor(message, statusCode){
3 | super(message);
4 | this.statusCode =statusCode;
5 | }
6 | }
7 |
8 | export const errorMiddleware = (err,req ,res,next) => {
9 | // Set a default error message and status code if they don't exist
10 | err.message = err.message || "internal server error"
11 | err.statusCode= err.statusCode || 500;
12 |
13 | if(err.code === 11000){
14 | const message = `Duplicate ${object.keys(err.keyValue)} entered`;
15 | err = new ErrorHandler(message,400);
16 | }
17 | if(err.name === "JsonWebTokenError"){
18 | const message = " Json web token is invalid,try again";
19 | err = new ErrorHandler(message,400);
20 | }
21 | if(err.name === "TokenExpiredError"){
22 | const message = " Json web token is expired,try again";
23 | err = new ErrorHandler(message,400);
24 | }
25 | if(err.name === "CastError"){
26 | const message = `invalid ${err.path}`;
27 | err = new ErrorHandler(message,400);
28 | }
29 |
30 | const errorMessage = err.errors ? Object.values(err.errors).map((error) => error.message).join(""): err.message;
31 |
32 | return res.status(err.statusCode).json({
33 | success: false,
34 | message: errorMessage,
35 | });
36 |
37 | }
38 |
39 | export default ErrorHandler;
--------------------------------------------------------------------------------
/frontend/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/models/appointmentSchema.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 | import validator from "validator";
3 |
4 | const appointmentSchema = new mongoose.Schema({
5 | firstName: {
6 | type: String,
7 | required: true,
8 | minLength: [3, "First name must contain at least 3 characters"],
9 | },
10 | lastName: {
11 | type: String,
12 | required: true,
13 | minLength: [3, "Last name must contain at least 3 characters"],
14 | },
15 | email: {
16 | type: String,
17 | required: true,
18 | validate: [validator.isEmail, "Please provide a valid email"],
19 | },
20 | phone: {
21 | type: String,
22 | required: true,
23 | minLength: [10, "phone number must contain 10"],
24 | maxLength: [10, "phone number must contain 10"],
25 | },
26 | nic: {
27 | type: String,
28 | required: true,
29 | minLength: [12, "nic must contain 12"],
30 | maxLength: [12, "nic must contain 12"],
31 | },
32 | dob: {
33 | type: Date,
34 | required: [true, "DOB is required!"],
35 | },
36 | gender: {
37 | type: String,
38 | required: true,
39 | enum: ["Male", "Female"],
40 | },
41 | appointment_date: {
42 | type: String,
43 | required: true,
44 | },
45 | department: {
46 | type: String,
47 | required: true,
48 | },
49 | doctor: {
50 | firstName:{
51 | type: String,
52 | required: true,
53 | },lastName:{
54 | type: String,
55 | required: true,
56 | },
57 | },
58 | hasVisited: {
59 | type: Boolean,
60 | default: false,
61 | },
62 | doctorId: {
63 | type: mongoose.Schema.ObjectId,
64 | required: true,
65 | },
66 | patientId: {
67 | type: mongoose.Schema.ObjectId,
68 | required: true,
69 | },
70 | address: {
71 | type: String,
72 | required: true,
73 | },
74 | status: {
75 | type: String,
76 | enum: ["Pending","Accepted","Rejected"],
77 | default: "Pending",
78 | }
79 |
80 | });
81 |
82 | export const Appointment = mongoose.model("Appointment", appointmentSchema);
83 |
--------------------------------------------------------------------------------
/backend/models/userScheme.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose"
2 | import validator from "validator"
3 | import bcrypt from "bcrypt"
4 | import jwt from "jsonwebtoken"
5 |
6 | const userSchema = new mongoose.Schema({
7 | firstName:{
8 | type:String,
9 | required: true,
10 | minLength: [3, "First name must contain at least 3 characters"]
11 | },
12 | lastName:{
13 | type:String,
14 | required: true,
15 | minLength: [3, "Last name must contain at least 3 characters"]
16 | },
17 | email:{
18 | type: String,
19 | required: true,
20 | validate: [validator.isEmail, "Please provide a valid email"]
21 | },
22 | phone:{
23 | type:String,
24 | required: true,
25 | minLength: [10, "phone number must contain 10"],
26 | maxLength: [10, "phone number must contain 10"]
27 | },
28 | nic:{
29 | type:String,
30 | required: true,
31 | minLength: [12, "nic must contain 12"],
32 | maxLength: [12, "nic must contain 12"]
33 | },
34 | dob:{
35 | type: Date,
36 | required: [true,"DOB is required!"],
37 | },
38 | gender:{
39 | type: String,
40 | required: true,
41 | enum: ["Male","Female"],
42 | },
43 | password:{
44 | type: String,
45 | minLength: [8, "password must contain at least 8 characters!"],
46 | required: true,
47 | select: false,
48 | },
49 | role:{
50 | type: String,
51 | required: true,
52 | enum: ["Admin","Patient","Doctor"],
53 | },
54 | doctorDepartment:{
55 | type: String,
56 |
57 | },
58 | docAvatar:{
59 | public_id: String,
60 | url: String,
61 | }
62 |
63 |
64 | });
65 |
66 | userSchema.pre("save", async function(next){
67 | /*.pre("save", ...): This defines a pre-save hook in Mongoose.
68 | It allows you to execute some code before the save operation
69 | occurs on the document (in this case, the user document).
70 | The "save" string specifies that the hook should run
71 | before a document is saved to the database.*/
72 | if(!this.isModified("password")) {
73 | next()
74 | }
75 | this.password = await bcrypt.hash(this.password,10)
76 | });
77 |
78 | userSchema.methods.comparePassword = async function (enteredPassword) {
79 | return await bcrypt.compare(enteredPassword,this.password)
80 | };
81 |
82 | userSchema.methods.generateJsonWebToken =function () {
83 | return jwt.sign({id: this._id}, process.env.JWT_SECRET_KEY,{
84 | expiresIn: process.env.JWT_EXPIRES,
85 | });
86 | }
87 |
88 |
89 | export const User = mongoose.model("User", userSchema);
--------------------------------------------------------------------------------
/backend/controller/appointmentController.js:
--------------------------------------------------------------------------------
1 | import {catchAsyncErrors} from '../middlewares/catchAsyncErrors.js'
2 | import ErrorHandler from '../middlewares/errorMiddleware.js'
3 | import {Appointment} from '../models/appointmentSchema.js';
4 | import {User} from '../models/userScheme.js'
5 |
6 | export const postAppointment = catchAsyncErrors(async(req,res,next) => {
7 | const{
8 | firstName,
9 | lastName,
10 | email,
11 | phone,
12 | nic,
13 | dob,
14 | gender,
15 | appointment_data,
16 | department,
17 | doctor_firstName,
18 | doctor_lastName,
19 | hasVisited,
20 | address,
21 | }= req.body;
22 |
23 | if (
24 | !firstName ||
25 | !lastName ||
26 | !email ||
27 | !phone ||
28 | !nic ||
29 | !dob ||
30 | !gender ||
31 | !appointment_data ||
32 | !department ||
33 | !doctor_firstName ||
34 | !doctor_lastName ||
35 | !address
36 | ) {
37 | return next(new ErrorHandler("Please fill full form!",400));
38 | }
39 |
40 | const isConflict = await User.find({
41 | firstName: doctor_firstName,
42 | lastName: doctor_lastName,
43 | role: "Doctor",
44 | doctorDepartment: department
45 | })
46 | if (isConflict.length === 0) {
47 | return next(new ErrorHandler("Doctor not found",404))
48 | }
49 | if (isConflict.length > 1) {
50 | return next(new ErrorHandler("Doctors Conflict! Please contact through email or Phone",404))
51 | }
52 |
53 | const doctorId = isConflict[0]._id;
54 | const patientId = req.user._id;
55 | const appointment = await Appointment.create({
56 | firstName,
57 | lastName,
58 | email,
59 | phone,
60 | nic,
61 | dob,
62 | gender,
63 | appointment_data,
64 | department,
65 | dovtor: {
66 | firstName: doctor_firstName,
67 | lastName: doctor_lastName
68 | },
69 | hasVisited,
70 | address,
71 | doctorId,
72 | patientId
73 | });
74 | res.status(200).json({
75 | success: true,
76 | message: "appointment send successfully",
77 | appointment,
78 | })
79 | });
80 |
81 | export const getAllAppointments = catchAsyncErrors(async(req,res,next) => {
82 | const appointments = await Appointment.find();
83 | res.status(200).json({
84 | success: true,
85 | appointments,
86 | })
87 |
88 | })
89 |
90 | export const updateAppointmentStatus = catchAsyncErrors(async(req,res,next) => {
91 | const {id} = req.params;
92 | let appointment = await Appointment.findById(id);
93 | if (!appointment) {
94 | return next(new ErrorHandler("Appointment not found",404));
95 | }
96 | appointment = await Appointment.findByIdAndUpdate(id,req.body, {
97 | new: true,
98 | runValidators: true,
99 | useFindAndModify: false,
100 | });
101 | res.status(200).json({
102 | success: true,
103 | message: "Appointment status updated",
104 | appointment,
105 | });
106 | });
107 |
108 | export const deleteAppointment = catchAsyncErrors(async(req,res,next) => {
109 | const {id} = req.params;
110 | let appointment = await Appointment.findById(id);
111 | if (!appointment) {
112 | return next(new ErrorHandler("Appointment not found",404));
113 | }
114 | await appointment.deleteOne();
115 | res.status(200).json({
116 | success: true,
117 | message: "Appointment deleted!"
118 | })
119 | })
120 |
121 |
122 |
--------------------------------------------------------------------------------
/backend/controller/userController.js:
--------------------------------------------------------------------------------
1 | import { catchAsyncErrors} from "../middlewares/catchAsyncErrors.js"
2 | import ErrorHandler from "../middlewares/errorMiddleware.js"
3 | import {User} from "../models/userScheme.js";
4 | import {generateToken} from "../utils/jwtToken.js"
5 | import cloudinary from "cloudinary"
6 |
7 | export const patientRegister= catchAsyncErrors(async(req,res,next) => {
8 | const{firstName,lastName,email,phone,password,gender,dob,nic,role} = req.body;
9 | if (!firstName||!lastName||!email||!phone||!password||!gender||!dob||!nic||!role) {
10 | return next(new ErrorHandler("please fill full form!", 400));
11 | }
12 | let user= await User.findOne({email});
13 | if(user){
14 | return next(new ErrorHandler("user already registered",400))
15 | }
16 | //creating model with help userSchema
17 | user = await User.create({
18 | firstName,lastName,email,phone,password,gender,dob,nic,role
19 | });
20 | //if success
21 | generateToken(user,"user registered",200,res);
22 | //finish
23 |
24 |
25 | });
26 |
27 | export const login = catchAsyncErrors(async(req,res,next)=>{
28 | const { email,password ,confirmPassword,role} = req.body;
29 | if (!email|| !password || !confirmPassword || !role) {
30 | return next(new ErrorHandler("please provide all detailes",400))
31 | }
32 | if(password !== confirmPassword){
33 | return next(new ErrorHandler("password and confirm password don't match", 400))
34 | }
35 | const user = await User.findOne({email}).select('+password +role');
36 | if(!user){
37 | return next(new ErrorHandler("Invalid password or email"),400)
38 |
39 | }
40 | const isPasswordMatched = await user.comparePassword(password);
41 | if(!isPasswordMatched){
42 | return next(new ErrorHandler("Invalid Password or Email", 400))
43 | }
44 | if (role !== user.role) {
45 | return next(new ErrorHandler("user with this role not found",400));
46 | }
47 | //if success
48 | generateToken(user,"user login successfully ",200,res);
49 |
50 | })
51 |
52 | export const addNewAdmin = catchAsyncErrors(async(req,res,next ) => {
53 | const{firstName,lastName,email,phone,password,gender,dob,nic} = req.body;
54 | if (!firstName||!lastName||!email||!phone||!password||!gender||!dob||!nic) {
55 | return next(new ErrorHandler("please fill full form!", 400));
56 | }
57 | const isRegistered = await User.findOne({email});
58 | if(isRegistered){
59 | return next(new ErrorHandler(`${isRegistered.role} with this email already exists!`));
60 | }
61 | const admin = await User.create({firstName,lastName,email,phone,password,gender,dob,nic, role: "Admin"})
62 |
63 | res.status(200).json({
64 | success: true,
65 | message: "New Admin Registered!",
66 | })
67 | })
68 |
69 | export const getAllDoctors = catchAsyncErrors(async(req,res,next) => {
70 | const doctors = await User.find({role: "Doctor"});
71 | res.status(200).json({
72 | success: true,
73 | doctors,
74 | });
75 | });
76 |
77 | export const getUserDetails = catchAsyncErrors(async(req,res,next) => {
78 | const user =req.user;
79 | res.status(200).json({
80 | success: true,
81 | user,
82 | })
83 | });
84 |
85 | export const logoutAdmin = catchAsyncErrors(async(req,res,next) => {
86 | res.status(200).cookie("adminToken","",{
87 | httpOnly: true,
88 | expires: new Date(Date.now()),
89 | }).json({
90 | success: true,
91 | message: "admin logged out successfully",
92 | })
93 | });
94 |
95 | export const logoutPatient = catchAsyncErrors(async(req,res,next) => {
96 | res.status(200).cookie("patientToken","",{
97 | httpOnly: true,
98 | expires: new Date(Date.now()),
99 | }).json({
100 | success: true,
101 | message: "patient logged out successfully",
102 | })
103 | });
104 |
105 | export const addNewDoctor = catchAsyncErrors(async (req,res,next) => {
106 | if (!req.files || Object.keys(req.files).length === 0) {
107 | return next(new ErrorHandler("Doctor Avatar required!",400))
108 | }
109 | const {docAvatar} = req.files;
110 | const allowedFormats= ["image/png","image/jpeg","image/webP"];
111 | if (!allowedFormats.includes(docAvatar.mimetype)) {
112 | return next(new ErrorHandler("File Format Not Supported!",400))
113 |
114 | }
115 | const {firstName,lastName,email,phone,password,gender,dob,nic,role,doctorDepartment}= req.body;
116 | if (!firstName||!lastName||!email||!phone||!password||!gender||!dob||!nic||!role||!doctorDepartment) {
117 | return next(new ErrorHandler("Please provide full details",400))
118 | }
119 | const isRegistered = await User.findOne({email});
120 | if (isRegistered) {
121 | return next(new ErrorHandler(`${isRegistered.role} already registered with this email!`,400))
122 | }
123 | const cloudinaryResponse = await cloudinary.uploader.upload(
124 | docAvatar.tempFilePath
125 | );
126 | if (!cloudinaryResponse || cloudinaryResponse.error ) {
127 | console.error("cloudinary error:",cloudinaryResponse.error || "Unknown cloudinary error")
128 | }
129 |
130 | const doctor = await User.create({
131 | firstName,lastName,email,phone,password,gender,dob,nic,role,doctorDepartment,role: "Doctor",docAvatar: {
132 | public_id: cloudinaryResponse.public_id,
133 | url: cloudinaryResponse.secure_url,
134 | },
135 | });
136 | res.status(200).json({
137 | success: true,
138 | message: "New doctor registered",
139 | doctor
140 | })
141 | })
142 |
143 |
--------------------------------------------------------------------------------
/frontend/src/App.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap");
2 | * {
3 | margin: 0;
4 | padding: 0;
5 | box-sizing: border-box;
6 | overflow-x: hidden;
7 | font-family: "Montserrat", sans-serif;
8 | }
9 | body {
10 | background: #e5e5e5;
11 | }
12 | .btn {
13 | padding: 7px 20px;
14 | border-radius: 12px;
15 | border: none;
16 | font-weight: bold;
17 | letter-spacing: 2px;
18 | }
19 | .white-btn {
20 | background: #fff;
21 | color: #111;
22 | }
23 | .purple-btn {
24 | background: #9083d5;
25 | color: #fff;
26 | }
27 | p,
28 | span,
29 | a {
30 | font-size: 20px;
31 | }
32 | h1 {
33 | font-size: 36px;
34 | font-weight: 900;
35 | }
36 | h1 {
37 | font-size: 36px;
38 | font-weight: 900;
39 | }
40 | h2 {
41 | font-size: 32px;
42 | font-weight: 900;
43 | }
44 | h3 {
45 | font-size: 28px;
46 | font-weight: 900;
47 | }
48 | h4 {
49 | font-size: 24px;
50 | font-weight: 900;
51 | }
52 | h5,
53 | h6 {
54 | font-size: 24px;
55 | font-weight: 700;
56 | }
57 | @media (max-width: 1186px) {
58 | h1 {
59 | font-size: 32px;
60 | font-weight: 900;
61 | }
62 | h2 {
63 | font-size: 30px;
64 | font-weight: 900;
65 | }
66 | }
67 | .container {
68 | padding: 0 100px;
69 | }
70 | @media (max-width: 700px) {
71 | .container {
72 | padding: 0 20px;
73 | }
74 | }
75 | .hero {
76 | display: flex;
77 | gap: 50px;
78 | padding-top: 120px;
79 | padding-bottom: 120px;
80 | position: relative;
81 | }
82 | .hero .banner {
83 | flex: 1;
84 | }
85 | .hero .banner h1,
86 | .hero .banner p {
87 | max-width: 650px;
88 | }
89 | .hero .banner h1 {
90 | letter-spacing: 2px;
91 | word-spacing: 5px;
92 | font-size: 40px;
93 | }
94 | .hero .banner p {
95 | color: #111;
96 | letter-spacing: 2px;
97 | }
98 | .hero .banner span {
99 | position: absolute;
100 | right: -300px;
101 | top: -200px;
102 | z-index: -1;
103 | }
104 | .hero .banner:first-child {
105 | display: flex;
106 | justify-content: center;
107 | flex-direction: column;
108 | gap: 50px;
109 | }
110 | .hero .banner:last-child {
111 | display: flex;
112 | justify-content: center;
113 | align-items: center;
114 | overflow-y: hidden;
115 | }
116 | .animated-image {
117 | animation: moveUpDown 1s infinite alternate ease-in-out;
118 | }
119 |
120 | @keyframes moveUpDown {
121 | 0% {
122 | transform: translateY(0);
123 | }
124 | 100% {
125 | transform: translateY(20px);
126 | }
127 | }
128 | @media (max-width: 1186px) {
129 | .hero .banner span {
130 | right: -400px;
131 | }
132 | .hero .banner h1 {
133 | font-size: 32px;
134 | }
135 | }
136 | @media (max-width: 1085px) {
137 | .hero .banner span {
138 | right: -480px;
139 | top: -315px;
140 | }
141 | }
142 | @media (max-width: 925px) {
143 | .hero {
144 | flex-direction: column;
145 | }
146 | @media (max-width: 700px) {
147 | .hero {
148 | padding-bottom: 40px;
149 | }
150 | }
151 | }
152 | .form-component {
153 | padding-top: 40px;
154 | padding-bottom: 60px;
155 | }
156 | .form-component h2 {
157 | color: gray;
158 | letter-spacing: 4px;
159 | margin-bottom: 30px;
160 | }
161 | .form-component h4 {
162 | color: gray;
163 | font-weight: 700;
164 | margin-bottom: 20px;
165 | }
166 | .form-component p {
167 | max-width: 750px;
168 | color: gray;
169 | margin-bottom: 20px;
170 | }
171 | .form-component form {
172 | display: flex;
173 | flex-direction: column;
174 | gap: 30px;
175 | }
176 | .form-component form div {
177 | display: flex;
178 | gap: 30px;
179 | }
180 | .form-component form input,
181 | .form-component form select,
182 | .form-component form textarea {
183 | flex: 1;
184 | font-size: 24px;
185 | padding: 10px 10px 10px 40px;
186 | border-radius: 7px;
187 | border: 1px solid gray;
188 | }
189 | .form-component button {
190 | padding: 10px 35px;
191 | color: #fff;
192 | font-weight: 700;
193 | width: fit-content;
194 | border: none;
195 | border-radius: 8px;
196 | font-size: 24px;
197 | margin-bottom: 30px;
198 | background: linear-gradient(140deg, #9083d5, #271776ca);
199 | }
200 | .form-component .wrapper {
201 | display: flex;
202 | gap: 50px;
203 | }
204 | .form-component .wrapper .banner {
205 | flex: 1;
206 | }
207 | .form-component .wrapper .banner:last-child {
208 | display: flex;
209 | justify-content: center;
210 | align-items: center;
211 | }
212 | .form-component .wrapper .banner:last-child img {
213 | max-width: 450px;
214 | }
215 | .login-form {
216 | margin: 100px auto 20px auto;
217 | max-width: 800px;
218 | text-align: center;
219 | }
220 | .register-form {
221 | max-width: 1200px;
222 | margin: 100px auto 20px auto;
223 | }
224 | .login-form h2 {
225 | color: #000;
226 | }
227 | .register-form h2 {
228 | color: #000;
229 | }
230 | @media (max-width: 1110px) {
231 | .appointment-form form div:nth-child(4) {
232 | flex-direction: column;
233 | }
234 | .appointment-form form div:nth-child(5) {
235 | flex-direction: column;
236 | }
237 | }
238 | @media (max-width: 888px) {
239 | .form-component {
240 | padding-top: 30px;
241 | padding-bottom: 30px;
242 | }
243 | .form-component form div {
244 | flex-direction: column;
245 | }
246 | }
247 | @media (max-width: 667px) {
248 | .form-component form input,
249 | .form-component form select,
250 | .form-component form textarea {
251 | font-size: 20px;
252 | padding: 10px;
253 | }
254 | }
255 | .biography {
256 | display: flex;
257 | gap: 50px;
258 | padding-top: 40px;
259 | padding-bottom: 60px;
260 | }
261 | .biography .banner:first-child {
262 | flex: 1;
263 | display: flex;
264 | justify-content: center;
265 | align-items: center;
266 | }
267 | .biography .banner:last-child {
268 | flex: 1;
269 | display: flex;
270 | flex-direction: column;
271 | gap: 10px;
272 | }
273 | .biography .banner h3 {
274 | font-weight: 700;
275 | letter-spacing: 3px;
276 | }
277 | .biography .banner p:first-child {
278 | font-size: 24px;
279 | letter-spacing: 2px;
280 | }
281 | @media (max-width: 925px) {
282 | .biography {
283 | flex-direction: column-reverse;
284 | }
285 | }
286 | .message-form {
287 | position: relative;
288 | }
289 | .message-form h2 {
290 | text-align: center;
291 | color: #000;
292 | position: relative;
293 | }
294 | .message-form img {
295 | position: absolute;
296 | top: 0;
297 | right: -16%;
298 | height: 600px;
299 | z-index: -1;
300 | }
301 | @media (max-width: 700px) {
302 | .message-form img {
303 | right: -35%;
304 | height: 450px;
305 | top: 10%;
306 | }
307 | }
308 | footer {
309 | padding-bottom: 30px !important;
310 | }
311 | footer hr {
312 | margin-bottom: 30px;
313 | }
314 | footer .content {
315 | display: flex;
316 | gap: 20px;
317 | }
318 | footer .content div {
319 | flex: 1;
320 | }
321 | footer .content div:nth-child(3) {
322 | flex: 2;
323 | }
324 | footer .content div h4 {
325 | font-weight: 700;
326 | margin-bottom: 20px;
327 | }
328 | footer .content div ul {
329 | display: flex;
330 | flex-direction: column;
331 | gap: 10px;
332 | }
333 | footer .content div ul a {
334 | color: gray;
335 | text-decoration: none;
336 | }
337 | footer .content div ul a:hover {
338 | color: #8570ed;
339 | transition: 0.3s;
340 | }
341 | footer .content div ul li span {
342 | color: gray;
343 | }
344 | footer .content div ul li span:first-child {
345 | width: 150px;
346 | display: inline-block;
347 | }
348 |
349 | footer .content div:last-child div {
350 | display: flex;
351 | align-items: center;
352 | gap: 12px;
353 | margin-bottom: 10px;
354 | }
355 | footer .content div:last-child div svg {
356 | font-size: 24px;
357 | }
358 | @media (max-width: 1135px) {
359 | footer .content {
360 | flex-wrap: wrap;
361 | justify-content: space-between;
362 | }
363 | footer .content div,
364 | footer .content div:nth-child(3) {
365 | flex: none;
366 | width: 340px;
367 | margin-bottom: 30px;
368 | }
369 | }
370 | @media (max-width: 900px) {
371 | footer {
372 | padding-bottom: 0 !important;
373 | }
374 | footer .content div,
375 | footer .content div:nth-child(3) {
376 | width: 100%;
377 | }
378 | }
379 | @media (max-width: 390px) {
380 | footer .content div:nth-child(3) ul li {
381 | display: flex;
382 | flex-direction: column;
383 | }
384 | }
385 |
386 | .departments {
387 | padding-top: 30px;
388 | padding-bottom: 50px;
389 | }
390 | .departments h2 {
391 | color: gray;
392 | margin-bottom: 30px;
393 | }
394 | .card {
395 | position: relative;
396 | border-radius: 8px;
397 | flex: 1;
398 | display: flex;
399 | justify-content: center;
400 | align-items: flex-end;
401 | padding-bottom: 15px;
402 | padding-left: 10px;
403 | padding-right: 20px;
404 | min-height: 360px;
405 | margin: 0 10px;
406 | text-decoration: none;
407 | }
408 | .card img {
409 | position: absolute;
410 | width: 100%;
411 | height: 100%;
412 | z-index: -1;
413 | top: 0;
414 | left: 0;
415 | }
416 | .card .depart-name {
417 | margin-bottom: 30px;
418 | background: #e5e5e5;
419 | width: 320px;
420 | font-size: 24px;
421 | text-transform: uppercase;
422 | display: flex;
423 | justify-content: center;
424 | padding: 12px;
425 | border-radius: 30px;
426 | left: 0;
427 | height: fit-content;
428 | font-weight: 700;
429 | }
430 |
431 | /**********************************************************************************************************************/
432 | nav {
433 | display: flex;
434 | width: 100%;
435 | margin: 0 auto;
436 | justify-content: space-between;
437 | position: absolute;
438 | align-items: center;
439 | border-bottom-right-radius: 7px;
440 | border-bottom-left-radius: 7px;
441 | padding-top: 20px !important;
442 | padding-bottom: 20px !important;
443 | z-index: 2;
444 | }
445 | nav .logo {
446 | flex: 1;
447 | display: flex;
448 | align-items: center;
449 | font-size: 2rem;
450 | }
451 | nav .navLinks {
452 | flex: 2;
453 | }
454 | nav .navLinks {
455 | display: flex;
456 | justify-content: space-between;
457 | align-items: center;
458 | }
459 | nav .navLinks .links {
460 | display: flex;
461 | gap: 25px;
462 | }
463 | nav .navLinks .links a {
464 | text-decoration: none;
465 | color: #222;
466 | font-size: 20px;
467 | font-weight: 600;
468 | letter-spacing: 1.4px;
469 | }
470 | nav .navLinks .links a:hover {
471 | color: #000;
472 | transition: 0.3s;
473 | cursor: pointer;
474 | }
475 | nav .btn {
476 | padding: 8px 20px;
477 | color: #e5e5e5;
478 | background: transparent;
479 | border: none;
480 | border-radius: 20px;
481 | font-size: 20px;
482 | font-weight: 600;
483 | z-index: 2;
484 | }
485 | nav .logoutBtn {
486 | background: linear-gradient(135deg, black, rgb(49, 49, 49));
487 | }
488 | nav .loginBtn {
489 | background: linear-gradient(135deg, black, rgb(49, 49, 49));
490 | }
491 | nav .hamburger {
492 | display: none;
493 | }
494 | nav svg {
495 | font-size: 1.75rem;
496 | }
497 | @media (max-width: 1520px) {
498 | nav {
499 | min-width: 100%;
500 | padding: 25px 20px 40px 20px;
501 | }
502 | }
503 | @media (max-width: 1100px) {
504 | nav {
505 | background: #ffffffbf;
506 | position: fixed;
507 | top: 0;
508 | left: 0;
509 | }
510 | nav .hamburger {
511 | display: flex;
512 | }
513 | nav .navLinks {
514 | display: flex;
515 | flex-direction: column;
516 | justify-content: space-evenly;
517 | padding: 15px 7.5px;
518 | z-index: 2;
519 | transition: 0.3s;
520 | position: fixed;
521 | left: 0;
522 | height: 100%;
523 | width: 400px;
524 | background: #ffffffbf;
525 | top: 79px;
526 | }
527 | nav .showmenu {
528 | display: flex;
529 | flex-direction: column;
530 | justify-content: space-evenly;
531 | padding: 15px 7.5px;
532 | z-index: 2;
533 | transition: 0.3s;
534 | position: fixed;
535 | left: -100%;
536 | width: 400px;
537 | height: 100%;
538 | background: #ffffffbf;
539 | top: 79px;
540 | }
541 | nav .navLinks .links {
542 | flex-direction: column;
543 | text-align: center;
544 | }
545 | nav .navLinks .links a {
546 | font-weight: 700;
547 | }
548 | nav .logoutBtn {
549 | margin-top: 20px;
550 | }
551 | }
552 | @media (max-width: 800px) {
553 | nav .showmenu {
554 | width: 96vw;
555 | }
556 | }
557 | @media (max-width: 650px) {
558 | nav .showmenu {
559 | margin: 0;
560 | width: 100%;
561 | border-radius: 0;
562 | }
563 | }
564 | @media (max-width: 555px) {
565 | nav {
566 | background: #fff;
567 | }
568 | nav .navLinks {
569 | background: #fff;
570 | width: 100%;
571 | }
572 | }
573 |
574 | input[type="date"]:before {
575 | content: attr(placeholder);
576 | color: #444;
577 | margin-right: 0.5em;
578 | }
579 | input[type="time"]:before {
580 | content: attr(placeholder);
581 | color: #444;
582 | margin-right: 0.5em;
583 | }
584 | .logo-img{
585 | width: 150px;
586 | }
587 | footer .logo-img{
588 | width: 100%;
589 | }
--------------------------------------------------------------------------------
/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 | "cloudinary": "^2.5.1",
14 | "cookie-parser": "^1.4.7",
15 | "cors": "^2.8.5",
16 | "dotenv": "^16.4.5",
17 | "express": "^4.21.1",
18 | "express-fileupload": "^1.5.1",
19 | "jsonwebtoken": "^9.0.2",
20 | "mongoose": "^8.7.2",
21 | "validator": "^13.12.0"
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/@mongodb-js/saslprep": {
44 | "version": "1.1.9",
45 | "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz",
46 | "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==",
47 | "dependencies": {
48 | "sparse-bitfield": "^3.0.3"
49 | }
50 | },
51 | "node_modules/@types/webidl-conversions": {
52 | "version": "7.0.3",
53 | "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
54 | "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
55 | },
56 | "node_modules/@types/whatwg-url": {
57 | "version": "11.0.5",
58 | "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
59 | "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
60 | "dependencies": {
61 | "@types/webidl-conversions": "*"
62 | }
63 | },
64 | "node_modules/abbrev": {
65 | "version": "1.1.1",
66 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
67 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
68 | },
69 | "node_modules/accepts": {
70 | "version": "1.3.8",
71 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
72 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
73 | "dependencies": {
74 | "mime-types": "~2.1.34",
75 | "negotiator": "0.6.3"
76 | },
77 | "engines": {
78 | "node": ">= 0.6"
79 | }
80 | },
81 | "node_modules/agent-base": {
82 | "version": "6.0.2",
83 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
84 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
85 | "dependencies": {
86 | "debug": "4"
87 | },
88 | "engines": {
89 | "node": ">= 6.0.0"
90 | }
91 | },
92 | "node_modules/agent-base/node_modules/debug": {
93 | "version": "4.3.7",
94 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
95 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
96 | "dependencies": {
97 | "ms": "^2.1.3"
98 | },
99 | "engines": {
100 | "node": ">=6.0"
101 | },
102 | "peerDependenciesMeta": {
103 | "supports-color": {
104 | "optional": true
105 | }
106 | }
107 | },
108 | "node_modules/agent-base/node_modules/ms": {
109 | "version": "2.1.3",
110 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
111 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
112 | },
113 | "node_modules/ansi-regex": {
114 | "version": "5.0.1",
115 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
116 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
117 | "engines": {
118 | "node": ">=8"
119 | }
120 | },
121 | "node_modules/aproba": {
122 | "version": "2.0.0",
123 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
124 | "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
125 | },
126 | "node_modules/are-we-there-yet": {
127 | "version": "2.0.0",
128 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
129 | "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
130 | "deprecated": "This package is no longer supported.",
131 | "dependencies": {
132 | "delegates": "^1.0.0",
133 | "readable-stream": "^3.6.0"
134 | },
135 | "engines": {
136 | "node": ">=10"
137 | }
138 | },
139 | "node_modules/array-flatten": {
140 | "version": "1.1.1",
141 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
142 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
143 | },
144 | "node_modules/balanced-match": {
145 | "version": "1.0.2",
146 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
147 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
148 | },
149 | "node_modules/bcrypt": {
150 | "version": "5.1.1",
151 | "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
152 | "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==",
153 | "hasInstallScript": true,
154 | "dependencies": {
155 | "@mapbox/node-pre-gyp": "^1.0.11",
156 | "node-addon-api": "^5.0.0"
157 | },
158 | "engines": {
159 | "node": ">= 10.0.0"
160 | }
161 | },
162 | "node_modules/body-parser": {
163 | "version": "1.20.3",
164 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
165 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
166 | "dependencies": {
167 | "bytes": "3.1.2",
168 | "content-type": "~1.0.5",
169 | "debug": "2.6.9",
170 | "depd": "2.0.0",
171 | "destroy": "1.2.0",
172 | "http-errors": "2.0.0",
173 | "iconv-lite": "0.4.24",
174 | "on-finished": "2.4.1",
175 | "qs": "6.13.0",
176 | "raw-body": "2.5.2",
177 | "type-is": "~1.6.18",
178 | "unpipe": "1.0.0"
179 | },
180 | "engines": {
181 | "node": ">= 0.8",
182 | "npm": "1.2.8000 || >= 1.4.16"
183 | }
184 | },
185 | "node_modules/brace-expansion": {
186 | "version": "1.1.11",
187 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
188 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
189 | "dependencies": {
190 | "balanced-match": "^1.0.0",
191 | "concat-map": "0.0.1"
192 | }
193 | },
194 | "node_modules/bson": {
195 | "version": "6.9.0",
196 | "resolved": "https://registry.npmjs.org/bson/-/bson-6.9.0.tgz",
197 | "integrity": "sha512-X9hJeyeM0//Fus+0pc5dSUMhhrrmWwQUtdavaQeF3Ta6m69matZkGWV/MrBcnwUeLC8W9kwwc2hfkZgUuCX3Ig==",
198 | "engines": {
199 | "node": ">=16.20.1"
200 | }
201 | },
202 | "node_modules/buffer-equal-constant-time": {
203 | "version": "1.0.1",
204 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
205 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
206 | },
207 | "node_modules/busboy": {
208 | "version": "1.6.0",
209 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
210 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
211 | "dependencies": {
212 | "streamsearch": "^1.1.0"
213 | },
214 | "engines": {
215 | "node": ">=10.16.0"
216 | }
217 | },
218 | "node_modules/bytes": {
219 | "version": "3.1.2",
220 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
221 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
222 | "engines": {
223 | "node": ">= 0.8"
224 | }
225 | },
226 | "node_modules/call-bind": {
227 | "version": "1.0.7",
228 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
229 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
230 | "dependencies": {
231 | "es-define-property": "^1.0.0",
232 | "es-errors": "^1.3.0",
233 | "function-bind": "^1.1.2",
234 | "get-intrinsic": "^1.2.4",
235 | "set-function-length": "^1.2.1"
236 | },
237 | "engines": {
238 | "node": ">= 0.4"
239 | },
240 | "funding": {
241 | "url": "https://github.com/sponsors/ljharb"
242 | }
243 | },
244 | "node_modules/chownr": {
245 | "version": "2.0.0",
246 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
247 | "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
248 | "engines": {
249 | "node": ">=10"
250 | }
251 | },
252 | "node_modules/cloudinary": {
253 | "version": "2.5.1",
254 | "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.5.1.tgz",
255 | "integrity": "sha512-CNg6uU53Hl4FEVynkTGpt5bQEAQWDHi3H+Sm62FzKf5uQHipSN2v7qVqS8GRVqeb0T1WNV+22+75DOJeRXYeSQ==",
256 | "dependencies": {
257 | "lodash": "^4.17.21",
258 | "q": "^1.5.1"
259 | },
260 | "engines": {
261 | "node": ">=9"
262 | }
263 | },
264 | "node_modules/color-support": {
265 | "version": "1.1.3",
266 | "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
267 | "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
268 | "bin": {
269 | "color-support": "bin.js"
270 | }
271 | },
272 | "node_modules/concat-map": {
273 | "version": "0.0.1",
274 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
275 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
276 | },
277 | "node_modules/console-control-strings": {
278 | "version": "1.1.0",
279 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
280 | "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
281 | },
282 | "node_modules/content-disposition": {
283 | "version": "0.5.4",
284 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
285 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
286 | "dependencies": {
287 | "safe-buffer": "5.2.1"
288 | },
289 | "engines": {
290 | "node": ">= 0.6"
291 | }
292 | },
293 | "node_modules/content-type": {
294 | "version": "1.0.5",
295 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
296 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
297 | "engines": {
298 | "node": ">= 0.6"
299 | }
300 | },
301 | "node_modules/cookie": {
302 | "version": "0.7.2",
303 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
304 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
305 | "engines": {
306 | "node": ">= 0.6"
307 | }
308 | },
309 | "node_modules/cookie-parser": {
310 | "version": "1.4.7",
311 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
312 | "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
313 | "dependencies": {
314 | "cookie": "0.7.2",
315 | "cookie-signature": "1.0.6"
316 | },
317 | "engines": {
318 | "node": ">= 0.8.0"
319 | }
320 | },
321 | "node_modules/cookie-signature": {
322 | "version": "1.0.6",
323 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
324 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
325 | },
326 | "node_modules/cors": {
327 | "version": "2.8.5",
328 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
329 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
330 | "dependencies": {
331 | "object-assign": "^4",
332 | "vary": "^1"
333 | },
334 | "engines": {
335 | "node": ">= 0.10"
336 | }
337 | },
338 | "node_modules/debug": {
339 | "version": "2.6.9",
340 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
341 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
342 | "dependencies": {
343 | "ms": "2.0.0"
344 | }
345 | },
346 | "node_modules/define-data-property": {
347 | "version": "1.1.4",
348 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
349 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
350 | "dependencies": {
351 | "es-define-property": "^1.0.0",
352 | "es-errors": "^1.3.0",
353 | "gopd": "^1.0.1"
354 | },
355 | "engines": {
356 | "node": ">= 0.4"
357 | },
358 | "funding": {
359 | "url": "https://github.com/sponsors/ljharb"
360 | }
361 | },
362 | "node_modules/delegates": {
363 | "version": "1.0.0",
364 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
365 | "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
366 | },
367 | "node_modules/depd": {
368 | "version": "2.0.0",
369 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
370 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
371 | "engines": {
372 | "node": ">= 0.8"
373 | }
374 | },
375 | "node_modules/destroy": {
376 | "version": "1.2.0",
377 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
378 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
379 | "engines": {
380 | "node": ">= 0.8",
381 | "npm": "1.2.8000 || >= 1.4.16"
382 | }
383 | },
384 | "node_modules/detect-libc": {
385 | "version": "2.0.3",
386 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
387 | "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
388 | "engines": {
389 | "node": ">=8"
390 | }
391 | },
392 | "node_modules/dotenv": {
393 | "version": "16.4.5",
394 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
395 | "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
396 | "engines": {
397 | "node": ">=12"
398 | },
399 | "funding": {
400 | "url": "https://dotenvx.com"
401 | }
402 | },
403 | "node_modules/ecdsa-sig-formatter": {
404 | "version": "1.0.11",
405 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
406 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
407 | "dependencies": {
408 | "safe-buffer": "^5.0.1"
409 | }
410 | },
411 | "node_modules/ee-first": {
412 | "version": "1.1.1",
413 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
414 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
415 | },
416 | "node_modules/emoji-regex": {
417 | "version": "8.0.0",
418 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
419 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
420 | },
421 | "node_modules/encodeurl": {
422 | "version": "2.0.0",
423 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
424 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
425 | "engines": {
426 | "node": ">= 0.8"
427 | }
428 | },
429 | "node_modules/es-define-property": {
430 | "version": "1.0.0",
431 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
432 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
433 | "dependencies": {
434 | "get-intrinsic": "^1.2.4"
435 | },
436 | "engines": {
437 | "node": ">= 0.4"
438 | }
439 | },
440 | "node_modules/es-errors": {
441 | "version": "1.3.0",
442 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
443 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
444 | "engines": {
445 | "node": ">= 0.4"
446 | }
447 | },
448 | "node_modules/escape-html": {
449 | "version": "1.0.3",
450 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
451 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
452 | },
453 | "node_modules/etag": {
454 | "version": "1.8.1",
455 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
456 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
457 | "engines": {
458 | "node": ">= 0.6"
459 | }
460 | },
461 | "node_modules/express": {
462 | "version": "4.21.1",
463 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
464 | "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
465 | "dependencies": {
466 | "accepts": "~1.3.8",
467 | "array-flatten": "1.1.1",
468 | "body-parser": "1.20.3",
469 | "content-disposition": "0.5.4",
470 | "content-type": "~1.0.4",
471 | "cookie": "0.7.1",
472 | "cookie-signature": "1.0.6",
473 | "debug": "2.6.9",
474 | "depd": "2.0.0",
475 | "encodeurl": "~2.0.0",
476 | "escape-html": "~1.0.3",
477 | "etag": "~1.8.1",
478 | "finalhandler": "1.3.1",
479 | "fresh": "0.5.2",
480 | "http-errors": "2.0.0",
481 | "merge-descriptors": "1.0.3",
482 | "methods": "~1.1.2",
483 | "on-finished": "2.4.1",
484 | "parseurl": "~1.3.3",
485 | "path-to-regexp": "0.1.10",
486 | "proxy-addr": "~2.0.7",
487 | "qs": "6.13.0",
488 | "range-parser": "~1.2.1",
489 | "safe-buffer": "5.2.1",
490 | "send": "0.19.0",
491 | "serve-static": "1.16.2",
492 | "setprototypeof": "1.2.0",
493 | "statuses": "2.0.1",
494 | "type-is": "~1.6.18",
495 | "utils-merge": "1.0.1",
496 | "vary": "~1.1.2"
497 | },
498 | "engines": {
499 | "node": ">= 0.10.0"
500 | }
501 | },
502 | "node_modules/express-fileupload": {
503 | "version": "1.5.1",
504 | "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.1.tgz",
505 | "integrity": "sha512-LsYG1ALXEB7vlmjuSw8ABeOctMp8a31aUC5ZF55zuz7O2jLFnmJYrCv10py357ky48aEoBQ/9bVXgFynjvaPmA==",
506 | "dependencies": {
507 | "busboy": "^1.6.0"
508 | },
509 | "engines": {
510 | "node": ">=12.0.0"
511 | }
512 | },
513 | "node_modules/express/node_modules/cookie": {
514 | "version": "0.7.1",
515 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
516 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
517 | "engines": {
518 | "node": ">= 0.6"
519 | }
520 | },
521 | "node_modules/finalhandler": {
522 | "version": "1.3.1",
523 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
524 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
525 | "dependencies": {
526 | "debug": "2.6.9",
527 | "encodeurl": "~2.0.0",
528 | "escape-html": "~1.0.3",
529 | "on-finished": "2.4.1",
530 | "parseurl": "~1.3.3",
531 | "statuses": "2.0.1",
532 | "unpipe": "~1.0.0"
533 | },
534 | "engines": {
535 | "node": ">= 0.8"
536 | }
537 | },
538 | "node_modules/forwarded": {
539 | "version": "0.2.0",
540 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
541 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
542 | "engines": {
543 | "node": ">= 0.6"
544 | }
545 | },
546 | "node_modules/fresh": {
547 | "version": "0.5.2",
548 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
549 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
550 | "engines": {
551 | "node": ">= 0.6"
552 | }
553 | },
554 | "node_modules/fs-minipass": {
555 | "version": "2.1.0",
556 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
557 | "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
558 | "dependencies": {
559 | "minipass": "^3.0.0"
560 | },
561 | "engines": {
562 | "node": ">= 8"
563 | }
564 | },
565 | "node_modules/fs-minipass/node_modules/minipass": {
566 | "version": "3.3.6",
567 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
568 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
569 | "dependencies": {
570 | "yallist": "^4.0.0"
571 | },
572 | "engines": {
573 | "node": ">=8"
574 | }
575 | },
576 | "node_modules/fs.realpath": {
577 | "version": "1.0.0",
578 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
579 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
580 | },
581 | "node_modules/function-bind": {
582 | "version": "1.1.2",
583 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
584 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
585 | "funding": {
586 | "url": "https://github.com/sponsors/ljharb"
587 | }
588 | },
589 | "node_modules/gauge": {
590 | "version": "3.0.2",
591 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
592 | "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
593 | "deprecated": "This package is no longer supported.",
594 | "dependencies": {
595 | "aproba": "^1.0.3 || ^2.0.0",
596 | "color-support": "^1.1.2",
597 | "console-control-strings": "^1.0.0",
598 | "has-unicode": "^2.0.1",
599 | "object-assign": "^4.1.1",
600 | "signal-exit": "^3.0.0",
601 | "string-width": "^4.2.3",
602 | "strip-ansi": "^6.0.1",
603 | "wide-align": "^1.1.2"
604 | },
605 | "engines": {
606 | "node": ">=10"
607 | }
608 | },
609 | "node_modules/get-intrinsic": {
610 | "version": "1.2.4",
611 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
612 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
613 | "dependencies": {
614 | "es-errors": "^1.3.0",
615 | "function-bind": "^1.1.2",
616 | "has-proto": "^1.0.1",
617 | "has-symbols": "^1.0.3",
618 | "hasown": "^2.0.0"
619 | },
620 | "engines": {
621 | "node": ">= 0.4"
622 | },
623 | "funding": {
624 | "url": "https://github.com/sponsors/ljharb"
625 | }
626 | },
627 | "node_modules/glob": {
628 | "version": "7.2.3",
629 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
630 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
631 | "deprecated": "Glob versions prior to v9 are no longer supported",
632 | "dependencies": {
633 | "fs.realpath": "^1.0.0",
634 | "inflight": "^1.0.4",
635 | "inherits": "2",
636 | "minimatch": "^3.1.1",
637 | "once": "^1.3.0",
638 | "path-is-absolute": "^1.0.0"
639 | },
640 | "engines": {
641 | "node": "*"
642 | },
643 | "funding": {
644 | "url": "https://github.com/sponsors/isaacs"
645 | }
646 | },
647 | "node_modules/gopd": {
648 | "version": "1.0.1",
649 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
650 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
651 | "dependencies": {
652 | "get-intrinsic": "^1.1.3"
653 | },
654 | "funding": {
655 | "url": "https://github.com/sponsors/ljharb"
656 | }
657 | },
658 | "node_modules/has-property-descriptors": {
659 | "version": "1.0.2",
660 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
661 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
662 | "dependencies": {
663 | "es-define-property": "^1.0.0"
664 | },
665 | "funding": {
666 | "url": "https://github.com/sponsors/ljharb"
667 | }
668 | },
669 | "node_modules/has-proto": {
670 | "version": "1.0.3",
671 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
672 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
673 | "engines": {
674 | "node": ">= 0.4"
675 | },
676 | "funding": {
677 | "url": "https://github.com/sponsors/ljharb"
678 | }
679 | },
680 | "node_modules/has-symbols": {
681 | "version": "1.0.3",
682 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
683 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
684 | "engines": {
685 | "node": ">= 0.4"
686 | },
687 | "funding": {
688 | "url": "https://github.com/sponsors/ljharb"
689 | }
690 | },
691 | "node_modules/has-unicode": {
692 | "version": "2.0.1",
693 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
694 | "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
695 | },
696 | "node_modules/hasown": {
697 | "version": "2.0.2",
698 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
699 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
700 | "dependencies": {
701 | "function-bind": "^1.1.2"
702 | },
703 | "engines": {
704 | "node": ">= 0.4"
705 | }
706 | },
707 | "node_modules/http-errors": {
708 | "version": "2.0.0",
709 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
710 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
711 | "dependencies": {
712 | "depd": "2.0.0",
713 | "inherits": "2.0.4",
714 | "setprototypeof": "1.2.0",
715 | "statuses": "2.0.1",
716 | "toidentifier": "1.0.1"
717 | },
718 | "engines": {
719 | "node": ">= 0.8"
720 | }
721 | },
722 | "node_modules/https-proxy-agent": {
723 | "version": "5.0.1",
724 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
725 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
726 | "dependencies": {
727 | "agent-base": "6",
728 | "debug": "4"
729 | },
730 | "engines": {
731 | "node": ">= 6"
732 | }
733 | },
734 | "node_modules/https-proxy-agent/node_modules/debug": {
735 | "version": "4.3.7",
736 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
737 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
738 | "dependencies": {
739 | "ms": "^2.1.3"
740 | },
741 | "engines": {
742 | "node": ">=6.0"
743 | },
744 | "peerDependenciesMeta": {
745 | "supports-color": {
746 | "optional": true
747 | }
748 | }
749 | },
750 | "node_modules/https-proxy-agent/node_modules/ms": {
751 | "version": "2.1.3",
752 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
753 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
754 | },
755 | "node_modules/iconv-lite": {
756 | "version": "0.4.24",
757 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
758 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
759 | "dependencies": {
760 | "safer-buffer": ">= 2.1.2 < 3"
761 | },
762 | "engines": {
763 | "node": ">=0.10.0"
764 | }
765 | },
766 | "node_modules/inflight": {
767 | "version": "1.0.6",
768 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
769 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
770 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
771 | "dependencies": {
772 | "once": "^1.3.0",
773 | "wrappy": "1"
774 | }
775 | },
776 | "node_modules/inherits": {
777 | "version": "2.0.4",
778 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
779 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
780 | },
781 | "node_modules/ipaddr.js": {
782 | "version": "1.9.1",
783 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
784 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
785 | "engines": {
786 | "node": ">= 0.10"
787 | }
788 | },
789 | "node_modules/is-fullwidth-code-point": {
790 | "version": "3.0.0",
791 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
792 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
793 | "engines": {
794 | "node": ">=8"
795 | }
796 | },
797 | "node_modules/jsonwebtoken": {
798 | "version": "9.0.2",
799 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
800 | "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
801 | "dependencies": {
802 | "jws": "^3.2.2",
803 | "lodash.includes": "^4.3.0",
804 | "lodash.isboolean": "^3.0.3",
805 | "lodash.isinteger": "^4.0.4",
806 | "lodash.isnumber": "^3.0.3",
807 | "lodash.isplainobject": "^4.0.6",
808 | "lodash.isstring": "^4.0.1",
809 | "lodash.once": "^4.0.0",
810 | "ms": "^2.1.1",
811 | "semver": "^7.5.4"
812 | },
813 | "engines": {
814 | "node": ">=12",
815 | "npm": ">=6"
816 | }
817 | },
818 | "node_modules/jsonwebtoken/node_modules/ms": {
819 | "version": "2.1.3",
820 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
821 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
822 | },
823 | "node_modules/jwa": {
824 | "version": "1.4.1",
825 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
826 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
827 | "dependencies": {
828 | "buffer-equal-constant-time": "1.0.1",
829 | "ecdsa-sig-formatter": "1.0.11",
830 | "safe-buffer": "^5.0.1"
831 | }
832 | },
833 | "node_modules/jws": {
834 | "version": "3.2.2",
835 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
836 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
837 | "dependencies": {
838 | "jwa": "^1.4.1",
839 | "safe-buffer": "^5.0.1"
840 | }
841 | },
842 | "node_modules/kareem": {
843 | "version": "2.6.3",
844 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
845 | "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==",
846 | "engines": {
847 | "node": ">=12.0.0"
848 | }
849 | },
850 | "node_modules/lodash": {
851 | "version": "4.17.21",
852 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
853 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
854 | },
855 | "node_modules/lodash.includes": {
856 | "version": "4.3.0",
857 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
858 | "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
859 | },
860 | "node_modules/lodash.isboolean": {
861 | "version": "3.0.3",
862 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
863 | "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
864 | },
865 | "node_modules/lodash.isinteger": {
866 | "version": "4.0.4",
867 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
868 | "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
869 | },
870 | "node_modules/lodash.isnumber": {
871 | "version": "3.0.3",
872 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
873 | "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
874 | },
875 | "node_modules/lodash.isplainobject": {
876 | "version": "4.0.6",
877 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
878 | "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
879 | },
880 | "node_modules/lodash.isstring": {
881 | "version": "4.0.1",
882 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
883 | "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
884 | },
885 | "node_modules/lodash.once": {
886 | "version": "4.1.1",
887 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
888 | "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
889 | },
890 | "node_modules/make-dir": {
891 | "version": "3.1.0",
892 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
893 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
894 | "dependencies": {
895 | "semver": "^6.0.0"
896 | },
897 | "engines": {
898 | "node": ">=8"
899 | },
900 | "funding": {
901 | "url": "https://github.com/sponsors/sindresorhus"
902 | }
903 | },
904 | "node_modules/make-dir/node_modules/semver": {
905 | "version": "6.3.1",
906 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
907 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
908 | "bin": {
909 | "semver": "bin/semver.js"
910 | }
911 | },
912 | "node_modules/media-typer": {
913 | "version": "0.3.0",
914 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
915 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
916 | "engines": {
917 | "node": ">= 0.6"
918 | }
919 | },
920 | "node_modules/memory-pager": {
921 | "version": "1.5.0",
922 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
923 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
924 | },
925 | "node_modules/merge-descriptors": {
926 | "version": "1.0.3",
927 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
928 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
929 | "funding": {
930 | "url": "https://github.com/sponsors/sindresorhus"
931 | }
932 | },
933 | "node_modules/methods": {
934 | "version": "1.1.2",
935 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
936 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
937 | "engines": {
938 | "node": ">= 0.6"
939 | }
940 | },
941 | "node_modules/mime": {
942 | "version": "1.6.0",
943 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
944 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
945 | "bin": {
946 | "mime": "cli.js"
947 | },
948 | "engines": {
949 | "node": ">=4"
950 | }
951 | },
952 | "node_modules/mime-db": {
953 | "version": "1.52.0",
954 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
955 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
956 | "engines": {
957 | "node": ">= 0.6"
958 | }
959 | },
960 | "node_modules/mime-types": {
961 | "version": "2.1.35",
962 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
963 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
964 | "dependencies": {
965 | "mime-db": "1.52.0"
966 | },
967 | "engines": {
968 | "node": ">= 0.6"
969 | }
970 | },
971 | "node_modules/minimatch": {
972 | "version": "3.1.2",
973 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
974 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
975 | "dependencies": {
976 | "brace-expansion": "^1.1.7"
977 | },
978 | "engines": {
979 | "node": "*"
980 | }
981 | },
982 | "node_modules/minipass": {
983 | "version": "5.0.0",
984 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
985 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
986 | "engines": {
987 | "node": ">=8"
988 | }
989 | },
990 | "node_modules/minizlib": {
991 | "version": "2.1.2",
992 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
993 | "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
994 | "dependencies": {
995 | "minipass": "^3.0.0",
996 | "yallist": "^4.0.0"
997 | },
998 | "engines": {
999 | "node": ">= 8"
1000 | }
1001 | },
1002 | "node_modules/minizlib/node_modules/minipass": {
1003 | "version": "3.3.6",
1004 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
1005 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
1006 | "dependencies": {
1007 | "yallist": "^4.0.0"
1008 | },
1009 | "engines": {
1010 | "node": ">=8"
1011 | }
1012 | },
1013 | "node_modules/mkdirp": {
1014 | "version": "1.0.4",
1015 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
1016 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
1017 | "bin": {
1018 | "mkdirp": "bin/cmd.js"
1019 | },
1020 | "engines": {
1021 | "node": ">=10"
1022 | }
1023 | },
1024 | "node_modules/mongodb": {
1025 | "version": "6.9.0",
1026 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.9.0.tgz",
1027 | "integrity": "sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA==",
1028 | "dependencies": {
1029 | "@mongodb-js/saslprep": "^1.1.5",
1030 | "bson": "^6.7.0",
1031 | "mongodb-connection-string-url": "^3.0.0"
1032 | },
1033 | "engines": {
1034 | "node": ">=16.20.1"
1035 | },
1036 | "peerDependencies": {
1037 | "@aws-sdk/credential-providers": "^3.188.0",
1038 | "@mongodb-js/zstd": "^1.1.0",
1039 | "gcp-metadata": "^5.2.0",
1040 | "kerberos": "^2.0.1",
1041 | "mongodb-client-encryption": ">=6.0.0 <7",
1042 | "snappy": "^7.2.2",
1043 | "socks": "^2.7.1"
1044 | },
1045 | "peerDependenciesMeta": {
1046 | "@aws-sdk/credential-providers": {
1047 | "optional": true
1048 | },
1049 | "@mongodb-js/zstd": {
1050 | "optional": true
1051 | },
1052 | "gcp-metadata": {
1053 | "optional": true
1054 | },
1055 | "kerberos": {
1056 | "optional": true
1057 | },
1058 | "mongodb-client-encryption": {
1059 | "optional": true
1060 | },
1061 | "snappy": {
1062 | "optional": true
1063 | },
1064 | "socks": {
1065 | "optional": true
1066 | }
1067 | }
1068 | },
1069 | "node_modules/mongodb-connection-string-url": {
1070 | "version": "3.0.1",
1071 | "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz",
1072 | "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==",
1073 | "dependencies": {
1074 | "@types/whatwg-url": "^11.0.2",
1075 | "whatwg-url": "^13.0.0"
1076 | }
1077 | },
1078 | "node_modules/mongoose": {
1079 | "version": "8.7.2",
1080 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.2.tgz",
1081 | "integrity": "sha512-Ok4VzMds9p5G3ZSUhmvBm1GdxanbzhS29jpSn02SPj+IXEVFnIdfwAlHHXWkyNscZKlcn8GuMi68FH++jo0flg==",
1082 | "dependencies": {
1083 | "bson": "^6.7.0",
1084 | "kareem": "2.6.3",
1085 | "mongodb": "6.9.0",
1086 | "mpath": "0.9.0",
1087 | "mquery": "5.0.0",
1088 | "ms": "2.1.3",
1089 | "sift": "17.1.3"
1090 | },
1091 | "engines": {
1092 | "node": ">=16.20.1"
1093 | },
1094 | "funding": {
1095 | "type": "opencollective",
1096 | "url": "https://opencollective.com/mongoose"
1097 | }
1098 | },
1099 | "node_modules/mongoose/node_modules/ms": {
1100 | "version": "2.1.3",
1101 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1102 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1103 | },
1104 | "node_modules/mpath": {
1105 | "version": "0.9.0",
1106 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
1107 | "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
1108 | "engines": {
1109 | "node": ">=4.0.0"
1110 | }
1111 | },
1112 | "node_modules/mquery": {
1113 | "version": "5.0.0",
1114 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
1115 | "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
1116 | "dependencies": {
1117 | "debug": "4.x"
1118 | },
1119 | "engines": {
1120 | "node": ">=14.0.0"
1121 | }
1122 | },
1123 | "node_modules/mquery/node_modules/debug": {
1124 | "version": "4.3.7",
1125 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
1126 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
1127 | "dependencies": {
1128 | "ms": "^2.1.3"
1129 | },
1130 | "engines": {
1131 | "node": ">=6.0"
1132 | },
1133 | "peerDependenciesMeta": {
1134 | "supports-color": {
1135 | "optional": true
1136 | }
1137 | }
1138 | },
1139 | "node_modules/mquery/node_modules/ms": {
1140 | "version": "2.1.3",
1141 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1142 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1143 | },
1144 | "node_modules/ms": {
1145 | "version": "2.0.0",
1146 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1147 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
1148 | },
1149 | "node_modules/negotiator": {
1150 | "version": "0.6.3",
1151 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
1152 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
1153 | "engines": {
1154 | "node": ">= 0.6"
1155 | }
1156 | },
1157 | "node_modules/node-addon-api": {
1158 | "version": "5.1.0",
1159 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz",
1160 | "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="
1161 | },
1162 | "node_modules/node-fetch": {
1163 | "version": "2.7.0",
1164 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
1165 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
1166 | "dependencies": {
1167 | "whatwg-url": "^5.0.0"
1168 | },
1169 | "engines": {
1170 | "node": "4.x || >=6.0.0"
1171 | },
1172 | "peerDependencies": {
1173 | "encoding": "^0.1.0"
1174 | },
1175 | "peerDependenciesMeta": {
1176 | "encoding": {
1177 | "optional": true
1178 | }
1179 | }
1180 | },
1181 | "node_modules/node-fetch/node_modules/tr46": {
1182 | "version": "0.0.3",
1183 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
1184 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
1185 | },
1186 | "node_modules/node-fetch/node_modules/webidl-conversions": {
1187 | "version": "3.0.1",
1188 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
1189 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
1190 | },
1191 | "node_modules/node-fetch/node_modules/whatwg-url": {
1192 | "version": "5.0.0",
1193 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
1194 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
1195 | "dependencies": {
1196 | "tr46": "~0.0.3",
1197 | "webidl-conversions": "^3.0.0"
1198 | }
1199 | },
1200 | "node_modules/nopt": {
1201 | "version": "5.0.0",
1202 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
1203 | "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
1204 | "dependencies": {
1205 | "abbrev": "1"
1206 | },
1207 | "bin": {
1208 | "nopt": "bin/nopt.js"
1209 | },
1210 | "engines": {
1211 | "node": ">=6"
1212 | }
1213 | },
1214 | "node_modules/npmlog": {
1215 | "version": "5.0.1",
1216 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
1217 | "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
1218 | "deprecated": "This package is no longer supported.",
1219 | "dependencies": {
1220 | "are-we-there-yet": "^2.0.0",
1221 | "console-control-strings": "^1.1.0",
1222 | "gauge": "^3.0.0",
1223 | "set-blocking": "^2.0.0"
1224 | }
1225 | },
1226 | "node_modules/object-assign": {
1227 | "version": "4.1.1",
1228 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1229 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
1230 | "engines": {
1231 | "node": ">=0.10.0"
1232 | }
1233 | },
1234 | "node_modules/object-inspect": {
1235 | "version": "1.13.2",
1236 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
1237 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
1238 | "engines": {
1239 | "node": ">= 0.4"
1240 | },
1241 | "funding": {
1242 | "url": "https://github.com/sponsors/ljharb"
1243 | }
1244 | },
1245 | "node_modules/on-finished": {
1246 | "version": "2.4.1",
1247 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
1248 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
1249 | "dependencies": {
1250 | "ee-first": "1.1.1"
1251 | },
1252 | "engines": {
1253 | "node": ">= 0.8"
1254 | }
1255 | },
1256 | "node_modules/once": {
1257 | "version": "1.4.0",
1258 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1259 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1260 | "dependencies": {
1261 | "wrappy": "1"
1262 | }
1263 | },
1264 | "node_modules/parseurl": {
1265 | "version": "1.3.3",
1266 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1267 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
1268 | "engines": {
1269 | "node": ">= 0.8"
1270 | }
1271 | },
1272 | "node_modules/path-is-absolute": {
1273 | "version": "1.0.1",
1274 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1275 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1276 | "engines": {
1277 | "node": ">=0.10.0"
1278 | }
1279 | },
1280 | "node_modules/path-to-regexp": {
1281 | "version": "0.1.10",
1282 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
1283 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
1284 | },
1285 | "node_modules/proxy-addr": {
1286 | "version": "2.0.7",
1287 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
1288 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1289 | "dependencies": {
1290 | "forwarded": "0.2.0",
1291 | "ipaddr.js": "1.9.1"
1292 | },
1293 | "engines": {
1294 | "node": ">= 0.10"
1295 | }
1296 | },
1297 | "node_modules/punycode": {
1298 | "version": "2.3.1",
1299 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
1300 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
1301 | "engines": {
1302 | "node": ">=6"
1303 | }
1304 | },
1305 | "node_modules/q": {
1306 | "version": "1.5.1",
1307 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
1308 | "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
1309 | "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)",
1310 | "engines": {
1311 | "node": ">=0.6.0",
1312 | "teleport": ">=0.2.0"
1313 | }
1314 | },
1315 | "node_modules/qs": {
1316 | "version": "6.13.0",
1317 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
1318 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
1319 | "dependencies": {
1320 | "side-channel": "^1.0.6"
1321 | },
1322 | "engines": {
1323 | "node": ">=0.6"
1324 | },
1325 | "funding": {
1326 | "url": "https://github.com/sponsors/ljharb"
1327 | }
1328 | },
1329 | "node_modules/range-parser": {
1330 | "version": "1.2.1",
1331 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1332 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
1333 | "engines": {
1334 | "node": ">= 0.6"
1335 | }
1336 | },
1337 | "node_modules/raw-body": {
1338 | "version": "2.5.2",
1339 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
1340 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
1341 | "dependencies": {
1342 | "bytes": "3.1.2",
1343 | "http-errors": "2.0.0",
1344 | "iconv-lite": "0.4.24",
1345 | "unpipe": "1.0.0"
1346 | },
1347 | "engines": {
1348 | "node": ">= 0.8"
1349 | }
1350 | },
1351 | "node_modules/readable-stream": {
1352 | "version": "3.6.2",
1353 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
1354 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
1355 | "dependencies": {
1356 | "inherits": "^2.0.3",
1357 | "string_decoder": "^1.1.1",
1358 | "util-deprecate": "^1.0.1"
1359 | },
1360 | "engines": {
1361 | "node": ">= 6"
1362 | }
1363 | },
1364 | "node_modules/rimraf": {
1365 | "version": "3.0.2",
1366 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1367 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1368 | "deprecated": "Rimraf versions prior to v4 are no longer supported",
1369 | "dependencies": {
1370 | "glob": "^7.1.3"
1371 | },
1372 | "bin": {
1373 | "rimraf": "bin.js"
1374 | },
1375 | "funding": {
1376 | "url": "https://github.com/sponsors/isaacs"
1377 | }
1378 | },
1379 | "node_modules/safe-buffer": {
1380 | "version": "5.2.1",
1381 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1382 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1383 | "funding": [
1384 | {
1385 | "type": "github",
1386 | "url": "https://github.com/sponsors/feross"
1387 | },
1388 | {
1389 | "type": "patreon",
1390 | "url": "https://www.patreon.com/feross"
1391 | },
1392 | {
1393 | "type": "consulting",
1394 | "url": "https://feross.org/support"
1395 | }
1396 | ]
1397 | },
1398 | "node_modules/safer-buffer": {
1399 | "version": "2.1.2",
1400 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1401 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1402 | },
1403 | "node_modules/semver": {
1404 | "version": "7.6.3",
1405 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
1406 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
1407 | "bin": {
1408 | "semver": "bin/semver.js"
1409 | },
1410 | "engines": {
1411 | "node": ">=10"
1412 | }
1413 | },
1414 | "node_modules/send": {
1415 | "version": "0.19.0",
1416 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
1417 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
1418 | "dependencies": {
1419 | "debug": "2.6.9",
1420 | "depd": "2.0.0",
1421 | "destroy": "1.2.0",
1422 | "encodeurl": "~1.0.2",
1423 | "escape-html": "~1.0.3",
1424 | "etag": "~1.8.1",
1425 | "fresh": "0.5.2",
1426 | "http-errors": "2.0.0",
1427 | "mime": "1.6.0",
1428 | "ms": "2.1.3",
1429 | "on-finished": "2.4.1",
1430 | "range-parser": "~1.2.1",
1431 | "statuses": "2.0.1"
1432 | },
1433 | "engines": {
1434 | "node": ">= 0.8.0"
1435 | }
1436 | },
1437 | "node_modules/send/node_modules/encodeurl": {
1438 | "version": "1.0.2",
1439 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
1440 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
1441 | "engines": {
1442 | "node": ">= 0.8"
1443 | }
1444 | },
1445 | "node_modules/send/node_modules/ms": {
1446 | "version": "2.1.3",
1447 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1448 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1449 | },
1450 | "node_modules/serve-static": {
1451 | "version": "1.16.2",
1452 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
1453 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
1454 | "dependencies": {
1455 | "encodeurl": "~2.0.0",
1456 | "escape-html": "~1.0.3",
1457 | "parseurl": "~1.3.3",
1458 | "send": "0.19.0"
1459 | },
1460 | "engines": {
1461 | "node": ">= 0.8.0"
1462 | }
1463 | },
1464 | "node_modules/set-blocking": {
1465 | "version": "2.0.0",
1466 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
1467 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
1468 | },
1469 | "node_modules/set-function-length": {
1470 | "version": "1.2.2",
1471 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
1472 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
1473 | "dependencies": {
1474 | "define-data-property": "^1.1.4",
1475 | "es-errors": "^1.3.0",
1476 | "function-bind": "^1.1.2",
1477 | "get-intrinsic": "^1.2.4",
1478 | "gopd": "^1.0.1",
1479 | "has-property-descriptors": "^1.0.2"
1480 | },
1481 | "engines": {
1482 | "node": ">= 0.4"
1483 | }
1484 | },
1485 | "node_modules/setprototypeof": {
1486 | "version": "1.2.0",
1487 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1488 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
1489 | },
1490 | "node_modules/side-channel": {
1491 | "version": "1.0.6",
1492 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
1493 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
1494 | "dependencies": {
1495 | "call-bind": "^1.0.7",
1496 | "es-errors": "^1.3.0",
1497 | "get-intrinsic": "^1.2.4",
1498 | "object-inspect": "^1.13.1"
1499 | },
1500 | "engines": {
1501 | "node": ">= 0.4"
1502 | },
1503 | "funding": {
1504 | "url": "https://github.com/sponsors/ljharb"
1505 | }
1506 | },
1507 | "node_modules/sift": {
1508 | "version": "17.1.3",
1509 | "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz",
1510 | "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ=="
1511 | },
1512 | "node_modules/signal-exit": {
1513 | "version": "3.0.7",
1514 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
1515 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
1516 | },
1517 | "node_modules/sparse-bitfield": {
1518 | "version": "3.0.3",
1519 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
1520 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
1521 | "dependencies": {
1522 | "memory-pager": "^1.0.2"
1523 | }
1524 | },
1525 | "node_modules/statuses": {
1526 | "version": "2.0.1",
1527 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1528 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
1529 | "engines": {
1530 | "node": ">= 0.8"
1531 | }
1532 | },
1533 | "node_modules/streamsearch": {
1534 | "version": "1.1.0",
1535 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
1536 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
1537 | "engines": {
1538 | "node": ">=10.0.0"
1539 | }
1540 | },
1541 | "node_modules/string_decoder": {
1542 | "version": "1.3.0",
1543 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
1544 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
1545 | "dependencies": {
1546 | "safe-buffer": "~5.2.0"
1547 | }
1548 | },
1549 | "node_modules/string-width": {
1550 | "version": "4.2.3",
1551 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1552 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1553 | "dependencies": {
1554 | "emoji-regex": "^8.0.0",
1555 | "is-fullwidth-code-point": "^3.0.0",
1556 | "strip-ansi": "^6.0.1"
1557 | },
1558 | "engines": {
1559 | "node": ">=8"
1560 | }
1561 | },
1562 | "node_modules/strip-ansi": {
1563 | "version": "6.0.1",
1564 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1565 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1566 | "dependencies": {
1567 | "ansi-regex": "^5.0.1"
1568 | },
1569 | "engines": {
1570 | "node": ">=8"
1571 | }
1572 | },
1573 | "node_modules/tar": {
1574 | "version": "6.2.1",
1575 | "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
1576 | "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
1577 | "dependencies": {
1578 | "chownr": "^2.0.0",
1579 | "fs-minipass": "^2.0.0",
1580 | "minipass": "^5.0.0",
1581 | "minizlib": "^2.1.1",
1582 | "mkdirp": "^1.0.3",
1583 | "yallist": "^4.0.0"
1584 | },
1585 | "engines": {
1586 | "node": ">=10"
1587 | }
1588 | },
1589 | "node_modules/toidentifier": {
1590 | "version": "1.0.1",
1591 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1592 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
1593 | "engines": {
1594 | "node": ">=0.6"
1595 | }
1596 | },
1597 | "node_modules/tr46": {
1598 | "version": "4.1.1",
1599 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
1600 | "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
1601 | "dependencies": {
1602 | "punycode": "^2.3.0"
1603 | },
1604 | "engines": {
1605 | "node": ">=14"
1606 | }
1607 | },
1608 | "node_modules/type-is": {
1609 | "version": "1.6.18",
1610 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1611 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1612 | "dependencies": {
1613 | "media-typer": "0.3.0",
1614 | "mime-types": "~2.1.24"
1615 | },
1616 | "engines": {
1617 | "node": ">= 0.6"
1618 | }
1619 | },
1620 | "node_modules/unpipe": {
1621 | "version": "1.0.0",
1622 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1623 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1624 | "engines": {
1625 | "node": ">= 0.8"
1626 | }
1627 | },
1628 | "node_modules/util-deprecate": {
1629 | "version": "1.0.2",
1630 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1631 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
1632 | },
1633 | "node_modules/utils-merge": {
1634 | "version": "1.0.1",
1635 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1636 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
1637 | "engines": {
1638 | "node": ">= 0.4.0"
1639 | }
1640 | },
1641 | "node_modules/validator": {
1642 | "version": "13.12.0",
1643 | "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
1644 | "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==",
1645 | "engines": {
1646 | "node": ">= 0.10"
1647 | }
1648 | },
1649 | "node_modules/vary": {
1650 | "version": "1.1.2",
1651 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1652 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
1653 | "engines": {
1654 | "node": ">= 0.8"
1655 | }
1656 | },
1657 | "node_modules/webidl-conversions": {
1658 | "version": "7.0.0",
1659 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
1660 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
1661 | "engines": {
1662 | "node": ">=12"
1663 | }
1664 | },
1665 | "node_modules/whatwg-url": {
1666 | "version": "13.0.0",
1667 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
1668 | "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
1669 | "dependencies": {
1670 | "tr46": "^4.1.1",
1671 | "webidl-conversions": "^7.0.0"
1672 | },
1673 | "engines": {
1674 | "node": ">=16"
1675 | }
1676 | },
1677 | "node_modules/wide-align": {
1678 | "version": "1.1.5",
1679 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
1680 | "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
1681 | "dependencies": {
1682 | "string-width": "^1.0.2 || 2 || 3 || 4"
1683 | }
1684 | },
1685 | "node_modules/wrappy": {
1686 | "version": "1.0.2",
1687 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1688 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
1689 | },
1690 | "node_modules/yallist": {
1691 | "version": "4.0.0",
1692 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
1693 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
1694 | }
1695 | }
1696 | }
1697 |
--------------------------------------------------------------------------------