From e33f856f2196fd0e5195e6ebcc2f4be859137ba5 Mon Sep 17 00:00:00 2001 From: Kshitij Date: Sat, 22 Feb 2025 12:51:15 +0530 Subject: [PATCH 1/5] Added Karan's name in README file for his branch. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 56619c4..621a74e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Status200 +Karan's branch for backend developement. + --- From 793e6c2009e24cf0baf78913782a9939aad43739 Mon Sep 17 00:00:00 2001 From: Karan Date: Sat, 22 Feb 2025 12:55:06 +0530 Subject: [PATCH 2/5] Added backend folder structure. --- Backend/.gitignore | 57 + Backend/Controllers/meeting.controller.js | 0 Backend/Controllers/user.controller.js | 464 +++++ Backend/Database/DB_connect.js | 21 + Backend/Middlewares/authentication.js | 46 + Backend/Middlewares/catchAsyncErrors.js | 3 + Backend/Middlewares/multer.js | 20 + Backend/Models/meeting.model.js | 51 + Backend/Models/user.model.js | 111 ++ Backend/Routes/meeting.routes.js | 0 Backend/Routes/user.routes.js | 50 + Backend/Utils/cloudinary.js | 23 + Backend/Utils/sendmail.js | 25 + Backend/app.js | 86 + Backend/index.js | 23 + Backend/package-lock.json | 2188 +++++++++++++++++++++ Backend/package.json | 28 + Backend/vercel.json | 19 + 18 files changed, 3215 insertions(+) create mode 100644 Backend/.gitignore create mode 100644 Backend/Controllers/meeting.controller.js create mode 100644 Backend/Controllers/user.controller.js create mode 100644 Backend/Database/DB_connect.js create mode 100644 Backend/Middlewares/authentication.js create mode 100644 Backend/Middlewares/catchAsyncErrors.js create mode 100644 Backend/Middlewares/multer.js create mode 100644 Backend/Models/meeting.model.js create mode 100644 Backend/Models/user.model.js create mode 100644 Backend/Routes/meeting.routes.js create mode 100644 Backend/Routes/user.routes.js create mode 100644 Backend/Utils/cloudinary.js create mode 100644 Backend/Utils/sendmail.js create mode 100644 Backend/app.js create mode 100644 Backend/index.js create mode 100644 Backend/package-lock.json create mode 100644 Backend/package.json create mode 100644 Backend/vercel.json diff --git a/Backend/.gitignore b/Backend/.gitignore new file mode 100644 index 0000000..30edd8d --- /dev/null +++ b/Backend/.gitignore @@ -0,0 +1,57 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Dependency directories +node_modules/ +jspm_packages/ + +# Environment files +.env +.env.*.local + +# Build outputs +dist/ +build/ + +# Static files +public/ +out/ + +# Test files +coverage/ +*.lcov + +# Database files +*.sqlite3 +*.db +*.db-wal +*.db-shm + +# Temporary files +*.tmp +*.temp +*.swp +*.swo + +# IDE and editor files +.vscode/ +.idea/ +*.iml + +# System files +.DS_Store +Thumbs.db + +# Other +*.log.* diff --git a/Backend/Controllers/meeting.controller.js b/Backend/Controllers/meeting.controller.js new file mode 100644 index 0000000..e69de29 diff --git a/Backend/Controllers/user.controller.js b/Backend/Controllers/user.controller.js new file mode 100644 index 0000000..be55245 --- /dev/null +++ b/Backend/Controllers/user.controller.js @@ -0,0 +1,464 @@ +const catchAsyncErrors = require("../Middlewares/catchAsyncErrors.js"); +const User = require("../Models/user.model.js"); +const { uploadOnCloudinary } = require("../Utils/cloudinary.js"); +const sendEmail = require("../Utils/sendmail.js"); +const crypto = require("crypto"); +const jwt = require("jsonwebtoken"); + +// Register or Sign up new User -- Done +const registerUser = catchAsyncErrors(async (req, res) => { + const { name, email, password, role } = req.body; + + const user = await User.create({ + name, + email, + password, + role, + }); + + if (!user) { + return res.status(500).json({ + success: false, + message: "User not created something went wrong.", + }); + } + + return res.status(200).json({ + success: true, + message: "User is registered successfully", + data: user, + }); +}); + +// Login user in our web app -- Done +const loginUser = catchAsyncErrors(async (req, res) => { + const { email, password } = req.body; + + const user = await User.findOne({ email }); + + if (!user) { + return res.status(404).json({ + success: false, + message: "User not found", + }); + } + + const checkUser = await user.isPasswordCorrect(password); + + if (!checkUser) { + return res.status(500).json({ + success: false, + message: "Password is incorrect", + }); + } + + const token = await user.generateRefreshToken(); + + if (!token) { + return res.status(500).json({ + success: false, + message: "token not created something went wrong.", + }); + } + + user.password = null; + + return res + .status(200) + .cookie(process.env.TOKEN_NAME, token, { + path: "/", + sameSite: "None", + secure: process.env.NODE_ENV === "production", + httpOnly: true, + expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), + }) + .json({ + success: true, + message: "User is successfully logged in.", + data: user, + }); +}); + +// Logout user in our web app -- Done +const logoutUser = catchAsyncErrors(async (req, res) => { + return res + .clearCookie(process.env.TOKEN_NAME, { + path: "/", + sameSite: "None", + secure: process.env.NODE_ENV === "production", + httpOnly: true, + expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), + }) + .status(201) + .json({ + success: true, + message: "User is logged out successfully", + }); +}); + +// -- DONE +const intializeUser = catchAsyncErrors(async (req, res) => { + const tokenValue = req.cookies[process.env.TOKEN_NAME]; + + // console.log("I am the one who is doing this : ", tokenValue); + + if (!tokenValue) { + return res.status(404).json({ + success: false, + message: "User is not logged in.", + }); + } + + try { + const payload = await jwt.verify( + tokenValue, + process.env.REFRESH_TOKEN_SECRET + ); + + if (!payload) { + return res.status(404).json({ + success: false, + message: "Something went wrong", + }); + } + + const user = await User.findById(payload._id).select("-password"); + + return res.status(200).json({ + success: true, + message: "User data get successfully", + data: user, + }); + } catch (error) { + return res.status(404).json({ + success: false, + message: "Something went wrong", + }); + } +}); + +// Update user deatails -- ADMIN +const updateUserDetails = catchAsyncErrors(async (req, res) => { + const user = await User.findById(req.params.id); + if (!user) { + return res.status(404).json({ + success: true, + message: "User not found", + }); + } + + const { name, email } = req.body; + + const updateUser = await User.findByIdAndUpdate(req.params.id, { + $set: { + name: name, + email: email, + }, + }).select("-password"); + + return res.status(200).json({ + success: true, + message: "User is updated successfully", + data: updateUser, + }); +}); + +// forget password -- Done +const forgetPassword = catchAsyncErrors(async (req, res) => { + const { email } = req.body; + const user = await User.findOne({ email }); + + if (!user) { + return res.status(404).json({ + success: false, + message: "User not found ", + }); + } + + // get reset password + + const resetToken = await user.getResetPassword(); + + await user.save({ validateBeforeSave: false }); + + /*const resetPasswordUrl = `${req.protocol}://${req.get( + "host" + )}/api/v1/password/reset/${resetToken}`;*/ + + const resetPasswordUrl = `${process.env.FRONTEND_URI}/user/api/v1/password/reset/${resetToken}`; + + const message = `Your password token is :-\n\n${resetPasswordUrl}\n\nIf you are not requested this email then please ingore this mail.`; + + try { + await sendEmail({ + email: user.email, + subject: "MentorFlux password recovery", + message: message, + }); + return res.status(200).json({ + success: true, + message: `Email sent to ${email} successfully`, + }); + } catch (error) { + user.resetPasswordToken = undefined; + user.resetPasswordExpiry = undefined; + await user.save({ validateBeforeSave: false }); + return res.status(500).json({ + success: false, + message: "Something went wrong ", + error: error, + }); + } +}); + +// reset users password -- DONE +const resetPassword = catchAsyncErrors(async (req, res) => { + const token = req.params.token; + + const { password, confirmPassword } = req.body; + + //console.log("My password is :", password); + //console.log("My confirmPassword is :", confirmPassword); + //console.log("My token is :", token); + const resetPasswordToken = await crypto + .createHash("sha256") + .update(token) + .digest("hex"); + + const user = await User.findOne({ + resetPasswordToken, + resetPasswordExpiry: { $gte: Date.now() }, + }); + + if (!user) { + return res.status(401).json({ + success: false, + message: "Reset Password token is invalid or has been expired", + }); + } + + if (password !== confirmPassword) { + return res.status(401).json({ + success: false, + message: "Please enter password and confirm password", + }); + } + + user.password = password; + user.resetPasswordToken = undefined; + user.resetPasswordExpiry = undefined; + + //console.log("To check the user ", user); + + await user.save(); + + return res.status(200).json({ + success: true, + message: "Password changed successfully", + }); +}); + +// get user personal details +const getUserDetails = catchAsyncErrors(async (req, res) => { + const user = await User.findById(req.user._id); + + if (!user) { + return res.status(500).json({ + success: false, + message: "Something went wrong ", + }); + } + + return res.status(200).json({ + success: true, + message: "User details are fetched successfully", + data: user, + }); +}); + +// Update users password +const updatePassword = catchAsyncErrors(async (req, res) => { + const { password, oldPassword, confirmPassword } = req.body; + + const user = await User.findById(req.user._id); + + const isPasswordMatched = await user.isPasswordCorrect(oldPassword); + + if (!user) { + return res.status(500).json({ + success: false, + message: "User not found", + }); + } + + if (!isPasswordMatched) { + return res.status(500).json({ + success: false, + message: "Old password is incorrect.Please enter correct password ", + }); + } + + if (password !== confirmPassword) { + return res.status(500).json({ + success: false, + message: "Password and Confirm password should be same.", + }); + } + + user.password = password; + await user.save({ validateBeforeSave: false }); + + return res.status(200).json({ + success: true, + message: "Password upadated successfully", + }); +}); + +// update personal details +const updatePersonalDetails = catchAsyncErrors(async (req, res) => { + const { name, email } = req.body; + const user = await User.findByIdAndUpdate(req.user._id, { + $set: { + name, + email, + }, + }); + + if (!user) { + return res.status(500).json({ + success: false, + message: "Something went wrong", + }); + } + + return res.status(200).json({ + success: true, + message: "User details updated successfully", + data: user, + }); +}); + +// Get all users details -- ADMIN +const getAllusersDetail = catchAsyncErrors(async (req, res) => { + const users = await find(); + return res.status(200).json({ + success: true, + message: "All user fetch successfully", + data: users, + }); +}); + +// get single user details +const getSingaluserDetail = catchAsyncErrors(async (req, res) => { + const user = await User.findById(req.params.id); + + if (!user) { + return res.status(404).json({ + success: false, + message: "User not found", + }); + } +}); + +// upadate user Role -- ADMIN +const updateUserRole = catchAsyncErrors(async (req, res) => { + const { name, email, role } = req.body; + const user = await User.findByIdAndUpdate(req.params.id, { + $set: { + name, + email, + role, + }, + }); + + if (!user) { + return res.status(500).json({ + success: false, + message: "Something went wrong", + }); + } + + return res.status(200).json({ + success: true, + message: "User Role updated successfully", + data: user, + }); +}); + +// Delete user -- ADMIN +const DeleteUser = catchAsyncErrors(async (req, res) => { + const user = await User.findByIdAndDelete(req.params.id); + + if (!user) { + return res.status(404).json({ + success: false, + message: "User does not exist", + }); + } + + return res.status(200).json({ + success: true, + message: "User deleted successfully", + data: user, + }); +}); + +// update avatar -- user +const updateAvatar = catchAsyncErrors(async (req, res) => { + //console.log("Our file is : ", req.file.path); + + if (!req.file.path) { + res.status(500).json({ + success: false, + message: "Avatar not uploaded on cloudinary.", + }); + } + + const avatarUrl = await uploadOnCloudinary(req.file.path); + + if (!avatarUrl) { + return res.status(500).json({ + success: false, + message: "Avatar not uploaded on cloudinary.", + }); + } + + //console.log("Avatar url is : ", avatarUrl); + + //console.log("our user is : ", req.user); + + const user = await User.findByIdAndUpdate(req.user._id, { + $set: { + avatar: avatarUrl, + }, + }); + + if (!user) { + return res.status(404).json({ + success: false, + message: "User not found.", + }); + } + + return res.status(200).json({ + success: true, + message: "Avatar updated successfully.", + data: user, + }); +}); + +module.exports = { + registerUser, + loginUser, + logoutUser, + updateUserDetails, + forgetPassword, + resetPassword, + getUserDetails, + updatePassword, + updatePersonalDetails, + updateUserRole, + DeleteUser, + intializeUser, + updateAvatar, +}; diff --git a/Backend/Database/DB_connect.js b/Backend/Database/DB_connect.js new file mode 100644 index 0000000..9fb8110 --- /dev/null +++ b/Backend/Database/DB_connect.js @@ -0,0 +1,21 @@ +const mongoose = require("mongoose"); +const catchAsyncErrors = require("../Middlewares/catchAsyncErrors.js"); + +const DB_connect = catchAsyncErrors(async () => { + try { + const connectionInstance = await mongoose.connect( + `${process.env.MONGODB_URI}/${process.env.DATABASE_NAME}` + ); + + if (!connectionInstance) { + console.log("MongoDB connection failed"); + } + console.log( + "MongoDB connected Successfully on server : " + + connectionInstance.connection.host + ); + } catch (error) { + console.log("MongoDB connection failed due to some error :", error); + } +}); +module.exports = DB_connect; diff --git a/Backend/Middlewares/authentication.js b/Backend/Middlewares/authentication.js new file mode 100644 index 0000000..601fbd1 --- /dev/null +++ b/Backend/Middlewares/authentication.js @@ -0,0 +1,46 @@ +const jwt = require("jsonwebtoken"); +const User = require("../Models/user.model.js"); + +function checkAuthenticated() { + return async (req, res, next) => { + const tokenValue = req.cookies[process.env.TOKEN_NAME]; + + // console.log("I am called",tokenValue); + if (!tokenValue) { + return next(); + } + try { + const payload = await jwt.verify( + tokenValue, + process.env.REFRESH_TOKEN_SECRET + ); + + if (!payload) { + return next(); + } + + req.user = await User.findById(payload._id).select("-password"); + + return next(); + } catch (error) { + return next(); + } + return next(); + }; +} + +function authorizeRoles(...roles) { + return async (req, res, next) => { + if (!roles.includes(req.user.role)) { + return res.status(401).json({ + success: false, + message: "You are unauthorised to access this resource", + }); + return next(); + } + + return next(); + }; +} + +module.exports = { checkAuthenticated, authorizeRoles }; diff --git a/Backend/Middlewares/catchAsyncErrors.js b/Backend/Middlewares/catchAsyncErrors.js new file mode 100644 index 0000000..8f3d955 --- /dev/null +++ b/Backend/Middlewares/catchAsyncErrors.js @@ -0,0 +1,3 @@ +module.exports = (theFunc) => (req, res, next) => { + Promise.resolve(theFunc(req, res, next)).catch(next); +}; diff --git a/Backend/Middlewares/multer.js b/Backend/Middlewares/multer.js new file mode 100644 index 0000000..237e292 --- /dev/null +++ b/Backend/Middlewares/multer.js @@ -0,0 +1,20 @@ +const multer = require("multer"); + +const storage = multer.diskStorage({ + + destination: function (req, file, cb) { + cb(null, "./public/images"); + }, + + filename: function (req, file, cb) { + const uniquePrefix = Date.now(); + cb(null, uniquePrefix + "-" + file.originalname); + }, + + +}); + + +const upload = multer({ storage: storage }); + +module.exports = upload; diff --git a/Backend/Models/meeting.model.js b/Backend/Models/meeting.model.js new file mode 100644 index 0000000..66ac00e --- /dev/null +++ b/Backend/Models/meeting.model.js @@ -0,0 +1,51 @@ +const mongoose = require("mongoose"); + +const meetingSchema = new mongoose.Schema( + { + meetingDate: { + type: Date, + required: true, + }, + meetingTime: { + type: String, + required: true, + }, + mentorName: { + type: String, + required: true, + }, + mentiName: { + type: String, + required: true, + }, + mentorId: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + required: true, + }, + mentiId: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + required: true, + }, + status: { + type: String, + default: "Pending", + }, + amount: { + type: Number, + required: true, + }, + paymentStatus: { + type: "Status", + default: "Pending", + }, + }, + { + timestamps: true, + } +); + +const Meeting = mongoose.model("Meeting", meetingSchema); + +module.exports = Meeting; diff --git a/Backend/Models/user.model.js b/Backend/Models/user.model.js new file mode 100644 index 0000000..0d662f7 --- /dev/null +++ b/Backend/Models/user.model.js @@ -0,0 +1,111 @@ +const mongoose = require("mongoose"); +const bcrypt = require("bcrypt"); +const jwt = require("jsonwebtoken"); +const crypto = require("crypto"); + +const userSchema = new mongoose.Schema( + { + name: { + type: String, + required: [true, "Please Enter your name"], + maxLength: [30, "Please Enter the valid name"], + minLength: [2, "Name should have more than 5 characters"], + }, + + skills: [ + { + type: String, + }, + ], + uniqueRole: { + type: String, + }, + country: { + type: String, + }, + description: { + type: String, + }, + email: { + type: String, + required: true, + unique: true, + lowerCase: true, + }, + password: { + type: String, + required: true, + minLength: [6, "Password should have more than 6 characters"], + }, + avatar: { + type: String, + default: "/images/profile.jpeg", + }, + role: { + type: String, + default: "user", + }, + mainInterest: [ + { + type: String, + }, + ], + documents: [ + { + type: String, + }, + ], + meettingFees: { + type: Number, + }, + resetPasswordToken: String, + resetPasswordExpiry: Date, + }, + { + timestamps: true, + } +); + +userSchema.pre("save", async function (next) { + if (!this.isModified("password")) return next(); + + this.password = await bcrypt.hash(this.password, 10); + return next(); +}); + +userSchema.methods.isPasswordCorrect = async function (password) { + return await bcrypt.compare(password, this.password); +}; + +userSchema.methods.generateRefreshToken = async function () { + return await jwt.sign( + { + _id: this._id, + email: this.email, + }, + process.env.REFRESH_TOKEN_SECRET + // { + // expiresIn: process.env.REFRESH_TOKEN_EXPIRY, + // } + ); +}; + +userSchema.methods.getResetPassword = async function () { + // Generating token + const resetToken = await crypto.randomBytes(20).toString("hex"); + + // Hashing and adding reset password token to userschema + + this.resetPasswordToken = crypto + .createHash("sha256") + .update(resetToken) + .digest("hex"); + + this.resetPasswordExpiry = Date.now() + 15 * 60 * 1000; + + return resetToken; +}; + +const User = mongoose.model("User", userSchema); + +module.exports = User; diff --git a/Backend/Routes/meeting.routes.js b/Backend/Routes/meeting.routes.js new file mode 100644 index 0000000..e69de29 diff --git a/Backend/Routes/user.routes.js b/Backend/Routes/user.routes.js new file mode 100644 index 0000000..b615ec0 --- /dev/null +++ b/Backend/Routes/user.routes.js @@ -0,0 +1,50 @@ +const express = require("express"); +const { + registerUser, + loginUser, + logoutUser, + updateUserDetails, + forgetPassword, + resetPassword, + getUserDetails, + updatePassword, + updatePersonalDetails, + DeleteUser, + updateUserRole, + intializeUser, + updateAvatar, +} = require("../Controllers/user.controller.js"); + +const { checkAuthenticated } = require("../Middlewares/authentication.js"); + +const upload = require("../Middlewares/multer.js"); + +const router = express.Router(); + +router.route("/register").post(registerUser); + +router.route("/login").post(loginUser); + +router.route("/password/forgot").post(forgetPassword); + +router.route("/password/reset/:token").put(resetPassword); + +router.route("/logout").get(logoutUser); + +router.route("/update/:id").put(updateUserDetails); + +router.route("/me").get(getUserDetails); + +router.route("/getuser").get(intializeUser); + +router.route("/password/update").put(updatePassword); + +router.route("/me/update").put(updatePersonalDetails); + +router.route("/user/delete/:id").delete(DeleteUser); + +router.route("/user/updateRole/:id").put(updateUserRole); + +router.route("/user/avatar").put(checkAuthenticated(),upload.single("avatar"), updateAvatar); + +module.exports = router; diff --git a/Backend/Utils/cloudinary.js b/Backend/Utils/cloudinary.js new file mode 100644 index 0000000..787b17f --- /dev/null +++ b/Backend/Utils/cloudinary.js @@ -0,0 +1,23 @@ +const cloudinary = require("cloudinary").v2; +const fs = require("fs"); + +const uploadOnCloudinary = async (localFilePath) => { + try { + if (!localFilePath) return null; + + const responce = await cloudinary.uploader.upload(localFilePath, { + resource_type: "auto", + }); + + // console.log("File is uploaded successfully"); + fs.unlinkSync(localFilePath, () => { + console.log("file removed successfully"); + }); + return responce.url; + } catch (error) { + fs.unlinkSync(localFilePath); + console.log("file removed successfully"); + return null; + } +}; +module.exports = { uploadOnCloudinary }; diff --git a/Backend/Utils/sendmail.js b/Backend/Utils/sendmail.js new file mode 100644 index 0000000..53c5ba6 --- /dev/null +++ b/Backend/Utils/sendmail.js @@ -0,0 +1,25 @@ +const nodemailer = require("nodemailer"); + +const sendEmail = async (options) => { + const transporter = await nodemailer.createTransport({ + service: "gmail", + host: process.env.HOST, + port: process.env.EMAIL_PORT, + secure: false, + auth: { + user: process.env.SMPT_MAIL, // senders email + pass: process.env.SMPT_PASSWORD, // app passoword created for your app by using step :: google account> manage your google account >security>enable two step verification > search app password and create password for your app + }, + }); + + const mailOptions = { + from: "", + to: options.email, + subject: options.subject, + text: options.message, + }; + + await transporter.sendMail(mailOptions); +}; + +module.exports = sendEmail; diff --git a/Backend/app.js b/Backend/app.js new file mode 100644 index 0000000..95a7166 --- /dev/null +++ b/Backend/app.js @@ -0,0 +1,86 @@ +const express = require("express"); +const cors = require("cors"); +const cookieParser = require("cookie-parser"); +const { Server } = require("socket.io"); +const { createServer } = require("http"); +const userRoute = require("./Routes/user.routes.js"); +const { checkAuthenticated } = require("./Middlewares/authentication.js"); +const dotenv = require("dotenv"); + +dotenv.config({ + path: "./.env", +}); + +const app = express(); + +const corsOptions = { + origin: process.env.FRONTEND_URI, + methods: "GET,HEAD,PUT,PATCH,POST,DELETE", + credentials: true, +}; + +const server = createServer(app); + +const io = new Server(server, { + cors: { + origin: process.env.FRONTEND_URI, + methods: ["GET", "PUT", "POST", "PATCH", "DELETE"], + credentials: true, + }, +}); + +app.use(cors(corsOptions)); +app.use(express.json({ limit: "16kb" })); +app.use(express.urlencoded({ extended: true, limit: "16kb" })); +app.use(express.static("public")); +app.use(cookieParser()); + +app.get("/", (req, res) => { + return res.send("Hiddskpkpk..."); +}); + +app.use("/api/v1", userRoute); + +const emailToSocketIdMap = new Map(); +const socketidToEmailMap = new Map(); + +io.on("connection", (socket) => { + // console.log(`Socket Connected`, socket.id); + socket.on("room:join", (data) => { + const { email, room } = data; + emailToSocketIdMap.set(email, socket.id); + socketidToEmailMap.set(socket.id, email); + io.to(room).emit("user:joined", { email, id: socket.id }); + socket.join(room); + io.to(socket.id).emit("room:join", data); + }); + + socket.on("message", ({ message, room }) => { + // console.log(message); + // console.log("Message is : ", message, "Room is : ", room); + //for sending the message all the users that are connected < --- > io.emit("receive-message", message); + //for sending the message for all the user except us <----> socket.broadcast.emit("receive-message", message); + socket.join(room); + io.to(room).emit("receive-message", message); // For sending the message for perticular room or user + }); + + socket.on("user:call", ({ to, offer }) => { + io.to(to).emit("incomming:call", { from: socket.id, offer }); + }); + + socket.on("call:accepted", ({ to, ans }) => { + io.to(to).emit("call:accepted", { from: socket.id, ans }); + }); + + socket.on("peer:nego:needed", ({ to, offer }) => { + //console.log("peer:nego:needed", offer); + io.to(to).emit("peer:nego:needed", { from: socket.id, offer }); + }); + + socket.on("peer:nego:done", ({ to, ans }) => { + // console.log("peer:nego:done", ans); + io.to(to).emit("peer:nego:final", { from: socket.id, ans }); + }); +}); + +module.exports = server; diff --git a/Backend/index.js b/Backend/index.js new file mode 100644 index 0000000..dd34608 --- /dev/null +++ b/Backend/index.js @@ -0,0 +1,23 @@ +const server = require("./app.js"); +const dotenv = require("dotenv"); +const cloudinary = require("cloudinary").v2; +const DB_connect = require("./Database/DB_connect.js"); + +// dotenv Configuration +dotenv.config({ + path: "./.env", +}); + +cloudinary.config({ + cloud_name: process.env.CLOUDINARY_CLOUD_NAME, + api_key: process.env.CLOUDINARY_API_KEY, + api_secret: process.env.CLOUDINARY_API_SECRET, +}); + +DB_connect(); + +// Listening the port +server.listen(process.env.PORT, () => { + console.log("Server is Running on ", process.env.PORT); + console.log("Frontend URI : ", process.env.FRONTEND_URI); +}); diff --git a/Backend/package-lock.json b/Backend/package-lock.json new file mode 100644 index 0000000..9341ae3 --- /dev/null +++ b/Backend/package-lock.json @@ -0,0 +1,2188 @@ +{ + "name": "backend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "backend", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "bcrypt": "^5.1.1", + "cloudinary": "^2.5.1", + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.6.1", + "multer": "^1.4.5-lts.1", + "nodemailer": "^6.9.15", + "socket.io": "^4.7.5" + }, + "devDependencies": { + "nodemon": "^3.1.4" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bson": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cloudinary": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.5.1.tgz", + "integrity": "sha512-CNg6uU53Hl4FEVynkTGpt5bQEAQWDHi3H+Sm62FzKf5uQHipSN2v7qVqS8GRVqeb0T1WNV+22+75DOJeRXYeSQ==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "q": "^1.5.1" + }, + "engines": { + "node": ">=9" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", + "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "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.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mongodb": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", + "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.1.tgz", + "integrity": "sha512-dppGcYqvsdg+VcnqXR5b467V4a+iNhmvkfYNpEPi6AjaUxnz6ioEDmrMLOi+sOWjvoHapuwPOigV4f2l7HC6ag==", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.8.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/nodemailer": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", + "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/nodemon": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", + "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "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)", + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/socket.io": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/Backend/package.json b/Backend/package.json new file mode 100644 index 0000000..59c97fc --- /dev/null +++ b/Backend/package.json @@ -0,0 +1,28 @@ +{ + "name": "backend", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "nodemon index.js" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "bcrypt": "^5.1.1", + "cloudinary": "^2.5.1", + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.6.1", + "multer": "^1.4.5-lts.1", + "nodemailer": "^6.9.15", + "socket.io": "^4.7.5" + }, + "devDependencies": { + "nodemon": "^3.1.4" + } +} diff --git a/Backend/vercel.json b/Backend/vercel.json new file mode 100644 index 0000000..1f7efcc --- /dev/null +++ b/Backend/vercel.json @@ -0,0 +1,19 @@ +{ + "version": 2, + "builds": [ + { + "src": "index.js", + "use": "@vercel/node" + } + ], + "routes": [ + { + "src": "/api/v1/(.*)", + "dest": "index.js" + }, + { + "src": "/(.*)", + "dest": "index.js" + } + ] +} From 1fdb7399503f417efc74c5637d6376039e45bb57 Mon Sep 17 00:00:00 2001 From: Karan Date: Sat, 22 Feb 2025 15:20:35 +0530 Subject: [PATCH 3/5] Add Model for backend --- ...eting.controller.js => crop.controller.js} | 0 .../farm.controller.js} | 0 Backend/Controllers/finance.controller.js | 0 Backend/Controllers/task.controller.js | 0 Backend/Models/crop.model.js | 21 ++++++++ Backend/Models/farm.model.js | 36 +++++++++++++ Backend/Models/finance.model.js | 21 ++++++++ Backend/Models/meeting.model.js | 51 ------------------ Backend/Models/task.model.js | 31 +++++++++++ Backend/Models/user.model.js | 32 ++--------- Backend/app.js | 54 +------------------ Backend/index.js | 3 +- Backend/vercel.json | 19 ------- 13 files changed, 115 insertions(+), 153 deletions(-) rename Backend/Controllers/{meeting.controller.js => crop.controller.js} (100%) rename Backend/{Routes/meeting.routes.js => Controllers/farm.controller.js} (100%) create mode 100644 Backend/Controllers/finance.controller.js create mode 100644 Backend/Controllers/task.controller.js create mode 100644 Backend/Models/crop.model.js create mode 100644 Backend/Models/farm.model.js create mode 100644 Backend/Models/finance.model.js delete mode 100644 Backend/Models/meeting.model.js create mode 100644 Backend/Models/task.model.js delete mode 100644 Backend/vercel.json diff --git a/Backend/Controllers/meeting.controller.js b/Backend/Controllers/crop.controller.js similarity index 100% rename from Backend/Controllers/meeting.controller.js rename to Backend/Controllers/crop.controller.js diff --git a/Backend/Routes/meeting.routes.js b/Backend/Controllers/farm.controller.js similarity index 100% rename from Backend/Routes/meeting.routes.js rename to Backend/Controllers/farm.controller.js diff --git a/Backend/Controllers/finance.controller.js b/Backend/Controllers/finance.controller.js new file mode 100644 index 0000000..e69de29 diff --git a/Backend/Controllers/task.controller.js b/Backend/Controllers/task.controller.js new file mode 100644 index 0000000..e69de29 diff --git a/Backend/Models/crop.model.js b/Backend/Models/crop.model.js new file mode 100644 index 0000000..b89c83e --- /dev/null +++ b/Backend/Models/crop.model.js @@ -0,0 +1,21 @@ +const mongoose = require("mongoose"); + +const cropSchema = new mongoose.Schema( + { + name: { type: String, required: true }, + farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true }, + plantedDate: { type: Date, required: true, default: Date.now() }, + harvestDate: { type: Date }, + growthStage: { + type: String, + enum: ["Planted", "Growing", "Ready to Harvest"], + default: "Planted", + }, + healthStatus: { type: String, default: "Healthy" }, + }, + { timestamps: true } +); + +const Crop = mongoose.model("Crop", cropSchema); + +module.exports = Crop; diff --git a/Backend/Models/farm.model.js b/Backend/Models/farm.model.js new file mode 100644 index 0000000..7e7b663 --- /dev/null +++ b/Backend/Models/farm.model.js @@ -0,0 +1,36 @@ +const mongoose = require("mongoose"); + +const farmSchema = new mongoose.Schema( + { + name: { type: String, required: true }, + location: { type: String, required: true }, + owner: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + required: true, + }, + waterContent: { type: String, required: true }, + soilType: { type: String, required: true }, + fertilizer: [ + { + name: { type: String }, + quantity: { type: Number }, + addedAt: { type: Date, default: Date.now }, + }, + ], + pestisides: [ + { + name: { type: String }, + quantity: { type: Number }, + addedAt: { type: Date, default: Date.now }, + }, + ], + crops: [{ type: mongoose.Schema.Types.ObjectId, ref: "Crop" }], + finances: { type: mongoose.Schema.Types.ObjectId, ref: "Finance" }, + }, + { timestamps: true } +); + +const Farm = mongoose.model("Farm", farmSchema); + +module.exports = Farm; diff --git a/Backend/Models/finance.model.js b/Backend/Models/finance.model.js new file mode 100644 index 0000000..06066d0 --- /dev/null +++ b/Backend/Models/finance.model.js @@ -0,0 +1,21 @@ +const mongoose = require("mongoose"); +const financeSchema = new mongoose.Schema( + { + farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true }, + transactions: [ + { + type: { type: String, enum: ["Expense", "Revenue"], required: true }, + amount: { type: Number, required: true }, + description: { type: String }, + date: { type: Date, default: Date.now }, + }, + ], + totalExpenses: { type: Number, default: 0 }, + totalRevenue: { type: Number, default: 0 }, + }, + { timestamps: true } +); + +const Finance = mongoose.model("Finance", financeSchema); + +module.exports = Finance; diff --git a/Backend/Models/meeting.model.js b/Backend/Models/meeting.model.js deleted file mode 100644 index 66ac00e..0000000 --- a/Backend/Models/meeting.model.js +++ /dev/null @@ -1,51 +0,0 @@ -const mongoose = require("mongoose"); - -const meetingSchema = new mongoose.Schema( - { - meetingDate: { - type: Date, - required: true, - }, - meetingTime: { - type: String, - required: true, - }, - mentorName: { - type: String, - required: true, - }, - mentiName: { - type: String, - required: true, - }, - mentorId: { - type: mongoose.Schema.Types.ObjectId, - ref: "User", - required: true, - }, - mentiId: { - type: mongoose.Schema.Types.ObjectId, - ref: "User", - required: true, - }, - status: { - type: String, - default: "Pending", - }, - amount: { - type: Number, - required: true, - }, - paymentStatus: { - type: "Status", - default: "Pending", - }, - }, - { - timestamps: true, - } -); - -const Meeting = mongoose.model("Meeting", meetingSchema); - -module.exports = Meeting; diff --git a/Backend/Models/task.model.js b/Backend/Models/task.model.js new file mode 100644 index 0000000..784b548 --- /dev/null +++ b/Backend/Models/task.model.js @@ -0,0 +1,31 @@ +const mongoose = require("mongoose"); + +const taskSchema = new mongoose.Schema( + { + farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true }, + crop: { type: mongoose.Schema.Types.ObjectId, ref: "Crop" }, + taskType: { + type: String, + enum: [ + "Sowing", + "Watering", + "Fertilization", + "Pest Control", + "Harvesting", + ], + required: true, + }, + description: { type: String }, + assignedDate: { type: Date, required: true, default: Date.now }, + status: { + type: String, + enum: ["Pending", "Completed"], + default: "Pending", + }, + }, + { timestamps: true } +); + +const Task = mongoose.model("Task", taskSchema); + +module.exports = Task; diff --git a/Backend/Models/user.model.js b/Backend/Models/user.model.js index 0d662f7..2e66b40 100644 --- a/Backend/Models/user.model.js +++ b/Backend/Models/user.model.js @@ -11,21 +11,9 @@ const userSchema = new mongoose.Schema( maxLength: [30, "Please Enter the valid name"], minLength: [2, "Name should have more than 5 characters"], }, - - skills: [ - { - type: String, - }, - ], - uniqueRole: { - type: String, - }, country: { type: String, }, - description: { - type: String, - }, email: { type: String, required: true, @@ -41,23 +29,9 @@ const userSchema = new mongoose.Schema( type: String, default: "/images/profile.jpeg", }, - role: { - type: String, - default: "user", - }, - mainInterest: [ - { - type: String, - }, - ], - documents: [ - { - type: String, - }, - ], - meettingFees: { - type: Number, - }, + role: { type: String, enum: ["farmer", "admin"], default: "farmer" }, + farms: [{ type: mongoose.Schema.Types.ObjectId, ref: "Farm" }], + resetPasswordToken: String, resetPasswordExpiry: Date, }, diff --git a/Backend/app.js b/Backend/app.js index 95a7166..4846a34 100644 --- a/Backend/app.js +++ b/Backend/app.js @@ -19,16 +19,6 @@ const corsOptions = { credentials: true, }; -const server = createServer(app); - -const io = new Server(server, { - cors: { - origin: process.env.FRONTEND_URI, - methods: ["GET", "PUT", "POST", "PATCH", "DELETE"], - credentials: true, - }, -}); - app.use(cors(corsOptions)); app.use(express.json({ limit: "16kb" })); app.use(express.urlencoded({ extended: true, limit: "16kb" })); @@ -41,46 +31,4 @@ app.get("/", (req, res) => { app.use("/api/v1", userRoute); -const emailToSocketIdMap = new Map(); -const socketidToEmailMap = new Map(); - -io.on("connection", (socket) => { - // console.log(`Socket Connected`, socket.id); - socket.on("room:join", (data) => { - const { email, room } = data; - emailToSocketIdMap.set(email, socket.id); - socketidToEmailMap.set(socket.id, email); - io.to(room).emit("user:joined", { email, id: socket.id }); - socket.join(room); - io.to(socket.id).emit("room:join", data); - }); - - socket.on("message", ({ message, room }) => { - // console.log(message); - // console.log("Message is : ", message, "Room is : ", room); - //for sending the message all the users that are connected < --- > io.emit("receive-message", message); - //for sending the message for all the user except us <----> socket.broadcast.emit("receive-message", message); - socket.join(room); - io.to(room).emit("receive-message", message); // For sending the message for perticular room or user - }); - - socket.on("user:call", ({ to, offer }) => { - io.to(to).emit("incomming:call", { from: socket.id, offer }); - }); - - socket.on("call:accepted", ({ to, ans }) => { - io.to(to).emit("call:accepted", { from: socket.id, ans }); - }); - - socket.on("peer:nego:needed", ({ to, offer }) => { - //console.log("peer:nego:needed", offer); - io.to(to).emit("peer:nego:needed", { from: socket.id, offer }); - }); - - socket.on("peer:nego:done", ({ to, ans }) => { - // console.log("peer:nego:done", ans); - io.to(to).emit("peer:nego:final", { from: socket.id, ans }); - }); -}); - -module.exports = server; +module.exports = app; diff --git a/Backend/index.js b/Backend/index.js index dd34608..9d577f8 100644 --- a/Backend/index.js +++ b/Backend/index.js @@ -2,6 +2,7 @@ const server = require("./app.js"); const dotenv = require("dotenv"); const cloudinary = require("cloudinary").v2; const DB_connect = require("./Database/DB_connect.js"); +const app = require("./app.js"); // dotenv Configuration dotenv.config({ @@ -17,7 +18,7 @@ cloudinary.config({ DB_connect(); // Listening the port -server.listen(process.env.PORT, () => { +app.listen(process.env.PORT, () => { console.log("Server is Running on ", process.env.PORT); console.log("Frontend URI : ", process.env.FRONTEND_URI); }); diff --git a/Backend/vercel.json b/Backend/vercel.json deleted file mode 100644 index 1f7efcc..0000000 --- a/Backend/vercel.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": 2, - "builds": [ - { - "src": "index.js", - "use": "@vercel/node" - } - ], - "routes": [ - { - "src": "/api/v1/(.*)", - "dest": "index.js" - }, - { - "src": "/(.*)", - "dest": "index.js" - } - ] -} From 330589bdf18062e52f1ab39669e1108025e79b25 Mon Sep 17 00:00:00 2001 From: Karan Date: Sat, 22 Feb 2025 17:03:24 +0530 Subject: [PATCH 4/5] Create and Test User and Farm Routes --- Backend/Controllers/crop.controller.js | 128 +++++++++++++++++++++ Backend/Controllers/farm.controller.js | 130 ++++++++++++++++++++++ Backend/Controllers/finance.controller.js | 126 +++++++++++++++++++++ Backend/Controllers/task.controller.js | 111 ++++++++++++++++++ Backend/Controllers/user.controller.js | 2 + Backend/Middlewares/authentication.js | 45 ++++---- Backend/Middlewares/multer.js | 4 - Backend/Models/crop.model.js | 1 + Backend/Routes/crop.routes.js | 20 ++++ Backend/Routes/farm.routes.js | 19 ++++ Backend/Routes/finance.routes.js | 24 ++++ Backend/Routes/task.routes.js | 24 ++++ Backend/Routes/user.routes.js | 6 +- Backend/app.js | 4 + 14 files changed, 617 insertions(+), 27 deletions(-) create mode 100644 Backend/Routes/crop.routes.js create mode 100644 Backend/Routes/farm.routes.js create mode 100644 Backend/Routes/finance.routes.js create mode 100644 Backend/Routes/task.routes.js diff --git a/Backend/Controllers/crop.controller.js b/Backend/Controllers/crop.controller.js index e69de29..60c3930 100644 --- a/Backend/Controllers/crop.controller.js +++ b/Backend/Controllers/crop.controller.js @@ -0,0 +1,128 @@ +import Crop from "../models/cropModel.js"; +import Farm from "../models/farmModel.js"; + +// Create a new crop +export const createCrop = async (req, res) => { + try { + const { name, farm, image, harvestDate, growthStage, healthStatus } = + req.body; + + // Check if the farm exists + const existingFarm = await Farm.findById(farm); + if (!existingFarm) + return res.status(404).json({ message: "Farm not found" }); + + const crop = new Crop({ + name, + farm, + image, + harvestDate, + growthStage, + healthStatus, + }); + + await crop.save(); + + // Add crop to farm + existingFarm.crops.push(crop._id); + await existingFarm.save(); + + res.status(201).json(crop); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all crops for a specific farm +export const getCropsByFarm = async (req, res) => { + try { + const crops = await Crop.find({ farm: req.params.farmId }); + + res.status(200).json(crops); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get a single crop by ID +export const getCropById = async (req, res) => { + try { + const crop = await Crop.findById(req.params.cropId).populate("farm"); + + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + res.status(200).json(crop); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update crop details +export const updateCrop = async (req, res) => { + try { + const updatedCrop = await Crop.findByIdAndUpdate( + req.params.cropId, + req.body, + { new: true } + ); + + if (!updatedCrop) + return res.status(404).json({ message: "Crop not found" }); + + res.status(200).json(updatedCrop); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a crop +export const deleteCrop = async (req, res) => { + try { + const crop = await Crop.findById(req.params.cropId); + + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + await crop.deleteOne(); + + // Remove crop from the farm + await Farm.findByIdAndUpdate(crop.farm, { $pull: { crops: crop._id } }); + + res.status(200).json({ message: "Crop deleted successfully" }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update crop growth stage +export const updateGrowthStage = async (req, res) => { + try { + const { growthStage } = req.body; + + const crop = await Crop.findById(req.params.cropId); + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + crop.growthStage = growthStage; + await crop.save(); + + res.status(200).json({ message: "Growth stage updated", crop }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update crop health status +export const updateHealthStatus = async (req, res) => { + try { + const { healthStatus } = req.body; + + const crop = await Crop.findById(req.params.cropId); + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + crop.healthStatus = healthStatus; + await crop.save(); + + res.status(200).json({ message: "Health status updated", crop }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; diff --git a/Backend/Controllers/farm.controller.js b/Backend/Controllers/farm.controller.js index e69de29..1e44f11 100644 --- a/Backend/Controllers/farm.controller.js +++ b/Backend/Controllers/farm.controller.js @@ -0,0 +1,130 @@ +const Farm = require("../Models/farm.model.js"); +const Crop = require("../Models/crop.model.js"); +const Finance = require("../Models/finance.model.js"); + +// Create a farm +const createFarm = async (req, res) => { + try { + const { name, location, waterContent, soilType } = req.body; + + const farm = new Farm({ + name, + location, + waterContent, + soilType, + owner: req.user._id, + }); + + await farm.save(); + res.status(201).json(farm); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all farms for a user +const getUserFarms = async (req, res) => { + try { + const farms = await Farm.find({ owner: req.user._id }) + .populate("crops") + .populate("finances"); + + res.status(200).json(farms); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get a single farm by ID +const getFarmById = async (req, res) => { + try { + const farm = await Farm.findById(req.params.farmId) + .populate("crops") + .populate("finances"); + + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + res.status(200).json(farm); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update farm details +const updateFarm = async (req, res) => { + try { + const updatedFarm = await Farm.findByIdAndUpdate( + req.params.farmId, + req.body, + { new: true } + ); + + if (!updatedFarm) + return res.status(404).json({ message: "Farm not found" }); + + res.status(200).json(updatedFarm); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a farm +const deleteFarm = async (req, res) => { + try { + const farm = await Farm.findById(req.params.farmId); + + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + await Crop.deleteMany({ farm: farm._id }); + await Finance.findByIdAndDelete(farm.finances); + await farm.deleteOne(); + + res.status(200).json({ message: "Farm deleted successfully" }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Add fertilizer to a farm +const addFertilizer = async (req, res) => { + try { + const { name, quantity } = req.body; + + const farm = await Farm.findById(req.params.farmId); + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + farm.fertilizer.push({ name, quantity }); + await farm.save(); + + res.status(200).json({ message: "Fertilizer added", farm }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Add pesticide to a farm +const addPesticide = async (req, res) => { + try { + const { name, quantity } = req.body; + + const farm = await Farm.findById(req.params.farmId); + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + farm.pestisides.push({ name, quantity }); + await farm.save(); + + res.status(200).json({ message: "Pesticide added", farm }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +module.exports = { + createFarm, + getUserFarms, + getFarmById, + updateFarm, + deleteFarm, + addFertilizer, + addPesticide, +}; diff --git a/Backend/Controllers/finance.controller.js b/Backend/Controllers/finance.controller.js index e69de29..a60683c 100644 --- a/Backend/Controllers/finance.controller.js +++ b/Backend/Controllers/finance.controller.js @@ -0,0 +1,126 @@ +import Finance from "../models/financeModel.js"; +import Farm from "../models/farmModel.js"; + +// Create finance record for a farm +export const createFinance = async (req, res) => { + try { + const { farm } = req.body; + + // Check if the farm exists + const existingFarm = await Farm.findById(farm); + if (!existingFarm) + return res.status(404).json({ message: "Farm not found" }); + + const finance = new Finance({ + farm, + transactions: [], + totalExpenses: 0, + totalRevenue: 0, + }); + + await finance.save(); + + // Link finance to farm + existingFarm.finances = finance._id; + await existingFarm.save(); + + res.status(201).json(finance); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get finance details by farm ID +export const getFinanceByFarm = async (req, res) => { + try { + const finance = await Finance.findOne({ farm: req.params.farmId }); + + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + res.status(200).json(finance); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Add a transaction (expense/revenue) +export const addTransaction = async (req, res) => { + try { + const { type, amount, description } = req.body; + + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + finance.transactions.push({ type, amount, description }); + + // Update totals + if (type === "Expense") { + finance.totalExpenses += amount; + } else if (type === "Revenue") { + finance.totalRevenue += amount; + } + + await finance.save(); + res.status(200).json({ message: "Transaction added", finance }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a transaction +export const deleteTransaction = async (req, res) => { + try { + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + const transaction = finance.transactions.id(req.params.transactionId); + if (!transaction) + return res.status(404).json({ message: "Transaction not found" }); + + // Adjust totals before removing + if (transaction.type === "Expense") { + finance.totalExpenses -= transaction.amount; + } else if (transaction.type === "Revenue") { + finance.totalRevenue -= transaction.amount; + } + + transaction.remove(); + await finance.save(); + + res.status(200).json({ message: "Transaction deleted", finance }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all transactions for a farm's finance +export const getTransactions = async (req, res) => { + try { + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + res.status(200).json(finance.transactions); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get total expenses and revenue +export const getFinancialSummary = async (req, res) => { + try { + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + res.status(200).json({ + totalExpenses: finance.totalExpenses, + totalRevenue: finance.totalRevenue, + }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; diff --git a/Backend/Controllers/task.controller.js b/Backend/Controllers/task.controller.js index e69de29..07f12fe 100644 --- a/Backend/Controllers/task.controller.js +++ b/Backend/Controllers/task.controller.js @@ -0,0 +1,111 @@ +import Task from "../models/taskModel.js"; +import Farm from "../models/farmModel.js"; +import Crop from "../models/cropModel.js"; + +// Create a new task +export const createTask = async (req, res) => { + try { + const { farm, crop, taskType, description, assignedDate, status } = + req.body; + + // Validate farm existence + const existingFarm = await Farm.findById(farm); + if (!existingFarm) + return res.status(404).json({ message: "Farm not found" }); + + // Validate crop if provided + if (crop) { + const existingCrop = await Crop.findById(crop); + if (!existingCrop) + return res.status(404).json({ message: "Crop not found" }); + } + + const task = new Task({ + farm, + crop, + taskType, + description, + assignedDate, + status, + }); + + await task.save(); + res.status(201).json(task); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all tasks for a specific farm +export const getTasksByFarm = async (req, res) => { + try { + const tasks = await Task.find({ farm: req.params.farmId }).populate("crop"); + + res.status(200).json(tasks); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get a single task by ID +export const getTaskById = async (req, res) => { + try { + const task = await Task.findById(req.params.taskId).populate("farm crop"); + + if (!task) return res.status(404).json({ message: "Task not found" }); + + res.status(200).json(task); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update task details +export const updateTask = async (req, res) => { + try { + const updatedTask = await Task.findByIdAndUpdate( + req.params.taskId, + req.body, + { new: true } + ); + + if (!updatedTask) + return res.status(404).json({ message: "Task not found" }); + + res.status(200).json(updatedTask); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a task +export const deleteTask = async (req, res) => { + try { + const task = await Task.findById(req.params.taskId); + + if (!task) return res.status(404).json({ message: "Task not found" }); + + await task.deleteOne(); + + res.status(200).json({ message: "Task deleted successfully" }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update task status (Pending → Completed) +export const updateTaskStatus = async (req, res) => { + try { + const { status } = req.body; + + const task = await Task.findById(req.params.taskId); + if (!task) return res.status(404).json({ message: "Task not found" }); + + task.status = status; + await task.save(); + + res.status(200).json({ message: "Task status updated", task }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; diff --git a/Backend/Controllers/user.controller.js b/Backend/Controllers/user.controller.js index be55245..ff83e6c 100644 --- a/Backend/Controllers/user.controller.js +++ b/Backend/Controllers/user.controller.js @@ -260,6 +260,8 @@ const resetPassword = catchAsyncErrors(async (req, res) => { // get user personal details const getUserDetails = catchAsyncErrors(async (req, res) => { + + const user = await User.findById(req.user._id); if (!user) { diff --git a/Backend/Middlewares/authentication.js b/Backend/Middlewares/authentication.js index 601fbd1..6503546 100644 --- a/Backend/Middlewares/authentication.js +++ b/Backend/Middlewares/authentication.js @@ -1,32 +1,35 @@ const jwt = require("jsonwebtoken"); const User = require("../Models/user.model.js"); +const dotenv = require("dotenv"); +dotenv.config({ + path: "./.env", +}); -function checkAuthenticated() { - return async (req, res, next) => { - const tokenValue = req.cookies[process.env.TOKEN_NAME]; +async function checkAuthenticated(req, res, next) { + const tokenValue = req.cookies[process.env.TOKEN_NAME]; - // console.log("I am called",tokenValue); - if (!tokenValue) { + console.log("I am called", tokenValue); + if (!tokenValue) { + return res.status(404).json({ + success: false, + message: "User is not logged in.", + }); + } + try { + const payload = await jwt.verify( + tokenValue, + process.env.REFRESH_TOKEN_SECRET + ); + + if (!payload) { return next(); } - try { - const payload = await jwt.verify( - tokenValue, - process.env.REFRESH_TOKEN_SECRET - ); - if (!payload) { - return next(); - } - - req.user = await User.findById(payload._id).select("-password"); - - return next(); - } catch (error) { - return next(); - } + req.user = payload; return next(); - }; + } catch (error) { + return next(); + } } function authorizeRoles(...roles) { diff --git a/Backend/Middlewares/multer.js b/Backend/Middlewares/multer.js index 237e292..87bab6f 100644 --- a/Backend/Middlewares/multer.js +++ b/Backend/Middlewares/multer.js @@ -1,7 +1,6 @@ const multer = require("multer"); const storage = multer.diskStorage({ - destination: function (req, file, cb) { cb(null, "./public/images"); }, @@ -10,11 +9,8 @@ const storage = multer.diskStorage({ const uniquePrefix = Date.now(); cb(null, uniquePrefix + "-" + file.originalname); }, - - }); - const upload = multer({ storage: storage }); module.exports = upload; diff --git a/Backend/Models/crop.model.js b/Backend/Models/crop.model.js index b89c83e..a406411 100644 --- a/Backend/Models/crop.model.js +++ b/Backend/Models/crop.model.js @@ -4,6 +4,7 @@ const cropSchema = new mongoose.Schema( { name: { type: String, required: true }, farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true }, + image: { type: String }, plantedDate: { type: Date, required: true, default: Date.now() }, harvestDate: { type: Date }, growthStage: { diff --git a/Backend/Routes/crop.routes.js b/Backend/Routes/crop.routes.js new file mode 100644 index 0000000..38fd0f1 --- /dev/null +++ b/Backend/Routes/crop.routes.js @@ -0,0 +1,20 @@ +import express from "express"; +import { + createCrop, + getCrops, + getCropById, + updateCrop, + deleteCrop, +} from "../controllers/cropController.js"; +import { checkAuthenticated } from "../Middlewares/authentication.js"; + +const router = express.Router(); + +// Routes for crop management +router.post("/", checkAuthenticated, createCrop); // Create a new crop +router.get("/", checkAuthenticated, getCrops); // Get all crops +router.get("/:cropId", checkAuthenticated, getCropById); // Get a crop by ID +router.put("/:cropId", checkAuthenticated, updateCrop); // Update crop details +router.delete("/:cropId", checkAuthenticated, deleteCrop); // Delete a crop + +export default router; diff --git a/Backend/Routes/farm.routes.js b/Backend/Routes/farm.routes.js new file mode 100644 index 0000000..caa74c6 --- /dev/null +++ b/Backend/Routes/farm.routes.js @@ -0,0 +1,19 @@ +const express = require("express"); +const { + createFarm, + getUserFarms, + getFarmById, + updateFarm, + deleteFarm, +} = require("../Controllers/farm.controller.js"); +const { checkAuthenticated } = require("../Middlewares/authentication.js"); + +const router = express.Router(); + +router.post("/", checkAuthenticated, createFarm); // Create a new farm +router.get("/", checkAuthenticated, getUserFarms); // Get all farms +router.get("/:farmId", checkAuthenticated, getFarmById); // Get a farm by ID +router.put("/:farmId", checkAuthenticated, updateFarm); // Update a farm +router.delete("/:farmId", checkAuthenticated, deleteFarm); // Delete a farm + +module.exports = router; diff --git a/Backend/Routes/finance.routes.js b/Backend/Routes/finance.routes.js new file mode 100644 index 0000000..4de0e0f --- /dev/null +++ b/Backend/Routes/finance.routes.js @@ -0,0 +1,24 @@ +import express from "express"; +import { + createFinanceRecord, + getFinanceRecords, + getFinanceById, + updateFinance, + deleteFinance, + addTransaction, +} from "../controllers/financeController.js"; +import { checkAuthenticated } from "../Middlewares/authentication.js"; + +const router = express.Router(); + +// Routes for finance management +router.post("/", checkAuthenticated, createFinanceRecord); // Create a new finance record +router.get("/", checkAuthenticated, getFinanceRecords); // Get all finance records +router.get("/:financeId", checkAuthenticated, getFinanceById); // Get a finance record by ID +router.put("/:financeId", checkAuthenticated, updateFinance); // Update finance record +router.delete("/:financeId", checkAuthenticated, deleteFinance); // Delete a finance record + +// Add transactions (Expense/Revenue) to a finance record +router.post("/:financeId/transaction", checkAuthenticated, addTransaction); + +export default router; diff --git a/Backend/Routes/task.routes.js b/Backend/Routes/task.routes.js new file mode 100644 index 0000000..0470aea --- /dev/null +++ b/Backend/Routes/task.routes.js @@ -0,0 +1,24 @@ +import express from "express"; +import { + createTask, + getTasksByFarm, + getTaskById, + updateTask, + deleteTask, + updateTaskStatus, +} from "../controllers/taskController.js"; +const { checkAuthenticated } = require("../Middlewares/authentication.js"); + +const router = express.Router(); + +// Routes for task management +router.post("/", checkAuthenticated, createTask); // Create a new task +router.get("/farm/:farmId", checkAuthenticated, getTasksByFarm); // Get all tasks for a specific farm +router.get("/:taskId", checkAuthenticated, getTaskById); // Get a task by ID +router.put("/:taskId", checkAuthenticated, updateTask); // Update task details +router.delete("/:taskId", checkAuthenticated, deleteTask); // Delete a task + +// Update task status (Pending → Completed) +router.patch("/:taskId/status", protect, updateTaskStatus); + +export default router; diff --git a/Backend/Routes/user.routes.js b/Backend/Routes/user.routes.js index b615ec0..0cd4380 100644 --- a/Backend/Routes/user.routes.js +++ b/Backend/Routes/user.routes.js @@ -33,7 +33,7 @@ router.route("/logout").get(logoutUser); router.route("/update/:id").put(updateUserDetails); -router.route("/me").get(getUserDetails); +router.route("/me").get(checkAuthenticated, getUserDetails); router.route("/getuser").get(intializeUser); @@ -45,6 +45,8 @@ router.route("/user/delete/:id").delete(DeleteUser); router.route("/user/updateRole/:id").put(updateUserRole); -router.route("/user/avatar").put(checkAuthenticated(),upload.single("avatar"), updateAvatar); +router + .route("/user/avatar") + .put(checkAuthenticated, upload.single("avatar"), updateAvatar); module.exports = router; diff --git a/Backend/app.js b/Backend/app.js index 4846a34..145fba4 100644 --- a/Backend/app.js +++ b/Backend/app.js @@ -4,6 +4,8 @@ const cookieParser = require("cookie-parser"); const { Server } = require("socket.io"); const { createServer } = require("http"); const userRoute = require("./Routes/user.routes.js"); +const farmRoute = require("./Routes/farm.routes.js"); + const { checkAuthenticated } = require("./Middlewares/authentication.js"); const dotenv = require("dotenv"); @@ -31,4 +33,6 @@ app.get("/", (req, res) => { app.use("/api/v1", userRoute); +app.use("/api/v1/farm", farmRoute); + module.exports = app; From 4897c532592a98199f1eb95e00e0aa461be2f806 Mon Sep 17 00:00:00 2001 From: Karan Date: Sat, 22 Feb 2025 19:10:33 +0530 Subject: [PATCH 5/5] feat:Create and Test user,crop,farm --- Backend/Controllers/crop.controller.js | 52 ++++++++++++++++++++------ Backend/Routes/crop.routes.js | 21 +++++++---- Backend/app.js | 3 ++ 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/Backend/Controllers/crop.controller.js b/Backend/Controllers/crop.controller.js index 60c3930..42dd896 100644 --- a/Backend/Controllers/crop.controller.js +++ b/Backend/Controllers/crop.controller.js @@ -1,11 +1,28 @@ -import Crop from "../models/cropModel.js"; -import Farm from "../models/farmModel.js"; +const Crop = require("../Models/crop.model.js"); +const Farm = require("../Models/farm.model.js"); +const { uploadOnCloudinary } = require("../Utils/cloudinary.js"); // Create a new crop -export const createCrop = async (req, res) => { +const createCrop = async (req, res) => { try { - const { name, farm, image, harvestDate, growthStage, healthStatus } = - req.body; + const { name, farm, harvestDate, growthStage, healthStatus } = req.body; + if (!req.file.path) { + res.status(500).json({ + success: false, + message: "Avatar not uploaded on cloudinary.", + }); + } + + const imageUrl = await uploadOnCloudinary(req.file.path); + + console.log("Image url is : ", imageUrl); + + if (!imageUrl) { + return res.status(500).json({ + success: false, + message: "Image not uploaded on cloudinary.", + }); + } // Check if the farm exists const existingFarm = await Farm.findById(farm); @@ -15,7 +32,7 @@ export const createCrop = async (req, res) => { const crop = new Crop({ name, farm, - image, + image: imageUrl, harvestDate, growthStage, healthStatus, @@ -34,8 +51,9 @@ export const createCrop = async (req, res) => { }; // Get all crops for a specific farm -export const getCropsByFarm = async (req, res) => { +const getCropsByFarm = async (req, res) => { try { + console.log("My farm id is : ", req.params.farmId); const crops = await Crop.find({ farm: req.params.farmId }); res.status(200).json(crops); @@ -45,7 +63,7 @@ export const getCropsByFarm = async (req, res) => { }; // Get a single crop by ID -export const getCropById = async (req, res) => { +const getCropById = async (req, res) => { try { const crop = await Crop.findById(req.params.cropId).populate("farm"); @@ -58,7 +76,7 @@ export const getCropById = async (req, res) => { }; // Update crop details -export const updateCrop = async (req, res) => { +const updateCrop = async (req, res) => { try { const updatedCrop = await Crop.findByIdAndUpdate( req.params.cropId, @@ -76,7 +94,7 @@ export const updateCrop = async (req, res) => { }; // Delete a crop -export const deleteCrop = async (req, res) => { +const deleteCrop = async (req, res) => { try { const crop = await Crop.findById(req.params.cropId); @@ -94,7 +112,7 @@ export const deleteCrop = async (req, res) => { }; // Update crop growth stage -export const updateGrowthStage = async (req, res) => { +const updateGrowthStage = async (req, res) => { try { const { growthStage } = req.body; @@ -111,7 +129,7 @@ export const updateGrowthStage = async (req, res) => { }; // Update crop health status -export const updateHealthStatus = async (req, res) => { +const updateHealthStatus = async (req, res) => { try { const { healthStatus } = req.body; @@ -126,3 +144,13 @@ export const updateHealthStatus = async (req, res) => { res.status(500).json({ message: error.message }); } }; + +module.exports = { + createCrop, + getCropsByFarm, + getCropById, + updateCrop, + deleteCrop, + updateGrowthStage, + updateHealthStatus, +}; diff --git a/Backend/Routes/crop.routes.js b/Backend/Routes/crop.routes.js index 38fd0f1..8a43234 100644 --- a/Backend/Routes/crop.routes.js +++ b/Backend/Routes/crop.routes.js @@ -1,20 +1,25 @@ -import express from "express"; -import { +const express = require("express"); +const { createCrop, - getCrops, + getCropsByFarm, getCropById, updateCrop, deleteCrop, -} from "../controllers/cropController.js"; -import { checkAuthenticated } from "../Middlewares/authentication.js"; + updateHealthStatus, + updateGrowthStage, +} = require("../Controllers/crop.controller.js"); +const { checkAuthenticated } = require("../Middlewares/authentication.js"); +const upload = require("../Middlewares/multer.js"); const router = express.Router(); // Routes for crop management -router.post("/", checkAuthenticated, createCrop); // Create a new crop -router.get("/", checkAuthenticated, getCrops); // Get all crops +router.post("/", checkAuthenticated, upload.single("image"), createCrop); // Create a new crop +router.get("/farm/:farmId", checkAuthenticated, getCropsByFarm); // Get all crops router.get("/:cropId", checkAuthenticated, getCropById); // Get a crop by ID router.put("/:cropId", checkAuthenticated, updateCrop); // Update crop details router.delete("/:cropId", checkAuthenticated, deleteCrop); // Delete a crop +router.put("/health/:cropId", checkAuthenticated, updateHealthStatus); +router.put("/growth/:cropId", checkAuthenticated, updateGrowthStage); -export default router; +module.exports = router; diff --git a/Backend/app.js b/Backend/app.js index 145fba4..34be975 100644 --- a/Backend/app.js +++ b/Backend/app.js @@ -5,6 +5,7 @@ const { Server } = require("socket.io"); const { createServer } = require("http"); const userRoute = require("./Routes/user.routes.js"); const farmRoute = require("./Routes/farm.routes.js"); +const cropRoute = require("./Routes/crop.routes.js"); const { checkAuthenticated } = require("./Middlewares/authentication.js"); const dotenv = require("dotenv"); @@ -35,4 +36,6 @@ app.use("/api/v1", userRoute); app.use("/api/v1/farm", farmRoute); +app.use("/api/v1/crop", cropRoute); + module.exports = app;