From 7dc300e614ed3863f502f854a82e105949ac3fdd Mon Sep 17 00:00:00 2001 From: Konrad Konik <88903994+KonradKinok@users.noreply.github.com> Date: Wed, 8 Jan 2025 18:09:17 +0100 Subject: [PATCH 1/7] KonradKonik08.01.2024 --- .eslintrc.js | 17 +++++- app.js | 56 ++++++++++++------ models/contacts.js | 102 +++++++++++++++++++++++++++++---- models/contacts.json | 50 +++++++++++----- package-lock.json | 126 ++++++++++++++++++++++++++++++++++++++++- package.json | 6 +- routes/api/contacts.js | 100 ++++++++++++++++++++++++++------ server.js | 8 +-- 8 files changed, 397 insertions(+), 68 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d7993327f51..81a86722ddc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,9 +4,20 @@ module.exports = { es2021: true, node: true, }, - extends: ['standard', 'prettier'], + extends: ["standard", "prettier"], parserOptions: { ecmaVersion: 12, }, - rules: {}, -} + rules: { + "no-unused-vars": [ + "error", + { + vars: "all", + args: "after-used", + caughtErrors: "all", + ignoreRestSiblings: false, + reportUsedIgnorePattern: false, + }, + ], + }, +}; diff --git a/app.js b/app.js index 40fd9bc167f..d8144d4177d 100644 --- a/app.js +++ b/app.js @@ -1,25 +1,49 @@ -const express = require('express') -const logger = require('morgan') -const cors = require('cors') +import express from "express"; +import logger from "morgan"; +import cors from "cors"; +import colors from "colors"; +import { contactsRouter } from "./routes/api/contacts.js"; -const contactsRouter = require('./routes/api/contacts') +const app = express(); -const app = express() +const formatsLogger = app.get("env") === "development" ? "dev" : "short"; +const logger1 = (req, res, next) => { + const { method, originalUrl } = req; -const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short' + const date = new Date().toLocaleString(); + console.log(`[${date}] [${method}] - ${originalUrl} `.yellow); -app.use(logger(formatsLogger)) -app.use(cors()) -app.use(express.json()) + next(); +}; -app.use('/api/contacts', contactsRouter) +app.use(logger1); +app.use(logger(formatsLogger)); +app.use(cors()); +app.use(express.json()); + +app.use("/api/contacts", contactsRouter); app.use((req, res) => { - res.status(404).json({ message: 'Not found' }) -}) + res.status(404).json({ message: "Not found" }); +}); app.use((err, req, res, next) => { - res.status(500).json({ message: err.message }) -}) - -module.exports = app + res.status(500).json({ message: err.message }); +}); + +export const startServer = (port) => { + app + .listen(port, () => { + console.log(`[server] Server running on port ${port}`.bgWhite); + }) + .on("error", (err) => { + if (err.code === "EADDRINUSE") { + console.log( + `Port ${port} is already in use. Trying a different port...`.red + ); + startServer(port + 1); + } else { + console.error(err); + } + }); +}; diff --git a/models/contacts.js b/models/contacts.js index 409d11c7c09..73bdfb4e5e4 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -1,19 +1,97 @@ -// const fs = require('fs/promises') +import fs from "node:fs"; +import path from "node:path"; +import { nanoid } from "nanoid"; +const dirName = import.meta.dirname; +const contactsPath = path.join(dirName, "/contacts.json"); -const listContacts = async () => {} +export const listContacts = async (filePath = contactsPath) => { + try { + const fileContent = await fs.promises.readFile(filePath, "utf-8"); + console.log(`Contacts reading from ${filePath}`.bgGreen); + return JSON.parse(fileContent); + } catch (error) { + if (error.code === "ENOENT") { + console.error(`File not found: ${filePath}`.bgRed); + } else { + console.error(`Error reading file: ${filePath}`.bgRed); + } + } +}; -const getContactById = async (contactId) => {} +export const getContactById = async (contactId) => { + try { + const contacts = await listContacts(); + const findedContact = contacts.find((contact) => contact.id === contactId); -const removeContact = async (contactId) => {} + if (!findedContact) { + return console.error(`Contact with ID: ${contactId} not found`.bgYellow); + } + return findedContact; + } catch (error) { + console.error(`Error getContactById: ${error}`.bgRed); + } +}; -const addContact = async (body) => {} +export const removeContact = async (contactId) => { + try { + const contacts = await listContacts(); + const findedContact = contacts.find((contact) => contact.id === contactId); -const updateContact = async (contactId, body) => {} + if (findedContact) { + const updatedContacts = contacts.filter( + (contact) => contact.id !== contactId + ); + await writeContactsToFile(updatedContacts); + } + return findedContact; + } catch (error) { + console.error(`Error remove contact: ${error}`.bgRed); + } +}; -module.exports = { - listContacts, - getContactById, - removeContact, - addContact, - updateContact, +export const addContact = async (body) => { + try { + const { name, email, phone } = body; + const contact = { id: nanoid(), name, email, phone }; + const contacts = await listContacts(); + contacts.push(contact); + await writeContactsToFile(contacts); + return contact; + } catch (error) { + console.error(`Error addContact: ${error}`.bgRed); + } +}; + +export const updateContact = async (contactId, body) => { + try { + const contacts = await listContacts(); + + const contactIndex = contacts.findIndex( + (contact) => contact.id === contactId + ); + + if (contactIndex === -1) { + console.error(`Contact with ID: ${contactId} not found`.bgYellow); + return null; + } + + const updatedContact = { ...contacts[contactIndex], ...body }; + contacts[contactIndex] = updatedContact; + + await writeContactsToFile(contacts); + console.log(`Contact with ID: ${contactId} updated successfully`.bgGreen); + + return updatedContact; + } catch (error) { + console.error(`Error updateContact: ${error}`.bgRed); + } +}; + +export async function writeContactsToFile(contacts, filePath = contactsPath) { + try { + await fs.promises.writeFile(filePath, JSON.stringify(contacts, null, 2)); + console.log(`Contacts saved to ${filePath}`); + } catch (error) { + throw new Error(`Error writing file: ${filePath}`); + } } diff --git a/models/contacts.json b/models/contacts.json index a21679132de..2c63431e2e8 100644 --- a/models/contacts.json +++ b/models/contacts.json @@ -1,16 +1,4 @@ [ - { - "id": "AeHIrLTr6JkxGE6SN-0Rw", - "name": "Allen Raymond", - "email": "nulla.ante@vestibul.co.uk", - "phone": "(992) 914-3792" - }, - { - "id": "qdggE76Jtbfd9eWJHrssH", - "name": "Chaim Lewis", - "email": "dui.in@egetlacus.ca", - "phone": "(294) 840-6685" - }, { "id": "drsAJ4SHPYqZeG-83QTVW", "name": "Kennedy Lane", @@ -58,5 +46,41 @@ "name": "Alec Howard", "email": "Donec.elementum@scelerisquescelerisquedui.net", "phone": "(748) 206-2688" + }, + { + "id": "YnTKMpTLNlbGtcMctbNS7", + "name": "Konrad", + "email": "konrad@gmail.com", + "phone": "989768567" + }, + { + "id": "Q9vm2DblpJShAv_MiTlUd", + "name": "Konrad", + "email": "konrad@gmail.com", + "phone": "989768567" + }, + { + "id": "BeWfJy-GwNiwFD6lZRKlY", + "name": "Marek", + "email": "Marek@gmail.com", + "phone": "11111111" + }, + { + "id": "riGNx7-zRKH5-KpXuOGXZ", + "name": "Marek", + "email": "Marek@gmail.com", + "phone": "11111111" + }, + { + "id": "GAnDHrMb330ggG5OFNHJa", + "name": "Konrad", + "email": "konrad@gmail.com", + "phone": "" + }, + { + "id": "nhVatiBoPPUbcZlk-oazU", + "name": "Konrad", + "email": "konrad@gmail.com", + "phone": "989768567" } -] +] \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e6d047044e5..f50e39073f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,13 @@ "name": "template", "version": "0.0.0", "dependencies": { + "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", "express": "4.17.1", - "morgan": "1.10.0" + "joi": "^17.13.3", + "morgan": "1.10.0", + "nanoid": "^5.0.9" }, "devDependencies": { "eslint": "7.19.0", @@ -141,6 +144,37 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -618,6 +652,14 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2166,6 +2208,18 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2439,6 +2493,23 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/nanoid": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", + "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3757,6 +3828,37 @@ "strip-json-comments": "^3.1.1" } }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -4118,6 +4220,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5269,6 +5376,18 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "requires": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5486,6 +5605,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "nanoid": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", + "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", diff --git a/package.json b/package.json index 5045e827160..43116662dbc 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "template", "version": "0.0.0", "private": true, + "type": "module", "scripts": { "start": "cross-env NODE_ENV=production node ./server.js", "start:dev": "cross-env NODE_ENV=development nodemon ./server.js", @@ -9,10 +10,13 @@ "lint:fix": "eslint --fix **/*.js" }, "dependencies": { + "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", "express": "4.17.1", - "morgan": "1.10.0" + "joi": "^17.13.3", + "morgan": "1.10.0", + "nanoid": "^5.0.9" }, "devDependencies": { "eslint": "7.19.0", diff --git a/routes/api/contacts.js b/routes/api/contacts.js index a60ebd69231..ce857bfe45d 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,25 +1,89 @@ -const express = require('express') +import { Router } from "express"; +import Joi from "joi"; +import * as ContactsModels from "../../models/contacts.js"; -const router = express.Router() +const contactSchema = Joi.object({ + name: Joi.string() + .pattern(/^[a-zA-Z\s]+$/) // Pattern: tylko litery i spacje + .required() + .messages({ + "any.required": "missing required name field", + "string.empty": "missing required name field", + "string.pattern.base": "name must contain only letters and spaces", + }), + email: Joi.string() + .email() // Walidacja adresu e-mail + .required() + .messages({ + "any.required": "missing required email field", + "string.empty": "missing required email field", + "string.email": "email must be a valid email address", + }), + phone: Joi.string() + .pattern(/^\d+$/) // Pattern: cyfry, spacje, opcjonalnie + + .required() + .messages({ + "any.required": "missing required phone field", + "string.empty": "missing required phone field", + "string.pattern.base": "phone must contain only numbers", + }), +}); -router.get('/', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +const router = Router(); -router.get('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.get("/", async (req, res, next) => { + const contactsList = await ContactsModels.listContacts(); + return res.status(200).json(contactsList); +}); -router.post('/', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.get("/:contactId", async (req, res, next) => { + const { contactId } = req.params; + const searchedContactById = await ContactsModels.getContactById(contactId); + if (searchedContactById) return res.status(200).json(searchedContactById); -router.delete('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) + return res.status(404).json({ message: "Not found" }); +}); -router.put('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.post("/", async (req, res, next) => { + const { error } = contactSchema.validate(req.body); + if (error) { + const message = error.details[0].message; + return res.status(400).json({ message }); + } -module.exports = router + const { name, email, phone } = req.body; + + const newContact = await ContactsModels.addContact({ name, email, phone }); + return res.status(201).json(newContact); +}); + +router.delete("/:contactId", async (req, res, next) => { + const { contactId } = req.params; + const contactDelete = await ContactsModels.removeContact(contactId); + + if (contactDelete) + return res.status(200).json({ message: "contact deleted" }); + + return res.status(404).json({ message: "Not found" }); +}); + +router.put("/:contactId", async (req, res, next) => { + const { contactId } = req.params; + const { error } = contactSchema.validate(req.body); + if (!req.body) { + return res.status(400).json({ message: "missing fields" }); + } + if (error) { + const message = error.details[0].message; + return res.status(404).json({ message }); + } + + const updatedContact = await ContactsModels.updateContact( + contactId, + req.body + ); + if (!updatedContact) return res.status(404).json({ message: "Not found" }); + return res.status(200).json(updatedContact); +}); + +export const contactsRouter = router; diff --git a/server.js b/server.js index db330824656..fe78a9bed4b 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,5 @@ -const app = require('./app') +import { startServer } from "./app.js"; -app.listen(3000, () => { - console.log("Server running. Use our API on port: 3000") -}) +const PORT = 3000; + +startServer(PORT); From 19ca9647b01634386a6e2d720feb85edf7d8b63a Mon Sep 17 00:00:00 2001 From: Konrad Konik <88903994+KonradKinok@users.noreply.github.com> Date: Fri, 17 Jan 2025 19:06:17 +0100 Subject: [PATCH 2/7] 17.01.2025 --- app.js | 1 + models/contactShemaMongoose.js | 26 ++ models/contacts.js | 126 +++--- models/contacts.json | 6 + models/dbConnection.js | 42 ++ package-lock.json | 768 ++++++++++++++++++++++++++++++++- package.json | 4 + routes/api/contacts.js | 59 ++- server.js | 4 +- 9 files changed, 950 insertions(+), 86 deletions(-) create mode 100644 models/contactShemaMongoose.js create mode 100644 models/dbConnection.js diff --git a/app.js b/app.js index d8144d4177d..0e58f183c7a 100644 --- a/app.js +++ b/app.js @@ -35,6 +35,7 @@ export const startServer = (port) => { app .listen(port, () => { console.log(`[server] Server running on port ${port}`.bgWhite); + console.log(`[server] http://localhost:${port}/api/contacts/ `.bgWhite); }) .on("error", (err) => { if (err.code === "EADDRINUSE") { diff --git a/models/contactShemaMongoose.js b/models/contactShemaMongoose.js new file mode 100644 index 00000000000..4bccf30871d --- /dev/null +++ b/models/contactShemaMongoose.js @@ -0,0 +1,26 @@ +import mongoose from "mongoose"; + +// Definiowanie schematu dla kontaktów +const contactSchema = new mongoose.Schema({ + name: { + type: String, + required: [true, "Set name for contact"], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, +}); + +// Tworzenie modelu na podstawie schematu +export const ContactModel = mongoose.model( + "Contact", + contactSchema, + "contacts" +); diff --git a/models/contacts.js b/models/contacts.js index 73bdfb4e5e4..16df0195503 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -1,61 +1,70 @@ -import fs from "node:fs"; -import path from "node:path"; +import mongoose from "mongoose"; import { nanoid } from "nanoid"; -const dirName = import.meta.dirname; -const contactsPath = path.join(dirName, "/contacts.json"); +import { ContactModel } from "../models/contactShemaMongoose.js"; -export const listContacts = async (filePath = contactsPath) => { +export const listContacts = async () => { try { - const fileContent = await fs.promises.readFile(filePath, "utf-8"); - console.log(`Contacts reading from ${filePath}`.bgGreen); - return JSON.parse(fileContent); + const contacts = await ContactModel.find({}); + console.log("Contacts fetched successfully".bgGreen); + return contacts; } catch (error) { - if (error.code === "ENOENT") { - console.error(`File not found: ${filePath}`.bgRed); - } else { - console.error(`Error reading file: ${filePath}`.bgRed); - } + console.error(`[DB] Error fetching contacts: ${error.message}`.red); + throw new Error("Error fetching contacts from the database"); } }; export const getContactById = async (contactId) => { try { - const contacts = await listContacts(); - const findedContact = contacts.find((contact) => contact.id === contactId); + if (!mongoose.Types.ObjectId.isValid(contactId)) { + console.error(`Invalid ID format: ${contactId}`.bgYellow); + return null; + } + + const contact = await ContactModel.findById(contactId); - if (!findedContact) { - return console.error(`Contact with ID: ${contactId} not found`.bgYellow); + if (!contact) { + console.error(`Contact with ID: ${contactId} not found`.bgYellow); + return null; } - return findedContact; + + return contact; } catch (error) { - console.error(`Error getContactById: ${error}`.bgRed); + console.error(`Error getContactById: ${error.message}`.bgRed); + throw new Error(`Unable to fetch contact by ID: ${contactId}`); } }; export const removeContact = async (contactId) => { try { - const contacts = await listContacts(); - const findedContact = contacts.find((contact) => contact.id === contactId); - - if (findedContact) { - const updatedContacts = contacts.filter( - (contact) => contact.id !== contactId - ); - await writeContactsToFile(updatedContacts); + const removedContact = await ContactModel.findByIdAndDelete(contactId); + + if (!removedContact) { + console.error(`Contact with ID: ${contactId} not found`.bgYellow); + return null; } - return findedContact; + + console.log(`Contact with ID: ${contactId} removed successfully`.bgGreen); + return removedContact; } catch (error) { - console.error(`Error remove contact: ${error}`.bgRed); + console.error(`Error removing contact: ${error}`.bgRed); + return null; } }; export const addContact = async (body) => { try { - const { name, email, phone } = body; - const contact = { id: nanoid(), name, email, phone }; - const contacts = await listContacts(); - contacts.push(contact); - await writeContactsToFile(contacts); + const { name, email, phone, favorite } = body; + + const contact = new ContactModel({ + id: nanoid(), + name, + email, + phone, + favorite: favorite || false, + }); + + await contact.save(); + return contact; } catch (error) { console.error(`Error addContact: ${error}`.bgRed); @@ -64,34 +73,47 @@ export const addContact = async (body) => { export const updateContact = async (contactId, body) => { try { - const contacts = await listContacts(); - - const contactIndex = contacts.findIndex( - (contact) => contact.id === contactId + const updatedContact = await ContactModel.findByIdAndUpdate( + contactId, + body, + { new: true, runValidators: true } ); - if (contactIndex === -1) { - console.error(`Contact with ID: ${contactId} not found`.bgYellow); + if (!updatedContact) { + console.error(`Contact with ID: ${contactId} not found`); return null; } - const updatedContact = { ...contacts[contactIndex], ...body }; - contacts[contactIndex] = updatedContact; - - await writeContactsToFile(contacts); - console.log(`Contact with ID: ${contactId} updated successfully`.bgGreen); - + console.log(`Contact with ID: ${contactId} updated successfully`); return updatedContact; } catch (error) { - console.error(`Error updateContact: ${error}`.bgRed); + console.error(`Error updateContact: ${error}`); + return null; } }; -export async function writeContactsToFile(contacts, filePath = contactsPath) { +export const updateStatusContact = async (contactId, body) => { try { - await fs.promises.writeFile(filePath, JSON.stringify(contacts, null, 2)); - console.log(`Contacts saved to ${filePath}`); + if (!Object.prototype.hasOwnProperty.call(body, "favorite")) { + console.error(`Missing "favorite" field in body`); + return null; + } + + const updatedContact = await ContactModel.findByIdAndUpdate( + contactId, + { favorite: body.favorite }, + { new: true, runValidators: true } + ); + + if (!updatedContact) { + console.error(`Contact with ID: ${contactId} not found`); + return null; + } + + console.log(`Contact with ID: ${contactId} updated successfully`); + return updatedContact; } catch (error) { - throw new Error(`Error writing file: ${filePath}`); + console.error(`Error updating favorite field: ${error}`); + return null; } -} +}; diff --git a/models/contacts.json b/models/contacts.json index 2c63431e2e8..4289afe111a 100644 --- a/models/contacts.json +++ b/models/contacts.json @@ -82,5 +82,11 @@ "name": "Konrad", "email": "konrad@gmail.com", "phone": "989768567" + }, + { + "id": "n7Mi8eIHRlDtx3yzdUenX", + "name": "Konrad", + "email": "konrad@gmail.com", + "phone": "989768567" } ] \ No newline at end of file diff --git a/models/dbConnection.js b/models/dbConnection.js new file mode 100644 index 00000000000..2679255aa42 --- /dev/null +++ b/models/dbConnection.js @@ -0,0 +1,42 @@ +import mongoose from "mongoose"; +const username = encodeURIComponent(process.env.DB_USERNAME); +const password = encodeURIComponent(process.env.DB_PASSWORD); +const cluster = process.env.DB_CLUSTER; +const appName = process.env.DB_APPNAME; +const dbName = process.env.DB_DBNAME; +const uri2 = + "mongodb+srv://konradkonikpoczta:K3gBMlkokxeneqhJ@mongodbkonrad.ebhjm.mongodb.net/db-contacts?retryWrites=true&w=majority&appName=MongoDbKonrad"; +const uri = `mongodb+srv://${username}:${password}@${cluster}/${dbName}?retryWrites=true&w=majority&appName=${appName}`; +console.log(uri2); +console.log(uri); +export const connectDB = async () => { + try { + console.log(`[DB] Connecting to MongoDB: ${dbName} ...`.blue); + await mongoose.connect(uri2); + console.log(`[DB] MongoDB: ${dbName} connected successfully`.blue); + } catch (error) { + console.error( + `[DB] Error connecting to MongoDB: ${dbName} :${error.message}`.red + ); + process.exit(1); + } +}; + +export const disconnectDB = async () => { + try { + await mongoose.disconnect(); + console.log("[DB] MongoDB disconnected successfully".blue); + } catch (error) { + console.error( + `[DB] Error disconnecting from MongoDB: ${error.message}`.red + ); + process.exit(1); + } +}; + +export function checkConnectionState() { + const state = mongoose.connections[0].readyState; + const stateText = mongoose.connections[0].states[state]; + console.log(`Current connection state: ${stateText}`); + return state; +} diff --git a/package-lock.json b/package-lock.json index f50e39073f9..567c2674c4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,11 +8,14 @@ "name": "template", "version": "0.0.0", "dependencies": { + "@dotenvx/dotenvx": "^1.32.1", "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.7", "express": "4.17.1", "joi": "^17.13.3", + "mongoose": "^8.9.4", "morgan": "1.10.0", "nanoid": "^5.0.9" }, @@ -123,6 +126,96 @@ "node": ">=4" } }, + "node_modules/@dotenvx/dotenvx": { + "version": "1.32.1", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.32.1.tgz", + "integrity": "sha512-xuTL8XLFkC0B0xHQzBPROY6WBwb9MA0LYBVNIinJ0VD9+gHOIuSyQut0RyDA7tmqxvZQ3C4roZ0HaWvHgX3sZQ==", + "dependencies": { + "commander": "^11.1.0", + "dotenv": "^16.4.5", + "eciesjs": "^0.4.10", + "execa": "^5.1.1", + "fdir": "^6.2.0", + "ignore": "^5.3.0", + "object-treeify": "1.1.33", + "picomatch": "^4.0.2", + "which": "^4.0.0" + }, + "bin": { + "dotenvx": "src/cli/dotenvx.js", + "git-dotenvx": "src/cli/dotenvx.js" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@dotenvx/dotenvx/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@ecies/ciphers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.2.tgz", + "integrity": "sha512-ylfGR7PyTd+Rm2PqQowG08BCKA22QuX8NzrL+LxAAvazN10DMwdJ2fWwAzRj05FI/M8vNFGm3cv9Wq/GFWCBLg==", + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + }, + "peerDependencies": { + "@noble/ciphers": "^1.0.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -157,6 +250,50 @@ "@hapi/hoek": "^9.0.0" } }, + "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/@noble/ciphers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.0.tgz", + "integrity": "sha512-YGdEUzYEd+82jeaVbSKKVp1jFZb8LwaNMIIzHFkihGvYdd/KKAr7KaJHdEdSYGredE3ssSravXIa0Jxg28Sv5w==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "dependencies": { + "@noble/hashes": "1.7.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -202,6 +339,19 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "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", @@ -486,6 +636,14 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.1.tgz", + "integrity": "sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -660,6 +818,14 @@ "node": ">=0.1.90" } }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -770,7 +936,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -865,12 +1030,39 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "node_modules/eciesjs": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.13.tgz", + "integrity": "sha512-zBdtR4K+wbj10bWPpIOF9DW+eFYQu8miU5ypunh0t4Bvt83ZPlEWgT5Dq/0G6uwEXumZKjfb5BZxYUZQ2Hzn/Q==", + "dependencies": { + "@ecies/ciphers": "^0.2.2", + "@noble/ciphers": "^1.0.0", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0" + }, + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1392,6 +1584,39 @@ "node": ">= 0.6" } }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -1815,6 +2040,14 @@ "node": ">= 0.6" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2149,6 +2382,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -2269,6 +2513,14 @@ "json5": "lib/cli.js" } }, + "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/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -2381,11 +2633,21 @@ "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": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -2424,6 +2686,14 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -2451,6 +2721,86 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "node_modules/mongodb": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.12.0.tgz", + "integrity": "sha512-RM7AHlvYfS7jv7+BXund/kR64DryVI+cHbVAy9P61fnb1RcWZqOW1/Wj2YhqMCx+MuYhqTRGv7AwHBzmsCKBfA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.1", + "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 || ^2.0.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.9.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.4.tgz", + "integrity": "sha512-DndoI01aV/q40P9DiYDXsYjhj8vZjmmuFwcC3Tro5wFznoE1z6Fe2JgMnbLR6ghglym5ziYizSfAJykp+UPZWg==", + "dependencies": { + "bson": "^6.10.1", + "kareem": "2.6.3", + "mongodb": "~6.12.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/mongoose/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/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -2487,11 +2837,29 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "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.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { "version": "5.0.9", @@ -2625,6 +2993,17 @@ "node": ">=8" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2651,6 +3030,14 @@ "node": ">= 0.4" } }, + "node_modules/object-treeify": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", + "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==", + "engines": { + "node": ">= 10" + } + }, "node_modules/object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -2714,6 +3101,20 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -2934,10 +3335,9 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -3256,11 +3656,15 @@ "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.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, "node_modules/slice-ansi": { "version": "4.0.0", @@ -3279,6 +3683,14 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "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/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3354,6 +3766,14 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3463,6 +3883,17 @@ "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/tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -3629,6 +4060,26 @@ "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/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3810,6 +4261,59 @@ } } }, + "@dotenvx/dotenvx": { + "version": "1.32.1", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.32.1.tgz", + "integrity": "sha512-xuTL8XLFkC0B0xHQzBPROY6WBwb9MA0LYBVNIinJ0VD9+gHOIuSyQut0RyDA7tmqxvZQ3C4roZ0HaWvHgX3sZQ==", + "requires": { + "commander": "^11.1.0", + "dotenv": "^16.4.5", + "eciesjs": "^0.4.10", + "execa": "^5.1.1", + "fdir": "^6.2.0", + "ignore": "^5.3.0", + "object-treeify": "1.1.33", + "picomatch": "^4.0.2", + "which": "^4.0.0" + }, + "dependencies": { + "fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "requires": {} + }, + "ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==" + }, + "isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" + }, + "picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==" + }, + "which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "requires": { + "isexe": "^3.1.1" + } + } + } + }, + "@ecies/ciphers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.2.tgz", + "integrity": "sha512-ylfGR7PyTd+Rm2PqQowG08BCKA22QuX8NzrL+LxAAvazN10DMwdJ2fWwAzRj05FI/M8vNFGm3cv9Wq/GFWCBLg==", + "requires": {} + }, "@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -3841,6 +4345,32 @@ "@hapi/hoek": "^9.0.0" } }, + "@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==", + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "@noble/ciphers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.0.tgz", + "integrity": "sha512-YGdEUzYEd+82jeaVbSKKVp1jFZb8LwaNMIIzHFkihGvYdd/KKAr7KaJHdEdSYGredE3ssSravXIa0Jxg28Sv5w==" + }, + "@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "requires": { + "@noble/hashes": "1.7.0" + } + }, + "@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==" + }, "@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -3880,6 +4410,19 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@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==" + }, + "@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==", + "requires": { + "@types/webidl-conversions": "*" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -4099,6 +4642,11 @@ "fill-range": "^7.0.1" } }, + "bson": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.1.tgz", + "integrity": "sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA==" + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -4225,6 +4773,11 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, + "commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4305,7 +4858,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -4374,12 +4926,28 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==" + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "eciesjs": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.13.tgz", + "integrity": "sha512-zBdtR4K+wbj10bWPpIOF9DW+eFYQu8miU5ypunh0t4Bvt83ZPlEWgT5Dq/0G6uwEXumZKjfb5BZxYUZQ2Hzn/Q==", + "requires": { + "@ecies/ciphers": "^0.2.2", + "@noble/ciphers": "^1.0.0", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4773,6 +5341,29 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + } + } + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -5106,6 +5697,11 @@ "toidentifier": "1.0.0" } }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5332,6 +5928,11 @@ "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", "dev": true }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, "is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -5431,6 +6032,11 @@ "minimist": "^1.2.0" } }, + "kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==" + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -5518,11 +6124,21 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "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==" + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -5546,6 +6162,11 @@ "mime-db": "1.51.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -5567,6 +6188,46 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mongodb": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.12.0.tgz", + "integrity": "sha512-RM7AHlvYfS7jv7+BXund/kR64DryVI+cHbVAy9P61fnb1RcWZqOW1/Wj2YhqMCx+MuYhqTRGv7AwHBzmsCKBfA==", + "requires": { + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.1", + "mongodb-connection-string-url": "^3.0.0" + } + }, + "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==", + "requires": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "mongoose": { + "version": "8.9.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.4.tgz", + "integrity": "sha512-DndoI01aV/q40P9DiYDXsYjhj8vZjmmuFwcC3Tro5wFznoE1z6Fe2JgMnbLR6ghglym5ziYizSfAJykp+UPZWg==", + "requires": { + "bson": "^6.10.1", + "kareem": "2.6.3", + "mongodb": "~6.12.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -5599,11 +6260,23 @@ } } }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "requires": { + "debug": "4.x" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { "version": "5.0.9", @@ -5692,6 +6365,14 @@ "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5709,6 +6390,11 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, + "object-treeify": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", + "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==" + }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -5754,6 +6440,14 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -5919,10 +6613,9 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "pupa": { "version": "2.1.1", @@ -6171,11 +6864,15 @@ "object-inspect": "^1.9.0" } }, + "sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, "slice-ansi": { "version": "4.0.0", @@ -6188,6 +6885,14 @@ "is-fullwidth-code-point": "^3.0.0" } }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "requires": { + "memory-pager": "^1.0.2" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6245,6 +6950,11 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6328,6 +7038,14 @@ "nopt": "~1.0.10" } }, + "tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "requires": { + "punycode": "^2.3.0" + } + }, "tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -6461,6 +7179,20 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "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==" + }, + "whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "requires": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 43116662dbc..c7ad02198d5 100644 --- a/package.json +++ b/package.json @@ -6,15 +6,19 @@ "scripts": { "start": "cross-env NODE_ENV=production node ./server.js", "start:dev": "cross-env NODE_ENV=development nodemon ./server.js", + "start3": "dotenvx run cross-env NODE_ENV=development nodemon ./server.js", "lint": "eslint **/*.js", "lint:fix": "eslint --fix **/*.js" }, "dependencies": { + "@dotenvx/dotenvx": "^1.32.1", "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.7", "express": "4.17.1", "joi": "^17.13.3", + "mongoose": "^8.9.4", "morgan": "1.10.0", "nanoid": "^5.0.9" }, diff --git a/routes/api/contacts.js b/routes/api/contacts.js index ce857bfe45d..ae4f8ddc4a6 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,24 +1,21 @@ import { Router } from "express"; import Joi from "joi"; -import * as ContactsModels from "../../models/contacts.js"; +import * as ContactsFunctions from "../../models/contacts.js"; const contactSchema = Joi.object({ name: Joi.string() - .pattern(/^[a-zA-Z\s]+$/) // Pattern: tylko litery i spacje + .pattern(/^[a-zA-Z\s]+$/) .required() .messages({ "any.required": "missing required name field", "string.empty": "missing required name field", "string.pattern.base": "name must contain only letters and spaces", }), - email: Joi.string() - .email() // Walidacja adresu e-mail - .required() - .messages({ - "any.required": "missing required email field", - "string.empty": "missing required email field", - "string.email": "email must be a valid email address", - }), + email: Joi.string().email().required().messages({ + "any.required": "missing required email field", + "string.empty": "missing required email field", + "string.email": "email must be a valid email address", + }), phone: Joi.string() .pattern(/^\d+$/) // Pattern: cyfry, spacje, opcjonalnie + .required() @@ -27,18 +24,27 @@ const contactSchema = Joi.object({ "string.empty": "missing required phone field", "string.pattern.base": "phone must contain only numbers", }), + favorite: Joi.boolean().default(false).messages({ + "boolean.base": "favorite must be a boolean value", + }), +}); + +const favoriteSchema = Joi.object({ + favorite: Joi.boolean().default(false).messages({ + "boolean.base": "favorite must be a boolean value", + }), }); const router = Router(); router.get("/", async (req, res, next) => { - const contactsList = await ContactsModels.listContacts(); + const contactsList = await ContactsFunctions.listContacts(); return res.status(200).json(contactsList); }); router.get("/:contactId", async (req, res, next) => { const { contactId } = req.params; - const searchedContactById = await ContactsModels.getContactById(contactId); + const searchedContactById = await ContactsFunctions.getContactById(contactId); if (searchedContactById) return res.status(200).json(searchedContactById); return res.status(404).json({ message: "Not found" }); @@ -53,13 +59,18 @@ router.post("/", async (req, res, next) => { const { name, email, phone } = req.body; - const newContact = await ContactsModels.addContact({ name, email, phone }); + const newContact = await ContactsFunctions.addContact({ + name, + email, + phone, + favorite: false, + }); return res.status(201).json(newContact); }); router.delete("/:contactId", async (req, res, next) => { const { contactId } = req.params; - const contactDelete = await ContactsModels.removeContact(contactId); + const contactDelete = await ContactsFunctions.removeContact(contactId); if (contactDelete) return res.status(200).json({ message: "contact deleted" }); @@ -78,7 +89,7 @@ router.put("/:contactId", async (req, res, next) => { return res.status(404).json({ message }); } - const updatedContact = await ContactsModels.updateContact( + const updatedContact = await ContactsFunctions.updateContact( contactId, req.body ); @@ -86,4 +97,22 @@ router.put("/:contactId", async (req, res, next) => { return res.status(200).json(updatedContact); }); +router.put("/:contactId/favorite", async (req, res, next) => { + const { contactId } = req.params; + const { error } = favoriteSchema.validate(req.body); + if (!req.body) { + return res.status(400).json({ message: "missing field favorite" }); + } + if (error) { + const message = error.details[0].message; + return res.status(404).json({ message }); + } + + const updatedContact = await ContactsFunctions.updateStatusContact( + contactId, + req.body + ); + if (!updatedContact) return res.status(404).json({ message: "Not found" }); + return res.status(200).json(updatedContact); +}); export const contactsRouter = router; diff --git a/server.js b/server.js index fe78a9bed4b..e725d620f27 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,7 @@ import { startServer } from "./app.js"; - +import * as dbConnection from "./models/dbConnection.js"; const PORT = 3000; +await dbConnection.connectDB(); + startServer(PORT); From e07bbc098e4c4f37943d31ce2bc8bea16657c130 Mon Sep 17 00:00:00 2001 From: Konrad Konik <88903994+KonradKinok@users.noreply.github.com> Date: Sat, 18 Jan 2025 21:21:22 +0100 Subject: [PATCH 3/7] fix 18.01.2025 --- models/dbConnection.js | 16 ++++++---------- routes/api/contacts.js | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/models/dbConnection.js b/models/dbConnection.js index 2679255aa42..d479794a015 100644 --- a/models/dbConnection.js +++ b/models/dbConnection.js @@ -1,18 +1,14 @@ import mongoose from "mongoose"; -const username = encodeURIComponent(process.env.DB_USERNAME); -const password = encodeURIComponent(process.env.DB_PASSWORD); -const cluster = process.env.DB_CLUSTER; -const appName = process.env.DB_APPNAME; +import dotenv from "dotenv"; +dotenv.config(); const dbName = process.env.DB_DBNAME; -const uri2 = - "mongodb+srv://konradkonikpoczta:K3gBMlkokxeneqhJ@mongodbkonrad.ebhjm.mongodb.net/db-contacts?retryWrites=true&w=majority&appName=MongoDbKonrad"; -const uri = `mongodb+srv://${username}:${password}@${cluster}/${dbName}?retryWrites=true&w=majority&appName=${appName}`; -console.log(uri2); +const uri = process.env.DB_URI; + console.log(uri); export const connectDB = async () => { try { console.log(`[DB] Connecting to MongoDB: ${dbName} ...`.blue); - await mongoose.connect(uri2); + await mongoose.connect(uri); console.log(`[DB] MongoDB: ${dbName} connected successfully`.blue); } catch (error) { console.error( @@ -30,7 +26,7 @@ export const disconnectDB = async () => { console.error( `[DB] Error disconnecting from MongoDB: ${error.message}`.red ); - process.exit(1); + process.exit(0); } }; diff --git a/routes/api/contacts.js b/routes/api/contacts.js index ae4f8ddc4a6..46545b96d56 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -97,7 +97,7 @@ router.put("/:contactId", async (req, res, next) => { return res.status(200).json(updatedContact); }); -router.put("/:contactId/favorite", async (req, res, next) => { +router.patch("/:contactId/favorite", async (req, res, next) => { const { contactId } = req.params; const { error } = favoriteSchema.validate(req.body); if (!req.body) { From 75831a1d0013fa407efdb1d4fd3eb835702167da Mon Sep 17 00:00:00 2001 From: Konrad Konik <88903994+KonradKinok@users.noreply.github.com> Date: Sun, 26 Jan 2025 13:38:25 +0100 Subject: [PATCH 4/7] 26.01.2025 --- app.js | 14 +- config/config.js | 33 + {models => config}/dbConnection.js | 2 +- middlewares/auth.js | 47 + .../contactShema.js} | 4 + models/{ => contact}/contacts.js | 18 +- models/users/userShema.js | 33 + package-lock.json | 973 ++++++++++++++++-- package.json | 9 +- routes/api/{contacts.js => contactsApi.js} | 20 +- routes/api/userApi.js | 118 +++ server.js | 5 +- 12 files changed, 1163 insertions(+), 113 deletions(-) create mode 100644 config/config.js rename {models => config}/dbConnection.js (98%) create mode 100644 middlewares/auth.js rename models/{contactShemaMongoose.js => contact/contactShema.js} (85%) rename models/{ => contact}/contacts.js (84%) create mode 100644 models/users/userShema.js rename routes/api/{contacts.js => contactsApi.js} (83%) create mode 100644 routes/api/userApi.js diff --git a/app.js b/app.js index 0e58f183c7a..691419d0ef6 100644 --- a/app.js +++ b/app.js @@ -2,7 +2,10 @@ import express from "express"; import logger from "morgan"; import cors from "cors"; import colors from "colors"; -import { contactsRouter } from "./routes/api/contacts.js"; +import { contactsRouter } from "./routes/api/contactsApi.js"; +import { usersRouter } from "./routes/api/userApi.js"; +import passport from "./config/config.js"; +import { auth } from "./middlewares/auth.js"; const app = express(); @@ -11,7 +14,7 @@ const logger1 = (req, res, next) => { const { method, originalUrl } = req; const date = new Date().toLocaleString(); - console.log(`[${date}] [${method}] - ${originalUrl} `.yellow); + console.log(`[${date}] [${method}] - ${originalUrl} app.js`.yellow); next(); }; @@ -20,14 +23,17 @@ app.use(logger1); app.use(logger(formatsLogger)); app.use(cors()); app.use(express.json()); - -app.use("/api/contacts", contactsRouter); +app.use(passport.initialize()); +app.use("/api/", usersRouter); +app.use("/api/contacts", auth, contactsRouter); app.use((req, res) => { res.status(404).json({ message: "Not found" }); }); app.use((err, req, res, next) => { + const error = err.stack; + console.error(error.bgRed, "[app.js]"); res.status(500).json({ message: err.message }); }); diff --git a/config/config.js b/config/config.js new file mode 100644 index 00000000000..128c8010b50 --- /dev/null +++ b/config/config.js @@ -0,0 +1,33 @@ +import passport from "passport"; +import passportJWT from "passport-jwt"; +import { UserModel } from "../models/users/userShema.js"; +import dotenv from "dotenv"; +dotenv.config(); + +const secret = process.env.JWT_SECRET_KEY; + +const ExtractJWT = passportJWT.ExtractJwt; +const Strategy = passportJWT.Strategy; +const params = { + secretOrKey: secret, + jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), +}; + +// JWT Strategy +passport.use( + new Strategy(params, async (payload, done) => { + try { + const user = await UserModel.findById(payload.id); + + if (!user) { + return done(null, false, { message: "User not found" }); + } + + return done(null, user); + } catch (err) { + return done(err, false); + } + }) +); + +export default passport; diff --git a/models/dbConnection.js b/config/dbConnection.js similarity index 98% rename from models/dbConnection.js rename to config/dbConnection.js index d479794a015..530f52f94db 100644 --- a/models/dbConnection.js +++ b/config/dbConnection.js @@ -1,10 +1,10 @@ import mongoose from "mongoose"; import dotenv from "dotenv"; dotenv.config(); + const dbName = process.env.DB_DBNAME; const uri = process.env.DB_URI; -console.log(uri); export const connectDB = async () => { try { console.log(`[DB] Connecting to MongoDB: ${dbName} ...`.blue); diff --git a/middlewares/auth.js b/middlewares/auth.js new file mode 100644 index 00000000000..2840244f587 --- /dev/null +++ b/middlewares/auth.js @@ -0,0 +1,47 @@ +import passport from "passport"; +import mongoose from "mongoose"; +import { UserModel } from "../models/users/userShema.js"; + +export const auth = (req, res, next) => { + passport.authenticate("jwt", { session: false }, async (err, user) => { + if (err || !user) { + return res.status(401).json({ + message: "Unauthorized", + data: "Unauthorized", + }); + } + + // Pobierz token z nagłówka `Authorization` + const tokenFromHeader = req.headers.authorization?.split(" ")[1]; + if (!tokenFromHeader) { + return res.status(401).json({ + message: "Not authorized", + }); + } + + // Sprawdź, czy token w bazie danych jest zgodny z tokenem w nagłówku + try { + if (!mongoose.Types.ObjectId.isValid(user._id)) { + console.error(`Invalid ID format: ${contactId}`.bgRed); + return res.status(400).json({ + message: "Bad Request: Invalid User.ID format", + }); + } + + const userFromDb = await UserModel.findById(user._id); // Znajdź użytkownika w bazie danych + if (!userFromDb || userFromDb.token !== tokenFromHeader) { + return res.status(401).json({ + message: "Not authorized", + }); + } + + req.user = userFromDb; // Przekaż użytkownika do kolejnych middleware'ów + next(); + } catch (dbError) { + console.log(`Database error occurred: ${dbError} [auth.js]`.bgRed); + return res.status(500).json({ + message: "Database error during token verification", + }); + } + })(req, res, next); +}; diff --git a/models/contactShemaMongoose.js b/models/contact/contactShema.js similarity index 85% rename from models/contactShemaMongoose.js rename to models/contact/contactShema.js index 4bccf30871d..85bafc0a601 100644 --- a/models/contactShemaMongoose.js +++ b/models/contact/contactShema.js @@ -16,6 +16,10 @@ const contactSchema = new mongoose.Schema({ type: Boolean, default: false, }, + owner: { + type: mongoose.Schema.Types.ObjectId, + ref: "user", + }, }); // Tworzenie modelu na podstawie schematu diff --git a/models/contacts.js b/models/contact/contacts.js similarity index 84% rename from models/contacts.js rename to models/contact/contacts.js index 16df0195503..e400b5de368 100644 --- a/models/contacts.js +++ b/models/contact/contacts.js @@ -1,11 +1,11 @@ import mongoose from "mongoose"; import { nanoid } from "nanoid"; -import { ContactModel } from "../models/contactShemaMongoose.js"; +import { ContactModel } from "./contactShema.js"; -export const listContacts = async () => { +export const listContacts = async (userId) => { try { - const contacts = await ContactModel.find({}); - console.log("Contacts fetched successfully".bgGreen); + const contacts = await ContactModel.find({ owner: userId }); // Filtrowanie kontaktów po owner + console.log("[DB] Contacts fetched successfully".bgGreen); return contacts; } catch (error) { console.error(`[DB] Error fetching contacts: ${error.message}`.red); @@ -53,21 +53,23 @@ export const removeContact = async (contactId) => { export const addContact = async (body) => { try { - const { name, email, phone, favorite } = body; + const { name, email, phone, favorite, owner } = body; const contact = new ContactModel({ - id: nanoid(), + // id: nanoid(), name, email, phone, favorite: favorite || false, + owner, }); await contact.save(); - + console.log(`Contact added successfully`.bgGreen); + console.log(contact.name.bgGreen); return contact; } catch (error) { - console.error(`Error addContact: ${error}`.bgRed); + console.error(`Error addContact: ${error} [contacts.js]`.bgRed); } }; diff --git a/models/users/userShema.js b/models/users/userShema.js new file mode 100644 index 00000000000..9ce54277bee --- /dev/null +++ b/models/users/userShema.js @@ -0,0 +1,33 @@ +import bCrypt from "bcryptjs"; +import mongoose from "mongoose"; + +// Definiowanie schematu dla userów +const userSchema = new mongoose.Schema({ + password: { + type: String, + required: [true, "Password is required"], + }, + email: { + type: String, + required: [true, "Email is required"], + unique: true, + }, + subscription: { + type: String, + enum: ["starter", "pro", "business"], + default: "starter", + }, + token: { + type: String, + default: null, + }, +}); +userSchema.methods.setPassword = function (password) { + this.password = bCrypt.hashSync(password, bCrypt.genSaltSync(6)); +}; + +userSchema.methods.validPassword = function (password) { + return bCrypt.compareSync(password, this.password); +}; +// Tworzenie modelu na podstawie schematu +export const UserModel = mongoose.model("User", userSchema, "users"); diff --git a/package-lock.json b/package-lock.json index 567c2674c4a..dbe83608f61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,15 +9,20 @@ "version": "0.0.0", "dependencies": { "@dotenvx/dotenvx": "^1.32.1", + "bcrypt": "^5.1.1", + "bcryptjs": "^2.4.3", "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", "dotenv": "^16.4.7", "express": "4.17.1", "joi": "^17.13.3", + "jsonwebtoken": "^9.0.2", "mongoose": "^8.9.4", "morgan": "1.10.0", - "nanoid": "^5.0.9" + "nanoid": "^5.0.9", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1" }, "devDependencies": { "eslint": "7.19.0", @@ -250,6 +255,39 @@ "@hapi/hoek": "^9.0.0" } }, + "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/@mapbox/node-pre-gyp/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/@mongodb-js/saslprep": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", @@ -355,8 +393,7 @@ "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==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/accepts": { "version": "1.3.7", @@ -391,6 +428,17 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "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/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -429,7 +477,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -462,6 +509,24 @@ "node": ">= 8" } }, + "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/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -524,8 +589,7 @@ "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==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/basic-auth": { "version": "2.0.1", @@ -538,6 +602,24 @@ "node": ">= 0.8" } }, + "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/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -618,7 +700,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -644,6 +725,11 @@ "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/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -765,6 +851,14 @@ "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/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -810,6 +904,14 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "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/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -829,8 +931,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/configstore": { "version": "5.0.1", @@ -849,6 +950,11 @@ "node": ">=8" } }, + "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.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -993,6 +1099,11 @@ "node": ">= 0.4" } }, + "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": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1006,6 +1117,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "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/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1047,6 +1166,14 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "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/eciesjs": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.13.tgz", @@ -1071,8 +1198,7 @@ "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==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -1789,11 +1915,32 @@ "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": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", @@ -1821,6 +1968,26 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "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.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -1867,7 +2034,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2010,6 +2176,11 @@ "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/has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -2040,6 +2211,18 @@ "node": ">= 0.6" } }, + "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/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -2112,7 +2295,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2258,7 +2440,6 @@ "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==", - "dev": true, "engines": { "node": ">=8" } @@ -2513,6 +2694,46 @@ "json5": "lib/cli.js" } }, + "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", @@ -2574,6 +2795,41 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "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/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -2589,23 +2845,10 @@ "node": ">=0.10.0" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "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==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -2620,7 +2863,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -2707,7 +2949,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2721,6 +2962,48 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "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": "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/mongodb": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.12.0.tgz", @@ -2892,6 +3175,49 @@ "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/nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", @@ -3004,6 +3330,18 @@ "node": ">=8" } }, + "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", @@ -3096,7 +3434,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -3218,6 +3555,40 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -3231,7 +3602,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3255,6 +3625,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -3414,6 +3789,19 @@ "node": ">=0.10.0" } }, + "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/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3506,7 +3894,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -3528,13 +3915,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "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" }, @@ -3618,6 +4001,11 @@ "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/setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -3705,11 +4093,37 @@ "node": ">= 0.6" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/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/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==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3749,7 +4163,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3836,6 +4249,22 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, + "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/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4038,6 +4467,11 @@ "node": ">=4" } }, + "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", @@ -4110,6 +4544,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -4151,8 +4593,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -4178,8 +4619,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } }, "dependencies": { @@ -4345,6 +4785,32 @@ "@hapi/hoek": "^9.0.0" } }, + "@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==", + "requires": { + "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" + }, + "dependencies": { + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + } + } + }, "@mongodb-js/saslprep": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", @@ -4426,8 +4892,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { "version": "1.3.7", @@ -4451,6 +4916,14 @@ "dev": true, "requires": {} }, + "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==", + "requires": { + "debug": "4" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4481,8 +4954,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -4503,6 +4975,20 @@ "picomatch": "^2.0.4" } }, + "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==" + }, + "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==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -4550,8 +5036,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "basic-auth": { "version": "2.0.1", @@ -4561,6 +5046,20 @@ "safe-buffer": "5.1.2" } }, + "bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -4627,7 +5126,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4647,6 +5145,11 @@ "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.1.tgz", "integrity": "sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA==" }, + "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==" + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -4732,6 +5235,11 @@ "readdirp": "~3.6.0" } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -4768,6 +5276,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "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==" + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -4781,8 +5294,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "configstore": { "version": "5.0.1", @@ -4798,6 +5310,11 @@ "xdg-basedir": "^4.0.0" } }, + "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==" + }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -4898,6 +5415,11 @@ "object-keys": "^1.0.12" } }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -4908,6 +5430,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==" + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4937,6 +5464,14 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "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==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "eciesjs": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.13.tgz", @@ -4956,8 +5491,7 @@ "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==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -5516,11 +6050,28 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -5541,6 +6092,22 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "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" + } + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -5575,7 +6142,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5673,6 +6239,11 @@ "has-symbols": "^1.0.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -5697,6 +6268,15 @@ "toidentifier": "1.0.0" } }, + "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==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -5748,7 +6328,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -5851,8 +6430,7 @@ "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==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.3", @@ -6032,6 +6610,42 @@ "minimist": "^1.2.0" } }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "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" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "kareem": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", @@ -6081,6 +6695,41 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "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==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "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==" + }, + "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==" + }, + "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==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -6093,20 +6742,10 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "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==", - "dev": true, "requires": { "semver": "^6.0.0" }, @@ -6114,8 +6753,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -6177,7 +6815,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6188,6 +6825,35 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, "mongodb": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.12.0.tgz", @@ -6294,6 +6960,40 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, + "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-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==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "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==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", @@ -6373,6 +7073,17 @@ "path-key": "^3.0.0" } }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6435,7 +7146,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -6526,6 +7236,30 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + } + }, + "passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "requires": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -6535,8 +7269,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", @@ -6554,6 +7287,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -6673,6 +7411,16 @@ } } }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6741,7 +7489,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -6757,13 +7504,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" }, "semver-diff": { "version": "3.1.1", @@ -6835,6 +7578,11 @@ "send": "0.17.1" } }, + "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==" + }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -6904,11 +7652,25 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "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==" + } + } + }, "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==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6939,7 +7701,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -7003,6 +7764,19 @@ } } }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "requires": { + "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" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -7163,6 +7937,11 @@ "prepend-http": "^2.0.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -7214,6 +7993,14 @@ "is-symbol": "^1.0.3" } }, + "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==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -7243,8 +8030,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "3.0.3", @@ -7267,8 +8053,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index c7ad02198d5..6e9b67d1c2b 100644 --- a/package.json +++ b/package.json @@ -5,22 +5,27 @@ "type": "module", "scripts": { "start": "cross-env NODE_ENV=production node ./server.js", - "start:dev": "cross-env NODE_ENV=development nodemon ./server.js", + "start2": "cross-env NODE_ENV=development nodemon ./server.js", "start3": "dotenvx run cross-env NODE_ENV=development nodemon ./server.js", "lint": "eslint **/*.js", "lint:fix": "eslint --fix **/*.js" }, "dependencies": { "@dotenvx/dotenvx": "^1.32.1", + "bcrypt": "^5.1.1", + "bcryptjs": "^2.4.3", "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", "dotenv": "^16.4.7", "express": "4.17.1", "joi": "^17.13.3", + "jsonwebtoken": "^9.0.2", "mongoose": "^8.9.4", "morgan": "1.10.0", - "nanoid": "^5.0.9" + "nanoid": "^5.0.9", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1" }, "devDependencies": { "eslint": "7.19.0", diff --git a/routes/api/contacts.js b/routes/api/contactsApi.js similarity index 83% rename from routes/api/contacts.js rename to routes/api/contactsApi.js index 46545b96d56..b06be236c13 100644 --- a/routes/api/contacts.js +++ b/routes/api/contactsApi.js @@ -1,6 +1,6 @@ import { Router } from "express"; import Joi from "joi"; -import * as ContactsFunctions from "../../models/contacts.js"; +import * as ContactsFunctions from "../../models/contact/contacts.js"; const contactSchema = Joi.object({ name: Joi.string() @@ -38,8 +38,20 @@ const favoriteSchema = Joi.object({ const router = Router(); router.get("/", async (req, res, next) => { - const contactsList = await ContactsFunctions.listContacts(); - return res.status(200).json(contactsList); + try { + const userId = req.user._id; // Pobranie ID zalogowanego użytkownika z middleware auth + + const contacts = await ContactsFunctions.listContacts(userId); // Filtrowanie kontaktów po owner + console.log("[DB] Contacts fetched successfully [contactsApi.js]".bgGreen); + return res.status(200).json(contacts); + } catch (error) { + console.error( + `[DB] Error fetching contacts: ${error.message} [contactsApi.js]`.red + ); + return res.status(500).json({ + message: "Error fetching contacts from the database [contactsApi.js]", + }); + } }); router.get("/:contactId", async (req, res, next) => { @@ -64,6 +76,7 @@ router.post("/", async (req, res, next) => { email, phone, favorite: false, + owner: req.user._id, // Przypisz ID użytkownika jako owner }); return res.status(201).json(newContact); }); @@ -115,4 +128,5 @@ router.patch("/:contactId/favorite", async (req, res, next) => { if (!updatedContact) return res.status(404).json({ message: "Not found" }); return res.status(200).json(updatedContact); }); + export const contactsRouter = router; diff --git a/routes/api/userApi.js b/routes/api/userApi.js new file mode 100644 index 00000000000..aa872547425 --- /dev/null +++ b/routes/api/userApi.js @@ -0,0 +1,118 @@ +import { Router } from "express"; +import Joi from "joi"; +import { UserModel } from "../../models/users/userShema.js"; +import { auth } from "../../middlewares/auth.js"; +import dotenv from "dotenv"; +dotenv.config(); +const secret = process.env.JWT_SECRET_KEY; +import jwt from "jsonwebtoken"; + +const userSchema = Joi.object({ + email: Joi.string().email().required().messages({ + "any.required": "missing required email field", + "string.empty": "missing required email field", + "string.email": "email must be a valid email address", + }), + password: Joi.string() + .min(8) + .max(32) + .pattern(/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d@$!%*?&]+$/) // Co najmniej jedna litera i jedna cyfra + .required() + .messages({ + "any.required": "missing required password field", + "string.empty": "missing required password field", + "string.min": "password must be at least 8 characters long", + "string.max": "password must not exceed 32 characters", + "string.pattern.base": + "password must contain at least one letter and one number", + }), +}); + +const router = Router(); + +router.post("/users/signup", async (req, res, next) => { + console.log(`Adding USER.... [usersApi.js]`.yellow); + const { error } = userSchema.validate(req.body); + if (error) { + const message = error.details[0].message; + return res.status(400).json({ message }); + } + const { email, password } = req.body; + const user = await UserModel.findOne({ email }).lean(); + if (user) { + console.log(`Email ${email} is in use [usersApi.js]`.bgRed); + return res.status(409).json({ message: `Email ${email} is in use` }); + } + try { + const user = new UserModel({ email }); + user.setPassword(password); + + await user.save(); + console.log(`Added USER: ${user.email} [usersApi.js]`.bgGreen); + return res + .status(201) + .json({ email: user.email, subscription: user.subscription }); + } catch (error) { + console.error(`Error add USER: ${error} [usersApi.js]`.bgRed); + next(error); + } +}); + +router.post("/users/login", async (req, res, next) => { + try { + console.log(`Login USER.... [usersApi.js]`.yellow); + const { error } = userSchema.validate(req.body); + if (error) { + const message = error.details[0].message; + return res.status(400).json({ message }); + } + + const { email, password } = req.body; + const user = await UserModel.findOne({ email }); + if (!user || !user.validPassword(password)) { + return res.status(400).json({ + message: "Email or password is wrong", + }); + } + const payload = { + id: user.id, + email: user.email, + }; + const token = jwt.sign(payload, secret, { expiresIn: "1h" }); + + user.token = token; + await user.save(); + res.status(200).json({ + data: { + token, + user: { + email: user.email, + subscription: user.subscription, + }, + }, + }); + } catch (error) { + console.error(`Error login USER: ${error} [usersApi.js]`.bgRed); + next(error); + } +}); + +router.post("/users/logout", auth, async (req, res, next) => { + try { + console.log(`Logout USER.... [usersApi.js]`.yellow); + const user = req.user; + if (!user) { + return res.status(401).json({ + message: "Not authorized", + }); + } + user.token = null; + await user.save(); + + res.sendStatus(204); + } catch (error) { + next(error); + } +}); + +export const usersRouter = router; diff --git a/server.js b/server.js index e725d620f27..25373435326 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,8 @@ import { startServer } from "./app.js"; -import * as dbConnection from "./models/dbConnection.js"; +import * as dbConnection from "./config/dbConnection.js"; +import * as jwtFunctions from "./models/users/userShema.js"; +import * as config from "./config/config.js"; + const PORT = 3000; await dbConnection.connectDB(); From 338a10d9881f4ba67df4be6175571105af2b6f90 Mon Sep 17 00:00:00 2001 From: Konrad Konik <88903994+KonradKinok@users.noreply.github.com> Date: Sun, 26 Jan 2025 22:26:24 +0100 Subject: [PATCH 5/7] fix: /users/current --- routes/api/userApi.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/routes/api/userApi.js b/routes/api/userApi.js index aa872547425..4d4b7ec1312 100644 --- a/routes/api/userApi.js +++ b/routes/api/userApi.js @@ -115,4 +115,22 @@ router.post("/users/logout", auth, async (req, res, next) => { } }); +router.get("/users/current", auth, async (req, res, next) => { + try { + console.log(`Getting USER.... [usersApi.js]`.yellow); + const user = req.user; + if (!user) { + return res.status(401).json({ + message: "Not authorized", + }); + } + return res.status(200).json({ + email: user.email, + subscription: user.subscription, + }); + } catch (error) { + next(error); + } +}); + export const usersRouter = router; From ed64bcf56b4f70cf4487f45ed29d0dd7f20c8469 Mon Sep 17 00:00:00 2001 From: Konrad Konik <88903994+KonradKinok@users.noreply.github.com> Date: Fri, 31 Jan 2025 15:57:24 +0100 Subject: [PATCH 6/7] 31.01.2025 --- app.js | 9 +- config/configDirectory.js | 8 + config/{config.js => configPassport.js} | 0 middlewares/upload.js | 39 + models/users/userShema.js | 4 + package-lock.json | 2078 ++++++++++++++++- package.json | 3 + ...79417264f121b31700ef133-sniezek-header.jpg | Bin 0 -> 255079 bytes .../679417264f121b31700ef133-tlo-header4.jpg | Bin 0 -> 323978 bytes .../679417264f121b31700ef133-tlo-home1.jpg | Bin 0 -> 303464 bytes ...9ce323a9e510252fb60afc-filmotekaonline.jpg | Bin 0 -> 1024142 bytes public/avatars/wigilia.jpg | Bin 0 -> 107129 bytes routes/api/userApi.js | 67 +- server.js | 1 - ..._maxRbp3b_-HoeD8veyJT8_filmotekaonline.jpg | Bin 0 -> 242836 bytes ..._doYpELRUZYT__NztJLBZW_filmotekaonline.jpg | Bin 0 -> 242836 bytes ...393075_bIUTh--HbWnEiSkkBe_6Q_Bez nazwy.jpg | Bin 0 -> 5493 bytes 17 files changed, 2072 insertions(+), 137 deletions(-) create mode 100644 config/configDirectory.js rename config/{config.js => configPassport.js} (100%) create mode 100644 middlewares/upload.js create mode 100644 public/avatars/679417264f121b31700ef133-sniezek-header.jpg create mode 100644 public/avatars/679417264f121b31700ef133-tlo-header4.jpg create mode 100644 public/avatars/679417264f121b31700ef133-tlo-home1.jpg create mode 100644 public/avatars/679ce323a9e510252fb60afc-filmotekaonline.jpg create mode 100644 public/avatars/wigilia.jpg create mode 100644 tmp/1738335160653_maxRbp3b_-HoeD8veyJT8_filmotekaonline.jpg create mode 100644 tmp/1738335162669_doYpELRUZYT__NztJLBZW_filmotekaonline.jpg create mode 100644 tmp/1738335393075_bIUTh--HbWnEiSkkBe_6Q_Bez nazwy.jpg diff --git a/app.js b/app.js index 691419d0ef6..d355e78a27a 100644 --- a/app.js +++ b/app.js @@ -4,9 +4,10 @@ import cors from "cors"; import colors from "colors"; import { contactsRouter } from "./routes/api/contactsApi.js"; import { usersRouter } from "./routes/api/userApi.js"; -import passport from "./config/config.js"; +import passport from "./config/configPassport.js"; +import { AVATARS_DIRECTORY, TEMP_DIRECTORY } from "./config/configDirectory.js"; import { auth } from "./middlewares/auth.js"; - +console.log("Directory: ", AVATARS_DIRECTORY); const app = express(); const formatsLogger = app.get("env") === "development" ? "dev" : "short"; @@ -14,7 +15,7 @@ const logger1 = (req, res, next) => { const { method, originalUrl } = req; const date = new Date().toLocaleString(); - console.log(`[${date}] [${method}] - ${originalUrl} app.js`.yellow); + console.log(`[${date}] [${method}] - ${originalUrl} [app.js]`.yellow); next(); }; @@ -24,6 +25,8 @@ app.use(logger(formatsLogger)); app.use(cors()); app.use(express.json()); app.use(passport.initialize()); + +app.use("/avatars", express.static(AVATARS_DIRECTORY)); app.use("/api/", usersRouter); app.use("/api/contacts", auth, contactsRouter); diff --git a/config/configDirectory.js b/config/configDirectory.js new file mode 100644 index 00000000000..206c8cc71e1 --- /dev/null +++ b/config/configDirectory.js @@ -0,0 +1,8 @@ +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const parentDirName = path.resolve(__dirname, ".."); +export const AVATARS_DIRECTORY = path.join(parentDirName, "public", "avatars"); +export const TEMP_DIRECTORY = path.join(parentDirName, "tmp"); diff --git a/config/config.js b/config/configPassport.js similarity index 100% rename from config/config.js rename to config/configPassport.js diff --git a/middlewares/upload.js b/middlewares/upload.js new file mode 100644 index 00000000000..16a30465ecb --- /dev/null +++ b/middlewares/upload.js @@ -0,0 +1,39 @@ +import multer from "multer"; +import { + AVATARS_DIRECTORY, + TEMP_DIRECTORY, +} from "../config/configDirectory.js"; +import { nanoid } from "nanoid"; +const storage = multer.diskStorage({ + destination: TEMP_DIRECTORY, + filename: (req, file, callback) => { + const timestamp = Date.now(); + const id = nanoid(); + const fileName = [timestamp, id, file.originalname].join("_"); + + console.log(`Uploading "${fileName} [upload.js]`.yellow); + + callback(null, fileName); + }, + limits: { fileSize: 1_000_000 }, +}); + +// const fileFilter = (req, file, callback) => { +// const isForbiddenFile = !file.originalname.includes("monke"); +// // const isForbiddenFile = file.originalname.includes("monke"); + +// callback(null, isForbiddenFile); +// }; + +// export const upload = multer({ storage, fileFilter }); + +// const storage = multer.diskStorage({ +// destination: AVATARS_DIRECTORY, +// filename: (req, file, cb) => { +// const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); +// const ext = path.extname(file.originalname); // Pobierz rozszerzenie pliku +// cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`); +// }, +// }); + +export const upload = multer({ storage }); diff --git a/models/users/userShema.js b/models/users/userShema.js index 9ce54277bee..6d8cc7cfc3b 100644 --- a/models/users/userShema.js +++ b/models/users/userShema.js @@ -21,6 +21,10 @@ const userSchema = new mongoose.Schema({ type: String, default: null, }, + avatarURL: { + type: String, + default: "", + }, }); userSchema.methods.setPassword = function (password) { this.password = bCrypt.hashSync(password, bCrypt.genSaltSync(6)); diff --git a/package-lock.json b/package-lock.json index dbe83608f61..46ff70e5997 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,10 +16,13 @@ "cross-env": "7.0.3", "dotenv": "^16.4.7", "express": "4.17.1", + "gravatar": "^1.8.2", + "jimp": "^1.6.0", "joi": "^17.13.3", "jsonwebtoken": "^9.0.2", "mongoose": "^8.9.4", "morgan": "1.10.0", + "multer": "^1.4.5-lts.1", "nanoid": "^5.0.9", "passport": "^0.7.0", "passport-jwt": "^4.0.1" @@ -255,6 +258,401 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@jimp/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", + "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", + "dependencies": { + "@jimp/file-ops": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "await-to-js": "^3.0.0", + "exif-parser": "^0.1.12", + "file-type": "^16.0.0", + "mime": "3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/core/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jimp/diff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", + "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", + "dependencies": { + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "pixelmatch": "^5.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/file-ops": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", + "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-bmp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", + "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "bmp-ts": "^1.0.9" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-gif": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", + "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "gifwrap": "^0.10.1", + "omggif": "^1.0.10" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-jpeg": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", + "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "jpeg-js": "^0.4.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-png": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", + "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "pngjs": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-tiff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", + "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "utif2": "^4.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", + "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", + "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/utils": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", + "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", + "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "tinycolor2": "^1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", + "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", + "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", + "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", + "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", + "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", + "dependencies": { + "@jimp/types": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", + "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", + "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-hash": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", + "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "any-base": "^1.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", + "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz", + "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/types": "1.6.0", + "parse-bmfont-ascii": "^1.0.6", + "parse-bmfont-binary": "^1.0.6", + "parse-bmfont-xml": "^1.1.6", + "simple-xml-to-json": "^1.2.2", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-quantize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", + "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", + "dependencies": { + "image-q": "^4.0.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", + "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", + "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-threshold": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", + "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/types": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", + "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", + "dependencies": { + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", + "dependencies": { + "@jimp/types": "1.6.0", + "tinycolor2": "^1.6.0" + }, + "engines": { + "node": ">=18" + } + }, "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", @@ -371,12 +769,22 @@ "node": ">=6" } }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -485,7 +893,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -496,6 +903,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -509,6 +921,11 @@ "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", @@ -586,6 +1003,14 @@ "node": ">=8" } }, + "node_modules/await-to-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", + "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -629,6 +1054,16 @@ "node": ">=8" } }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==" + }, + "node_modules/bmp-ts": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", + "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==" + }, "node_modules/body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -706,12 +1141,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "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.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -730,6 +1165,22 @@ "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.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -877,6 +1328,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -890,7 +1364,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -901,8 +1374,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/color-support": { "version": "1.1.3", @@ -933,6 +1405,42 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "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/concat-stream/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/concat-stream/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/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -987,6 +1495,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "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", @@ -1017,9 +1530,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1054,6 +1567,14 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -1195,6 +1716,14 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "node_modules/email-validator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", + "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==", + "engines": { + "node": ">4.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1540,9 +2069,9 @@ } }, "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1743,6 +2272,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" + }, "node_modules/express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -1826,10 +2360,26 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "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" @@ -1988,6 +2538,14 @@ "node": ">=10" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -2030,6 +2588,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -2119,8 +2686,25 @@ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", + "node_modules/gravatar": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/gravatar/-/gravatar-1.8.2.tgz", + "integrity": "sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w==", + "dependencies": { + "blueimp-md5": "^2.16.0", + "email-validator": "^2.0.4", + "querystring": "0.2.0", + "yargs": "^15.4.1" + }, + "bin": { + "gravatar": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/has": { + "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, @@ -2191,9 +2775,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "node_modules/http-errors": { @@ -2242,6 +2826,25 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -2257,6 +2860,14 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "dependencies": { + "@types/node": "16.9.1" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2628,11 +3239,53 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "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/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "node_modules/jimp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz", + "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/diff": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-gif": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-blur": "1.6.0", + "@jimp/plugin-circle": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-contain": "1.6.0", + "@jimp/plugin-cover": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-displace": "1.6.0", + "@jimp/plugin-dither": "1.6.0", + "@jimp/plugin-fisheye": "1.6.0", + "@jimp/plugin-flip": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/plugin-mask": "1.6.0", + "@jimp/plugin-print": "1.6.0", + "@jimp/plugin-quantize": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/plugin-rotate": "1.6.0", + "@jimp/plugin-threshold": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/joi": { "version": "17.13.3", "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", @@ -2645,6 +3298,11 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2683,9 +3341,9 @@ "dev": true }, "node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { "minimist": "^1.2.0" @@ -2860,9 +3518,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "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" } @@ -2946,9 +3604,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "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" }, @@ -2957,10 +3615,12 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "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", @@ -3059,9 +3719,9 @@ } }, "node_modules/mongoose": { - "version": "8.9.4", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.4.tgz", - "integrity": "sha512-DndoI01aV/q40P9DiYDXsYjhj8vZjmmuFwcC3Tro5wFznoE1z6Fe2JgMnbLR6ghglym5ziYizSfAJykp+UPZWg==", + "version": "8.9.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.5.tgz", + "integrity": "sha512-SPhOrgBm0nKV3b+IIHGqpUTOmgVL5Z3OO9AwkFEmvOZznXTvplbomstCnPOGAyungtRXE5pJTgKpKcZTdjeESg==", "dependencies": { "bson": "^6.10.1", "kareem": "2.6.3", @@ -3144,6 +3804,34 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "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/multer/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/nanoid": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", @@ -3266,9 +3954,9 @@ } }, "node_modules/nodemon/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -3411,6 +4099,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -3527,14 +4220,19 @@ } }, "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3547,6 +4245,25 @@ "node": ">=6" } }, + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==" + }, + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==" + }, + "node_modules/parse-bmfont-xml": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", + "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", + "dependencies": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.5.0" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3623,13 +4340,25 @@ "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": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -3642,6 +4371,25 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pixelmatch": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", + "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==", + "dependencies": { + "pngjs": "^6.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pixelmatch/node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "engines": { + "node": ">=12.13.0" + } + }, "node_modules/pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -3654,6 +4402,14 @@ "node": ">=4" } }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "engines": { + "node": ">=14.19.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3672,6 +4428,11 @@ "node": ">=4" } }, + "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/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -3737,6 +4498,15 @@ "node": ">=0.6" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -3802,6 +4572,21 @@ "node": ">= 6" } }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3850,6 +4635,14 @@ "node": ">=8" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -3859,6 +4652,11 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -3914,6 +4712,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3938,9 +4741,9 @@ } }, "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -4054,6 +4857,14 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, + "node_modules/simple-xml-to-json": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.3.tgz", + "integrity": "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==", + "engines": { + "node": ">=20.12.2" + } + }, "node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -4093,6 +4904,14 @@ "node": ">= 0.6" } }, + "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.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4199,6 +5018,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4271,6 +5106,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "node_modules/to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -4300,6 +5140,22 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -4368,6 +5224,11 @@ "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/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -4467,6 +5328,14 @@ "node": ">=4" } }, + "node_modules/utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "dependencies": { + "pako": "^1.0.11" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4544,6 +5413,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -4565,9 +5439,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -4616,10 +5490,161 @@ "node": ">=8" } }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "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/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/zod": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } }, "dependencies": { @@ -4748,41 +5773,348 @@ } } }, - "@ecies/ciphers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.2.tgz", - "integrity": "sha512-ylfGR7PyTd+Rm2PqQowG08BCKA22QuX8NzrL+LxAAvazN10DMwdJ2fWwAzRj05FI/M8vNFGm3cv9Wq/GFWCBLg==", - "requires": {} + "@ecies/ciphers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.2.tgz", + "integrity": "sha512-ylfGR7PyTd+Rm2PqQowG08BCKA22QuX8NzrL+LxAAvazN10DMwdJ2fWwAzRj05FI/M8vNFGm3cv9Wq/GFWCBLg==", + "requires": {} + }, + "@eslint/eslintrc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", + "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.20", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@jimp/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", + "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", + "requires": { + "@jimp/file-ops": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "await-to-js": "^3.0.0", + "exif-parser": "^0.1.12", + "file-type": "^16.0.0", + "mime": "3" + }, + "dependencies": { + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" + } + } + }, + "@jimp/diff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", + "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", + "requires": { + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "pixelmatch": "^5.3.0" + } + }, + "@jimp/file-ops": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", + "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==" + }, + "@jimp/js-bmp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", + "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "bmp-ts": "^1.0.9" + } + }, + "@jimp/js-gif": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", + "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "gifwrap": "^0.10.1", + "omggif": "^1.0.10" + } + }, + "@jimp/js-jpeg": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", + "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "jpeg-js": "^0.4.4" + } + }, + "@jimp/js-png": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", + "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "pngjs": "^7.0.0" + } + }, + "@jimp/js-tiff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", + "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "utif2": "^4.1.0" + } + }, + "@jimp/plugin-blit": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", + "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", + "requires": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-blur": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", + "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/utils": "1.6.0" + } + }, + "@jimp/plugin-circle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", + "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", + "requires": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-color": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", + "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "tinycolor2": "^1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-contain": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", + "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-cover": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", + "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-crop": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", + "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-displace": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", + "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", + "requires": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } }, - "@eslint/eslintrc": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", - "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", - "dev": true, + "@jimp/plugin-dither": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", + "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "lodash": "^4.17.20", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" + "@jimp/types": "1.6.0" } }, - "@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + "@jimp/plugin-fisheye": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", + "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", + "requires": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "@jimp/plugin-flip": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", + "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", "requires": { - "@hapi/hoek": "^9.0.0" + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-hash": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", + "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "any-base": "^1.1.0" + } + }, + "@jimp/plugin-mask": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", + "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", + "requires": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-print": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz", + "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/types": "1.6.0", + "parse-bmfont-ascii": "^1.0.6", + "parse-bmfont-binary": "^1.0.6", + "parse-bmfont-xml": "^1.1.6", + "simple-xml-to-json": "^1.2.2", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-quantize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", + "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", + "requires": { + "image-q": "^4.0.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-resize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", + "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-rotate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", + "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-threshold": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", + "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/types": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", + "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", + "requires": { + "zod": "^3.23.8" + } + }, + "@jimp/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", + "requires": { + "@jimp/types": "1.6.0", + "tinycolor2": "^1.6.0" } }, "@mapbox/node-pre-gyp": { @@ -4870,12 +6202,22 @@ "defer-to-connect": "^1.0.1" } }, + "@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + }, "@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -4960,11 +6302,15 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -4975,6 +6321,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -5033,6 +6384,11 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "await-to-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", + "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5066,6 +6422,16 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==" + }, + "bmp-ts": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", + "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -5132,12 +6498,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "bson": { @@ -5150,6 +6516,19 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "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==" + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -5252,6 +6631,28 @@ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -5265,7 +6666,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -5273,8 +6673,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "color-support": { "version": "1.1.3", @@ -5296,6 +6695,41 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "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" + } + }, + "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==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -5338,6 +6772,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "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==" + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -5356,9 +6795,9 @@ } }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5379,6 +6818,11 @@ "ms": "2.1.2" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -5488,6 +6932,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "email-validator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", + "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -5752,9 +7201,9 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -5898,6 +7347,11 @@ } } }, + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -5977,10 +7431,20 @@ "flat-cache": "^3.0.4" } }, + "file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "requires": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + } + }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -6108,6 +7572,11 @@ "wide-align": "^1.1.2" } }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -6138,6 +7607,15 @@ "get-intrinsic": "^1.1.1" } }, + "gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "requires": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -6203,6 +7681,17 @@ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "gravatar": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/gravatar/-/gravatar-1.8.2.tgz", + "integrity": "sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w==", + "requires": { + "blueimp-md5": "^2.16.0", + "email-validator": "^2.0.4", + "querystring": "0.2.0", + "yargs": "^15.4.1" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -6251,9 +7740,9 @@ "dev": true }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "http-errors": { @@ -6290,6 +7779,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -6302,6 +7796,14 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "requires": { + "@types/node": "16.9.1" + } + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -6550,11 +8052,50 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "jimp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz", + "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/diff": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-gif": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-blur": "1.6.0", + "@jimp/plugin-circle": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-contain": "1.6.0", + "@jimp/plugin-cover": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-displace": "1.6.0", + "@jimp/plugin-dither": "1.6.0", + "@jimp/plugin-fisheye": "1.6.0", + "@jimp/plugin-flip": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/plugin-mask": "1.6.0", + "@jimp/plugin-print": "1.6.0", + "@jimp/plugin-quantize": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/plugin-rotate": "1.6.0", + "@jimp/plugin-threshold": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0" + } + }, "joi": { "version": "17.13.3", "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", @@ -6567,6 +8108,11 @@ "@sideway/pinpoint": "^2.0.0" } }, + "jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6602,9 +8148,9 @@ "dev": true }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -6751,9 +8297,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -6812,18 +8358,17 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { "version": "5.0.0", @@ -6874,9 +8419,9 @@ } }, "mongoose": { - "version": "8.9.4", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.4.tgz", - "integrity": "sha512-DndoI01aV/q40P9DiYDXsYjhj8vZjmmuFwcC3Tro5wFznoE1z6Fe2JgMnbLR6ghglym5ziYizSfAJykp+UPZWg==", + "version": "8.9.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.5.tgz", + "integrity": "sha512-SPhOrgBm0nKV3b+IIHGqpUTOmgVL5Z3OO9AwkFEmvOZznXTvplbomstCnPOGAyungtRXE5pJTgKpKcZTdjeESg==", "requires": { "bson": "^6.10.1", "kareem": "2.6.3", @@ -6944,6 +8489,30 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "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==", + "requires": { + "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" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + } + } + }, "nanoid": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", @@ -7028,9 +8597,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "supports-color": { @@ -7129,6 +8698,11 @@ "es-abstract": "^1.19.1" } }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -7215,13 +8789,18 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -7231,6 +8810,25 @@ "callsites": "^3.0.0" } }, + "parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==" + }, + "parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==" + }, + "parse-bmfont-xml": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", + "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", + "requires": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.5.0" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -7285,19 +8883,39 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==" + }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, + "pixelmatch": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", + "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==", + "requires": { + "pngjs": "^6.0.0" + }, + "dependencies": { + "pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==" + } + } + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -7307,6 +8925,11 @@ "find-up": "^2.1.0" } }, + "pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==" + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7319,6 +8942,11 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "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==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -7369,6 +8997,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7421,6 +9054,14 @@ "util-deprecate": "^1.0.1" } }, + "readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "requires": { + "readable-stream": "^3.6.0" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -7454,12 +9095,22 @@ "rc": "^1.2.8" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -7503,6 +9154,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, "semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -7518,9 +9174,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -7622,6 +9278,11 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, + "simple-xml-to-json": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.3.tgz", + "integrity": "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==" + }, "slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -7652,6 +9313,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -7722,6 +9388,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "requires": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -7783,6 +9458,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -7803,6 +9483,15 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "requires": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + } + }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -7856,6 +9545,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -7937,6 +9631,14 @@ "prepend-http": "^2.0.0" } }, + "utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "requires": { + "pako": "^1.0.11" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7993,6 +9695,11 @@ "is-symbol": "^1.0.3" } }, + "which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -8011,9 +9718,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "wrap-ansi": { @@ -8050,10 +9757,123 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" + }, + "xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + } + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + } + } + }, + "zod": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==" } } } diff --git a/package.json b/package.json index 6e9b67d1c2b..08f6e485cf9 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,13 @@ "cross-env": "7.0.3", "dotenv": "^16.4.7", "express": "4.17.1", + "gravatar": "^1.8.2", + "jimp": "^1.6.0", "joi": "^17.13.3", "jsonwebtoken": "^9.0.2", "mongoose": "^8.9.4", "morgan": "1.10.0", + "multer": "^1.4.5-lts.1", "nanoid": "^5.0.9", "passport": "^0.7.0", "passport-jwt": "^4.0.1" diff --git a/public/avatars/679417264f121b31700ef133-sniezek-header.jpg b/public/avatars/679417264f121b31700ef133-sniezek-header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d4d743655595bed7ca6bb1c0be280d2d61e77af0 GIT binary patch literal 255079 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