From 84799ef6023f85d21e8042a5f2482c6ec0c3f631 Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Fri, 10 Jan 2025 17:47:43 +0100 Subject: [PATCH 01/13] =?UTF-8?q?Commit=20pierwszy=20testowy=20-=20czy=20w?= =?UTF-8?q?szystko=20dzia=C5=82a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routes/api/contacts.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/routes/api/contacts.js b/routes/api/contacts.js index a60ebd69231..ba25acb0a49 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,25 +1,25 @@ -const express = require('express') +const express = require("express"); -const router = express.Router() +const router = express.Router(); -router.get('/', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.get("/", async (req, res, next) => { + res.json({ message: "template message by gf" }); +}); -router.get('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.get("/:contactId", async (req, res, next) => { + res.json({ message: "template message" }); +}); -router.post('/', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.post("/", async (req, res, next) => { + res.json({ message: "template message" }); +}); -router.delete('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.delete("/:contactId", async (req, res, next) => { + res.json({ message: "template message" }); +}); -router.put('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +router.put("/:contactId", async (req, res, next) => { + res.json({ message: "template message" }); +}); -module.exports = router +module.exports = router; From 8a7c139633ed8968468441c2c4fc4169cd2da41b Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Fri, 10 Jan 2025 19:17:17 +0100 Subject: [PATCH 02/13] zadanie nr 2 --- app.js | 30 +++++------ models/contacts.js | 120 ++++++++++++++++++++++++++++++++++++++--- package-lock.json | 117 +++++++++++++++++++++++++++++++++++++++- package.json | 6 ++- routes/api/contacts.js | 112 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 354 insertions(+), 31 deletions(-) diff --git a/app.js b/app.js index 40fd9bc167f..1df09b71cd0 100644 --- a/app.js +++ b/app.js @@ -1,25 +1,25 @@ -const express = require('express') -const logger = require('morgan') -const cors = require('cors') +const express = require("express"); +const logger = require("morgan"); +const cors = require("cors"); -const contactsRouter = require('./routes/api/contacts') +const contactsRouter = require("./routes/api/contacts"); -const app = express() +const app = express(); -const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short' +const formatsLogger = app.get("env") === "development" ? "dev" : "short"; -app.use(logger(formatsLogger)) -app.use(cors()) -app.use(express.json()) +app.use(logger(formatsLogger)); +app.use(cors()); +app.use(express.json()); -app.use('/api/contacts', contactsRouter) +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 }) -}) + res.status(500).json({ message: err.message }); +}); -module.exports = app +module.exports = app; diff --git a/models/contacts.js b/models/contacts.js index 409d11c7c09..e13dcaab1ff 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -1,14 +1,120 @@ -// const fs = require('fs/promises') +const { v4: uuidv4 } = require("uuid"); +const fs = require("fs").promises; +const path = require("path"); +const contactsPath = path.join(__dirname, "contacts.json"); -const listContacts = async () => {} +const listContacts = async () => { + try { + const data = await fs.readFile(contactsPath); + const contacts = JSON.parse(data); + return contacts; + } catch (err) { + console.error("Error reading contacts file in listContacts:", err); + throw err; + } +}; -const getContactById = async (contactId) => {} +const getContactById = async (contactId) => { + let contacts; -const removeContact = async (contactId) => {} + try { + const data = await fs.readFile(contactsPath); + contacts = JSON.parse(data); + } catch (err) { + console.error("Error reading contacts file in getContactById:", err); + throw err; + } -const addContact = async (body) => {} + const contact = contacts.filter((contact) => contact.id === contactId); + if (contact.length === 0) { + return null; + } + return contact; +}; -const updateContact = async (contactId, body) => {} +const removeContact = async (contactId) => { + let contacts; + + try { + contacts = await listContacts(); + } catch (err) { + console.error("Error reading contacts file in removeContact:", err); + throw err; + } + + const index = contacts.findIndex((contact) => contact.id === contactId); + if (index === -1) { + return null; + } + + contacts.splice(index, 1); + + try { + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + } catch (err) { + console.error("Error writing to contacts file in removeContact:", err); + throw err; + } + + return contacts; +}; + +const addContact = async (body) => { + let contacts; + + try { + contacts = await listContacts(); + } catch (err) { + console.error("Error reading contacts file in addContact:", err); + throw err; + } + + const newContact = { + id: uuidv4(), + ...body, + }; + + contacts.push(newContact); + + try { + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + return newContact; + } catch (err) { + console.error("Error writing to contacts file in addContact:", err); + throw err; + } +}; + +const updateContact = async (contactId, body) => { + let contacts; + + try { + contacts = await listContacts(); + } catch (err) { + console.error("Error reading contacts file in updateContact:", err); + throw err; + } + + const index = contacts.findIndex((contact) => contact.id === contactId); + if (index === -1) { + return null; + } + + const newContact = { + id: uuidv4(), + ...body, + }; + + contacts.splice(index, 1, newContact); + + try { + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + return newContact; + } catch (err) { + console.error("Error writing to contacts file in updateContact:", err); + throw err; + } +}; module.exports = { listContacts, @@ -16,4 +122,4 @@ module.exports = { removeContact, addContact, updateContact, -} +}; diff --git a/package-lock.json b/package-lock.json index e6d047044e5..0f1b50b8478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,10 @@ "dependencies": { "cors": "2.8.5", "cross-env": "7.0.3", - "express": "4.17.1", - "morgan": "1.10.0" + "express": "^4.17.1", + "joi": "^17.13.3", + "morgan": "1.10.0", + "uuid": "^11.0.5" }, "devDependencies": { "eslint": "7.19.0", @@ -141,6 +143,42 @@ "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==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "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==", + "license": "BSD-3-Clause", + "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==", + "license": "BSD-3-Clause" + }, + "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==", + "license": "BSD-3-Clause" + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -1354,6 +1392,7 @@ "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "license": "MIT", "dependencies": { "accepts": "~1.3.7", "array-flatten": "1.1.1", @@ -2166,6 +2205,19 @@ "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==", + "license": "BSD-3-Clause", + "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", @@ -3544,6 +3596,19 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -3757,6 +3822,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", @@ -5269,6 +5365,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", @@ -6326,6 +6434,11 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", diff --git a/package.json b/package.json index 5045e827160..e101f6def06 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ "dependencies": { "cors": "2.8.5", "cross-env": "7.0.3", - "express": "4.17.1", - "morgan": "1.10.0" + "express": "^4.17.1", + "joi": "^17.13.3", + "morgan": "1.10.0", + "uuid": "^11.0.5" }, "devDependencies": { "eslint": "7.19.0", diff --git a/routes/api/contacts.js b/routes/api/contacts.js index ba25acb0a49..47437644d82 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,25 +1,127 @@ +const Joi = require("joi"); +const contactsFunctions = require("../../models/contacts.js"); + +const schema = Joi.object({ + name: Joi.string().required(), + email: Joi.string() + .email({ + minDomainSegments: 2, + tlds: { allow: ["com", "net"] }, + }) + .required(), + phone: Joi.number().integer().positive().required(), +}); + const express = require("express"); const router = express.Router(); router.get("/", async (req, res, next) => { - res.json({ message: "template message by gf" }); + try { + const contacts = await contactsFunctions.listContacts(); + res.json({ + status: 200, + data: { contacts }, + }); + } catch (err) { + console.error(err); + next(err); + } }); router.get("/:contactId", async (req, res, next) => { - res.json({ message: "template message" }); + try { + const contactId = req.params.contactId; + const contact = await contactsFunctions.getContactById(contactId); + if (contact) { + res.json({ + status: 200, + data: { contact }, + }); + } else { + res.status(404).json({ + status: 404, + message: "Not found", + }); + } + } catch (err) { + console.error(err); + next(err); + } }); router.post("/", async (req, res, next) => { - res.json({ message: "template message" }); + const { error } = schema.validate(req.body); + if (error) { + res.status(400).json({ + status: 400, + message: error.message, + }); + } else { + try { + const newContact = await contactsFunctions.addContact(req.body); + res.json({ + status: 201, + data: { newContact }, + }); + } catch (err) { + console.error(err); + next(err); + } + } }); router.delete("/:contactId", async (req, res, next) => { - res.json({ message: "template message" }); + try { + const contactId = req.params.contactId; + const index = await contactsFunctions.removeContact(contactId); + if (index !== -1) { + res.json({ + status: 200, + message: "contact deleted", + }); + } else { + res.status(404).json({ + status: 404, + message: "Not found", + }); + } + } catch (err) { + console.error(err); + next(err); + } }); router.put("/:contactId", async (req, res, next) => { - res.json({ message: "template message" }); + const contactId = req.params.contactId; + const { error } = schema.validate(req.body); + if (error) { + res.status(400).json({ + status: 400, + message: error.message, + }); + } else { + try { + const newContact = await contactsFunctions.updateContact( + contactId, + req.body + ); + if (newContact) { + res.json({ + status: 200, + data: { newContact }, + }); + } else { + res.status(404).json({ + status: 404, + message: "Not found", + }); + } + } catch (err) { + console.error(err); + next(err); + } + } }); module.exports = router; From fbc5933259635485066b2d9ef9a3b49bd1b25b2e Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Fri, 17 Jan 2025 21:15:51 +0100 Subject: [PATCH 03/13] zadanie nr 3 - startowy commit --- .env.example | 1 + controllers/contacts.js | 162 ++++++++++++++++ models/contacts.js | 125 ------------- models/contacts.json | 62 ------- package-lock.json | 368 +++++++++++++++++++++++++++++++++++-- package.json | 2 + routes/api/contacts.js | 129 +------------ server.js | 21 ++- service/index.js | 33 ++++ service/schemas/contact.js | 23 +++ 10 files changed, 599 insertions(+), 327 deletions(-) create mode 100644 .env.example create mode 100644 controllers/contacts.js delete mode 100644 models/contacts.js delete mode 100644 models/contacts.json create mode 100644 service/index.js create mode 100644 service/schemas/contact.js diff --git a/.env.example b/.env.example new file mode 100644 index 00000000000..adfd4ccd0bb --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +DB_URL= \ No newline at end of file diff --git a/controllers/contacts.js b/controllers/contacts.js new file mode 100644 index 00000000000..d9f9c72f88a --- /dev/null +++ b/controllers/contacts.js @@ -0,0 +1,162 @@ +const service = require("../service"); +const Joi = require("joi"); + +const schema = Joi.object({ + name: Joi.string().required(), + email: Joi.string() + .email({ + minDomainSegments: 2, + tlds: { allow: ["com", "net"] }, + }) + .required(), + phone: Joi.number().integer().positive().required(), + favorite: Joi.bool(), +}); + +const get = async (req, res, next) => { + try { + const results = await service.getAllContacts(); + res.json({ + status: 200, + data: { contacts: results }, + }); + } catch (err) { + console.error("Error getting contacts list:", err); + next(err); + } +}; + +const getById = async (req, res, next) => { + const id = req.params.contactId; + + try { + const result = await service.getContactById(id); + if (result) { + return res.json({ + status: 200, + data: { contact: result }, + }); + } + + res.status(404).json({ + status: 404, + message: "Not found", + }); + } catch (err) { + console.error("Error getting contact:", err); + next(err); + } +}; + +const remove = async (req, res, next) => { + const id = req.params.contactId; + + try { + const result = await service.removeContact(id); + if (result) { + return res.json({ + status: 200, + message: "Contact deleted", + }); + } + + res.status(404).json({ + status: 404, + message: "Not found", + }); + } catch (err) { + console.error("Error removing contact:", err); + next(err); + } +}; + +const create = async (req, res, next) => { + const { error } = schema.validate(req.body); + + if (error) { + return res.status(400).json({ + status: 400, + message: error.message, + }); + } + + try { + const result = await service.createContact(req.body); + res.status(201).json({ + status: 201, + data: { newContact: result }, + }); + } catch (err) { + console.error("Error creating contact:", err); + next(err); + } +}; + +const update = async (req, res, next) => { + const id = req.params.contactId; + const { error } = schema.validate(req.body); + + if (error) { + return res.status(400).json({ + status: 400, + message: error.message, + }); + } + + try { + const result = await service.updateContact(id, req.body); + if (result) { + return res.json({ + status: 200, + data: { newContact: result }, + }); + } + + res.status(404).json({ + status: 404, + message: "Not found", + }); + } catch (err) { + console.error("Error updating contact:", err); + next(err); + } +}; + +const updateStatus = async (req, res, next) => { + const id = req.params.contactId; + const { error } = req.body; + + if (error) { + return res.status(400).json({ + status: 400, + message: error.message, + }); + } + + try { + const result = await service.updateContact(id, req.body); + if (result) { + return res.json({ + status: 200, + data: { updatedContact: result }, + }); + } + + res.status(404).json({ + status: 404, + message: "Not found", + }); + } catch (err) { + console.error("Error updating favorite status in contact:", err); + next(err); + } +}; + +module.exports = { + get, + getById, + remove, + create, + update, + updateStatus, +}; diff --git a/models/contacts.js b/models/contacts.js deleted file mode 100644 index e13dcaab1ff..00000000000 --- a/models/contacts.js +++ /dev/null @@ -1,125 +0,0 @@ -const { v4: uuidv4 } = require("uuid"); -const fs = require("fs").promises; -const path = require("path"); -const contactsPath = path.join(__dirname, "contacts.json"); - -const listContacts = async () => { - try { - const data = await fs.readFile(contactsPath); - const contacts = JSON.parse(data); - return contacts; - } catch (err) { - console.error("Error reading contacts file in listContacts:", err); - throw err; - } -}; - -const getContactById = async (contactId) => { - let contacts; - - try { - const data = await fs.readFile(contactsPath); - contacts = JSON.parse(data); - } catch (err) { - console.error("Error reading contacts file in getContactById:", err); - throw err; - } - - const contact = contacts.filter((contact) => contact.id === contactId); - if (contact.length === 0) { - return null; - } - return contact; -}; - -const removeContact = async (contactId) => { - let contacts; - - try { - contacts = await listContacts(); - } catch (err) { - console.error("Error reading contacts file in removeContact:", err); - throw err; - } - - const index = contacts.findIndex((contact) => contact.id === contactId); - if (index === -1) { - return null; - } - - contacts.splice(index, 1); - - try { - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - } catch (err) { - console.error("Error writing to contacts file in removeContact:", err); - throw err; - } - - return contacts; -}; - -const addContact = async (body) => { - let contacts; - - try { - contacts = await listContacts(); - } catch (err) { - console.error("Error reading contacts file in addContact:", err); - throw err; - } - - const newContact = { - id: uuidv4(), - ...body, - }; - - contacts.push(newContact); - - try { - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - return newContact; - } catch (err) { - console.error("Error writing to contacts file in addContact:", err); - throw err; - } -}; - -const updateContact = async (contactId, body) => { - let contacts; - - try { - contacts = await listContacts(); - } catch (err) { - console.error("Error reading contacts file in updateContact:", err); - throw err; - } - - const index = contacts.findIndex((contact) => contact.id === contactId); - if (index === -1) { - return null; - } - - const newContact = { - id: uuidv4(), - ...body, - }; - - contacts.splice(index, 1, newContact); - - try { - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - return newContact; - } catch (err) { - console.error("Error writing to contacts file in updateContact:", err); - throw err; - } -}; - -module.exports = { - listContacts, - getContactById, - removeContact, - addContact, - updateContact, -}; diff --git a/models/contacts.json b/models/contacts.json deleted file mode 100644 index a21679132de..00000000000 --- a/models/contacts.json +++ /dev/null @@ -1,62 +0,0 @@ -[ - { - "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", - "email": "mattis.Cras@nonenimMauris.net", - "phone": "(542) 451-7038" - }, - { - "id": "vza2RIzNGIwutCVCs4mCL", - "name": "Wylie Pope", - "email": "est@utquamvel.net", - "phone": "(692) 802-2949" - }, - { - "id": "05olLMgyVQdWRwgKfg5J6", - "name": "Cyrus Jackson", - "email": "nibh@semsempererat.com", - "phone": "(501) 472-5218" - }, - { - "id": "1DEXoP8AuCGYc1YgoQ6hw", - "name": "Abbot Franks", - "email": "scelerisque@magnis.org", - "phone": "(186) 568-3720" - }, - { - "id": "Z5sbDlS7pCzNsnAHLtDJd", - "name": "Reuben Henry", - "email": "pharetra.ut@dictum.co.uk", - "phone": "(715) 598-5792" - }, - { - "id": "C9sjBfCo4UJCWjzBnOtxl", - "name": "Simon Morton", - "email": "dui.Fusce.diam@Donec.com", - "phone": "(233) 738-2360" - }, - { - "id": "e6ywwRe4jcqxXfCZOj_1e", - "name": "Thomas Lucas", - "email": "nec@Nulla.com", - "phone": "(704) 398-7993" - }, - { - "id": "rsKkOQUi80UsgVPCcLZZW", - "name": "Alec Howard", - "email": "Donec.elementum@scelerisquescelerisquedui.net", - "phone": "(748) 206-2688" - } -] diff --git a/package-lock.json b/package-lock.json index 0f1b50b8478..b96d0244e0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,10 @@ "dependencies": { "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.7", "express": "^4.17.1", "joi": "^17.13.3", + "mongoose": "^8.9.5", "morgan": "1.10.0", "uuid": "^11.0.5" }, @@ -158,6 +160,15 @@ "@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==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -206,6 +217,21 @@ "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -490,6 +516,15 @@ "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==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -766,7 +801,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" }, @@ -861,6 +895,18 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "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", @@ -2267,6 +2313,15 @@ "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==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -2379,6 +2434,12 @@ "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==", + "license": "MIT" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -2449,6 +2510,90 @@ "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==", + "license": "Apache-2.0", + "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.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.9.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.5.tgz", + "integrity": "sha512-SPhOrgBm0nKV3b+IIHGqpUTOmgVL5Z3OO9AwkFEmvOZznXTvplbomstCnPOGAyungtRXE5pJTgKpKcZTdjeESg==", + "license": "MIT", + "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==", + "license": "MIT" + }, "node_modules/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -2485,11 +2630,31 @@ "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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/natural-compare": { "version": "1.4.0", @@ -2915,10 +3080,10 @@ } }, "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==", + "license": "MIT", "engines": { "node": ">=6" } @@ -3237,6 +3402,12 @@ "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==", + "license": "MIT" + }, "node_modules/signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", @@ -3260,6 +3431,15 @@ "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==", + "license": "MIT", + "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", @@ -3444,6 +3624,18 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -3623,6 +3815,28 @@ "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==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3835,6 +4049,14 @@ "@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" + } + }, "@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -3874,6 +4096,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", @@ -4093,6 +4328,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", @@ -4294,7 +4534,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" } @@ -4363,6 +4602,11 @@ "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", @@ -5420,6 +5664,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", @@ -5507,6 +5756,11 @@ "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", @@ -5556,6 +5810,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.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "requires": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "mongoose": { + "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", + "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", @@ -5588,11 +5882,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==" }, "natural-compare": { "version": "1.4.0", @@ -5903,10 +6209,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", @@ -6155,6 +6460,11 @@ "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", @@ -6172,6 +6482,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", @@ -6312,6 +6630,14 @@ "nopt": "~1.0.10" } }, + "tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "requires": { + "punycode": "^2.3.1" + } + }, "tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -6450,6 +6776,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": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", + "requires": { + "tr46": "^5.0.0", + "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 e101f6def06..e777040e92e 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ "dependencies": { "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.7", "express": "^4.17.1", "joi": "^17.13.3", + "mongoose": "^8.9.5", "morgan": "1.10.0", "uuid": "^11.0.5" }, diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 47437644d82..fe81eeecf20 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,127 +1,12 @@ -const Joi = require("joi"); -const contactsFunctions = require("../../models/contacts.js"); - -const schema = Joi.object({ - name: Joi.string().required(), - email: Joi.string() - .email({ - minDomainSegments: 2, - tlds: { allow: ["com", "net"] }, - }) - .required(), - phone: Joi.number().integer().positive().required(), -}); - const express = require("express"); - +const ctrlContact = require("../../controller/contacts"); const router = express.Router(); -router.get("/", async (req, res, next) => { - try { - const contacts = await contactsFunctions.listContacts(); - res.json({ - status: 200, - data: { contacts }, - }); - } catch (err) { - console.error(err); - next(err); - } -}); - -router.get("/:contactId", async (req, res, next) => { - try { - const contactId = req.params.contactId; - const contact = await contactsFunctions.getContactById(contactId); - if (contact) { - res.json({ - status: 200, - data: { contact }, - }); - } else { - res.status(404).json({ - status: 404, - message: "Not found", - }); - } - } catch (err) { - console.error(err); - next(err); - } -}); - -router.post("/", async (req, res, next) => { - const { error } = schema.validate(req.body); - if (error) { - res.status(400).json({ - status: 400, - message: error.message, - }); - } else { - try { - const newContact = await contactsFunctions.addContact(req.body); - res.json({ - status: 201, - data: { newContact }, - }); - } catch (err) { - console.error(err); - next(err); - } - } -}); - -router.delete("/:contactId", async (req, res, next) => { - try { - const contactId = req.params.contactId; - const index = await contactsFunctions.removeContact(contactId); - if (index !== -1) { - res.json({ - status: 200, - message: "contact deleted", - }); - } else { - res.status(404).json({ - status: 404, - message: "Not found", - }); - } - } catch (err) { - console.error(err); - next(err); - } -}); - -router.put("/:contactId", async (req, res, next) => { - const contactId = req.params.contactId; - const { error } = schema.validate(req.body); - if (error) { - res.status(400).json({ - status: 400, - message: error.message, - }); - } else { - try { - const newContact = await contactsFunctions.updateContact( - contactId, - req.body - ); - if (newContact) { - res.json({ - status: 200, - data: { newContact }, - }); - } else { - res.status(404).json({ - status: 404, - message: "Not found", - }); - } - } catch (err) { - console.error(err); - next(err); - } - } -}); +router.get("/", ctrlContact.get); +router.get("/:contactId", ctrlContact.getById); +router.post("/", ctrlContact.create); +router.put("/:contactId", ctrlContact.update); +router.delete("/:contactId", ctrlContact.remove); +router.patch("/:contactId/status", ctrlContact.updateStatus); module.exports = router; diff --git a/server.js b/server.js index db330824656..5fc65a3c035 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,18 @@ -const app = require('./app') +const mongoose = require("mongoose"); +const app = require("./app"); -app.listen(3000, () => { - console.log("Server running. Use our API on port: 3000") -}) +const MAIN_PORT = process.env.PORT || 3000; +const uriDb = process.env.DB_URL; + +const connection = mongoose.connect(uriDb); + +connection + .then(() => { + app.listen(MAIN_PORT, function () { + console.log("Database connection successful"); + }); + }) + .catch((err) => { + console.log(`Server not running. Error message: ${err.message}`); + process.exit(1); + }); diff --git a/service/index.js b/service/index.js new file mode 100644 index 00000000000..ba96ff17d0e --- /dev/null +++ b/service/index.js @@ -0,0 +1,33 @@ +const Contact = require("./schemas/contact"); + +const getAllContacts = async () => { + return Contact.find(); +}; + +const getContactById = (id) => { + return Contact.findOne({ _id: id }); +}; + +const createContact = ({ name, email, phone }) => { + return Contact.create({ name, email, phone }); +}; + +const removeContact = (id) => { + return Contact.findByIdAndDelete({ _id: id }); +}; + +const updateContact = (id, fields) => { + return Contact.findByIdAndUpdate( + { _id: id }, + { $set: fields }, + { new: true } + ); +}; + +module.exports = { + getAllContacts, + getContactById, + createContact, + removeContact, + updateContact, +}; diff --git a/service/schemas/contact.js b/service/schemas/contact.js new file mode 100644 index 00000000000..c74a19f164c --- /dev/null +++ b/service/schemas/contact.js @@ -0,0 +1,23 @@ +const mongoose = require("mongoose"); +const Schema = mongoose.Schema; + +const contact = new Schema({ + name: { + type: String, + required: [true, "Set name for contact"], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, +}); + +const Contact = mongoose.model("contacts", contact); + +module.exports = Contact; From af41696f74d387da305628874d416e981b4e5b36 Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Sat, 18 Jan 2025 01:05:27 +0100 Subject: [PATCH 04/13] dodanie s w controllers oraz dodanie zapisu require(dotenv).config() --- routes/api/contacts.js | 2 +- server.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/routes/api/contacts.js b/routes/api/contacts.js index fe81eeecf20..6b5fb706c40 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,5 +1,5 @@ const express = require("express"); -const ctrlContact = require("../../controller/contacts"); +const ctrlContact = require("../../controllers/contacts"); const router = express.Router(); router.get("/", ctrlContact.get); diff --git a/server.js b/server.js index 5fc65a3c035..a8c4e18a492 100644 --- a/server.js +++ b/server.js @@ -1,3 +1,5 @@ +require("dotenv").config(); + const mongoose = require("mongoose"); const app = require("./app"); From b04d06ff40f173bff4a0e9e9d004d3a49dd7eafe Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Fri, 24 Jan 2025 18:31:57 +0100 Subject: [PATCH 05/13] startowe - zadanie 04 --- .env.example | 4 +- app.js | 11 +- controllers/user.js | 232 ++++++++++++++++++++++++++ package-lock.json | 322 +++++++++++++++++++++++++++++++------ package.json | 3 + passport.js | 29 ++++ routes/api/index.js | 10 ++ routes/api/user.js | 11 ++ server.js | 2 - service/index.js | 3 +- service/schemas/contact.js | 9 +- 11 files changed, 578 insertions(+), 58 deletions(-) create mode 100644 controllers/user.js create mode 100644 passport.js create mode 100644 routes/api/index.js create mode 100644 routes/api/user.js diff --git a/.env.example b/.env.example index adfd4ccd0bb..b8222b0b36d 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,3 @@ -DB_URL= \ No newline at end of file +MAIN_PORT= +DB_URL= +AUTH_SECRET= \ No newline at end of file diff --git a/app.js b/app.js index 1df09b71cd0..e4583f4b0f4 100644 --- a/app.js +++ b/app.js @@ -1,8 +1,10 @@ const express = require("express"); const logger = require("morgan"); const cors = require("cors"); +require("./passport"); +require("dotenv").config(); -const contactsRouter = require("./routes/api/contacts"); +const apiRouter = require("./routes/api/index"); const app = express(); @@ -11,14 +13,13 @@ const formatsLogger = app.get("env") === "development" ? "dev" : "short"; app.use(logger(formatsLogger)); app.use(cors()); app.use(express.json()); +app.use("/api", apiRouter); -app.use("/api/contacts", contactsRouter); - -app.use((req, res) => { +app.use((_, res, __) => { res.status(404).json({ message: "Not found" }); }); -app.use((err, req, res, next) => { +app.use((err, _, res, __) => { res.status(500).json({ message: err.message }); }); diff --git a/controllers/user.js b/controllers/user.js new file mode 100644 index 00000000000..304b1176315 --- /dev/null +++ b/controllers/user.js @@ -0,0 +1,232 @@ +const User = require("../service/schemas/user"); +const Joi = require("joi"); +const passport = require("passport"); +const jwt = require("jsonwebtoken"); + +const schema = Joi.object({ + password: Joi.string().required(), + email: Joi.string() + .email({ + minDomainSegments: 2, + tlds: { allow: ["com", "net"] }, + }) + .required(), + subscription: Joi.string() + .valid("starter", "pro", "business") + .default("starter"), + token: Joi.string().default(null), +}); + +const auth = (req, res, next) => { + passport.authenticate("jwt", { session: false }, (err, user) => { + if (!user || err) { + return res.status(401).json({ + status: "401 Unauthorized", + contentType: "application/json", + responseBody: { message: "Not authorized" }, + }); + } + + req.user = user; + next(); + })(req, res, next); +}; + +const register = async (req, res, next) => { + const { error } = schema.validate(req.body); + const user = await User.findOne({ email: req.body.email }); + + if (error) { + return res.status(400).json({ + status: "400 Bad Request", + contentType: "application/json", + responseBody: error.message, + }); + } + + if (user) { + return res.status(409).json({ + status: "409 Conflict", + contentType: "application/json", + responseBody: { + message: "Email in use", + }, + }); + } + + try { + const newUser = new User({ + email: req.body.email, + subscription: "starter", + }); + await newUser.setPassword(req.body.password); + await newUser.save(); + + res.status(201).json({ + status: "201 Created", + contentType: "application/json", + responseBody: { + user: { + email: req.body.email, + subscription: "starter", + }, + }, + }); + } catch (err) { + next(err); + } +}; + +const login = async (req, res, next) => { + const { error } = schema.validate(req.body); + + if (error) { + return res.status(400).json({ + status: "400 Bad Request", + contentType: "application/json", + responseBody: error.message, + }); + } + + const user = await User.findOne({ email: req.body.email }); + + if (!user) { + return res.status(401).json({ + status: "401 Unauthorized", + responseBody: { + message: "User with this email doesn't exist", + }, + }); + } + + const isPasswordValid = await user.validatePassword(req.body.password); + + if (!isPasswordValid) { + return res.status(401).json({ + status: "401 Unauthorized", + responseBody: { + message: "Incorrect password", + }, + }); + } + + try { + const payload = { + id: user._id, + username: user.username, + }; + const secret = process.env.AUTH_SECRET; + const token = jwt.sign(payload, secret, { expiresIn: "12h" }); + + user.token = token; + await user.save(); + + return res.json({ + status: "200 OK", + contentType: "application/json", + responseBody: { + token: token, + user: { + email: req.body.email, + subscription: user.subscription, + }, + }, + }); + } catch (err) { + next(err); + } +}; + +const logout = async (req, res, next) => { + try { + const userId = req.user._id; + const user = await User.findById(userId); + + user.token = null; + await user.save(); + + return res.status(204).send(); + } catch (err) { + next(err); + } +}; + +const current = async (req, res, next) => { + try { + const userId = req.user._id; + const user = await User.findById(userId); + + if (!user || !user.token) { + return res.status(401).json({ + status: "401 Unauthorized", + contentType: "application/json", + responseBody: { + message: "Not authorized", + }, + }); + } + + res.json({ + status: "200 OK", + contentType: "application/json", + responseBody: { + email: req.user.email, + subscription: req.user.subscription, + }, + }); + } catch (err) { + next(err); + } +}; + +const updateSub = async (req, res, next) => { + const userId = req.user._id; + const { error } = req.body; + + if (error || !req.body.subscription) { + return res.status(400).json({ + status: "400 Bad Request", + contentType: "application/json", + responseBody: { + message: "Invalid subscription type", + }, + }); + } + + try { + const user = await User.findById(userId); + + if (!user) { + return res.status(401).json({ + status: "401 Unauthorized", + contentType: "application/json", + responseBody: { + message: "Not authorized", + }, + }); + } + + user.subscription = req.body.subscription; + await user.save(); + + res.json({ + status: "200 OK", + contentType: "application/json", + responseBody: { + email: user.email, + subscription: user.subscription, + }, + }); + } catch (err) { + next(err); + } +}; + +module.exports = { + register, + login, + logout, + auth, + current, + updateSub, +}; diff --git a/package-lock.json b/package-lock.json index b96d0244e0a..0ece1875e1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "template", "version": "0.0.0", "dependencies": { + "bcryptjs": "^2.4.3", "cors": "2.8.5", "cross-env": "7.0.3", "dotenv": "^16.4.7", @@ -15,6 +16,8 @@ "joi": "^17.13.3", "mongoose": "^8.9.5", "morgan": "1.10.0", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "uuid": "^11.0.5" }, "devDependencies": { @@ -418,6 +421,12 @@ "node": ">= 0.8" } }, + "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==", + "license": "MIT" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -525,6 +534,12 @@ "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==", + "license": "BSD-3-Clause" + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -913,6 +928,15 @@ "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==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -2313,6 +2337,49 @@ "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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", @@ -2375,6 +2442,48 @@ "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -2390,18 +2499,6 @@ "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", @@ -2963,6 +3060,42 @@ "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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", @@ -3000,6 +3133,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", @@ -3274,13 +3412,10 @@ "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==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -3931,12 +4066,6 @@ "engines": { "node": ">=8" } - }, - "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 } }, "dependencies": { @@ -4247,6 +4376,11 @@ "safe-buffer": "5.1.2" } }, + "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", @@ -4333,6 +4467,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", @@ -4613,6 +4752,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" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -5664,6 +5811,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", @@ -5713,6 +5896,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", @@ -5725,15 +5943,6 @@ "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", @@ -6122,6 +6331,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", @@ -6150,6 +6383,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", @@ -6353,13 +6591,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", @@ -6860,12 +7094,6 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } } diff --git a/package.json b/package.json index e777040e92e..a071fb8fa4c 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint:fix": "eslint --fix **/*.js" }, "dependencies": { + "bcryptjs": "^2.4.3", "cors": "2.8.5", "cross-env": "7.0.3", "dotenv": "^16.4.7", @@ -16,6 +17,8 @@ "joi": "^17.13.3", "mongoose": "^8.9.5", "morgan": "1.10.0", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "uuid": "^11.0.5" }, "devDependencies": { diff --git a/passport.js b/passport.js new file mode 100644 index 00000000000..00a986a6518 --- /dev/null +++ b/passport.js @@ -0,0 +1,29 @@ +const passport = require("passport"); +const passportJWT = require("passport-jwt"); +const User = require("./service/schemas/user"); +require("dotenv").config(); +const secret = process.env.AUTH_SECRET; + +const ExtractJWT = passportJWT.ExtractJwt; +const Strategy = passportJWT.Strategy; +const params = { + secretOrKey: secret, + jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), +}; + +passport.use( + new Strategy(params, function (payload, done) { + User.findById(payload.id) + .then((user) => { + if (!user) { + return done(null, false, { message: "User not found" }); + } + return done(null, user); + }) + .catch((err) => { + return done(err, false); + }); + }) +); + +module.exports = passport; diff --git a/routes/api/index.js b/routes/api/index.js new file mode 100644 index 00000000000..5a1eb827617 --- /dev/null +++ b/routes/api/index.js @@ -0,0 +1,10 @@ +const express = require("express"); +const router = express.Router(); + +const userRoutes = require("./users"); +const contactRoutes = require("./contacts"); + +router.use("/users", userRoutes); +router.use("/contacts", contactRoutes); + +module.exports = router; diff --git a/routes/api/user.js b/routes/api/user.js new file mode 100644 index 00000000000..32349919ac0 --- /dev/null +++ b/routes/api/user.js @@ -0,0 +1,11 @@ +const express = require("express"); +const ctrlUser = require("../../controller/users"); +const router = express.Router(); + +router.post("/signup", ctrlUser.register); +router.post("/login", ctrlUser.login); +router.get("/logout", ctrlUser.auth, ctrlUser.logout); +router.get("/current", ctrlUser.auth, ctrlUser.current); +router.patch("/", ctrlUser.updateSub); + +module.exports = router; diff --git a/server.js b/server.js index a8c4e18a492..5fc65a3c035 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,3 @@ -require("dotenv").config(); - const mongoose = require("mongoose"); const app = require("./app"); diff --git a/service/index.js b/service/index.js index ba96ff17d0e..a2fded047fb 100644 --- a/service/index.js +++ b/service/index.js @@ -1,7 +1,8 @@ const Contact = require("./schemas/contact"); const getAllContacts = async () => { - return Contact.find(); + const skip = (page - 1) * limit; + return Contact.find(filter).skip(skip).limit(limit); }; const getContactById = (id) => { diff --git a/service/schemas/contact.js b/service/schemas/contact.js index c74a19f164c..7d0173ee647 100644 --- a/service/schemas/contact.js +++ b/service/schemas/contact.js @@ -1,7 +1,7 @@ const mongoose = require("mongoose"); const Schema = mongoose.Schema; -const contact = new Schema({ +const contactSchema = new Schema({ name: { type: String, required: [true, "Set name for contact"], @@ -16,8 +16,13 @@ const contact = new Schema({ type: Boolean, default: false, }, + owner: { + type: Schema.Types.ObjectId, + ref: "user", + required: true, + }, }); -const Contact = mongoose.model("contacts", contact); +const Contact = mongoose.model("contact", contactSchema); module.exports = Contact; From 29aa202e923919da80da5c2502b629f21dc72571 Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Sat, 25 Jan 2025 00:33:02 +0100 Subject: [PATCH 06/13] =?UTF-8?q?Poprawienie=20nazw=20plik=C3=B3w=20-=20li?= =?UTF-8?q?ter=C3=B3wki,=20po=C5=82=C4=85czenie=20z=20baz=C4=85=20i=20inne?= =?UTF-8?q?=20drobne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/contacts.js | 25 +++++++++++++++++-------- package-lock.json | 1 + package.json | 1 + routes/api/index.js | 2 +- routes/api/user.js | 2 +- server.js | 21 +++++++++++++++++++++ service/schemas/user.js | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 service/schemas/user.js diff --git a/controllers/contacts.js b/controllers/contacts.js index d9f9c72f88a..47bda723429 100644 --- a/controllers/contacts.js +++ b/controllers/contacts.js @@ -11,17 +11,30 @@ const schema = Joi.object({ .required(), phone: Joi.number().integer().positive().required(), favorite: Joi.bool(), + owner: Joi.string().alphanum().required(), }); const get = async (req, res, next) => { try { - const results = await service.getAllContacts(); + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 20; + + const filter = {}; + filter.owner = req.user._id; + if (req.query.favorite) { + filter.favorite = req.query.favorite === "true"; + } + + const results = await service.getAllContacts(page, limit, filter); res.json({ status: 200, data: { contacts: results }, + pagination: { + page, + limit, + }, }); } catch (err) { - console.error("Error getting contacts list:", err); next(err); } }; @@ -43,7 +56,6 @@ const getById = async (req, res, next) => { message: "Not found", }); } catch (err) { - console.error("Error getting contact:", err); next(err); } }; @@ -65,7 +77,6 @@ const remove = async (req, res, next) => { message: "Not found", }); } catch (err) { - console.error("Error removing contact:", err); next(err); } }; @@ -81,13 +92,13 @@ const create = async (req, res, next) => { } try { - const result = await service.createContact(req.body); + const userId = req.user._id; + const result = await service.createContact(req.body, userId); res.status(201).json({ status: 201, data: { newContact: result }, }); } catch (err) { - console.error("Error creating contact:", err); next(err); } }; @@ -117,7 +128,6 @@ const update = async (req, res, next) => { message: "Not found", }); } catch (err) { - console.error("Error updating contact:", err); next(err); } }; @@ -147,7 +157,6 @@ const updateStatus = async (req, res, next) => { message: "Not found", }); } catch (err) { - console.error("Error updating favorite status in contact:", err); next(err); } }; diff --git a/package-lock.json b/package-lock.json index 0ece1875e1c..b7f2ca5374b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "dotenv": "^16.4.7", "express": "^4.17.1", "joi": "^17.13.3", + "mongodb": "^6.12.0", "mongoose": "^8.9.5", "morgan": "1.10.0", "passport": "^0.7.0", diff --git a/package.json b/package.json index a071fb8fa4c..ee5d0bd069a 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "dotenv": "^16.4.7", "express": "^4.17.1", "joi": "^17.13.3", + "mongodb": "^6.12.0", "mongoose": "^8.9.5", "morgan": "1.10.0", "passport": "^0.7.0", diff --git a/routes/api/index.js b/routes/api/index.js index 5a1eb827617..36cc0d967b0 100644 --- a/routes/api/index.js +++ b/routes/api/index.js @@ -1,7 +1,7 @@ const express = require("express"); const router = express.Router(); -const userRoutes = require("./users"); +const userRoutes = require("./user"); const contactRoutes = require("./contacts"); router.use("/users", userRoutes); diff --git a/routes/api/user.js b/routes/api/user.js index 32349919ac0..610768ea982 100644 --- a/routes/api/user.js +++ b/routes/api/user.js @@ -1,5 +1,5 @@ const express = require("express"); -const ctrlUser = require("../../controller/users"); +const ctrlUser = require("../../controllers/user"); const router = express.Router(); router.post("/signup", ctrlUser.register); diff --git a/server.js b/server.js index 5fc65a3c035..06b94e69332 100644 --- a/server.js +++ b/server.js @@ -1,3 +1,24 @@ +// const mongoose = require("mongoose"); +// const app = require("./app"); + +// const MAIN_PORT = process.env.PORT || 3000; +// const uriDb = process.env.DB_URL; + +// const connection = mongoose.connect(uriDb); + +// connection +// .then(() => { +// app.listen(MAIN_PORT, function () { +// console.log("Database connection successful"); +// }); +// }) +// .catch((err) => { +// console.log(`Server not running. Error message: ${err.message}`); +// process.exit(1); +// }); + +require("dotenv").config(); + const mongoose = require("mongoose"); const app = require("./app"); diff --git a/service/schemas/user.js b/service/schemas/user.js new file mode 100644 index 00000000000..a23042df6cf --- /dev/null +++ b/service/schemas/user.js @@ -0,0 +1,37 @@ +const mongoose = require("mongoose"); +const bCrypt = require("bcryptjs"); + +const Schema = mongoose.Schema; + +const userSchema = new 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 = async function (password) { + this.password = await bCrypt.hash(password, 10); +}; + +userSchema.methods.validatePassword = async function (password) { + return await bCrypt.compare(password, this.password); +}; + +const User = mongoose.model("user", userSchema); + +module.exports = User; From 25c14f6b3c14175fa5904018f17b27458d6bb61b Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Sun, 26 Jan 2025 00:12:42 +0100 Subject: [PATCH 07/13] =?UTF-8?q?Dodanie=20tras=20z=20autoryzacj=C4=85=20d?= =?UTF-8?q?o=20obslugi=20kontakt=C3=B3w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routes/api/contacts.js | 27 +++++++++++++++++++++------ server.js | 20 +------------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 6b5fb706c40..02f4efa171a 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,12 +1,27 @@ +// const express = require("express"); +// const ctrlContact = require("../../controllers/contacts"); +// const router = express.Router(); + +// router.get("/", ctrlContact.get); +// router.get("/:contactId", ctrlContact.getById); +// router.post("/", ctrlContact.create); +// router.put("/:contactId", ctrlContact.update); +// router.delete("/:contactId", ctrlContact.remove); +// router.patch("/:contactId/status", ctrlContact.updateStatus); + +// module.exports = router; + const express = require("express"); const ctrlContact = require("../../controllers/contacts"); +const auth = require("../../controllers/user").auth; // Zaimportowanie funkcję auth z kontrolera user.js const router = express.Router(); -router.get("/", ctrlContact.get); -router.get("/:contactId", ctrlContact.getById); -router.post("/", ctrlContact.create); -router.put("/:contactId", ctrlContact.update); -router.delete("/:contactId", ctrlContact.remove); -router.patch("/:contactId/status", ctrlContact.updateStatus); +// Trasy z autoryzacją +router.get("/", auth, ctrlContact.get); // Zastosowanie auth jako middleware +router.get("/:contactId", auth, ctrlContact.getById); +router.post("/", auth, ctrlContact.create); +router.put("/:contactId", auth, ctrlContact.update); +router.delete("/:contactId", auth, ctrlContact.remove); +router.patch("/:contactId/status", auth, ctrlContact.updateStatus); module.exports = router; diff --git a/server.js b/server.js index 06b94e69332..da134858394 100644 --- a/server.js +++ b/server.js @@ -1,22 +1,3 @@ -// const mongoose = require("mongoose"); -// const app = require("./app"); - -// const MAIN_PORT = process.env.PORT || 3000; -// const uriDb = process.env.DB_URL; - -// const connection = mongoose.connect(uriDb); - -// connection -// .then(() => { -// app.listen(MAIN_PORT, function () { -// console.log("Database connection successful"); -// }); -// }) -// .catch((err) => { -// console.log(`Server not running. Error message: ${err.message}`); -// process.exit(1); -// }); - require("dotenv").config(); const mongoose = require("mongoose"); @@ -31,6 +12,7 @@ connection .then(() => { app.listen(MAIN_PORT, function () { console.log("Database connection successful"); + console.log(`Server is running on http://localhost:${MAIN_PORT}`); }); }) .catch((err) => { From 141420484b17d571f3a37fd8a6b47a2a48fa5ce2 Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Sun, 26 Jan 2025 18:36:28 +0100 Subject: [PATCH 08/13] Zmiana adresu do bazy w env --- server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server.js b/server.js index da134858394..8c6d7e9d8e6 100644 --- a/server.js +++ b/server.js @@ -13,6 +13,7 @@ connection app.listen(MAIN_PORT, function () { console.log("Database connection successful"); console.log(`Server is running on http://localhost:${MAIN_PORT}`); + console.log(process.env.DB_URL); }); }) .catch((err) => { From a21b443bc7863cba75880c31cf853329c05b5b21 Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Sat, 1 Feb 2025 13:27:05 +0100 Subject: [PATCH 09/13] Commit init dla zadania nr 5 --- app.js | 1 + controllers/user.js | 101 ++ package-lock.json | 2082 ++++++++++++++++++++++++++++++++++-- package.json | 3 + public/avatars/avatar.jpg | Bin 0 -> 47642 bytes routes/api/contacts.js | 13 - routes/api/user.js | 4 + service/schemas/contact.js | 3 + 8 files changed, 2126 insertions(+), 81 deletions(-) create mode 100644 public/avatars/avatar.jpg diff --git a/app.js b/app.js index e4583f4b0f4..0b94f3bf7ea 100644 --- a/app.js +++ b/app.js @@ -13,6 +13,7 @@ const formatsLogger = app.get("env") === "development" ? "dev" : "short"; app.use(logger(formatsLogger)); app.use(cors()); app.use(express.json()); +app.use(express.static("public")); app.use("/api", apiRouter); app.use((_, res, __) => { diff --git a/controllers/user.js b/controllers/user.js index 304b1176315..4dd5d2d24e8 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -2,6 +2,11 @@ const User = require("../service/schemas/user"); const Joi = require("joi"); const passport = require("passport"); const jwt = require("jsonwebtoken"); +const gravatar = require("gravatar"); +const multer = require("multer"); +const path = require("path"); +const jimp = require("jimp"); +const fs = require("fs"); const schema = Joi.object({ password: Joi.string().required(), @@ -17,6 +22,29 @@ const schema = Joi.object({ token: Joi.string().default(null), }); +// Multer storage configuration for avatar +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, "tmp/"); // Files are uploaded to 'tmp' folder + }, + filename: (req, file, cb) => { + cb(null, `${Date.now()}-${file.originalname}`); // Unique file name + }, +}); + +const upload = multer({ + storage: storage, + fileFilter: (req, file, cb) => { + const ext = path.extname(file.originalname).toLowerCase(); + if (ext === ".jpg" || ext === ".jpeg" || ext === ".png") { + cb(null, true); + } else { + cb(new Error("Only .jpg, .jpeg, and .png files are allowed"), false); + } + }, +}).single("avatar"); // The field name will be 'avatar' + +// Authentication middleware const auth = (req, res, next) => { passport.authenticate("jwt", { session: false }, (err, user) => { if (!user || err) { @@ -32,6 +60,7 @@ const auth = (req, res, next) => { })(req, res, next); }; +// Register user const register = async (req, res, next) => { const { error } = schema.validate(req.body); const user = await User.findOne({ email: req.body.email }); @@ -55,9 +84,16 @@ const register = async (req, res, next) => { } try { + const avatarURL = gravatar.url(req.body.email, { + s: "250", + r: "pg", + d: "mm", + }); + const newUser = new User({ email: req.body.email, subscription: "starter", + avatarURL, }); await newUser.setPassword(req.body.password); await newUser.save(); @@ -69,6 +105,7 @@ const register = async (req, res, next) => { user: { email: req.body.email, subscription: "starter", + avatarURL: avatarURL, }, }, }); @@ -77,6 +114,66 @@ const register = async (req, res, next) => { } }; +// Update avatar +const updateAvatar = async (req, res, next) => { + upload(req, res, async (err) => { + if (err) { + return res.status(400).json({ + status: "400 Bad Request", + contentType: "application/json", + responseBody: { message: err.message }, + }); + } + + try { + const userId = req.user._id; + const user = await User.findById(userId); + + if (!user) { + return res.status(404).json({ + status: "404 Not Found", + responseBody: { message: "User not found" }, + }); + } + + // Process image with Jimp (resize to 250x250) + const avatarPath = req.file.path; + const image = await jimp.read(avatarPath); + await image.resize(250, 250); // Resize to 250x250 + const uniqueFilename = `${userId}-${Date.now()}${path.extname( + req.file.originalname + )}`; + const finalPath = path.join( + __dirname, + "../public/avatars", + uniqueFilename + ); + + // Save the resized image + await image.writeAsync(finalPath); + + // Delete the temporary file from 'tmp' folder + fs.unlinkSync(avatarPath); + + // Update user document with the new avatar URL + user.avatarURL = `/avatars/${uniqueFilename}`; + await user.save(); + + return res.status(200).json({ + status: "200 OK", + contentType: "application/json", + responseBody: { + message: "Avatar updated successfully", + avatarURL: user.avatarURL, + }, + }); + } catch (err) { + next(err); + } + }); +}; + +// Login user const login = async (req, res, next) => { const { error } = schema.validate(req.body); @@ -137,6 +234,7 @@ const login = async (req, res, next) => { } }; +// Logout user const logout = async (req, res, next) => { try { const userId = req.user._id; @@ -151,6 +249,7 @@ const logout = async (req, res, next) => { } }; +// Get current user data const current = async (req, res, next) => { try { const userId = req.user._id; @@ -172,6 +271,7 @@ const current = async (req, res, next) => { responseBody: { email: req.user.email, subscription: req.user.subscription, + avatarURL: req.user.avatarURL, // Include avatar URL in response }, }); } catch (err) { @@ -229,4 +329,5 @@ module.exports = { auth, current, updateSub, + updateAvatar, // Expose the new method }; diff --git a/package-lock.json b/package-lock.json index b7f2ca5374b..56dd80b53f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,10 +13,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", "mongodb": "^6.12.0", "mongoose": "^8.9.5", "morgan": "1.10.0", + "multer": "^1.4.5-lts.1", "passport": "^0.7.0", "passport-jwt": "^4.0.1", "uuid": "^11.0.5" @@ -164,6 +167,430 @@ "@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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "tinycolor2": "^1.6.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", @@ -215,12 +642,24 @@ "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==", + "license": "MIT" + }, "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==", + "license": "MIT" + }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -313,7 +752,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" } @@ -322,7 +760,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" }, @@ -333,6 +770,12 @@ "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==", + "license": "MIT" + }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -346,6 +789,12 @@ "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==", + "license": "MIT" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -405,6 +854,15 @@ "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==", + "license": "MIT", + "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", @@ -437,6 +895,18 @@ "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -541,6 +1011,23 @@ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "license": "BSD-3-Clause" }, + "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==", + "license": "MIT" + }, + "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", @@ -680,6 +1167,31 @@ "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==", + "license": "ISC", + "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==", + "license": "MIT", + "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", @@ -693,7 +1205,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" }, @@ -704,8 +1215,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/concat-map": { "version": "0.0.1", @@ -713,6 +1223,21 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "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" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -762,6 +1287,12 @@ "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==", + "license": "MIT" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -829,6 +1360,15 @@ } } }, + "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==", + "license": "MIT", + "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", @@ -943,11 +1483,18 @@ "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", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -1459,6 +2006,11 @@ "node": ">= 0.6" } }, + "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", @@ -1543,6 +2095,23 @@ "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==", + "license": "MIT", + "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", @@ -1664,6 +2233,15 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "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==", + "license": "ISC", + "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", @@ -1706,6 +2284,16 @@ "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==", + "license": "MIT", + "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", @@ -1796,6 +2384,24 @@ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "node_modules/gravatar": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/gravatar/-/gravatar-1.8.2.tgz", + "integrity": "sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w==", + "license": "MIT", + "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", @@ -1894,6 +2500,26 @@ "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" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -1909,6 +2535,15 @@ "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==", + "license": "MIT", + "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", @@ -2093,7 +2728,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" } @@ -2271,11 +2905,55 @@ "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==", + "license": "MIT" + }, "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==", + "license": "MIT", + "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", @@ -2289,6 +2967,12 @@ "@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==", + "license": "BSD-3-Clause" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2603,10 +3287,25 @@ } }, "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } }, "node_modules/mongodb": { "version": "6.12.0", @@ -2754,6 +3453,24 @@ "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==", + "license": "MIT", + "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/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2930,6 +3647,12 @@ "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==", + "license": "MIT" + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -3041,6 +3764,12 @@ "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==", + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3053,6 +3782,28 @@ "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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", @@ -3139,6 +3890,19 @@ "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==", + "license": "MIT", + "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", @@ -3151,6 +3915,27 @@ "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==", + "license": "ISC", + "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==", + "license": "MIT", + "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", @@ -3163,6 +3948,15 @@ "node": ">=4" } }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "license": "MIT", + "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", @@ -3181,6 +3975,12 @@ "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==", + "license": "MIT" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -3247,6 +4047,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", @@ -3280,23 +4089,68 @@ "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, - "bin": { - "rc": "cli.js" + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "MIT", + "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/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==", + "license": "MIT", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, + "node_modules/readable-web-to-node-stream/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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, "node_modules/readdirp": { @@ -3347,6 +4201,15 @@ "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==", + "license": "MIT", + "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", @@ -3356,6 +4219,12 @@ "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==", + "license": "ISC" + }, "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -3412,6 +4281,12 @@ "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==", + "license": "ISC" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3500,6 +4375,12 @@ "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==", + "license": "ISC" + }, "node_modules/setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -3550,6 +4431,15 @@ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, + "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==", + "license": "MIT", + "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", @@ -3590,11 +4480,27 @@ "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.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3634,7 +4540,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" }, @@ -3663,6 +4568,23 @@ "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==", + "license": "MIT", + "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", @@ -3719,6 +4641,12 @@ "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==", + "license": "MIT" + }, "node_modules/to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -3748,6 +4676,23 @@ "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==", + "license": "MIT", + "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", @@ -3817,6 +4762,12 @@ "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==", + "license": "MIT" + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -3916,6 +4867,21 @@ "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==", + "license": "MIT", + "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", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -4003,6 +4969,12 @@ "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==", + "license": "ISC" + }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -4067,6 +5039,172 @@ "engines": { "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "ISC" + }, + "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==", + "license": "MIT", + "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==", + "license": "ISC", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } }, "dependencies": { @@ -4148,35 +5286,342 @@ } } }, - "@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, + "@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": { - "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/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" } }, - "@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-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" + } }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "@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": { - "@hapi/hoek": "^9.0.0" + "@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" + } + }, + "@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": { + "@jimp/types": "1.6.0" + } + }, + "@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" + } + }, + "@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": { + "@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" } }, "@mongodb-js/saslprep": { @@ -4220,12 +5665,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", @@ -4297,18 +5752,21 @@ "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", "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", @@ -4319,6 +5777,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==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -4363,6 +5826,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", @@ -4388,6 +5856,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", @@ -4473,6 +5951,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", @@ -4570,6 +6061,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", @@ -4583,7 +6096,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" } @@ -4591,8 +6103,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==" }, "concat-map": { "version": "0.0.1", @@ -4600,6 +6111,17 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "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" + } + }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -4637,6 +6159,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", @@ -4678,6 +6205,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", @@ -4766,11 +6298,15 @@ "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", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -5154,6 +6690,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "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", @@ -5233,6 +6774,16 @@ "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", @@ -5331,6 +6882,11 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "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", @@ -5361,6 +6917,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", @@ -5427,6 +6992,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", @@ -5495,6 +7071,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", @@ -5507,6 +7088,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", @@ -5636,8 +7225,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", @@ -5752,11 +7340,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", @@ -5769,6 +7396,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", @@ -6015,10 +7647,17 @@ } }, "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==" + }, + "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" + } }, "mongodb": { "version": "6.12.0", @@ -6110,6 +7749,20 @@ "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" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6232,6 +7885,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", @@ -6318,6 +7976,11 @@ } } }, + "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", @@ -6327,6 +7990,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", @@ -6389,12 +8071,32 @@ "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", @@ -6404,6 +8106,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", @@ -6416,6 +8123,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", @@ -6466,6 +8178,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", @@ -6508,6 +8225,40 @@ } } }, + "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" + } + }, + "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" + }, + "dependencies": { + "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", @@ -6541,12 +8292,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", @@ -6591,6 +8352,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", @@ -6666,6 +8432,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", @@ -6706,6 +8477,11 @@ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, + "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", @@ -6736,11 +8512,23 @@ "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.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" + } + }, "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", @@ -6771,7 +8559,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" } @@ -6788,6 +8575,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", @@ -6836,6 +8632,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", @@ -6856,6 +8657,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", @@ -6909,6 +8719,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", @@ -6990,6 +8805,19 @@ "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", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -7046,6 +8874,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==" + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -7095,6 +8928,119 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "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==" + }, + "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 ee5d0bd069a..75f1893302d 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,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", "mongodb": "^6.12.0", "mongoose": "^8.9.5", "morgan": "1.10.0", + "multer": "^1.4.5-lts.1", "passport": "^0.7.0", "passport-jwt": "^4.0.1", "uuid": "^11.0.5" diff --git a/public/avatars/avatar.jpg b/public/avatars/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d9a0cc850957b3d205ae541d339ee913e3ccd819 GIT binary patch literal 47642 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 J+R}f&{}0)CC*A-6 literal 0 HcmV?d00001 diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 02f4efa171a..2907899360e 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,16 +1,3 @@ -// const express = require("express"); -// const ctrlContact = require("../../controllers/contacts"); -// const router = express.Router(); - -// router.get("/", ctrlContact.get); -// router.get("/:contactId", ctrlContact.getById); -// router.post("/", ctrlContact.create); -// router.put("/:contactId", ctrlContact.update); -// router.delete("/:contactId", ctrlContact.remove); -// router.patch("/:contactId/status", ctrlContact.updateStatus); - -// module.exports = router; - const express = require("express"); const ctrlContact = require("../../controllers/contacts"); const auth = require("../../controllers/user").auth; // Zaimportowanie funkcję auth z kontrolera user.js diff --git a/routes/api/user.js b/routes/api/user.js index 610768ea982..07fef5678f3 100644 --- a/routes/api/user.js +++ b/routes/api/user.js @@ -2,10 +2,14 @@ const express = require("express"); const ctrlUser = require("../../controllers/user"); const router = express.Router(); +// Trasy związane z użytkownikami router.post("/signup", ctrlUser.register); router.post("/login", ctrlUser.login); router.get("/logout", ctrlUser.auth, ctrlUser.logout); router.get("/current", ctrlUser.auth, ctrlUser.current); router.patch("/", ctrlUser.updateSub); +// Trasa do aktualizacji awatara +router.patch("/avatars", ctrlUser.auth, ctrlUser.updateAvatar); // Dodanie trasy do aktualizacji awatara + module.exports = router; diff --git a/service/schemas/contact.js b/service/schemas/contact.js index 7d0173ee647..54edab8741f 100644 --- a/service/schemas/contact.js +++ b/service/schemas/contact.js @@ -16,6 +16,9 @@ const contactSchema = new Schema({ type: Boolean, default: false, }, + avatarURL: { + type: String, + }, owner: { type: Schema.Types.ObjectId, ref: "user", From 66ea98dfcdb604c073067e9d3916e5cb569872df Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Sat, 1 Feb 2025 22:30:14 +0100 Subject: [PATCH 10/13] Dodano czyszczenie katalogu tmp oraz zmiana wersji jimp z 1.6.0 na 0.16.1 --- controllers/user.js | 31 +- package-lock.json | 1597 +++++++++++++++++++++++++------------------ package.json | 2 +- 3 files changed, 962 insertions(+), 668 deletions(-) diff --git a/controllers/user.js b/controllers/user.js index 4dd5d2d24e8..fa888ae2596 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -136,10 +136,10 @@ const updateAvatar = async (req, res, next) => { }); } - // Process image with Jimp (resize to 250x250) + // Przetwarzanie obrazu w Jimp (zmiana rozmiaru do 250x250) const avatarPath = req.file.path; const image = await jimp.read(avatarPath); - await image.resize(250, 250); // Resize to 250x250 + await image.resize(250, 250); // Skalowanie do 250x250 const uniqueFilename = `${userId}-${Date.now()}${path.extname( req.file.originalname )}`; @@ -149,13 +149,16 @@ const updateAvatar = async (req, res, next) => { uniqueFilename ); - // Save the resized image + // Zapisz przetworzony obraz await image.writeAsync(finalPath); - // Delete the temporary file from 'tmp' folder - fs.unlinkSync(avatarPath); + // Usuń plik tymczasowy + await fs.promises.unlink(avatarPath); - // Update user document with the new avatar URL + // Wyczyść cały folder tmp + await cleanTmpFolder(); + + // Zaktualizuj ścieżkę avatara w bazie danych user.avatarURL = `/avatars/${uniqueFilename}`; await user.save(); @@ -173,6 +176,22 @@ const updateAvatar = async (req, res, next) => { }); }; +// Czyszczenie katalogu +async function cleanTmpFolder() { + const tmpDir = path.join(__dirname, "../tmp"); + try { + const files = await fs.promises.readdir(tmpDir); + for (const file of files) { + const filePath = path.join(tmpDir, file); + await fs.promises.unlink(filePath); // Usuń plik + console.log(`Usunięto: ${filePath}`); + } + console.log("Folder tmp wyczyszczony."); + } catch (error) { + console.error("Błąd podczas czyszczenia tmp:", error); + } +} + // Login user const login = async (req, res, next) => { const { error } = schema.validate(req.body); diff --git a/package-lock.json b/package-lock.json index 56dd80b53f3..1722c5b6576 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "dotenv": "^16.4.7", "express": "^4.17.1", "gravatar": "^1.8.2", - "jimp": "^1.6.0", + "jimp": "^0.16.1", "joi": "^17.13.3", "mongodb": "^6.12.0", "mongoose": "^8.9.5", @@ -131,6 +131,24 @@ "node": ">=4" } }, + "node_modules/@babel/runtime": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, "node_modules/@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -167,428 +185,456 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@jimp/bmp": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.13.tgz", + "integrity": "sha512-9edAxu7N2FX7vzkdl5Jo1BbACfycUtBQX+XBMcHA2bk62P8R0otgkHg798frgAk/WxQIzwxqOH6wMiCwrlAzdQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "bmp-js": "^0.1.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, "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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.13.tgz", + "integrity": "sha512-qXpA1tzTnlkTku9yqtuRtS/wVntvE6f3m3GNxdTdtmc+O+Wcg9Xo2ABPMh7Nc0AHbMKzwvwgB2JnjZmlmJEObg==", "license": "MIT", "dependencies": { - "@jimp/file-ops": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "await-to-js": "^3.0.0", + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "any-base": "^1.1.0", + "buffer": "^5.2.0", "exif-parser": "^0.1.12", - "file-type": "^16.0.0", - "mime": "3" - }, - "engines": { - "node": ">=18" + "file-type": "^16.5.4", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + } + }, + "node_modules/@jimp/custom": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.13.tgz", + "integrity": "sha512-LTATglVUPGkPf15zX1wTMlZ0+AU7cGEGF6ekVF1crA8eHUWsGjrYTB+Ht4E3HTrCok8weQG+K01rJndCp/l4XA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.16.13" } }, - "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==", + "node_modules/@jimp/gif": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.13.tgz", + "integrity": "sha512-yFAMZGv3o+YcjXilMWWwS/bv1iSqykFahFMSO169uVMtfQVfa90kt4/kDwrXNR6Q9i6VHpFiGZMlF2UnHClBvg==", "license": "MIT", - "bin": { - "mime": "cli.js" + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" }, - "engines": { - "node": ">=10.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/jpeg": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.13.tgz", + "integrity": "sha512-BJHlDxzTlCqP2ThqP8J0eDrbBfod7npWCbJAcfkKqdQuFk0zBPaZ6KKaQKyKxmWJ87Z6ohANZoMKEbtvrwz1AA==", "license": "MIT", "dependencies": { - "@jimp/plugin-resize": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "pixelmatch": "^5.3.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "jpeg-js": "^0.4.2" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-blit": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.16.13.tgz", + "integrity": "sha512-8Z1k96ZFxlhK2bgrY1JNWNwvaBeI/bciLM0yDOni2+aZwfIIiC7Y6PeWHTAvjHNjphz+XCt01WQmOYWCn0ML6g==", "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-blur": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.16.13.tgz", + "integrity": "sha512-PvLrfa8vkej3qinlebyhLpksJgCF5aiysDMSVhOZqwH5nQLLtDE9WYbnsofGw4r0VVpyw3H/ANCIzYTyCtP9Cg==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "bmp-ts": "^1.0.9" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-circle": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.16.13.tgz", + "integrity": "sha512-RNave7EFgZrb5V5EpdvJGAEHMnDAJuwv05hKscNfIYxf0kR3KhViBTDy+MoTnMlIvaKFULfwIgaZWzyhuINMzA==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "gifwrap": "^0.10.1", - "omggif": "^1.0.10" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-color": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.16.13.tgz", + "integrity": "sha512-xW+9BtEvoIkkH/Wde9ql4nAFbYLkVINhpgAE7VcBUsuuB34WUbcBl/taOuUYQrPEFQJ4jfXiAJZ2H/rvKjCVnQ==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "jpeg-js": "^0.4.4" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "tinycolor2": "^1.4.1" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-contain": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.16.13.tgz", + "integrity": "sha512-QayTXw4tXMwU6q6acNTQrTTFTXpNRBe+MgTGMDU0lk+23PjlFCO/9sacflelG8lsp7vNHhAxFeHptDMAksEYzg==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "pngjs": "^7.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-cover": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.16.13.tgz", + "integrity": "sha512-BSsP71GTNaqWRcvkbWuIVH+zK7b3TSNebbhDkFK0fVaUTzHuKMS/mgY4hDZIEVt7Rf5FjadAYtsujHN9w0iSYA==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "utif2": "^4.1.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-crop": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.16.13.tgz", + "integrity": "sha512-WEl2tPVYwzYL8OKme6Go2xqiWgKsgxlMwyHabdAU4tXaRwOCnOI7v4021gCcBb9zn/oWwguHuKHmK30Fw2Z/PA==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-displace": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.16.13.tgz", + "integrity": "sha512-qt9WKq8vWrcjySa9DyQ0x/RBMHQeiVjdVSY1SJsMjssPUf0pS74qorcuAkGi89biN3YoGUgPkpqECnAWnYwgGA==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/utils": "1.6.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-dither": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.16.13.tgz", + "integrity": "sha512-5/N3yJggbWQTlGZHQYJPmQXEwR52qaXjEzkp1yRBbtdaekXE3BG/suo0fqeoV/csf8ooI78sJzYmIrxNoWVtgQ==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-fisheye": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.16.13.tgz", + "integrity": "sha512-2rZmTdFbT/cF9lEZIkXCYO0TsT114Q27AX5IAo0Sju6jVQbvIk1dFUTnwLDadTo8wkJlFzGqMQ24Cs8cHWOliA==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "tinycolor2": "^1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-flip": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.16.13.tgz", + "integrity": "sha512-EmcgAA74FTc5u7Z+hUO/sRjWwfPPLuOQP5O64x5g4j0T12Bd29IgsYZxoutZo/rb3579+JNa/3wsSEmyVv1EpA==", "license": "MIT", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-rotate": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-gaussian": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.16.13.tgz", + "integrity": "sha512-A1XKfGQD0iDdIiKqFYi8nZMv4dDVYdxbrmgR7y/CzUHhSYdcmoljLIIsZZM3Iks/Wa353W3vtvkWLuDbQbch1w==", "license": "MIT", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-invert": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.16.13.tgz", + "integrity": "sha512-xFMrIn7czEZbdbMzZWuaZFnlLGJDVJ82y5vlsKsXRTG2kcxRsMPXvZRWHV57nSs1YFsNqXSbrC8B98n0E32njQ==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-mask": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.16.13.tgz", + "integrity": "sha512-wLRYKVBXql2GAYgt6FkTnCfE+q5NomM7Dlh0oIPGAoMBWDyTx0eYutRK6PlUrRK2yMHuroAJCglICTbxqGzowQ==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-normalize": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.16.13.tgz", + "integrity": "sha512-3tfad0n9soRna4IfW9NzQdQ2Z3ijkmo21DREHbE6CGcMIxOSvfRdSvf1qQPApxjTSo8LTU4MCi/fidx/NZ0GqQ==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-print": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.16.13.tgz", + "integrity": "sha512-0m6i3p01PGRkGAK9r53hDYrkyMq+tlhLOIbsSTmZyh6HLshUKlTB7eXskF5OpVd5ZUHoltlNc6R+ggvKIzxRFw==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "load-bmfont": "^1.4.0" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-resize": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.13.tgz", + "integrity": "sha512-qoqtN8LDknm3fJm9nuPygJv30O3vGhSBD2TxrsCnhtOsxKAqVPJtFVdGd/qVuZ8nqQANQmTlfqTiK9mVWQ7MiQ==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-rotate": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.16.13.tgz", + "integrity": "sha512-Ev+Jjmj1nHYw897z9C3R9dYsPv7S2/nxdgfFb/h8hOwK0Ovd1k/+yYS46A0uj/JCKK0pQk8wOslYBkPwdnLorw==", "license": "MIT", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-scale": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.16.13.tgz", + "integrity": "sha512-05POQaEJVucjTiSGMoH68ZiELc7QqpIpuQlZ2JBbhCV+WCbPFUBcGSmE7w4Jd0E2GvCho/NoMODLwgcVGQA97A==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-shadow": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.16.13.tgz", + "integrity": "sha512-nmu5VSZ9hsB1JchTKhnnCY+paRBnwzSyK5fhkhtQHHoFD5ArBQ/5wU8y6tCr7k/GQhhGq1OrixsECeMjPoc8Zw==", "license": "MIT", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blur": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/plugin-threshold": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.16.13.tgz", + "integrity": "sha512-+3zArBH0OE3Rhjm4HyAokMsZlIq5gpQec33CncyoSwxtRBM2WAhUVmCUKuBo+Lr/2/4ISoY4BWpHKhMLDix6cA==", "license": "MIT", "dependencies": { - "image-q": "^4.0.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-color": ">=0.8.0", + "@jimp/plugin-resize": ">=0.8.0" } }, - "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==", + "node_modules/@jimp/plugins": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.16.13.tgz", + "integrity": "sha512-CJLdqODEhEVs4MgWCxpWL5l95sCBlkuSLz65cxEm56X5akIsn4LOlwnKoSEZioYcZUBvHhCheH67AyPTudfnQQ==", "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/plugin-blit": "^0.16.13", + "@jimp/plugin-blur": "^0.16.13", + "@jimp/plugin-circle": "^0.16.13", + "@jimp/plugin-color": "^0.16.13", + "@jimp/plugin-contain": "^0.16.13", + "@jimp/plugin-cover": "^0.16.13", + "@jimp/plugin-crop": "^0.16.13", + "@jimp/plugin-displace": "^0.16.13", + "@jimp/plugin-dither": "^0.16.13", + "@jimp/plugin-fisheye": "^0.16.13", + "@jimp/plugin-flip": "^0.16.13", + "@jimp/plugin-gaussian": "^0.16.13", + "@jimp/plugin-invert": "^0.16.13", + "@jimp/plugin-mask": "^0.16.13", + "@jimp/plugin-normalize": "^0.16.13", + "@jimp/plugin-print": "^0.16.13", + "@jimp/plugin-resize": "^0.16.13", + "@jimp/plugin-rotate": "^0.16.13", + "@jimp/plugin-scale": "^0.16.13", + "@jimp/plugin-shadow": "^0.16.13", + "@jimp/plugin-threshold": "^0.16.13", + "timm": "^1.6.1" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/png": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.13.tgz", + "integrity": "sha512-8cGqINvbWJf1G0Her9zbq9I80roEX0A+U45xFby3tDWfzn+Zz8XKDF1Nv9VUwVx0N3zpcG1RPs9hfheG4Cq2kg==", "license": "MIT", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "pngjs": "^3.3.3" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "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==", + "node_modules/@jimp/tiff": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.13.tgz", + "integrity": "sha512-oJY8d9u95SwW00VPHuCNxPap6Q1+E/xM5QThb9Hu+P6EGuu6lIeLaNBMmFZyblwFbwrH+WBOZlvIzDhi4Dm/6Q==", "license": "MIT", "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" + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/types": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", - "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.13.tgz", + "integrity": "sha512-mC0yVNUobFDjoYLg4hoUwzMKgNlxynzwt3cDXzumGvRJ7Kb8qQGOWJQjQFo5OxmGExqzPphkirdbBF88RVLBCg==", "license": "MIT", "dependencies": { - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.16.13", + "@jimp/gif": "^0.16.13", + "@jimp/jpeg": "^0.16.13", + "@jimp/png": "^0.16.13", + "@jimp/tiff": "^0.16.13", + "timm": "^1.6.1" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, "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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.13.tgz", + "integrity": "sha512-VyCpkZzFTHXtKgVO35iKN0sYR10psGpV6SkcSeV4oF7eSYlR8Bl6aQLCzVeFjvESF7mxTmIiI3/XrMobVrtxDA==", "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "tinycolor2": "^1.6.0" - }, - "engines": { - "node": ">=18" + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" } }, "node_modules/@mongodb-js/saslprep": { @@ -854,21 +900,32 @@ "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==", - "license": "MIT", - "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", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -901,10 +958,10 @@ "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", "license": "MIT" }, - "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/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", "license": "MIT" }, "node_modules/body-parser": { @@ -1005,6 +1062,39 @@ "node": ">=16.20.1" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "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", @@ -1112,6 +1202,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/centra": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz", + "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1439,6 +1538,11 @@ "node": ">=6.0.0" } }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -2185,6 +2289,26 @@ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2285,9 +2409,9 @@ } }, "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==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.4.tgz", + "integrity": "sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ==", "license": "MIT", "dependencies": { "image-q": "^4.0.0", @@ -2326,6 +2450,16 @@ "node": ">= 6" } }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "license": "MIT", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "node_modules/global-dirs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", @@ -2732,6 +2866,12 @@ "node": ">=8" } }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "license": "MIT" + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2917,41 +3057,16 @@ "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==", + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.16.1.tgz", + "integrity": "sha512-+EKVxbR36Td7Hfd23wKGIeEyHbxShZDX6L8uJkgVW3ESA9GiTEPK08tG1XI2r/0w5Ch0HyJF5kPqF9K7EmGjaw==", "license": "MIT", "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" + "@babel/runtime": "^7.7.2", + "@jimp/custom": "^0.16.1", + "@jimp/plugins": "^0.16.1", + "@jimp/types": "^0.16.1", + "regenerator-runtime": "^0.13.3" } }, "node_modules/joi": { @@ -3108,6 +3223,34 @@ "node": ">= 0.8.0" } }, + "node_modules/load-bmfont": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.2.tgz", + "integrity": "sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==", + "license": "MIT", + "dependencies": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^3.7.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, + "node_modules/load-bmfont/node_modules/phin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz", + "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==", + "license": "MIT", + "dependencies": { + "centra": "^2.7.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -3274,6 +3417,14 @@ "node": ">=4" } }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dependencies": { + "dom-walk": "^0.1.0" + } + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -3804,6 +3955,12 @@ "xml2js": "^0.5.0" } }, + "node_modules/parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==", + "license": "MIT" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3903,6 +4060,13 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, "node_modules/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -3916,26 +4080,17 @@ } }, "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==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", "license": "ISC", "dependencies": { - "pngjs": "^6.0.0" + "pngjs": "^3.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==", - "license": "MIT", - "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", @@ -3949,12 +4104,12 @@ } }, "node_modules/pngjs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", - "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", "license": "MIT", "engines": { - "node": ">=14.19.0" + "node": ">=4.0.0" } }, "node_modules/prelude-ls": { @@ -3975,6 +4130,15 @@ "node": ">=4" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4165,6 +4329,12 @@ "node": ">=8.10.0" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -4431,15 +4601,6 @@ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, - "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==", - "license": "MIT", - "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", @@ -4641,6 +4802,12 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==", + "license": "MIT" + }, "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", @@ -4867,13 +5034,13 @@ "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==", + "node_modules/utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", "license": "MIT", "dependencies": { - "pako": "^1.0.11" + "pako": "^1.0.5" } }, "node_modules/util-deprecate": { @@ -5040,6 +5207,18 @@ "node": ">=8" } }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "license": "MIT", + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, "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", @@ -5196,15 +5375,6 @@ "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==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } }, "dependencies": { @@ -5286,6 +5456,21 @@ } } }, + "@babel/runtime": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "requires": { + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + } + } + }, "@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -5317,311 +5502,325 @@ "@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==", + "@jimp/bmp": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.13.tgz", + "integrity": "sha512-9edAxu7N2FX7vzkdl5Jo1BbACfycUtBQX+XBMcHA2bk62P8R0otgkHg798frgAk/WxQIzwxqOH6wMiCwrlAzdQ==", "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==" - } + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "bmp-js": "^0.1.0" } }, - "@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/core": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.13.tgz", + "integrity": "sha512-qXpA1tzTnlkTku9yqtuRtS/wVntvE6f3m3GNxdTdtmc+O+Wcg9Xo2ABPMh7Nc0AHbMKzwvwgB2JnjZmlmJEObg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^16.5.4", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" } }, - "@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==", + "@jimp/custom": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.13.tgz", + "integrity": "sha512-LTATglVUPGkPf15zX1wTMlZ0+AU7cGEGF6ekVF1crA8eHUWsGjrYTB+Ht4E3HTrCok8weQG+K01rJndCp/l4XA==", "requires": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "gifwrap": "^0.10.1", - "omggif": "^1.0.10" + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.16.13" } }, - "@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==", + "@jimp/gif": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.13.tgz", + "integrity": "sha512-yFAMZGv3o+YcjXilMWWwS/bv1iSqykFahFMSO169uVMtfQVfa90kt4/kDwrXNR6Q9i6VHpFiGZMlF2UnHClBvg==", "requires": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "jpeg-js": "^0.4.4" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" } }, - "@jimp/js-png": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", - "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "@jimp/jpeg": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.13.tgz", + "integrity": "sha512-BJHlDxzTlCqP2ThqP8J0eDrbBfod7npWCbJAcfkKqdQuFk0zBPaZ6KKaQKyKxmWJ87Z6ohANZoMKEbtvrwz1AA==", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "jpeg-js": "^0.4.2" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.16.13.tgz", + "integrity": "sha512-8Z1k96ZFxlhK2bgrY1JNWNwvaBeI/bciLM0yDOni2+aZwfIIiC7Y6PeWHTAvjHNjphz+XCt01WQmOYWCn0ML6g==", "requires": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.16.13.tgz", + "integrity": "sha512-PvLrfa8vkej3qinlebyhLpksJgCF5aiysDMSVhOZqwH5nQLLtDE9WYbnsofGw4r0VVpyw3H/ANCIzYTyCtP9Cg==", "requires": { - "@jimp/core": "1.6.0", - "@jimp/utils": "1.6.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.16.13.tgz", + "integrity": "sha512-RNave7EFgZrb5V5EpdvJGAEHMnDAJuwv05hKscNfIYxf0kR3KhViBTDy+MoTnMlIvaKFULfwIgaZWzyhuINMzA==", "requires": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.16.13.tgz", + "integrity": "sha512-xW+9BtEvoIkkH/Wde9ql4nAFbYLkVINhpgAE7VcBUsuuB34WUbcBl/taOuUYQrPEFQJ4jfXiAJZ2H/rvKjCVnQ==", "requires": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "tinycolor2": "^1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "tinycolor2": "^1.4.1" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.16.13.tgz", + "integrity": "sha512-QayTXw4tXMwU6q6acNTQrTTFTXpNRBe+MgTGMDU0lk+23PjlFCO/9sacflelG8lsp7vNHhAxFeHptDMAksEYzg==", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.16.13.tgz", + "integrity": "sha512-BSsP71GTNaqWRcvkbWuIVH+zK7b3TSNebbhDkFK0fVaUTzHuKMS/mgY4hDZIEVt7Rf5FjadAYtsujHN9w0iSYA==", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.16.13.tgz", + "integrity": "sha512-WEl2tPVYwzYL8OKme6Go2xqiWgKsgxlMwyHabdAU4tXaRwOCnOI7v4021gCcBb9zn/oWwguHuKHmK30Fw2Z/PA==", "requires": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.16.13.tgz", + "integrity": "sha512-qt9WKq8vWrcjySa9DyQ0x/RBMHQeiVjdVSY1SJsMjssPUf0pS74qorcuAkGi89biN3YoGUgPkpqECnAWnYwgGA==", "requires": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@jimp/plugin-dither": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", - "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.16.13.tgz", + "integrity": "sha512-5/N3yJggbWQTlGZHQYJPmQXEwR52qaXjEzkp1yRBbtdaekXE3BG/suo0fqeoV/csf8ooI78sJzYmIrxNoWVtgQ==", "requires": { - "@jimp/types": "1.6.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.16.13.tgz", + "integrity": "sha512-2rZmTdFbT/cF9lEZIkXCYO0TsT114Q27AX5IAo0Sju6jVQbvIk1dFUTnwLDadTo8wkJlFzGqMQ24Cs8cHWOliA==", "requires": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.16.13.tgz", + "integrity": "sha512-EmcgAA74FTc5u7Z+hUO/sRjWwfPPLuOQP5O64x5g4j0T12Bd29IgsYZxoutZo/rb3579+JNa/3wsSEmyVv1EpA==", "requires": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, - "@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==", + "@jimp/plugin-gaussian": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.16.13.tgz", + "integrity": "sha512-A1XKfGQD0iDdIiKqFYi8nZMv4dDVYdxbrmgR7y/CzUHhSYdcmoljLIIsZZM3Iks/Wa353W3vtvkWLuDbQbch1w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" + } + }, + "@jimp/plugin-invert": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.16.13.tgz", + "integrity": "sha512-xFMrIn7czEZbdbMzZWuaZFnlLGJDVJ82y5vlsKsXRTG2kcxRsMPXvZRWHV57nSs1YFsNqXSbrC8B98n0E32njQ==", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.16.13.tgz", + "integrity": "sha512-wLRYKVBXql2GAYgt6FkTnCfE+q5NomM7Dlh0oIPGAoMBWDyTx0eYutRK6PlUrRK2yMHuroAJCglICTbxqGzowQ==", "requires": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" + } + }, + "@jimp/plugin-normalize": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.16.13.tgz", + "integrity": "sha512-3tfad0n9soRna4IfW9NzQdQ2Z3ijkmo21DREHbE6CGcMIxOSvfRdSvf1qQPApxjTSo8LTU4MCi/fidx/NZ0GqQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.16.13.tgz", + "integrity": "sha512-0m6i3p01PGRkGAK9r53hDYrkyMq+tlhLOIbsSTmZyh6HLshUKlTB7eXskF5OpVd5ZUHoltlNc6R+ggvKIzxRFw==", "requires": { - "image-q": "^4.0.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "load-bmfont": "^1.4.0" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.13.tgz", + "integrity": "sha512-qoqtN8LDknm3fJm9nuPygJv30O3vGhSBD2TxrsCnhtOsxKAqVPJtFVdGd/qVuZ8nqQANQmTlfqTiK9mVWQ7MiQ==", "requires": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, "@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==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.16.13.tgz", + "integrity": "sha512-Ev+Jjmj1nHYw897z9C3R9dYsPv7S2/nxdgfFb/h8hOwK0Ovd1k/+yYS46A0uj/JCKK0pQk8wOslYBkPwdnLorw==", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" } }, - "@jimp/plugin-threshold": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", - "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", + "@jimp/plugin-scale": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.16.13.tgz", + "integrity": "sha512-05POQaEJVucjTiSGMoH68ZiELc7QqpIpuQlZ2JBbhCV+WCbPFUBcGSmE7w4Jd0E2GvCho/NoMODLwgcVGQA97A==", "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" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" + } + }, + "@jimp/plugin-shadow": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.16.13.tgz", + "integrity": "sha512-nmu5VSZ9hsB1JchTKhnnCY+paRBnwzSyK5fhkhtQHHoFD5ArBQ/5wU8y6tCr7k/GQhhGq1OrixsECeMjPoc8Zw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" + } + }, + "@jimp/plugin-threshold": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.16.13.tgz", + "integrity": "sha512-+3zArBH0OE3Rhjm4HyAokMsZlIq5gpQec33CncyoSwxtRBM2WAhUVmCUKuBo+Lr/2/4ISoY4BWpHKhMLDix6cA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" + } + }, + "@jimp/plugins": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.16.13.tgz", + "integrity": "sha512-CJLdqODEhEVs4MgWCxpWL5l95sCBlkuSLz65cxEm56X5akIsn4LOlwnKoSEZioYcZUBvHhCheH67AyPTudfnQQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/plugin-blit": "^0.16.13", + "@jimp/plugin-blur": "^0.16.13", + "@jimp/plugin-circle": "^0.16.13", + "@jimp/plugin-color": "^0.16.13", + "@jimp/plugin-contain": "^0.16.13", + "@jimp/plugin-cover": "^0.16.13", + "@jimp/plugin-crop": "^0.16.13", + "@jimp/plugin-displace": "^0.16.13", + "@jimp/plugin-dither": "^0.16.13", + "@jimp/plugin-fisheye": "^0.16.13", + "@jimp/plugin-flip": "^0.16.13", + "@jimp/plugin-gaussian": "^0.16.13", + "@jimp/plugin-invert": "^0.16.13", + "@jimp/plugin-mask": "^0.16.13", + "@jimp/plugin-normalize": "^0.16.13", + "@jimp/plugin-print": "^0.16.13", + "@jimp/plugin-resize": "^0.16.13", + "@jimp/plugin-rotate": "^0.16.13", + "@jimp/plugin-scale": "^0.16.13", + "@jimp/plugin-shadow": "^0.16.13", + "@jimp/plugin-threshold": "^0.16.13", + "timm": "^1.6.1" + } + }, + "@jimp/png": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.13.tgz", + "integrity": "sha512-8cGqINvbWJf1G0Her9zbq9I80roEX0A+U45xFby3tDWfzn+Zz8XKDF1Nv9VUwVx0N3zpcG1RPs9hfheG4Cq2kg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "pngjs": "^3.3.3" + } + }, + "@jimp/tiff": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.13.tgz", + "integrity": "sha512-oJY8d9u95SwW00VPHuCNxPap6Q1+E/xM5QThb9Hu+P6EGuu6lIeLaNBMmFZyblwFbwrH+WBOZlvIzDhi4Dm/6Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" } }, "@jimp/types": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", - "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.13.tgz", + "integrity": "sha512-mC0yVNUobFDjoYLg4hoUwzMKgNlxynzwt3cDXzumGvRJ7Kb8qQGOWJQjQFo5OxmGExqzPphkirdbBF88RVLBCg==", "requires": { - "zod": "^3.23.8" + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.16.13", + "@jimp/gif": "^0.16.13", + "@jimp/jpeg": "^0.16.13", + "@jimp/png": "^0.16.13", + "@jimp/tiff": "^0.16.13", + "timm": "^1.6.1" } }, "@jimp/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.13.tgz", + "integrity": "sha512-VyCpkZzFTHXtKgVO35iKN0sYR10psGpV6SkcSeV4oF7eSYlR8Bl6aQLCzVeFjvESF7mxTmIiI3/XrMobVrtxDA==", "requires": { - "@jimp/types": "1.6.0", - "tinycolor2": "^1.6.0" + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" } }, "@mongodb-js/saslprep": { @@ -5826,17 +6025,17 @@ "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", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -5861,10 +6060,10 @@ "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==" + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" }, "body-parser": { "version": "1.19.0", @@ -5946,6 +6145,20 @@ "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.1.tgz", "integrity": "sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA==" }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==" + }, "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", @@ -6023,6 +6236,14 @@ "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==", "dev": true }, + "centra": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz", + "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==", + "requires": { + "follow-redirects": "^1.15.6" + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6265,6 +6486,11 @@ "esutils": "^2.0.2" } }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -6847,6 +7073,11 @@ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", "dev": true }, + "follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -6918,9 +7149,9 @@ } }, "gifwrap": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", - "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.4.tgz", + "integrity": "sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ==", "requires": { "image-q": "^4.0.0", "omggif": "^1.0.10" @@ -6949,6 +7180,15 @@ "is-glob": "^4.0.1" } }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "global-dirs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", @@ -7227,6 +7467,11 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7351,37 +7596,15 @@ "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" + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.16.1.tgz", + "integrity": "sha512-+EKVxbR36Td7Hfd23wKGIeEyHbxShZDX6L8uJkgVW3ESA9GiTEPK08tG1XI2r/0w5Ch0HyJF5kPqF9K7EmGjaw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/custom": "^0.16.1", + "@jimp/plugins": "^0.16.1", + "@jimp/types": "^0.16.1", + "regenerator-runtime": "^0.13.3" } }, "joi": { @@ -7513,6 +7736,31 @@ "type-check": "~0.4.0" } }, + "load-bmfont": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.2.tgz", + "integrity": "sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==", + "requires": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^3.7.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "phin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz", + "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==", + "requires": { + "centra": "^2.7.0" + } + } + } + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -7637,6 +7885,14 @@ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "dev": true }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "requires": { + "dom-walk": "^0.1.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -8009,6 +8265,11 @@ "xml2js": "^0.5.0" } }, + "parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -8076,6 +8337,11 @@ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==" }, + "phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -8083,18 +8349,11 @@ "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==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", "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==" - } + "pngjs": "^3.0.0" } }, "pkg-dir": { @@ -8107,9 +8366,9 @@ } }, "pngjs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", - "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" }, "prelude-ls": { "version": "1.2.1", @@ -8123,6 +8382,11 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -8268,6 +8532,11 @@ "picomatch": "^2.2.1" } }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -8477,11 +8746,6 @@ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "dev": true }, - "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", @@ -8632,6 +8896,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" + }, "tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", @@ -8805,12 +9074,12 @@ "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==", + "utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", "requires": { - "pako": "^1.0.11" + "pako": "^1.0.5" } }, "util-deprecate": { @@ -8929,6 +9198,17 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "requires": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, "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", @@ -9036,11 +9316,6 @@ "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 75f1893302d..144aeaa863d 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dotenv": "^16.4.7", "express": "^4.17.1", "gravatar": "^1.8.2", - "jimp": "^1.6.0", + "jimp": "^0.16.1", "joi": "^17.13.3", "mongodb": "^6.12.0", "mongoose": "^8.9.5", From f5fb16569813862bee867ba01f02eadfa18c8222 Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Sun, 2 Feb 2025 21:07:49 +0100 Subject: [PATCH 11/13] Commit inicjalizacyjny dla zadania 6 --- controllers/user.js | 282 +++++++++++++++++----------------------- package-lock.json | 180 +++++++++++++++++++++++++ package.json | 1 + routes/api/user.js | 3 + service/schemas/user.js | 10 ++ 5 files changed, 312 insertions(+), 164 deletions(-) diff --git a/controllers/user.js b/controllers/user.js index fa888ae2596..7dd94d35724 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -1,4 +1,4 @@ -const User = require("../service/schemas/user"); +const User = require("../service/schemas/user"); // Import modelu użytkownika const Joi = require("joi"); const passport = require("passport"); const jwt = require("jsonwebtoken"); @@ -7,6 +7,7 @@ const multer = require("multer"); const path = require("path"); const jimp = require("jimp"); const fs = require("fs"); +const sgMail = require("@sendgrid/mail"); // Importujemy SendGrid const schema = Joi.object({ password: Joi.string().required(), @@ -95,18 +96,36 @@ const register = async (req, res, next) => { subscription: "starter", avatarURL, }); + + // Generowanie tokenu weryfikacyjnego + const verificationToken = jwt.sign( + { id: newUser._id }, + process.env.VERIFY_SECRET, + { expiresIn: "24h" } + ); + newUser.verificationToken = verificationToken; + await newUser.setPassword(req.body.password); await newUser.save(); + // Logika wysyłania e-maila z linkiem do weryfikacji + const verifyUrl = `${process.env.BASE_URL}/verify-email/${verificationToken}`; + sgMail.setApiKey(process.env.SENDGRID_API_KEY); + const msg = { + to: req.body.email, + from: process.env.EMAIL_USER, // Użyj zweryfikowanego nadawcy w SendGrid + subject: "Email Verification", + html: `

