├── .gitignore ├── README.md ├── db └── conn.js ├── erd.png ├── index.js ├── loadEnv.js ├── models ├── comments.js ├── posts.js └── users.js ├── package-lock.json ├── package.json └── routes ├── comments.js ├── posts.js └── users.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blog App Backend 2 | 3 | ## About 4 | 5 | A blog api for a blog application where users can post, comment, and like each other's post. 6 | 7 | ## Frontend Repository 8 | 9 | [frontend repository link](https://github.com/mindy-d-tran/blog-app-frontend) 10 | 11 | ## Live Demo 12 | 13 | Deployed on netlify: [blog app live demo](https://main--ps-blog-app.netlify.app/) 14 | 15 | # Approach 16 | 17 | Users can use full CRUD for users, posts, and comments 18 | 19 | ## Technology Used 20 | 21 | ### Backend 22 | 23 | - Nodejs 24 | - Express 25 | - Mongoose 26 | - MongoDB 27 | - Bcrypt (Password encrypting, hashing) 28 | 29 | ## Planning 30 | 31 | ## Trello Board 32 | 33 | [trello board link](https://trello.com/invite/b/xMjVRQSG/ATTI0edbb0da239b30e52dd61d33368ae80f69D00CD7/ps-capstone-project) 34 | 35 | ## Entity Relationship Diagram (ERD) 36 | 37 | [ERD](https://drive.google.com/file/d/14j2IKmw6vyK-PiW4wrSRmKZa3s_J_noH/view) 38 | ![erd](./erd.png) 39 | 40 | # Routes 41 | 42 | ## Users Route 43 | 44 | ### GET /api/users 45 | 46 | Reads all users in the database 47 | 48 | ### PUT /api/users/login 49 | 50 | Returns the user data if the login attempt is a sucess 51 | 52 | #### Body (JSON) 53 | 54 | ``` 55 | { 56 | emailOrUsername: String, 57 | password: String 58 | } 59 | ``` 60 | 61 | ### GET /api/users/:id 62 | 63 | Read a single user's data 64 | 65 | - id = user \_id 66 | 67 | ### POST /api/users 68 | 69 | Create a new user and returns new user data 70 | 71 | #### Body (JSON) 72 | 73 | ``` 74 | { 75 | email: String (required, unique), 76 | username: String (required, unique), 77 | password: String (required) 78 | } 79 | ``` 80 | 81 | ### PUT /api/users/:id/update-profile-pic 82 | 83 | Updates the user's profile picture 84 | 85 | - id = user \_id 86 | 87 | #### Body (JSON) 88 | 89 | ``` 90 | { 91 | profile_pic: String 92 | } 93 | ``` 94 | 95 | ### PUT /api/users/:id/update-username 96 | 97 | Updates the user's username 98 | 99 | - id = user \_id 100 | 101 | #### Body (JSON) 102 | 103 | ``` 104 | { 105 | username: String 106 | } 107 | ``` 108 | 109 | ### PUT /api/users/:id/update-email 110 | 111 | Updates the user's email 112 | 113 | - id = user \_id 114 | 115 | #### Body (JSON) 116 | 117 | ``` 118 | { 119 | email: String 120 | } 121 | ``` 122 | 123 | ### PUT /api/users/:id/update-password 124 | 125 | Updates the user's password. Shout out to Abraham Tavarez for the [code](https://github.com/AbeTavarez/cohort107/blob/main/nodejs/mongoose-api/backend/routes/users.js) 126 | 127 | - id = user \_id 128 | 129 | #### Body (JSON) 130 | 131 | ``` 132 | { 133 | currentPassword: String, 134 | newPassword: String 135 | } 136 | ``` 137 | 138 | ### DELETE /api/users/:id/ 139 | 140 | Delete a user from the database 141 | 142 | - id = user \_id 143 | 144 | ## Posts Route 145 | 146 | ### GET /api/posts 147 | 148 | Reads all posts in the database 149 | 150 | ### GET /api/posts/:id 151 | 152 | Read a single post's data 153 | 154 | - id = post \_id 155 | 156 | ### POST /api/posts 157 | 158 | Create a new post and returns new post data 159 | 160 | #### Body (JSON) 161 | 162 | ``` 163 | { 164 | user_id: String (required, unique), 165 | post_title: String (default ""), 166 | post_content: { 167 | text: String, 168 | img: [String] 169 | } (required), 170 | post_hashtag: [String] 171 | } 172 | ``` 173 | 174 | ### PUT /api/posts/:id 175 | 176 | Create a new post and returns new post data 177 | 178 | - id = post \_id 179 | 180 | #### Body (JSON) 181 | 182 | ``` 183 | { 184 | user_id: String (required, unique), 185 | post_title: String (default ""), 186 | post_content: { 187 | text: String, 188 | img: [String] 189 | } (required), 190 | post_hashtag: [String] 191 | } 192 | ``` 193 | 194 | ### PUT /api/posts/:id/update_content 195 | 196 | Updates the post's content 197 | 198 | - id = post \_id 199 | 200 | #### Body (JSON) 201 | 202 | ``` 203 | { 204 | post_title: String (default ""), 205 | post_content: { 206 | text: String, 207 | img: [String] 208 | }, 209 | post_hashtag: [String] 210 | } 211 | ``` 212 | 213 | ### PUT /api/posts/:id/update_content_text 214 | 215 | Updates the post's content's text 216 | 217 | - id = post \_id 218 | 219 | #### Body (JSON) 220 | 221 | ``` 222 | { 223 | text: String, 224 | } 225 | ``` 226 | 227 | ### PUT /api/posts/:id/update_content_img 228 | 229 | Updates the post's content's image 230 | 231 | - id = post \_id 232 | 233 | #### Body (JSON) 234 | 235 | ``` 236 | { 237 | img: [String] 238 | } 239 | ``` 240 | 241 | ### PUT /api/posts/:id/update_title 242 | 243 | Updates the post's title 244 | 245 | - id = post \_id 246 | 247 | #### Body (JSON) 248 | 249 | ``` 250 | { 251 | post_title: String 252 | } 253 | ``` 254 | 255 | ### PUT /api/posts/:id/update_hashtag 256 | 257 | Updates the post's hashtags 258 | 259 | - id = post \_id 260 | 261 | #### Body (JSON) 262 | 263 | ``` 264 | { 265 | post_hashtag: [String] 266 | } 267 | ``` 268 | 269 | ### PUT /api/posts/:id/like 270 | 271 | Updates the post's like (user like the post) 272 | 273 | - id = post \_id 274 | 275 | ### PUT /api/posts/:id/unlike 276 | 277 | Updates the post's like (user unlike the post) 278 | 279 | - id = post \_id 280 | 281 | ### DELETE /api/posts/:id 282 | 283 | Delete a post 284 | 285 | - id = post \_id 286 | 287 | ## Comments Route 288 | 289 | ### GET /api/comments 290 | 291 | Reads all comments in the database 292 | 293 | ### GET /api/comments/:id 294 | 295 | Read a single comment's data 296 | 297 | - id = comment \_id 298 | 299 | ### GET /api/comments/post/:post_id 300 | 301 | Read all comment's for one post 302 | 303 | - post_id = post \_id 304 | 305 | ### POST /api/comments 306 | 307 | Create new comment 308 | 309 | #### Body (JSON) 310 | 311 | ```{ 312 | user_id: String (required), 313 | post_id: String (required), 314 | comment_content: String (required) 315 | } 316 | ``` 317 | 318 | ### PUT /api/comments/:id/like 319 | 320 | Updates the comment's like (user like the comment) 321 | 322 | - id = comment \_id 323 | 324 | ### PUT /api/comments/:id/unlike 325 | 326 | Updates the comment's like (user unlike the comment) 327 | 328 | - id = comment \_id 329 | 330 | ### DELETE /api/comments/:id/ 331 | 332 | Delete a comment from the database 333 | 334 | - id = comment \_id 335 | 336 | # Future Implementations 337 | 338 | - Create search route so user's can search for posts through query 339 | - Create search router for advance search to give users filters when searching for things on the application 340 | - Create a profile schema so users can learn more about each other in the app 341 | -------------------------------------------------------------------------------- /db/conn.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | export async function conn() { 4 | try { 5 | await mongoose.connect(process.env.ATLAS_URI); 6 | console.log("connected to MongoDB"); 7 | } catch (error) { 8 | console.log(error.message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /erd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindy-d-tran/blog-app-backend/8fd1db05154cfbb72590fd84034dd2ead6eca545/erd.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import "./loadEnv.js"; 2 | import { conn } from "./db/conn.js"; conn(); 3 | import express from "express"; 4 | import cors from "cors"; 5 | import morgan from "morgan"; 6 | 7 | // importing routes 8 | import usersRouter from "./routes/users.js"; 9 | import postsRouter from "./routes/posts.js"; 10 | import commentsRouter from "./routes/comments.js"; 11 | 12 | const app = express(); 13 | const PORT = process.env.PORT || 4000; 14 | 15 | // middlewares 16 | app.use(cors()); // allows frontend to connect to backend 17 | app.use(morgan("dev")); // logger to know what requests you are calling 18 | app.use(express.json()); // for data in req.body 19 | app.use(express.urlencoded({ extended: true })); // allow data in url 20 | 21 | app.use("/api/users", usersRouter); 22 | app.use("/api/posts", postsRouter); 23 | app.use("/api/comments", commentsRouter); 24 | 25 | // routes 26 | app.get("/", (req, res) => res.send("welcome to blog app api")); 27 | 28 | app.listen(PORT, () => console.log(`server is running on port ${PORT}`)); 29 | -------------------------------------------------------------------------------- /loadEnv.js: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | dotenv.config(); -------------------------------------------------------------------------------- /models/comments.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const user = new mongoose.Schema( 4 | { 5 | user_id: { 6 | type: mongoose.Schema.ObjectId, 7 | ref: "User", 8 | }, 9 | }, 10 | { _id: false } 11 | ); 12 | 13 | const commentsSchema = new mongoose.Schema( 14 | { 15 | user_id: { 16 | type: mongoose.Schema.ObjectId, 17 | ref: "User", 18 | required: true, 19 | }, 20 | post_id: { 21 | type: mongoose.Schema.ObjectId, 22 | ref: "Post", 23 | required: true, 24 | }, 25 | comment_like: { 26 | type: [user], 27 | }, 28 | comment_content: { 29 | type: String, 30 | required: true 31 | }, 32 | }, 33 | { timestamps: true } 34 | ); 35 | 36 | export default mongoose.model("Comment", commentsSchema); 37 | -------------------------------------------------------------------------------- /models/posts.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | // subschema for user 4 | const user = new mongoose.Schema( 5 | { 6 | user_id: { 7 | type: mongoose.Schema.ObjectId, 8 | ref: "User", 9 | }, 10 | }, 11 | { _id: false } 12 | ); 13 | // subschema for comment 14 | const comment = new mongoose.Schema( 15 | { 16 | comment_id: { 17 | type: mongoose.Schema.ObjectId, 18 | ref: "Comment", 19 | }, 20 | }, 21 | { _id: false } 22 | ); 23 | // subschema for post content 24 | const post_content = new mongoose.Schema( 25 | { 26 | text: String, 27 | img: [String], 28 | }, 29 | { _id: false } 30 | ); 31 | 32 | // Schema 33 | const postsSchema = new mongoose.Schema( 34 | { 35 | user_id: { 36 | type: mongoose.Schema.ObjectId, 37 | ref: "User", 38 | required: true, 39 | }, 40 | post_likes: { 41 | type: [user], 42 | }, 43 | post_views: { 44 | type: Number, 45 | default: 0, 46 | }, 47 | post_comments: { 48 | type: [comment], 49 | }, 50 | post_title: { 51 | type: String, 52 | default: "", 53 | }, 54 | post_content: { 55 | type: post_content, 56 | required: true, 57 | }, 58 | post_hashtag: { 59 | type: [String], 60 | }, 61 | }, 62 | { 63 | timestamps: true, 64 | } 65 | ); 66 | 67 | export default mongoose.model("Post", postsSchema); 68 | -------------------------------------------------------------------------------- /models/users.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | import bcrypt from "bcrypt"; 3 | 4 | const SALT_ROUNDS = 8; 5 | 6 | const usersSchema = new mongoose.Schema( 7 | { 8 | username: { 9 | type: String, 10 | unique: true, 11 | }, 12 | email: { 13 | type: String, 14 | required: true, 15 | unique: true, 16 | }, 17 | password: { 18 | type: String, 19 | required: true, 20 | minLength: 8, 21 | maxLength: 30, 22 | }, 23 | }, 24 | { 25 | toJSON: { 26 | transform: function (doc, retDoc) { 27 | delete retDoc.password; 28 | return retDoc; 29 | }, 30 | }, 31 | } 32 | ); 33 | 34 | // encrypting the password 35 | usersSchema.pre("save", async function (next) { 36 | this.password = await bcrypt.hash(this.password, SALT_ROUNDS); 37 | return next(); 38 | }); 39 | 40 | export default mongoose.model("User", usersSchema); 41 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "backend", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "bcrypt": "^5.1.1", 13 | "cors": "^2.8.5", 14 | "dotenv": "^16.4.1", 15 | "express": "^4.18.2", 16 | "mongoose": "^8.1.1", 17 | "morgan": "^1.10.0" 18 | } 19 | }, 20 | "node_modules/@mapbox/node-pre-gyp": { 21 | "version": "1.0.11", 22 | "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", 23 | "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", 24 | "dependencies": { 25 | "detect-libc": "^2.0.0", 26 | "https-proxy-agent": "^5.0.0", 27 | "make-dir": "^3.1.0", 28 | "node-fetch": "^2.6.7", 29 | "nopt": "^5.0.0", 30 | "npmlog": "^5.0.1", 31 | "rimraf": "^3.0.2", 32 | "semver": "^7.3.5", 33 | "tar": "^6.1.11" 34 | }, 35 | "bin": { 36 | "node-pre-gyp": "bin/node-pre-gyp" 37 | } 38 | }, 39 | "node_modules/@mongodb-js/saslprep": { 40 | "version": "1.1.4", 41 | "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz", 42 | "integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==", 43 | "dependencies": { 44 | "sparse-bitfield": "^3.0.3" 45 | } 46 | }, 47 | "node_modules/@types/webidl-conversions": { 48 | "version": "7.0.3", 49 | "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", 50 | "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" 51 | }, 52 | "node_modules/@types/whatwg-url": { 53 | "version": "11.0.4", 54 | "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", 55 | "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", 56 | "dependencies": { 57 | "@types/webidl-conversions": "*" 58 | } 59 | }, 60 | "node_modules/abbrev": { 61 | "version": "1.1.1", 62 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 63 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 64 | }, 65 | "node_modules/accepts": { 66 | "version": "1.3.8", 67 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 68 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 69 | "dependencies": { 70 | "mime-types": "~2.1.34", 71 | "negotiator": "0.6.3" 72 | }, 73 | "engines": { 74 | "node": ">= 0.6" 75 | } 76 | }, 77 | "node_modules/agent-base": { 78 | "version": "6.0.2", 79 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 80 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 81 | "dependencies": { 82 | "debug": "4" 83 | }, 84 | "engines": { 85 | "node": ">= 6.0.0" 86 | } 87 | }, 88 | "node_modules/agent-base/node_modules/debug": { 89 | "version": "4.3.4", 90 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 91 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 92 | "dependencies": { 93 | "ms": "2.1.2" 94 | }, 95 | "engines": { 96 | "node": ">=6.0" 97 | }, 98 | "peerDependenciesMeta": { 99 | "supports-color": { 100 | "optional": true 101 | } 102 | } 103 | }, 104 | "node_modules/agent-base/node_modules/ms": { 105 | "version": "2.1.2", 106 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 107 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 108 | }, 109 | "node_modules/ansi-regex": { 110 | "version": "5.0.1", 111 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 112 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 113 | "engines": { 114 | "node": ">=8" 115 | } 116 | }, 117 | "node_modules/aproba": { 118 | "version": "2.0.0", 119 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", 120 | "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" 121 | }, 122 | "node_modules/are-we-there-yet": { 123 | "version": "2.0.0", 124 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", 125 | "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", 126 | "dependencies": { 127 | "delegates": "^1.0.0", 128 | "readable-stream": "^3.6.0" 129 | }, 130 | "engines": { 131 | "node": ">=10" 132 | } 133 | }, 134 | "node_modules/array-flatten": { 135 | "version": "1.1.1", 136 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 137 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 138 | }, 139 | "node_modules/balanced-match": { 140 | "version": "1.0.2", 141 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 142 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 143 | }, 144 | "node_modules/basic-auth": { 145 | "version": "2.0.1", 146 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 147 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 148 | "dependencies": { 149 | "safe-buffer": "5.1.2" 150 | }, 151 | "engines": { 152 | "node": ">= 0.8" 153 | } 154 | }, 155 | "node_modules/basic-auth/node_modules/safe-buffer": { 156 | "version": "5.1.2", 157 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 158 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 159 | }, 160 | "node_modules/bcrypt": { 161 | "version": "5.1.1", 162 | "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", 163 | "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", 164 | "hasInstallScript": true, 165 | "dependencies": { 166 | "@mapbox/node-pre-gyp": "^1.0.11", 167 | "node-addon-api": "^5.0.0" 168 | }, 169 | "engines": { 170 | "node": ">= 10.0.0" 171 | } 172 | }, 173 | "node_modules/body-parser": { 174 | "version": "1.20.1", 175 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 176 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 177 | "dependencies": { 178 | "bytes": "3.1.2", 179 | "content-type": "~1.0.4", 180 | "debug": "2.6.9", 181 | "depd": "2.0.0", 182 | "destroy": "1.2.0", 183 | "http-errors": "2.0.0", 184 | "iconv-lite": "0.4.24", 185 | "on-finished": "2.4.1", 186 | "qs": "6.11.0", 187 | "raw-body": "2.5.1", 188 | "type-is": "~1.6.18", 189 | "unpipe": "1.0.0" 190 | }, 191 | "engines": { 192 | "node": ">= 0.8", 193 | "npm": "1.2.8000 || >= 1.4.16" 194 | } 195 | }, 196 | "node_modules/brace-expansion": { 197 | "version": "1.1.11", 198 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 199 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 200 | "dependencies": { 201 | "balanced-match": "^1.0.0", 202 | "concat-map": "0.0.1" 203 | } 204 | }, 205 | "node_modules/bson": { 206 | "version": "6.3.0", 207 | "resolved": "https://registry.npmjs.org/bson/-/bson-6.3.0.tgz", 208 | "integrity": "sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw==", 209 | "engines": { 210 | "node": ">=16.20.1" 211 | } 212 | }, 213 | "node_modules/bytes": { 214 | "version": "3.1.2", 215 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 216 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 217 | "engines": { 218 | "node": ">= 0.8" 219 | } 220 | }, 221 | "node_modules/call-bind": { 222 | "version": "1.0.6", 223 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", 224 | "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", 225 | "dependencies": { 226 | "es-errors": "^1.3.0", 227 | "function-bind": "^1.1.2", 228 | "get-intrinsic": "^1.2.3", 229 | "set-function-length": "^1.2.0" 230 | }, 231 | "engines": { 232 | "node": ">= 0.4" 233 | }, 234 | "funding": { 235 | "url": "https://github.com/sponsors/ljharb" 236 | } 237 | }, 238 | "node_modules/chownr": { 239 | "version": "2.0.0", 240 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", 241 | "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", 242 | "engines": { 243 | "node": ">=10" 244 | } 245 | }, 246 | "node_modules/color-support": { 247 | "version": "1.1.3", 248 | "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", 249 | "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", 250 | "bin": { 251 | "color-support": "bin.js" 252 | } 253 | }, 254 | "node_modules/concat-map": { 255 | "version": "0.0.1", 256 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 257 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 258 | }, 259 | "node_modules/console-control-strings": { 260 | "version": "1.1.0", 261 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 262 | "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" 263 | }, 264 | "node_modules/content-disposition": { 265 | "version": "0.5.4", 266 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 267 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 268 | "dependencies": { 269 | "safe-buffer": "5.2.1" 270 | }, 271 | "engines": { 272 | "node": ">= 0.6" 273 | } 274 | }, 275 | "node_modules/content-type": { 276 | "version": "1.0.5", 277 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 278 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 279 | "engines": { 280 | "node": ">= 0.6" 281 | } 282 | }, 283 | "node_modules/cookie": { 284 | "version": "0.5.0", 285 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 286 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 287 | "engines": { 288 | "node": ">= 0.6" 289 | } 290 | }, 291 | "node_modules/cookie-signature": { 292 | "version": "1.0.6", 293 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 294 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 295 | }, 296 | "node_modules/cors": { 297 | "version": "2.8.5", 298 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 299 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 300 | "dependencies": { 301 | "object-assign": "^4", 302 | "vary": "^1" 303 | }, 304 | "engines": { 305 | "node": ">= 0.10" 306 | } 307 | }, 308 | "node_modules/debug": { 309 | "version": "2.6.9", 310 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 311 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 312 | "dependencies": { 313 | "ms": "2.0.0" 314 | } 315 | }, 316 | "node_modules/define-data-property": { 317 | "version": "1.1.2", 318 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", 319 | "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", 320 | "dependencies": { 321 | "es-errors": "^1.3.0", 322 | "get-intrinsic": "^1.2.2", 323 | "gopd": "^1.0.1", 324 | "has-property-descriptors": "^1.0.1" 325 | }, 326 | "engines": { 327 | "node": ">= 0.4" 328 | } 329 | }, 330 | "node_modules/delegates": { 331 | "version": "1.0.0", 332 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", 333 | "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" 334 | }, 335 | "node_modules/depd": { 336 | "version": "2.0.0", 337 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 338 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 339 | "engines": { 340 | "node": ">= 0.8" 341 | } 342 | }, 343 | "node_modules/destroy": { 344 | "version": "1.2.0", 345 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 346 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 347 | "engines": { 348 | "node": ">= 0.8", 349 | "npm": "1.2.8000 || >= 1.4.16" 350 | } 351 | }, 352 | "node_modules/detect-libc": { 353 | "version": "2.0.2", 354 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", 355 | "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", 356 | "engines": { 357 | "node": ">=8" 358 | } 359 | }, 360 | "node_modules/dotenv": { 361 | "version": "16.4.1", 362 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", 363 | "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", 364 | "engines": { 365 | "node": ">=12" 366 | }, 367 | "funding": { 368 | "url": "https://github.com/motdotla/dotenv?sponsor=1" 369 | } 370 | }, 371 | "node_modules/ee-first": { 372 | "version": "1.1.1", 373 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 374 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 375 | }, 376 | "node_modules/emoji-regex": { 377 | "version": "8.0.0", 378 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 379 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 380 | }, 381 | "node_modules/encodeurl": { 382 | "version": "1.0.2", 383 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 384 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 385 | "engines": { 386 | "node": ">= 0.8" 387 | } 388 | }, 389 | "node_modules/es-errors": { 390 | "version": "1.3.0", 391 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 392 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 393 | "engines": { 394 | "node": ">= 0.4" 395 | } 396 | }, 397 | "node_modules/escape-html": { 398 | "version": "1.0.3", 399 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 400 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 401 | }, 402 | "node_modules/etag": { 403 | "version": "1.8.1", 404 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 405 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 406 | "engines": { 407 | "node": ">= 0.6" 408 | } 409 | }, 410 | "node_modules/express": { 411 | "version": "4.18.2", 412 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 413 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 414 | "dependencies": { 415 | "accepts": "~1.3.8", 416 | "array-flatten": "1.1.1", 417 | "body-parser": "1.20.1", 418 | "content-disposition": "0.5.4", 419 | "content-type": "~1.0.4", 420 | "cookie": "0.5.0", 421 | "cookie-signature": "1.0.6", 422 | "debug": "2.6.9", 423 | "depd": "2.0.0", 424 | "encodeurl": "~1.0.2", 425 | "escape-html": "~1.0.3", 426 | "etag": "~1.8.1", 427 | "finalhandler": "1.2.0", 428 | "fresh": "0.5.2", 429 | "http-errors": "2.0.0", 430 | "merge-descriptors": "1.0.1", 431 | "methods": "~1.1.2", 432 | "on-finished": "2.4.1", 433 | "parseurl": "~1.3.3", 434 | "path-to-regexp": "0.1.7", 435 | "proxy-addr": "~2.0.7", 436 | "qs": "6.11.0", 437 | "range-parser": "~1.2.1", 438 | "safe-buffer": "5.2.1", 439 | "send": "0.18.0", 440 | "serve-static": "1.15.0", 441 | "setprototypeof": "1.2.0", 442 | "statuses": "2.0.1", 443 | "type-is": "~1.6.18", 444 | "utils-merge": "1.0.1", 445 | "vary": "~1.1.2" 446 | }, 447 | "engines": { 448 | "node": ">= 0.10.0" 449 | } 450 | }, 451 | "node_modules/finalhandler": { 452 | "version": "1.2.0", 453 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 454 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 455 | "dependencies": { 456 | "debug": "2.6.9", 457 | "encodeurl": "~1.0.2", 458 | "escape-html": "~1.0.3", 459 | "on-finished": "2.4.1", 460 | "parseurl": "~1.3.3", 461 | "statuses": "2.0.1", 462 | "unpipe": "~1.0.0" 463 | }, 464 | "engines": { 465 | "node": ">= 0.8" 466 | } 467 | }, 468 | "node_modules/forwarded": { 469 | "version": "0.2.0", 470 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 471 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 472 | "engines": { 473 | "node": ">= 0.6" 474 | } 475 | }, 476 | "node_modules/fresh": { 477 | "version": "0.5.2", 478 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 479 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 480 | "engines": { 481 | "node": ">= 0.6" 482 | } 483 | }, 484 | "node_modules/fs-minipass": { 485 | "version": "2.1.0", 486 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", 487 | "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", 488 | "dependencies": { 489 | "minipass": "^3.0.0" 490 | }, 491 | "engines": { 492 | "node": ">= 8" 493 | } 494 | }, 495 | "node_modules/fs-minipass/node_modules/minipass": { 496 | "version": "3.3.6", 497 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 498 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 499 | "dependencies": { 500 | "yallist": "^4.0.0" 501 | }, 502 | "engines": { 503 | "node": ">=8" 504 | } 505 | }, 506 | "node_modules/fs.realpath": { 507 | "version": "1.0.0", 508 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 509 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 510 | }, 511 | "node_modules/function-bind": { 512 | "version": "1.1.2", 513 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 514 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 515 | "funding": { 516 | "url": "https://github.com/sponsors/ljharb" 517 | } 518 | }, 519 | "node_modules/gauge": { 520 | "version": "3.0.2", 521 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", 522 | "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", 523 | "dependencies": { 524 | "aproba": "^1.0.3 || ^2.0.0", 525 | "color-support": "^1.1.2", 526 | "console-control-strings": "^1.0.0", 527 | "has-unicode": "^2.0.1", 528 | "object-assign": "^4.1.1", 529 | "signal-exit": "^3.0.0", 530 | "string-width": "^4.2.3", 531 | "strip-ansi": "^6.0.1", 532 | "wide-align": "^1.1.2" 533 | }, 534 | "engines": { 535 | "node": ">=10" 536 | } 537 | }, 538 | "node_modules/get-intrinsic": { 539 | "version": "1.2.4", 540 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 541 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 542 | "dependencies": { 543 | "es-errors": "^1.3.0", 544 | "function-bind": "^1.1.2", 545 | "has-proto": "^1.0.1", 546 | "has-symbols": "^1.0.3", 547 | "hasown": "^2.0.0" 548 | }, 549 | "engines": { 550 | "node": ">= 0.4" 551 | }, 552 | "funding": { 553 | "url": "https://github.com/sponsors/ljharb" 554 | } 555 | }, 556 | "node_modules/glob": { 557 | "version": "7.2.3", 558 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 559 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 560 | "dependencies": { 561 | "fs.realpath": "^1.0.0", 562 | "inflight": "^1.0.4", 563 | "inherits": "2", 564 | "minimatch": "^3.1.1", 565 | "once": "^1.3.0", 566 | "path-is-absolute": "^1.0.0" 567 | }, 568 | "engines": { 569 | "node": "*" 570 | }, 571 | "funding": { 572 | "url": "https://github.com/sponsors/isaacs" 573 | } 574 | }, 575 | "node_modules/gopd": { 576 | "version": "1.0.1", 577 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 578 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 579 | "dependencies": { 580 | "get-intrinsic": "^1.1.3" 581 | }, 582 | "funding": { 583 | "url": "https://github.com/sponsors/ljharb" 584 | } 585 | }, 586 | "node_modules/has-property-descriptors": { 587 | "version": "1.0.1", 588 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", 589 | "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", 590 | "dependencies": { 591 | "get-intrinsic": "^1.2.2" 592 | }, 593 | "funding": { 594 | "url": "https://github.com/sponsors/ljharb" 595 | } 596 | }, 597 | "node_modules/has-proto": { 598 | "version": "1.0.1", 599 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 600 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 601 | "engines": { 602 | "node": ">= 0.4" 603 | }, 604 | "funding": { 605 | "url": "https://github.com/sponsors/ljharb" 606 | } 607 | }, 608 | "node_modules/has-symbols": { 609 | "version": "1.0.3", 610 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 611 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 612 | "engines": { 613 | "node": ">= 0.4" 614 | }, 615 | "funding": { 616 | "url": "https://github.com/sponsors/ljharb" 617 | } 618 | }, 619 | "node_modules/has-unicode": { 620 | "version": "2.0.1", 621 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 622 | "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" 623 | }, 624 | "node_modules/hasown": { 625 | "version": "2.0.0", 626 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", 627 | "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", 628 | "dependencies": { 629 | "function-bind": "^1.1.2" 630 | }, 631 | "engines": { 632 | "node": ">= 0.4" 633 | } 634 | }, 635 | "node_modules/http-errors": { 636 | "version": "2.0.0", 637 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 638 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 639 | "dependencies": { 640 | "depd": "2.0.0", 641 | "inherits": "2.0.4", 642 | "setprototypeof": "1.2.0", 643 | "statuses": "2.0.1", 644 | "toidentifier": "1.0.1" 645 | }, 646 | "engines": { 647 | "node": ">= 0.8" 648 | } 649 | }, 650 | "node_modules/https-proxy-agent": { 651 | "version": "5.0.1", 652 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 653 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 654 | "dependencies": { 655 | "agent-base": "6", 656 | "debug": "4" 657 | }, 658 | "engines": { 659 | "node": ">= 6" 660 | } 661 | }, 662 | "node_modules/https-proxy-agent/node_modules/debug": { 663 | "version": "4.3.4", 664 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 665 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 666 | "dependencies": { 667 | "ms": "2.1.2" 668 | }, 669 | "engines": { 670 | "node": ">=6.0" 671 | }, 672 | "peerDependenciesMeta": { 673 | "supports-color": { 674 | "optional": true 675 | } 676 | } 677 | }, 678 | "node_modules/https-proxy-agent/node_modules/ms": { 679 | "version": "2.1.2", 680 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 681 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 682 | }, 683 | "node_modules/iconv-lite": { 684 | "version": "0.4.24", 685 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 686 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 687 | "dependencies": { 688 | "safer-buffer": ">= 2.1.2 < 3" 689 | }, 690 | "engines": { 691 | "node": ">=0.10.0" 692 | } 693 | }, 694 | "node_modules/inflight": { 695 | "version": "1.0.6", 696 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 697 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 698 | "dependencies": { 699 | "once": "^1.3.0", 700 | "wrappy": "1" 701 | } 702 | }, 703 | "node_modules/inherits": { 704 | "version": "2.0.4", 705 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 706 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 707 | }, 708 | "node_modules/ipaddr.js": { 709 | "version": "1.9.1", 710 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 711 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 712 | "engines": { 713 | "node": ">= 0.10" 714 | } 715 | }, 716 | "node_modules/is-fullwidth-code-point": { 717 | "version": "3.0.0", 718 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 719 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 720 | "engines": { 721 | "node": ">=8" 722 | } 723 | }, 724 | "node_modules/kareem": { 725 | "version": "2.5.1", 726 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", 727 | "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", 728 | "engines": { 729 | "node": ">=12.0.0" 730 | } 731 | }, 732 | "node_modules/lru-cache": { 733 | "version": "6.0.0", 734 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 735 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 736 | "dependencies": { 737 | "yallist": "^4.0.0" 738 | }, 739 | "engines": { 740 | "node": ">=10" 741 | } 742 | }, 743 | "node_modules/make-dir": { 744 | "version": "3.1.0", 745 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 746 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 747 | "dependencies": { 748 | "semver": "^6.0.0" 749 | }, 750 | "engines": { 751 | "node": ">=8" 752 | }, 753 | "funding": { 754 | "url": "https://github.com/sponsors/sindresorhus" 755 | } 756 | }, 757 | "node_modules/make-dir/node_modules/semver": { 758 | "version": "6.3.1", 759 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 760 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 761 | "bin": { 762 | "semver": "bin/semver.js" 763 | } 764 | }, 765 | "node_modules/media-typer": { 766 | "version": "0.3.0", 767 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 768 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 769 | "engines": { 770 | "node": ">= 0.6" 771 | } 772 | }, 773 | "node_modules/memory-pager": { 774 | "version": "1.5.0", 775 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 776 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" 777 | }, 778 | "node_modules/merge-descriptors": { 779 | "version": "1.0.1", 780 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 781 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 782 | }, 783 | "node_modules/methods": { 784 | "version": "1.1.2", 785 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 786 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 787 | "engines": { 788 | "node": ">= 0.6" 789 | } 790 | }, 791 | "node_modules/mime": { 792 | "version": "1.6.0", 793 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 794 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 795 | "bin": { 796 | "mime": "cli.js" 797 | }, 798 | "engines": { 799 | "node": ">=4" 800 | } 801 | }, 802 | "node_modules/mime-db": { 803 | "version": "1.52.0", 804 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 805 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 806 | "engines": { 807 | "node": ">= 0.6" 808 | } 809 | }, 810 | "node_modules/mime-types": { 811 | "version": "2.1.35", 812 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 813 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 814 | "dependencies": { 815 | "mime-db": "1.52.0" 816 | }, 817 | "engines": { 818 | "node": ">= 0.6" 819 | } 820 | }, 821 | "node_modules/minimatch": { 822 | "version": "3.1.2", 823 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 824 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 825 | "dependencies": { 826 | "brace-expansion": "^1.1.7" 827 | }, 828 | "engines": { 829 | "node": "*" 830 | } 831 | }, 832 | "node_modules/minipass": { 833 | "version": "5.0.0", 834 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 835 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 836 | "engines": { 837 | "node": ">=8" 838 | } 839 | }, 840 | "node_modules/minizlib": { 841 | "version": "2.1.2", 842 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", 843 | "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", 844 | "dependencies": { 845 | "minipass": "^3.0.0", 846 | "yallist": "^4.0.0" 847 | }, 848 | "engines": { 849 | "node": ">= 8" 850 | } 851 | }, 852 | "node_modules/minizlib/node_modules/minipass": { 853 | "version": "3.3.6", 854 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 855 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 856 | "dependencies": { 857 | "yallist": "^4.0.0" 858 | }, 859 | "engines": { 860 | "node": ">=8" 861 | } 862 | }, 863 | "node_modules/mkdirp": { 864 | "version": "1.0.4", 865 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 866 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", 867 | "bin": { 868 | "mkdirp": "bin/cmd.js" 869 | }, 870 | "engines": { 871 | "node": ">=10" 872 | } 873 | }, 874 | "node_modules/mongodb": { 875 | "version": "6.3.0", 876 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz", 877 | "integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==", 878 | "dependencies": { 879 | "@mongodb-js/saslprep": "^1.1.0", 880 | "bson": "^6.2.0", 881 | "mongodb-connection-string-url": "^3.0.0" 882 | }, 883 | "engines": { 884 | "node": ">=16.20.1" 885 | }, 886 | "peerDependencies": { 887 | "@aws-sdk/credential-providers": "^3.188.0", 888 | "@mongodb-js/zstd": "^1.1.0", 889 | "gcp-metadata": "^5.2.0", 890 | "kerberos": "^2.0.1", 891 | "mongodb-client-encryption": ">=6.0.0 <7", 892 | "snappy": "^7.2.2", 893 | "socks": "^2.7.1" 894 | }, 895 | "peerDependenciesMeta": { 896 | "@aws-sdk/credential-providers": { 897 | "optional": true 898 | }, 899 | "@mongodb-js/zstd": { 900 | "optional": true 901 | }, 902 | "gcp-metadata": { 903 | "optional": true 904 | }, 905 | "kerberos": { 906 | "optional": true 907 | }, 908 | "mongodb-client-encryption": { 909 | "optional": true 910 | }, 911 | "snappy": { 912 | "optional": true 913 | }, 914 | "socks": { 915 | "optional": true 916 | } 917 | } 918 | }, 919 | "node_modules/mongodb-connection-string-url": { 920 | "version": "3.0.0", 921 | "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", 922 | "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", 923 | "dependencies": { 924 | "@types/whatwg-url": "^11.0.2", 925 | "whatwg-url": "^13.0.0" 926 | } 927 | }, 928 | "node_modules/mongoose": { 929 | "version": "8.1.1", 930 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.1.1.tgz", 931 | "integrity": "sha512-DbLb0NsiEXmaqLOpEz+AtAsgwhRw6f25gwa1dF5R7jj6lS1D8X6uTdhBSC8GDVtOwe5Tfw2EL7nTn6hiJT3Bgg==", 932 | "dependencies": { 933 | "bson": "^6.2.0", 934 | "kareem": "2.5.1", 935 | "mongodb": "6.3.0", 936 | "mpath": "0.9.0", 937 | "mquery": "5.0.0", 938 | "ms": "2.1.3", 939 | "sift": "16.0.1" 940 | }, 941 | "engines": { 942 | "node": ">=16.20.1" 943 | }, 944 | "funding": { 945 | "type": "opencollective", 946 | "url": "https://opencollective.com/mongoose" 947 | } 948 | }, 949 | "node_modules/mongoose/node_modules/ms": { 950 | "version": "2.1.3", 951 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 952 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 953 | }, 954 | "node_modules/morgan": { 955 | "version": "1.10.0", 956 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", 957 | "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", 958 | "dependencies": { 959 | "basic-auth": "~2.0.1", 960 | "debug": "2.6.9", 961 | "depd": "~2.0.0", 962 | "on-finished": "~2.3.0", 963 | "on-headers": "~1.0.2" 964 | }, 965 | "engines": { 966 | "node": ">= 0.8.0" 967 | } 968 | }, 969 | "node_modules/morgan/node_modules/on-finished": { 970 | "version": "2.3.0", 971 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 972 | "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", 973 | "dependencies": { 974 | "ee-first": "1.1.1" 975 | }, 976 | "engines": { 977 | "node": ">= 0.8" 978 | } 979 | }, 980 | "node_modules/mpath": { 981 | "version": "0.9.0", 982 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", 983 | "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", 984 | "engines": { 985 | "node": ">=4.0.0" 986 | } 987 | }, 988 | "node_modules/mquery": { 989 | "version": "5.0.0", 990 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", 991 | "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", 992 | "dependencies": { 993 | "debug": "4.x" 994 | }, 995 | "engines": { 996 | "node": ">=14.0.0" 997 | } 998 | }, 999 | "node_modules/mquery/node_modules/debug": { 1000 | "version": "4.3.4", 1001 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1002 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1003 | "dependencies": { 1004 | "ms": "2.1.2" 1005 | }, 1006 | "engines": { 1007 | "node": ">=6.0" 1008 | }, 1009 | "peerDependenciesMeta": { 1010 | "supports-color": { 1011 | "optional": true 1012 | } 1013 | } 1014 | }, 1015 | "node_modules/mquery/node_modules/ms": { 1016 | "version": "2.1.2", 1017 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1018 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1019 | }, 1020 | "node_modules/ms": { 1021 | "version": "2.0.0", 1022 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1023 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1024 | }, 1025 | "node_modules/negotiator": { 1026 | "version": "0.6.3", 1027 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1028 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 1029 | "engines": { 1030 | "node": ">= 0.6" 1031 | } 1032 | }, 1033 | "node_modules/node-addon-api": { 1034 | "version": "5.1.0", 1035 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", 1036 | "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" 1037 | }, 1038 | "node_modules/node-fetch": { 1039 | "version": "2.7.0", 1040 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 1041 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 1042 | "dependencies": { 1043 | "whatwg-url": "^5.0.0" 1044 | }, 1045 | "engines": { 1046 | "node": "4.x || >=6.0.0" 1047 | }, 1048 | "peerDependencies": { 1049 | "encoding": "^0.1.0" 1050 | }, 1051 | "peerDependenciesMeta": { 1052 | "encoding": { 1053 | "optional": true 1054 | } 1055 | } 1056 | }, 1057 | "node_modules/node-fetch/node_modules/tr46": { 1058 | "version": "0.0.3", 1059 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1060 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 1061 | }, 1062 | "node_modules/node-fetch/node_modules/webidl-conversions": { 1063 | "version": "3.0.1", 1064 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1065 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 1066 | }, 1067 | "node_modules/node-fetch/node_modules/whatwg-url": { 1068 | "version": "5.0.0", 1069 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 1070 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 1071 | "dependencies": { 1072 | "tr46": "~0.0.3", 1073 | "webidl-conversions": "^3.0.0" 1074 | } 1075 | }, 1076 | "node_modules/nopt": { 1077 | "version": "5.0.0", 1078 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", 1079 | "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", 1080 | "dependencies": { 1081 | "abbrev": "1" 1082 | }, 1083 | "bin": { 1084 | "nopt": "bin/nopt.js" 1085 | }, 1086 | "engines": { 1087 | "node": ">=6" 1088 | } 1089 | }, 1090 | "node_modules/npmlog": { 1091 | "version": "5.0.1", 1092 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", 1093 | "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", 1094 | "dependencies": { 1095 | "are-we-there-yet": "^2.0.0", 1096 | "console-control-strings": "^1.1.0", 1097 | "gauge": "^3.0.0", 1098 | "set-blocking": "^2.0.0" 1099 | } 1100 | }, 1101 | "node_modules/object-assign": { 1102 | "version": "4.1.1", 1103 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1104 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1105 | "engines": { 1106 | "node": ">=0.10.0" 1107 | } 1108 | }, 1109 | "node_modules/object-inspect": { 1110 | "version": "1.13.1", 1111 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", 1112 | "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", 1113 | "funding": { 1114 | "url": "https://github.com/sponsors/ljharb" 1115 | } 1116 | }, 1117 | "node_modules/on-finished": { 1118 | "version": "2.4.1", 1119 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1120 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1121 | "dependencies": { 1122 | "ee-first": "1.1.1" 1123 | }, 1124 | "engines": { 1125 | "node": ">= 0.8" 1126 | } 1127 | }, 1128 | "node_modules/on-headers": { 1129 | "version": "1.0.2", 1130 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 1131 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", 1132 | "engines": { 1133 | "node": ">= 0.8" 1134 | } 1135 | }, 1136 | "node_modules/once": { 1137 | "version": "1.4.0", 1138 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1139 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1140 | "dependencies": { 1141 | "wrappy": "1" 1142 | } 1143 | }, 1144 | "node_modules/parseurl": { 1145 | "version": "1.3.3", 1146 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1147 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1148 | "engines": { 1149 | "node": ">= 0.8" 1150 | } 1151 | }, 1152 | "node_modules/path-is-absolute": { 1153 | "version": "1.0.1", 1154 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1155 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1156 | "engines": { 1157 | "node": ">=0.10.0" 1158 | } 1159 | }, 1160 | "node_modules/path-to-regexp": { 1161 | "version": "0.1.7", 1162 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1163 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 1164 | }, 1165 | "node_modules/proxy-addr": { 1166 | "version": "2.0.7", 1167 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1168 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1169 | "dependencies": { 1170 | "forwarded": "0.2.0", 1171 | "ipaddr.js": "1.9.1" 1172 | }, 1173 | "engines": { 1174 | "node": ">= 0.10" 1175 | } 1176 | }, 1177 | "node_modules/punycode": { 1178 | "version": "2.3.1", 1179 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 1180 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 1181 | "engines": { 1182 | "node": ">=6" 1183 | } 1184 | }, 1185 | "node_modules/qs": { 1186 | "version": "6.11.0", 1187 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 1188 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 1189 | "dependencies": { 1190 | "side-channel": "^1.0.4" 1191 | }, 1192 | "engines": { 1193 | "node": ">=0.6" 1194 | }, 1195 | "funding": { 1196 | "url": "https://github.com/sponsors/ljharb" 1197 | } 1198 | }, 1199 | "node_modules/range-parser": { 1200 | "version": "1.2.1", 1201 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1202 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1203 | "engines": { 1204 | "node": ">= 0.6" 1205 | } 1206 | }, 1207 | "node_modules/raw-body": { 1208 | "version": "2.5.1", 1209 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1210 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1211 | "dependencies": { 1212 | "bytes": "3.1.2", 1213 | "http-errors": "2.0.0", 1214 | "iconv-lite": "0.4.24", 1215 | "unpipe": "1.0.0" 1216 | }, 1217 | "engines": { 1218 | "node": ">= 0.8" 1219 | } 1220 | }, 1221 | "node_modules/readable-stream": { 1222 | "version": "3.6.2", 1223 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1224 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1225 | "dependencies": { 1226 | "inherits": "^2.0.3", 1227 | "string_decoder": "^1.1.1", 1228 | "util-deprecate": "^1.0.1" 1229 | }, 1230 | "engines": { 1231 | "node": ">= 6" 1232 | } 1233 | }, 1234 | "node_modules/rimraf": { 1235 | "version": "3.0.2", 1236 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1237 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1238 | "dependencies": { 1239 | "glob": "^7.1.3" 1240 | }, 1241 | "bin": { 1242 | "rimraf": "bin.js" 1243 | }, 1244 | "funding": { 1245 | "url": "https://github.com/sponsors/isaacs" 1246 | } 1247 | }, 1248 | "node_modules/safe-buffer": { 1249 | "version": "5.2.1", 1250 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1251 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1252 | "funding": [ 1253 | { 1254 | "type": "github", 1255 | "url": "https://github.com/sponsors/feross" 1256 | }, 1257 | { 1258 | "type": "patreon", 1259 | "url": "https://www.patreon.com/feross" 1260 | }, 1261 | { 1262 | "type": "consulting", 1263 | "url": "https://feross.org/support" 1264 | } 1265 | ] 1266 | }, 1267 | "node_modules/safer-buffer": { 1268 | "version": "2.1.2", 1269 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1270 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1271 | }, 1272 | "node_modules/semver": { 1273 | "version": "7.6.0", 1274 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", 1275 | "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", 1276 | "dependencies": { 1277 | "lru-cache": "^6.0.0" 1278 | }, 1279 | "bin": { 1280 | "semver": "bin/semver.js" 1281 | }, 1282 | "engines": { 1283 | "node": ">=10" 1284 | } 1285 | }, 1286 | "node_modules/send": { 1287 | "version": "0.18.0", 1288 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1289 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1290 | "dependencies": { 1291 | "debug": "2.6.9", 1292 | "depd": "2.0.0", 1293 | "destroy": "1.2.0", 1294 | "encodeurl": "~1.0.2", 1295 | "escape-html": "~1.0.3", 1296 | "etag": "~1.8.1", 1297 | "fresh": "0.5.2", 1298 | "http-errors": "2.0.0", 1299 | "mime": "1.6.0", 1300 | "ms": "2.1.3", 1301 | "on-finished": "2.4.1", 1302 | "range-parser": "~1.2.1", 1303 | "statuses": "2.0.1" 1304 | }, 1305 | "engines": { 1306 | "node": ">= 0.8.0" 1307 | } 1308 | }, 1309 | "node_modules/send/node_modules/ms": { 1310 | "version": "2.1.3", 1311 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1312 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1313 | }, 1314 | "node_modules/serve-static": { 1315 | "version": "1.15.0", 1316 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1317 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1318 | "dependencies": { 1319 | "encodeurl": "~1.0.2", 1320 | "escape-html": "~1.0.3", 1321 | "parseurl": "~1.3.3", 1322 | "send": "0.18.0" 1323 | }, 1324 | "engines": { 1325 | "node": ">= 0.8.0" 1326 | } 1327 | }, 1328 | "node_modules/set-blocking": { 1329 | "version": "2.0.0", 1330 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1331 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" 1332 | }, 1333 | "node_modules/set-function-length": { 1334 | "version": "1.2.1", 1335 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", 1336 | "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", 1337 | "dependencies": { 1338 | "define-data-property": "^1.1.2", 1339 | "es-errors": "^1.3.0", 1340 | "function-bind": "^1.1.2", 1341 | "get-intrinsic": "^1.2.3", 1342 | "gopd": "^1.0.1", 1343 | "has-property-descriptors": "^1.0.1" 1344 | }, 1345 | "engines": { 1346 | "node": ">= 0.4" 1347 | } 1348 | }, 1349 | "node_modules/setprototypeof": { 1350 | "version": "1.2.0", 1351 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1352 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1353 | }, 1354 | "node_modules/side-channel": { 1355 | "version": "1.0.5", 1356 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", 1357 | "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", 1358 | "dependencies": { 1359 | "call-bind": "^1.0.6", 1360 | "es-errors": "^1.3.0", 1361 | "get-intrinsic": "^1.2.4", 1362 | "object-inspect": "^1.13.1" 1363 | }, 1364 | "engines": { 1365 | "node": ">= 0.4" 1366 | }, 1367 | "funding": { 1368 | "url": "https://github.com/sponsors/ljharb" 1369 | } 1370 | }, 1371 | "node_modules/sift": { 1372 | "version": "16.0.1", 1373 | "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", 1374 | "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" 1375 | }, 1376 | "node_modules/signal-exit": { 1377 | "version": "3.0.7", 1378 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 1379 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 1380 | }, 1381 | "node_modules/sparse-bitfield": { 1382 | "version": "3.0.3", 1383 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 1384 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", 1385 | "dependencies": { 1386 | "memory-pager": "^1.0.2" 1387 | } 1388 | }, 1389 | "node_modules/statuses": { 1390 | "version": "2.0.1", 1391 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1392 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1393 | "engines": { 1394 | "node": ">= 0.8" 1395 | } 1396 | }, 1397 | "node_modules/string_decoder": { 1398 | "version": "1.3.0", 1399 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1400 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1401 | "dependencies": { 1402 | "safe-buffer": "~5.2.0" 1403 | } 1404 | }, 1405 | "node_modules/string-width": { 1406 | "version": "4.2.3", 1407 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1408 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1409 | "dependencies": { 1410 | "emoji-regex": "^8.0.0", 1411 | "is-fullwidth-code-point": "^3.0.0", 1412 | "strip-ansi": "^6.0.1" 1413 | }, 1414 | "engines": { 1415 | "node": ">=8" 1416 | } 1417 | }, 1418 | "node_modules/strip-ansi": { 1419 | "version": "6.0.1", 1420 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1421 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1422 | "dependencies": { 1423 | "ansi-regex": "^5.0.1" 1424 | }, 1425 | "engines": { 1426 | "node": ">=8" 1427 | } 1428 | }, 1429 | "node_modules/tar": { 1430 | "version": "6.2.0", 1431 | "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", 1432 | "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", 1433 | "dependencies": { 1434 | "chownr": "^2.0.0", 1435 | "fs-minipass": "^2.0.0", 1436 | "minipass": "^5.0.0", 1437 | "minizlib": "^2.1.1", 1438 | "mkdirp": "^1.0.3", 1439 | "yallist": "^4.0.0" 1440 | }, 1441 | "engines": { 1442 | "node": ">=10" 1443 | } 1444 | }, 1445 | "node_modules/toidentifier": { 1446 | "version": "1.0.1", 1447 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1448 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1449 | "engines": { 1450 | "node": ">=0.6" 1451 | } 1452 | }, 1453 | "node_modules/tr46": { 1454 | "version": "4.1.1", 1455 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", 1456 | "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", 1457 | "dependencies": { 1458 | "punycode": "^2.3.0" 1459 | }, 1460 | "engines": { 1461 | "node": ">=14" 1462 | } 1463 | }, 1464 | "node_modules/type-is": { 1465 | "version": "1.6.18", 1466 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1467 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1468 | "dependencies": { 1469 | "media-typer": "0.3.0", 1470 | "mime-types": "~2.1.24" 1471 | }, 1472 | "engines": { 1473 | "node": ">= 0.6" 1474 | } 1475 | }, 1476 | "node_modules/unpipe": { 1477 | "version": "1.0.0", 1478 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1479 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1480 | "engines": { 1481 | "node": ">= 0.8" 1482 | } 1483 | }, 1484 | "node_modules/util-deprecate": { 1485 | "version": "1.0.2", 1486 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1487 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1488 | }, 1489 | "node_modules/utils-merge": { 1490 | "version": "1.0.1", 1491 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1492 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 1493 | "engines": { 1494 | "node": ">= 0.4.0" 1495 | } 1496 | }, 1497 | "node_modules/vary": { 1498 | "version": "1.1.2", 1499 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1500 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1501 | "engines": { 1502 | "node": ">= 0.8" 1503 | } 1504 | }, 1505 | "node_modules/webidl-conversions": { 1506 | "version": "7.0.0", 1507 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 1508 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", 1509 | "engines": { 1510 | "node": ">=12" 1511 | } 1512 | }, 1513 | "node_modules/whatwg-url": { 1514 | "version": "13.0.0", 1515 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", 1516 | "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", 1517 | "dependencies": { 1518 | "tr46": "^4.1.1", 1519 | "webidl-conversions": "^7.0.0" 1520 | }, 1521 | "engines": { 1522 | "node": ">=16" 1523 | } 1524 | }, 1525 | "node_modules/wide-align": { 1526 | "version": "1.1.5", 1527 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", 1528 | "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", 1529 | "dependencies": { 1530 | "string-width": "^1.0.2 || 2 || 3 || 4" 1531 | } 1532 | }, 1533 | "node_modules/wrappy": { 1534 | "version": "1.0.2", 1535 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1536 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1537 | }, 1538 | "node_modules/yallist": { 1539 | "version": "4.0.0", 1540 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1541 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1542 | } 1543 | } 1544 | } 1545 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "node index.js", 10 | "dev": "nodemon index.js" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "bcrypt": "^5.1.1", 17 | "cors": "^2.8.5", 18 | "dotenv": "^16.4.1", 19 | "express": "^4.18.2", 20 | "mongoose": "^8.1.1", 21 | "morgan": "^1.10.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /routes/comments.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | 3 | //importing model 4 | import Comment from "../models/comments.js"; 5 | import Post from "../models/posts.js"; 6 | 7 | const router = new Router(); 8 | 9 | // GET comments 10 | router.get("/", async (req, res) => { 11 | try { 12 | const comments = await Comment.find({}); 13 | res.send(comments); 14 | } catch (error) { 15 | res 16 | .status(404) 17 | .json({ msg: "something went wrong", errormsg: error.message }); 18 | } 19 | }); 20 | 21 | // GET 1 comment 22 | router.get("/:id", async (req, res) => { 23 | try { 24 | const comment = await Comment.findById(req.params.id); 25 | res.send(comment); 26 | } catch (error) { 27 | res 28 | .status(404) 29 | .json({ msg: "something went wrong", errormsg: error.message }); 30 | } 31 | }); 32 | 33 | router.get("/post/:post_id", async (req, res) => { 34 | try { 35 | const postComments = await Comment.find({post_id: req.params.post_id}).populate('user_id'); 36 | res.send(postComments); 37 | } catch (error) { 38 | res 39 | .status(404) 40 | .json({ msg: "something went wrong", errormsg: error.message }); 41 | } 42 | }); 43 | 44 | // POST (create) new comment 45 | router.post("/", async (req, res) => { 46 | try { 47 | const newComment = await Comment.create(req.body); 48 | const post = await Post.findById(req.body.post_id); 49 | if (post) { 50 | post.post_comments.push({ comment_id: newComment._id }); 51 | await post.save(); 52 | } 53 | res.status(201).send(newComment); 54 | } catch (error) { 55 | res 56 | .status(404) 57 | .json({ msg: "something went wrong", errormsg: error.message }); 58 | } 59 | }); 60 | 61 | // PUT add user to like array (so the ui can show differently) 62 | router.put("/:id/like", async (req, res) => { 63 | try { 64 | const comment = await Comment.findById(req.params.id).populate('user_id'); 65 | if (comment) { 66 | comment.comment_like.push(req.body); 67 | await comment.save(); 68 | return res.send({ msg: "user like the comment" , comment}); 69 | } 70 | } catch (error) { 71 | res 72 | .status(404) 73 | .json({ msg: "something went wrong", errormsg: error.message }); 74 | } 75 | }); 76 | // PUT remove user from like array (unlike) 77 | router.put("/:id/unlike", async (req, res) => { 78 | try { 79 | const comment = await Comment.findById(req.params.id).populate('user_id'); 80 | if (comment) { 81 | comment.comment_like.pull(req.body); 82 | await comment.save(); 83 | return res.send({ msg: "user unlike the comment", comment }); 84 | } 85 | } catch (error) { 86 | res 87 | .status(404) 88 | .json({ msg: "something went wrong", errormsg: error.message }); 89 | } 90 | }); 91 | 92 | // DELETE comment 93 | router.delete("/:id", async (req, res) => { 94 | try { 95 | // find comment to find post_id 96 | const comment = await Comment.findById(req.params.id); 97 | 98 | //find post 99 | const post = await Post.findById(comment.post_id); 100 | // delete the comment from the array 101 | post.post_comments.pull({ comment_id: req.params.id }); 102 | await post.save(); 103 | 104 | // delete comment from database 105 | const deleteComment = await Comment.findByIdAndDelete(req.params.id); 106 | res.json({ msg: "comment deleted", deleteComment }); 107 | } catch (error) { 108 | res 109 | .status(404) 110 | .json({ msg: "something went wrong", errormsg: error.message }); 111 | } 112 | }); 113 | export default router; 114 | -------------------------------------------------------------------------------- /routes/posts.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | 3 | //importing model 4 | import Post from "../models/posts.js"; 5 | 6 | const router = new Router(); 7 | 8 | // GET all posts 9 | router.get("/", async (req, res) => { 10 | try { 11 | const posts = await Post.find({}).sort({createdAt: -1}).populate("user_id").populate('post_comments.comment_id'); 12 | res.status(200).send(posts); 13 | } catch (error) { 14 | res 15 | .status(404) 16 | .json({ msg: "something went wrong", errormsg: error.message }); 17 | } 18 | }); 19 | 20 | // GET 1 post 21 | router.get("/:id", async (req, res) => { 22 | try { 23 | const post = await Post.findById(req.params.id).populate('user_id').populate('post_comments.comment_id'); 24 | // if get post then increase the view by one 25 | if (!post) return res.send("post not found"); 26 | 27 | post.post_views++; 28 | await post.save(); 29 | res.send(post); 30 | } catch (error) { 31 | res 32 | .status(404) 33 | .json({ msg: "something went wrong", errormsg: error.message }); 34 | } 35 | }); 36 | 37 | // POST (create) a new post 38 | router.post("/", async (req, res) => { 39 | try { 40 | const newPost = await Post.create(req.body); 41 | res.status(201).send(newPost); 42 | } catch (error) { 43 | res 44 | .status(404) 45 | .json({ msg: "something went wrong", errormsg: error.message }); 46 | } 47 | }); 48 | 49 | // PUT (update) post if they are updating more than 1 item in the post 50 | router.put("/:id", async (req, res) => { 51 | try { 52 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 53 | new: true, 54 | }); 55 | res.status(200).send(post); 56 | } catch (error) { 57 | res 58 | .status(404) 59 | .json({ msg: "something went wrong", errormsg: error.message }); 60 | } 61 | }); 62 | 63 | // PUT (update) post's content 64 | router.put("/:id/update_content", async (req, res) => { 65 | try { 66 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 67 | new: true, 68 | }); 69 | res.status(200).send(post); 70 | } catch (error) { 71 | res 72 | .status(404) 73 | .json({ msg: "something went wrong", errormsg: error.message }); 74 | } 75 | }); 76 | // PUT (update) post's content's text 77 | router.put("/:id/update_content_text", async (req, res) => { 78 | try { 79 | // find post 80 | const post = await Post.findById(req.params.id); 81 | 82 | // update post 83 | post.post_content.text = req.body.text; 84 | post.save(); 85 | 86 | // send final result 87 | res.status(200).send(post); 88 | } catch (error) { 89 | res 90 | .status(404) 91 | .json({ msg: "something went wrong", errormsg: error.message }); 92 | } 93 | }); 94 | 95 | // PUT (update) post's content 96 | router.put("/:id/update_content_img", async (req, res) => { 97 | try { 98 | // find post 99 | const post = await Post.findById(req.params.id); 100 | 101 | // update post 102 | post.post_content.img = req.body.img; 103 | post.save(); 104 | 105 | // send final result 106 | res.status(200).send(post); 107 | } catch (error) { 108 | res 109 | .status(404) 110 | .json({ msg: "something went wrong", errormsg: error.message }); 111 | } 112 | }); 113 | 114 | // PUT (update) post's title 115 | router.put("/:id/update_title", async (req, res) => { 116 | try { 117 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 118 | new: true, 119 | }); 120 | res.status(200).send(post); 121 | } catch (error) { 122 | res 123 | .status(404) 124 | .json({ msg: "something went wrong", errormsg: error.message }); 125 | } 126 | }); 127 | 128 | // PUT (update) post's hashtag 129 | router.put("/:id/update_hashtag", async (req, res) => { 130 | try { 131 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 132 | new: true, 133 | }); 134 | res.status(200).send(post); 135 | } catch (error) { 136 | res 137 | .status(404) 138 | .json({ msg: "something went wrong", errormsg: error.message }); 139 | } 140 | }); 141 | 142 | // PUT add user to like array (so the ui can show differently) 143 | router.put("/:id/like", async (req, res) => { 144 | try { 145 | const post = await Post.findById(req.params.id).populate('user_id'); 146 | if (post) { 147 | post.post_likes.push(req.body); 148 | await post.save(); 149 | return res.send({ msg: "user like the post", post }); 150 | } 151 | } catch (error) { 152 | res 153 | .status(404) 154 | .json({ msg: "something went wrong", errormsg: error.message }); 155 | } 156 | }); 157 | 158 | // PUT remove user from like array (unlike) 159 | router.put("/:id/unlike", async (req, res) => { 160 | try { 161 | const post = await Post.findById(req.params.id).populate('user_id'); 162 | if (post) { 163 | post.post_likes.pull(req.body); 164 | await post.save(); 165 | return res.send({ msg: "user unlike the post",post }); 166 | } 167 | } catch (error) { 168 | res 169 | .status(404) 170 | .json({ msg: "something went wrong", errormsg: error.message }); 171 | } 172 | }); 173 | // DELETE post 174 | router.delete("/:id/", async (req, res) => { 175 | try { 176 | const deletePost = await Post.findByIdAndDelete(req.params.id); 177 | res.json({ msg: "post deleted", deletePost }); 178 | } catch (error) { 179 | res 180 | .status(404) 181 | .json({ msg: "something went wrong", errormsg: error.message }); 182 | } 183 | }); 184 | export default router; 185 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import bcrypt from "bcrypt"; 3 | 4 | //importing model 5 | import User from "../models/users.js"; 6 | 7 | const SALT_ROUNDS = 8; 8 | 9 | const router = new Router(); 10 | 11 | // GET all users 12 | router.get("/", async (req, res) => { 13 | try { 14 | const users = await User.find({}); 15 | res.status(200).send(users); 16 | } catch (error) { 17 | res 18 | .status(404) 19 | .json({ msg: "something went wrong", errormsg: error.message }); 20 | } 21 | }); 22 | 23 | router.put("/login", async (req, res) => { 24 | try { 25 | // try to find user by email or username 26 | const user = await User.findOne({ 27 | $or: [{ username: req.body.emailOrUsername }, { email: req.body.emailOrUsername }], 28 | }); 29 | 30 | // tell user if the email or username not found in the system 31 | if (!user) return res.status(404).send("Can't find email or username in system"); 32 | 33 | // check if password match with user info 34 | const passwordMatched = await bcrypt.compare( 35 | req.body.password, // plaintext password 36 | user.password // hash password 37 | ); 38 | if (!passwordMatched) { 39 | return res.status(401).send("Password doesn't match"); 40 | } 41 | 42 | // log in if it is success 43 | console.log("password matched!"); 44 | res.json(user); 45 | } catch (error) { 46 | res 47 | .status(404) 48 | .json({ msg: "something went wrong", errormsg: error.message }); 49 | } 50 | }); 51 | 52 | // GET single user 53 | router.get("/:id", async (req, res) => { 54 | try { 55 | const user = await User.findById(req.params.id); 56 | if (!user) return res.send("can't find user"); 57 | res.send(user); 58 | } catch (error) { 59 | res 60 | .status(404) 61 | .json({ msg: "something went wrong", errormsg: error.message }); 62 | } 63 | }); 64 | 65 | // POST (create) new user 66 | router.post("/", async (req, res) => { 67 | try { 68 | if (await User.findOne({ username: req.body.username })) 69 | return res.status(404).send("Username already in use"); 70 | if (await User.findOne({ email: req.body.email })) 71 | return res.status(404).send("Email already in use"); 72 | const user = await User.create(req.body); 73 | res.status(201).json(user); 74 | } catch (error) { 75 | res 76 | .status(404) 77 | .json({ msg: "something went wrong", errormsg: error.message }); 78 | } 79 | }); 80 | 81 | // PUT (update) user's profile pic 82 | router.put("/:id/update-profile-pic", async (req, res) => { 83 | try { 84 | const updateUserProfilePic = await User.findByIdAndUpdate( 85 | req.params.id, 86 | req.body, 87 | { 88 | new: true, 89 | } 90 | ); 91 | res.send(updateUserProfilePic); 92 | } catch (error) { 93 | res 94 | .status(404) 95 | .json({ msg: "something went wrong", errormsg: error.message }); 96 | } 97 | }); 98 | 99 | // PUT (update) user's username 100 | router.put("/:id/update-username/", async (req, res) => { 101 | try { 102 | const updateUserProfilePic = await User.findByIdAndUpdate( 103 | req.params.id, 104 | req.body, 105 | { 106 | new: true, 107 | } 108 | ); 109 | res.send(updateUserProfilePic); 110 | } catch (error) { 111 | res 112 | .status(404) 113 | .json({ msg: "something went wrong", errormsg: error.message }); 114 | } 115 | }); 116 | 117 | // PUT (update) user's email 118 | router.put("/:id/update-email/", async (req, res) => { 119 | try { 120 | const updateUserUsername = await User.findByIdAndUpdate( 121 | req.params.id, 122 | req.body, 123 | { 124 | new: true, 125 | } 126 | ); 127 | res.send(updateUserUsername); 128 | } catch (error) { 129 | res 130 | .status(404) 131 | .json({ msg: "something went wrong", errormsg: error.message }); 132 | } 133 | }); 134 | 135 | // PUT (update) user's password 136 | // code from Abraham Tavarez 137 | // https://github.com/AbeTavarez/cohort107/blob/main/nodejs/mongoose-api/backend/routes/users.js 138 | router.put("/:id/update-password", async (req, res) => { 139 | try { 140 | const { id } = req.params; 141 | const { currentPassword, newPassword } = req.body; 142 | 143 | // find the user to update 144 | const user = await User.findById(id); 145 | if (!user) return res.status(404).json({ msg: "User not found!" }); 146 | 147 | // verify the old password with the password hash in db 148 | const passwordMatched = await bcrypt.compare( 149 | currentPassword, 150 | user.password 151 | ); 152 | if (!passwordMatched) { 153 | return res.status(401).json({ msg: "Authentication Error" }); 154 | } 155 | 156 | console.log("password matched!"); 157 | 158 | // hash the new password 159 | const hashedPassword = await bcrypt.hash(newPassword, SALT_ROUNDS); 160 | 161 | // set the old password hash to the newPassword hash 162 | await User.findByIdAndUpdate(id, { password: hashedPassword }); 163 | 164 | res.json({ msg: "User password updated", user }); 165 | } catch (error) { 166 | console.log(error); 167 | } 168 | }); 169 | 170 | // DELETE user 171 | router.delete("/:id/", async (req, res) => { 172 | try { 173 | const deleteUser = await User.findByIdAndDelete(req.params.id); 174 | res.json({ msg: "user deleted", deleteUser }); 175 | } catch (error) { 176 | res 177 | .status(404) 178 | .json({ msg: "something went wrong", errormsg: error.message }); 179 | } 180 | }); 181 | 182 | export default router; 183 | --------------------------------------------------------------------------------