Click the link to verify your email: ${verifyUrl}

`, + }; + + await sgMail.send(msg); + res.status(201).json({ status: "201 Created", contentType: "application/json", responseBody: { - user: { - email: req.body.email, - subscription: "starter", - avatarURL: avatarURL, - }, + message: + "Registration successful. Please check your email to verify your account.", }, }); } catch (err) { @@ -114,6 +133,94 @@ const register = async (req, res, next) => { } }; +// Verify email +const verifyEmail = async (req, res, next) => { + try { + const { verificationToken } = req.params; + + // Szukamy użytkownika z podanym tokenem + const user = await User.findOne({ verificationToken }); + + if (!user) { + return res.status(404).json({ + status: "404 Not Found", + responseBody: { message: "User not found or already verified" }, + }); + } + + // Aktualizujemy użytkownika - usuwamy token i ustawiamy verify na true + user.verificationToken = null; + user.verify = true; + await user.save(); + + return res.status(200).json({ + status: "200 OK", + responseBody: { message: "Verification successful" }, + }); + } catch (error) { + next(error); + } +}; + +// Resend verification email +const resendVerificationEmail = async (req, res, next) => { + const { email } = req.body; + + if (!email) { + return res.status(400).json({ + status: "400 Bad Request", + responseBody: { message: "Missing required field email" }, + }); + } + + try { + const user = await User.findOne({ email }); + + if (!user) { + return res.status(404).json({ + status: "404 Not Found", + responseBody: { message: "User not found" }, + }); + } + + if (user.verify) { + return res.status(400).json({ + status: "400 Bad Request", + responseBody: { message: "Verification has already been passed" }, + }); + } + + // Generowanie nowego tokenu weryfikacyjnego + const verificationToken = jwt.sign( + { id: user._id }, + process.env.VERIFY_SECRET, + { expiresIn: "24h" } + ); + user.verificationToken = verificationToken; + await user.save(); + + // Wysyłanie e-maila z nowym tokenem weryfikacyjnym + const verifyUrl = `${process.env.BASE_URL}/verify-email/${verificationToken}`; + const msg = { + to: user.email, + from: process.env.EMAIL_USER, + subject: "Email Verification", + html: `

Click the link to verify your email: ${verifyUrl}

`, + }; + + await sgMail.send(msg); + + res.status(200).json({ + status: "200 OK", + responseBody: { + message: "Verification email sent successfully", + }, + }); + } catch (error) { + next(error); + } +}; + // Update avatar const updateAvatar = async (req, res, next) => { upload(req, res, async (err) => { @@ -136,10 +243,9 @@ const updateAvatar = async (req, res, next) => { }); } - // Przetwarzanie obrazu w Jimp (zmiana rozmiaru do 250x250) const avatarPath = req.file.path; const image = await jimp.read(avatarPath); - await image.resize(250, 250); // Skalowanie do 250x250 + await image.resize(250, 250); const uniqueFilename = `${userId}-${Date.now()}${path.extname( req.file.originalname )}`; @@ -149,16 +255,11 @@ const updateAvatar = async (req, res, next) => { uniqueFilename ); - // Zapisz przetworzony obraz await image.writeAsync(finalPath); - // Usuń plik tymczasowy await fs.promises.unlink(avatarPath); - - // Wyczyść cały folder tmp await cleanTmpFolder(); - // Zaktualizuj ścieżkę avatara w bazie danych user.avatarURL = `/avatars/${uniqueFilename}`; await user.save(); @@ -183,7 +284,7 @@ async function cleanTmpFolder() { const files = await fs.promises.readdir(tmpDir); for (const file of files) { const filePath = path.join(tmpDir, file); - await fs.promises.unlink(filePath); // Usuń plik + await fs.promises.unlink(filePath); console.log(`Usunięto: ${filePath}`); } console.log("Folder tmp wyczyszczony."); @@ -192,155 +293,6 @@ async function cleanTmpFolder() { } } -// Login user -const login = async (req, res, next) => { - const { error } = schema.validate(req.body); - - if (error) { - return res.status(400).json({ - status: "400 Bad Request", - contentType: "application/json", - responseBody: error.message, - }); - } - - const user = await User.findOne({ email: req.body.email }); - - if (!user) { - return res.status(401).json({ - status: "401 Unauthorized", - responseBody: { - message: "User with this email doesn't exist", - }, - }); - } - - const isPasswordValid = await user.validatePassword(req.body.password); - - if (!isPasswordValid) { - return res.status(401).json({ - status: "401 Unauthorized", - responseBody: { - message: "Incorrect password", - }, - }); - } - - try { - const payload = { - id: user._id, - username: user.username, - }; - const secret = process.env.AUTH_SECRET; - const token = jwt.sign(payload, secret, { expiresIn: "12h" }); - - user.token = token; - await user.save(); - - return res.json({ - status: "200 OK", - contentType: "application/json", - responseBody: { - token: token, - user: { - email: req.body.email, - subscription: user.subscription, - }, - }, - }); - } catch (err) { - next(err); - } -}; - -// Logout user -const logout = async (req, res, next) => { - try { - const userId = req.user._id; - const user = await User.findById(userId); - - user.token = null; - await user.save(); - - return res.status(204).send(); - } catch (err) { - next(err); - } -}; - -// Get current user data -const current = async (req, res, next) => { - try { - const userId = req.user._id; - const user = await User.findById(userId); - - if (!user || !user.token) { - return res.status(401).json({ - status: "401 Unauthorized", - contentType: "application/json", - responseBody: { - message: "Not authorized", - }, - }); - } - - res.json({ - status: "200 OK", - contentType: "application/json", - responseBody: { - email: req.user.email, - subscription: req.user.subscription, - avatarURL: req.user.avatarURL, // Include avatar URL in response - }, - }); - } catch (err) { - next(err); - } -}; - -const updateSub = async (req, res, next) => { - const userId = req.user._id; - const { error } = req.body; - - if (error || !req.body.subscription) { - return res.status(400).json({ - status: "400 Bad Request", - contentType: "application/json", - responseBody: { - message: "Invalid subscription type", - }, - }); - } - - try { - const user = await User.findById(userId); - - if (!user) { - return res.status(401).json({ - status: "401 Unauthorized", - contentType: "application/json", - responseBody: { - message: "Not authorized", - }, - }); - } - - user.subscription = req.body.subscription; - await user.save(); - - res.json({ - status: "200 OK", - contentType: "application/json", - responseBody: { - email: user.email, - subscription: user.subscription, - }, - }); - } catch (err) { - next(err); - } -}; - module.exports = { register, login, @@ -348,5 +300,7 @@ module.exports = { auth, current, updateSub, - updateAvatar, // Expose the new method + updateAvatar, + verifyEmail, + resendVerificationEmail, // Dodano metodę wysyłania ponownego e-maila }; diff --git a/package-lock.json b/package-lock.json index 1722c5b6576..a0dfa8ab6c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "template", "version": "0.0.0", "dependencies": { + "@sendgrid/mail": "^8.1.4", "bcryptjs": "^2.4.3", "cors": "2.8.5", "cross-env": "7.0.3", @@ -646,6 +647,44 @@ "sparse-bitfield": "^3.0.3" } }, + "node_modules/@sendgrid/client": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.4.tgz", + "integrity": "sha512-VxZoQ82MpxmjSXLR3ZAE2OWxvQIW2k2G24UeRPr/SYX8HqWLV/8UBN15T2WmjjnEb5XSmFImTJOKDzzSeKr9YQ==", + "license": "MIT", + "dependencies": { + "@sendgrid/helpers": "^8.0.0", + "axios": "^1.7.4" + }, + "engines": { + "node": ">=12.*" + } + }, + "node_modules/@sendgrid/helpers": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz", + "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.2.2" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/@sendgrid/mail": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.4.tgz", + "integrity": "sha512-MUpIZykD9ARie8LElYCqbcBhGGMaA/E6I7fEcG7Hc2An26QJyLtwOaKQ3taGp8xO8BICPJrSKuYV4bDeAJKFGQ==", + "license": "MIT", + "dependencies": { + "@sendgrid/client": "^8.1.4", + "@sendgrid/helpers": "^8.0.0" + }, + "engines": { + "node": ">=12.*" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -900,6 +939,23 @@ "node": ">=8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1316,6 +1372,18 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1495,6 +1563,15 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -1513,6 +1590,15 @@ "node": ">= 0.4" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2309,6 +2395,20 @@ } } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -4166,6 +4266,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -5831,6 +5937,32 @@ "sparse-bitfield": "^3.0.3" } }, + "@sendgrid/client": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.4.tgz", + "integrity": "sha512-VxZoQ82MpxmjSXLR3ZAE2OWxvQIW2k2G24UeRPr/SYX8HqWLV/8UBN15T2WmjjnEb5XSmFImTJOKDzzSeKr9YQ==", + "requires": { + "@sendgrid/helpers": "^8.0.0", + "axios": "^1.7.4" + } + }, + "@sendgrid/helpers": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz", + "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==", + "requires": { + "deepmerge": "^4.2.2" + } + }, + "@sendgrid/mail": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.4.tgz", + "integrity": "sha512-MUpIZykD9ARie8LElYCqbcBhGGMaA/E6I7fEcG7Hc2An26QJyLtwOaKQ3taGp8xO8BICPJrSKuYV4bDeAJKFGQ==", + "requires": { + "@sendgrid/client": "^8.1.4", + "@sendgrid/helpers": "^8.0.0" + } + }, "@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -6025,6 +6157,21 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6326,6 +6473,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -6452,6 +6607,11 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -6467,6 +6627,11 @@ "object-keys": "^1.0.12" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -7078,6 +7243,16 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, + "form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -8407,6 +8582,11 @@ "ipaddr.js": "1.9.1" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", diff --git a/package.json b/package.json index 144aeaa863d..f8895c5b62c 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint:fix": "eslint --fix **/*.js" }, "dependencies": { + "@sendgrid/mail": "^8.1.4", "bcryptjs": "^2.4.3", "cors": "2.8.5", "cross-env": "7.0.3", diff --git a/routes/api/user.js b/routes/api/user.js index 07fef5678f3..a8d6345e8a5 100644 --- a/routes/api/user.js +++ b/routes/api/user.js @@ -12,4 +12,7 @@ router.patch("/", ctrlUser.updateSub); // Trasa do aktualizacji awatara router.patch("/avatars", ctrlUser.auth, ctrlUser.updateAvatar); // Dodanie trasy do aktualizacji awatara +// Trasa do weryfikacji emaila +router.get("/verify/:verificationToken", ctrlUser.verifyEmail); + module.exports = router; diff --git a/service/schemas/user.js b/service/schemas/user.js index a23042df6cf..e30c3457c93 100644 --- a/service/schemas/user.js +++ b/service/schemas/user.js @@ -22,12 +22,22 @@ const userSchema = new Schema({ type: String, default: null, }, + verify: { + type: Boolean, + default: false, // Domyślnie użytkownik nie jest zweryfikowany + }, + verificationToken: { + type: String, + required: [true, "Verify token is required"], // Pole wymagane + }, }); +// Funkcja do hashowania hasła userSchema.methods.setPassword = async function (password) { this.password = await bCrypt.hash(password, 10); }; +// Funkcja do sprawdzania poprawności hasła userSchema.methods.validatePassword = async function (password) { return await bCrypt.compare(password, this.password); }; From 110696b85a823e98773321704102ffffa7129491 Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Mon, 3 Feb 2025 17:27:23 +0100 Subject: [PATCH 12/13] =?UTF-8?q?Dodanie=20brakuj=C4=85cych=20funkcji=20do?= =?UTF-8?q?=20pliku=20user.js=20w=20controllers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/user.js | 149 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/controllers/user.js b/controllers/user.js index 7dd94d35724..ad4588844e4 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -293,6 +293,155 @@ async function cleanTmpFolder() { } } +// Login user +const login = async (req, res, next) => { + const { error } = schema.validate(req.body); + + if (error) { + return res.status(400).json({ + status: "400 Bad Request", + contentType: "application/json", + responseBody: error.message, + }); + } + + const user = await User.findOne({ email: req.body.email }); + + if (!user) { + return res.status(401).json({ + status: "401 Unauthorized", + responseBody: { + message: "User with this email doesn't exist", + }, + }); + } + + const isPasswordValid = await user.validatePassword(req.body.password); + + if (!isPasswordValid) { + return res.status(401).json({ + status: "401 Unauthorized", + responseBody: { + message: "Incorrect password", + }, + }); + } + + try { + const payload = { + id: user._id, + username: user.username, + }; + const secret = process.env.AUTH_SECRET; + const token = jwt.sign(payload, secret, { expiresIn: "12h" }); + + user.token = token; + await user.save(); + + return res.json({ + status: "200 OK", + contentType: "application/json", + responseBody: { + token: token, + user: { + email: req.body.email, + subscription: user.subscription, + }, + }, + }); + } catch (err) { + next(err); + } +}; + +// Logout user +const logout = async (req, res, next) => { + try { + const userId = req.user._id; + const user = await User.findById(userId); + + user.token = null; + await user.save(); + + return res.status(204).send(); + } catch (err) { + next(err); + } +}; + +// Get current user data +const current = async (req, res, next) => { + try { + const userId = req.user._id; + const user = await User.findById(userId); + + if (!user || !user.token) { + return res.status(401).json({ + status: "401 Unauthorized", + contentType: "application/json", + responseBody: { + message: "Not authorized", + }, + }); + } + + res.json({ + status: "200 OK", + contentType: "application/json", + responseBody: { + email: req.user.email, + subscription: req.user.subscription, + avatarURL: req.user.avatarURL, // Include avatar URL in response + }, + }); + } catch (err) { + next(err); + } +}; + +const updateSub = async (req, res, next) => { + const userId = req.user._id; + const { error } = req.body; + + if (error || !req.body.subscription) { + return res.status(400).json({ + status: "400 Bad Request", + contentType: "application/json", + responseBody: { + message: "Invalid subscription type", + }, + }); + } + + try { + const user = await User.findById(userId); + + if (!user) { + return res.status(401).json({ + status: "401 Unauthorized", + contentType: "application/json", + responseBody: { + message: "Not authorized", + }, + }); + } + + user.subscription = req.body.subscription; + await user.save(); + + res.json({ + status: "200 OK", + contentType: "application/json", + responseBody: { + email: user.email, + subscription: user.subscription, + }, + }); + } catch (err) { + next(err); + } +}; + module.exports = { register, login, From ce2b4e3776417061c72b720290ab375c7b27dbcc Mon Sep 17 00:00:00 2001 From: Grzesiek1982 Date: Mon, 3 Feb 2025 22:07:43 +0100 Subject: [PATCH 13/13] =?UTF-8?q?Zmiana=20weryfikacji=20tokena=20z=20wymag?= =?UTF-8?q?anego=20na=20domy=C5=9Bln=C4=85=20warto=C5=9B=C4=87=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/schemas/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/schemas/user.js b/service/schemas/user.js index e30c3457c93..cec5801f830 100644 --- a/service/schemas/user.js +++ b/service/schemas/user.js @@ -28,7 +28,7 @@ const userSchema = new Schema({ }, verificationToken: { type: String, - required: [true, "Verify token is required"], // Pole wymagane + default: null, // pole nie jest wymagane i domyślnie ma wartość null }, });