From f8cea9d69e8325f238c66d5520683e78b08e9846 Mon Sep 17 00:00:00 2001 From: zetdou Date: Mon, 12 Aug 2024 18:32:58 +0200 Subject: [PATCH 01/21] first commit --- routes/api/contacts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/api/contacts.js b/routes/api/contacts.js index a60ebd69231..c819d6c9b96 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -3,7 +3,7 @@ const express = require('express') const router = express.Router() router.get('/', async (req, res, next) => { - res.json({ message: 'template message' }) + res.json({ message: 'hello' }) }) router.get('/:contactId', async (req, res, next) => { From 2e2a716b5b965d3b964384b82f76e3a5b9482704 Mon Sep 17 00:00:00 2001 From: zetdou Date: Mon, 12 Aug 2024 21:55:33 +0200 Subject: [PATCH 02/21] contacts.js Working listContacts, getContactById, removeContact --- app.js | 2 +- models/contacts.js | 74 ++++++++++++++++++++++++++++++++++++++---- package-lock.json | 25 +++++++++++++- package.json | 3 +- routes/api/contacts.js | 51 +++++++++++++++++++++++++---- 5 files changed, 140 insertions(+), 15 deletions(-) diff --git a/app.js b/app.js index 40fd9bc167f..ca825569669 100644 --- a/app.js +++ b/app.js @@ -4,7 +4,7 @@ const cors = require('cors') const contactsRouter = require('./routes/api/contacts') -const app = express() +const app = express(); const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short' diff --git a/models/contacts.js b/models/contacts.js index 409d11c7c09..b76053f5b4b 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -1,14 +1,76 @@ -// const fs = require('fs/promises') +const fs = require('fs/promises'); +const path = require('path'); -const listContacts = async () => {} -const getContactById = async (contactId) => {} +const contactsPath = path.join(__dirname, 'contacts.json'); -const removeContact = async (contactId) => {} +const listContacts = async () => { + try { + const data = await fs.readFile(contactsPath, 'utf-8'); + const contacts = JSON.parse(data); + return contacts; + } catch (error) { + console.error("Error reading contacts file: ", error); + throw error; + } +} + +const getContactById = async (contactId) => { + try { + const contacts = await listContacts(); + const contact = contacts.find(item => item.id === contactId); + return contact || null; + } catch (error) { + console.error("Error getting contact by ID: ", error); + throw error; + } +} + +const removeContact = async (contactId) => { + try { + const contacts = await listContacts(); + const index = contacts.findIndex(contact => contact.id === contactId); + + if (index === -1) { + return false; + } + + contacts.splice(index, 1); + + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + return true; -const addContact = async (body) => {} + } catch (error) { + console.error("Error removing contact:", error); + throw error; + } + }; -const updateContact = async (contactId, body) => {} +const addContact = async ({ name, email, phone }) => { +const { nanoid } = await import('nanoid'); + + const newContact = { + id: nanoid(21), + name, + email, + phone + }; + + try { + const contacts = await listContacts(); + contacts.push(newContact); + + await fs.writeFile(contactsPath, JSON.stringify(contact, null, 2)); + return newContact; + } catch (error) { + console.error("Error adding contact: ", error); + throw error; + } +}; + +const updateContact = async (contactId, body) => { + +} module.exports = { listContacts, diff --git a/package-lock.json b/package-lock.json index e6d047044e5..37f49febd08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "cors": "2.8.5", "cross-env": "7.0.3", "express": "4.17.1", - "morgan": "1.10.0" + "morgan": "1.10.0", + "nanoid": "^5.0.7" }, "devDependencies": { "eslint": "7.19.0", @@ -2439,6 +2440,23 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5486,6 +5504,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", diff --git a/package.json b/package.json index 5045e827160..6befd1a285d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "cors": "2.8.5", "cross-env": "7.0.3", "express": "4.17.1", - "morgan": "1.10.0" + "morgan": "1.10.0", + "nanoid": "^5.0.7" }, "devDependencies": { "eslint": "7.19.0", diff --git a/routes/api/contacts.js b/routes/api/contacts.js index c819d6c9b96..bf726904ebe 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,22 +1,61 @@ const express = require('express') +const { listContacts, getContactById, removeContact, addContact } = require('../../models/contacts') const router = express.Router() router.get('/', async (req, res, next) => { - res.json({ message: 'hello' }) + try { + const contacts = await listContacts(); + res.status(200).json(contacts); + } catch (error) { + next(error); + } }) router.get('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) + try { + const { contactId } = req.params; + const contact = await getContactById(contactId); + + if (contact) { + res.status(200).json(contact); + } else { + res.status(404).json({ message: 'Not found' }); + } + } catch (error) { + next(error); + } }) router.post('/', async (req, res, next) => { - res.json({ message: 'template message' }) -}) + try { + const { name, email, phone } = req.body; + + if (!name || !email || !phone) { + return res.status(400).json({ message: 'Missing required value!' }); + } + + const newContact = await addContact({ name, email, phone }); + res.status(201).json(newContact); + } catch (error) { + next(error); + } +}); router.delete('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) + try { + const { contactId } = req.params; + const wasDeleted = await removeContact(contactId); + + if (wasDeleted) { + res.status(200).json({ message: 'Contact removed!' }); + } else { + res.status(404).json({ message: 'Not found' }); + } + } catch (error) { + next(error); + } +}); router.put('/:contactId', async (req, res, next) => { res.json({ message: 'template message' }) From c5dd79209c354b9cfef9afab34c80ef0ddd0b92d Mon Sep 17 00:00:00 2001 From: zetdou Date: Tue, 13 Aug 2024 19:54:59 +0200 Subject: [PATCH 03/21] contacts.js Working post http api method (downgrade nanoid) --- models/contacts.js | 9 +++++---- models/contacts.json | 2 +- package-lock.json | 18 +++++++++--------- package.json | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/models/contacts.js b/models/contacts.js index b76053f5b4b..0a5ee41f039 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -1,6 +1,6 @@ const fs = require('fs/promises'); const path = require('path'); - +const { nanoid } = require('nanoid'); const contactsPath = path.join(__dirname, 'contacts.json'); @@ -8,6 +8,7 @@ const listContacts = async () => { try { const data = await fs.readFile(contactsPath, 'utf-8'); const contacts = JSON.parse(data); + return contacts; } catch (error) { console.error("Error reading contacts file: ", error); @@ -46,8 +47,7 @@ const removeContact = async (contactId) => { } }; -const addContact = async ({ name, email, phone }) => { -const { nanoid } = await import('nanoid'); +const addContact = async ({name, email, phone }) => { const newContact = { id: nanoid(21), @@ -58,9 +58,10 @@ const { nanoid } = await import('nanoid'); try { const contacts = await listContacts(); + contacts.push(newContact); - await fs.writeFile(contactsPath, JSON.stringify(contact, null, 2)); + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); return newContact; } catch (error) { console.error("Error adding contact: ", error); diff --git a/models/contacts.json b/models/contacts.json index a21679132de..7e4ed721b24 100644 --- a/models/contacts.json +++ b/models/contacts.json @@ -59,4 +59,4 @@ "email": "Donec.elementum@scelerisquescelerisquedui.net", "phone": "(748) 206-2688" } -] +] \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 37f49febd08..ec5c1f75bf8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "cross-env": "7.0.3", "express": "4.17.1", "morgan": "1.10.0", - "nanoid": "^5.0.7" + "nanoid": "^3.3.5" }, "devDependencies": { "eslint": "7.19.0", @@ -2441,9 +2441,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", - "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -2451,10 +2451,10 @@ } ], "bin": { - "nanoid": "bin/nanoid.js" + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "^18 || >=20" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/natural-compare": { @@ -5505,9 +5505,9 @@ "dev": true }, "nanoid": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", - "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==" + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" }, "natural-compare": { "version": "1.4.0", diff --git a/package.json b/package.json index 6befd1a285d..cb391563993 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "cross-env": "7.0.3", "express": "4.17.1", "morgan": "1.10.0", - "nanoid": "^5.0.7" + "nanoid": "3.3.5" }, "devDependencies": { "eslint": "7.19.0", From e8d960b790e2689654f0fb5648f1240f6f1ba933 Mon Sep 17 00:00:00 2001 From: zetdou Date: Tue, 13 Aug 2024 20:13:22 +0200 Subject: [PATCH 04/21] contacts.js updateContact, put method working --- models/contacts.js | 17 +++++++++++++++++ routes/api/contacts.js | 23 ++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/models/contacts.js b/models/contacts.js index 0a5ee41f039..84ccbcced0e 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -70,7 +70,24 @@ const addContact = async ({name, email, phone }) => { }; const updateContact = async (contactId, body) => { + try { + const contacts = await listContacts(); + const index = contacts.findIndex(contact => contact.id === contactId); + + if (index === -1) { + return null; + } + const updatedContact = { ...contacts[index], ...body }; + contacts[index] = updatedContact; + + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + + return updatedContact; + } catch (error) { + console.error("Error updategin cotnact: ", error); + throw error; + } } module.exports = { diff --git a/routes/api/contacts.js b/routes/api/contacts.js index bf726904ebe..447b16dd079 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,5 +1,5 @@ const express = require('express') -const { listContacts, getContactById, removeContact, addContact } = require('../../models/contacts') +const { listContacts, getContactById, removeContact, addContact, updateContact } = require('../../models/contacts') const router = express.Router() @@ -58,7 +58,24 @@ router.delete('/:contactId', async (req, res, next) => { }); router.put('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) + try { + const { contactId } = req.params; + const body = req.body; + + if (Object.keys(body).length === 0) { + return res.status(400).json({ message: "missing fields" }); + } + + const updatedContact = await updateContact(contactId, body); + + if (updatedContact) { + res.status(200).json(updatedContact); + } else { + res.status(404).json({ message: "Not found" }); + } + } catch (error) { + next(error); + } +}); module.exports = router From e1d299075d711d52d08aaa5426f3ca64c769d467 Mon Sep 17 00:00:00 2001 From: zetdou Date: Tue, 13 Aug 2024 20:18:08 +0200 Subject: [PATCH 05/21] Final commit --- models/contacts.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/models/contacts.json b/models/contacts.json index 7e4ed721b24..8435aeb287f 100644 --- a/models/contacts.json +++ b/models/contacts.json @@ -58,5 +58,11 @@ "name": "Alec Howard", "email": "Donec.elementum@scelerisquescelerisquedui.net", "phone": "(748) 206-2688" + }, + { + "id": "7paH1YntEb-CSRs02gSSL", + "name": "Mikolaj Zydorek", + "email": "zyziupoz@wp.pl", + "phone": "524345345" } ] \ No newline at end of file From 38b0c149092ca168a4962d46ae2b84d599246853 Mon Sep 17 00:00:00 2001 From: zetdou Date: Tue, 13 Aug 2024 21:14:31 +0200 Subject: [PATCH 06/21] Fix routes --- app.js | 2 +- routes/api/contacts.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app.js b/app.js index ca825569669..1f3524d91be 100644 --- a/app.js +++ b/app.js @@ -12,7 +12,7 @@ app.use(logger(formatsLogger)) app.use(cors()) app.use(express.json()) -app.use('/api/contacts', contactsRouter) +app.use('/', contactsRouter) app.use((req, res) => { res.status(404).json({ message: 'Not found' }) diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 447b16dd079..6bcd3b7037f 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -3,7 +3,7 @@ const { listContacts, getContactById, removeContact, addContact, updateContact } const router = express.Router() -router.get('/', async (req, res, next) => { +router.get('/contacts', async (req, res, next) => { try { const contacts = await listContacts(); res.status(200).json(contacts); @@ -12,7 +12,7 @@ router.get('/', async (req, res, next) => { } }) -router.get('/:contactId', async (req, res, next) => { +router.get('/contacts/:contactId', async (req, res, next) => { try { const { contactId } = req.params; const contact = await getContactById(contactId); @@ -27,7 +27,7 @@ router.get('/:contactId', async (req, res, next) => { } }) -router.post('/', async (req, res, next) => { +router.post('/contacts', async (req, res, next) => { try { const { name, email, phone } = req.body; @@ -42,7 +42,7 @@ router.post('/', async (req, res, next) => { } }); -router.delete('/:contactId', async (req, res, next) => { +router.delete('/contacts/:contactId', async (req, res, next) => { try { const { contactId } = req.params; const wasDeleted = await removeContact(contactId); @@ -57,7 +57,7 @@ router.delete('/:contactId', async (req, res, next) => { } }); -router.put('/:contactId', async (req, res, next) => { +router.put('/contacts/:contactId', async (req, res, next) => { try { const { contactId } = req.params; const body = req.body; From d9ea879ee50b15f259256199c4690db7e453e2ff Mon Sep 17 00:00:00 2001 From: zetdou Date: Sun, 25 Aug 2024 18:43:57 +0200 Subject: [PATCH 07/21] Routes and global middleware Fix correct paths to routes and add global middleware to handle errors --- app.js | 17 ++++++++--------- models/contacts.json | 6 +++--- routes/api/contacts.js | 10 +++++----- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app.js b/app.js index 1f3524d91be..d3ce70e8046 100644 --- a/app.js +++ b/app.js @@ -12,14 +12,13 @@ app.use(logger(formatsLogger)) app.use(cors()) app.use(express.json()) -app.use('/', contactsRouter) - -app.use((req, res) => { - res.status(404).json({ message: 'Not found' }) -}) - -app.use((err, req, res, next) => { - res.status(500).json({ message: err.message }) -}) +app.use('/api/contacts', contactsRouter) + +app.use((error, req, res, next) => { + console.error(error) + const status = error.status || 500; + const message = error.message || "Internal server error"; + res.status(status).json({message}); +}); module.exports = app diff --git a/models/contacts.json b/models/contacts.json index 8435aeb287f..e0309e18ecd 100644 --- a/models/contacts.json +++ b/models/contacts.json @@ -60,9 +60,9 @@ "phone": "(748) 206-2688" }, { - "id": "7paH1YntEb-CSRs02gSSL", + "id": "Vi8gav5WMhFpt-d-hSYbR", "name": "Mikolaj Zydorek", - "email": "zyziupoz@wp.pl", - "phone": "524345345" + "email": "dfndnfj@wp.pl", + "phone": "23232" } ] \ No newline at end of file diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 6bcd3b7037f..447b16dd079 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -3,7 +3,7 @@ const { listContacts, getContactById, removeContact, addContact, updateContact } const router = express.Router() -router.get('/contacts', async (req, res, next) => { +router.get('/', async (req, res, next) => { try { const contacts = await listContacts(); res.status(200).json(contacts); @@ -12,7 +12,7 @@ router.get('/contacts', async (req, res, next) => { } }) -router.get('/contacts/:contactId', async (req, res, next) => { +router.get('/:contactId', async (req, res, next) => { try { const { contactId } = req.params; const contact = await getContactById(contactId); @@ -27,7 +27,7 @@ router.get('/contacts/:contactId', async (req, res, next) => { } }) -router.post('/contacts', async (req, res, next) => { +router.post('/', async (req, res, next) => { try { const { name, email, phone } = req.body; @@ -42,7 +42,7 @@ router.post('/contacts', async (req, res, next) => { } }); -router.delete('/contacts/:contactId', async (req, res, next) => { +router.delete('/:contactId', async (req, res, next) => { try { const { contactId } = req.params; const wasDeleted = await removeContact(contactId); @@ -57,7 +57,7 @@ router.delete('/contacts/:contactId', async (req, res, next) => { } }); -router.put('/contacts/:contactId', async (req, res, next) => { +router.put('/:contactId', async (req, res, next) => { try { const { contactId } = req.params; const body = req.body; From 725999f4333b0add3a35270250c4f3d1c24dfd85 Mon Sep 17 00:00:00 2001 From: zetdou Date: Sun, 25 Aug 2024 19:30:04 +0200 Subject: [PATCH 08/21] Split code Logic moved to controllers and services. Add joi package to validation entering data in post and put method --- .eslintrc.js | 4 +- app.js | 24 ++-- controllers/contactController.js | 65 ++++++++++ models/contacts.js | 198 ++++++++++++++--------------- package-lock.json | 101 ++++++++++++++- package.json | 1 + readme.es.md | 2 +- readme.pl.md | 4 +- routes/.DS_Store | Bin 0 -> 6148 bytes routes/api/contacts.js | 89 +++---------- server.js | 6 +- services/contactService.js | 55 ++++++++ {models => services}/contacts.json | 8 +- validation/contactValidation.js | 16 +++ 14 files changed, 373 insertions(+), 200 deletions(-) create mode 100644 controllers/contactController.js create mode 100644 routes/.DS_Store create mode 100644 services/contactService.js rename {models => services}/contacts.json (90%) create mode 100644 validation/contactValidation.js diff --git a/.eslintrc.js b/.eslintrc.js index d7993327f51..6184fae5e0e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,9 +4,9 @@ module.exports = { es2021: true, node: true, }, - extends: ['standard', 'prettier'], + extends: ["standard", "prettier"], parserOptions: { ecmaVersion: 12, }, rules: {}, -} +}; diff --git a/app.js b/app.js index d3ce70e8046..7d38bdaa23c 100644 --- a/app.js +++ b/app.js @@ -1,24 +1,24 @@ -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 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((error, req, res, next) => { - console.error(error) + console.error(error); const status = error.status || 500; const message = error.message || "Internal server error"; - res.status(status).json({message}); + res.status(status).json({ message }); }); -module.exports = app +module.exports = app; diff --git a/controllers/contactController.js b/controllers/contactController.js new file mode 100644 index 00000000000..7d3cd5655da --- /dev/null +++ b/controllers/contactController.js @@ -0,0 +1,65 @@ +const contactService = require("../services/contactService"); + +async function getAllContacts(req, res, next) { + try { + const contacts = await contactService.listContacts(); + res.json(contacts); + } catch (error) { + next(error); + } +} + +async function getContactById(req, res, next) { + try { + const contact = await contactService.getContactById(req.params.contactId); + if (contact) { + res.json(contact); + } else { + res.status(404).json({ message: "Not found" }); + } + } catch (error) { + next(error); + } +} + +async function createContact(req, res, next) { + try { + const newContact = await contactService.addContact(req.body); + res.status(201).json(newContact); + } catch (error) { + next(error); + } +} + +async function updateExistingContact(req, res, next) { + try { + const updatedContact = await contactService.updateContact( + req.params.contactId, + req.body, + ); + res.json(updatedContact); + } catch (error) { + next(error); + } +} + +async function deleteContact(req, res, next) { + try { + const wasDeleted = await contactService.removeContact(req.params.contactId); + if (wasDeleted) { + res.status(200).json({ message: "Contact removed!" }); + } else { + res.status(404).json({ message: "Not found" }); + } + } catch (error) { + next(error); + } +} + +module.exports = { + getAllContacts, + getContactById, + createContact, + updateExistingContact, + deleteContact, +}; diff --git a/models/contacts.js b/models/contacts.js index 84ccbcced0e..4bee1032f59 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -1,99 +1,99 @@ -const fs = require('fs/promises'); -const path = require('path'); -const { nanoid } = require('nanoid'); - -const contactsPath = path.join(__dirname, 'contacts.json'); - -const listContacts = async () => { - try { - const data = await fs.readFile(contactsPath, 'utf-8'); - const contacts = JSON.parse(data); - - return contacts; - } catch (error) { - console.error("Error reading contacts file: ", error); - throw error; - } -} - -const getContactById = async (contactId) => { - try { - const contacts = await listContacts(); - const contact = contacts.find(item => item.id === contactId); - return contact || null; - } catch (error) { - console.error("Error getting contact by ID: ", error); - throw error; - } -} - -const removeContact = async (contactId) => { - try { - const contacts = await listContacts(); - const index = contacts.findIndex(contact => contact.id === contactId); - - if (index === -1) { - return false; - } - - contacts.splice(index, 1); - - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - return true; - - } catch (error) { - console.error("Error removing contact:", error); - throw error; - } - }; - -const addContact = async ({name, email, phone }) => { - - const newContact = { - id: nanoid(21), - name, - email, - phone - }; - - try { - const contacts = await listContacts(); - - contacts.push(newContact); - - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - return newContact; - } catch (error) { - console.error("Error adding contact: ", error); - throw error; - } -}; - -const updateContact = async (contactId, body) => { - try { - const contacts = await listContacts(); - const index = contacts.findIndex(contact => contact.id === contactId); - - if (index === -1) { - return null; - } - - const updatedContact = { ...contacts[index], ...body }; - contacts[index] = updatedContact; - - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - - return updatedContact; - } catch (error) { - console.error("Error updategin cotnact: ", error); - throw error; - } -} - -module.exports = { - listContacts, - getContactById, - removeContact, - addContact, - updateContact, -} +// const fs = require('fs/promises'); +// const path = require('path'); +// const { nanoid } = require('nanoid'); + +// const contactsPath = path.join(__dirname, 'contacts.json'); + +// const listContacts = async () => { +// try { +// const data = await fs.readFile(contactsPath, 'utf-8'); +// const contacts = JSON.parse(data); + +// return contacts; +// } catch (error) { +// console.error("Error reading contacts file: ", error); +// throw error; +// } +// } + +// const getContactById = async (contactId) => { +// try { +// const contacts = await listContacts(); +// const contact = contacts.find(item => item.id === contactId); +// return contact || null; +// } catch (error) { +// console.error("Error getting contact by ID: ", error); +// throw error; +// } +// } + +// const removeContact = async (contactId) => { +// try { +// const contacts = await listContacts(); +// const index = contacts.findIndex(contact => contact.id === contactId); + +// if (index === -1) { +// return false; +// } + +// contacts.splice(index, 1); + +// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); +// return true; + +// } catch (error) { +// console.error("Error removing contact:", error); +// throw error; +// } +// }; + +// const addContact = async ({name, email, phone }) => { + +// const newContact = { +// id: nanoid(21), +// name, +// email, +// phone +// }; + +// try { +// const contacts = await listContacts(); + +// contacts.push(newContact); + +// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); +// return newContact; +// } catch (error) { +// console.error("Error adding contact: ", error); +// throw error; +// } +// }; + +// const updateContact = async (contactId, body) => { +// try { +// const contacts = await listContacts(); +// const index = contacts.findIndex(contact => contact.id === contactId); + +// if (index === -1) { +// return null; +// } + +// const updatedContact = { ...contacts[index], ...body }; +// contacts[index] = updatedContact; + +// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + +// return updatedContact; +// } catch (error) { +// console.error("Error updategin cotnact: ", error); +// throw error; +// } +// } + +// module.exports = { +// listContacts, +// getContactById, +// removeContact, +// addContact, +// updateContact, +// } diff --git a/package-lock.json b/package-lock.json index ec5c1f75bf8..435b5f93cee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,9 @@ "cors": "2.8.5", "cross-env": "7.0.3", "express": "4.17.1", + "joi": "^17.13.3", "morgan": "1.10.0", - "nanoid": "^3.3.5" + "nanoid": "3.3.5" }, "devDependencies": { "eslint": "7.19.0", @@ -142,6 +143,37 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -2167,6 +2199,18 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2441,9 +2485,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.5.tgz", + "integrity": "sha512-nvgaJGpIANf4+VWJAaDGORQyMzhFkze8aXVdrHq+BaSvzfpOuponEysaVFKV/0Bca5V+3SBiDvRabEPbpalEBg==", "funding": [ { "type": "github", @@ -3775,6 +3819,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", @@ -5287,6 +5362,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", @@ -5505,9 +5592,9 @@ "dev": true }, "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.5.tgz", + "integrity": "sha512-nvgaJGpIANf4+VWJAaDGORQyMzhFkze8aXVdrHq+BaSvzfpOuponEysaVFKV/0Bca5V+3SBiDvRabEPbpalEBg==" }, "natural-compare": { "version": "1.4.0", diff --git a/package.json b/package.json index cb391563993..cbd6f90f0ec 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "cors": "2.8.5", "cross-env": "7.0.3", "express": "4.17.1", + "joi": "^17.13.3", "morgan": "1.10.0", "nanoid": "3.3.5" }, diff --git a/readme.es.md b/readme.es.md index 25cf77f2ef2..6e2ff4ad58b 100644 --- a/readme.es.md +++ b/readme.es.md @@ -24,4 +24,4 @@ Lea atentamente los comentarios del mentor. Corrija los comentarios y haga un co - `npm start` — Inicia el servidor en modo de producción. - `npm run start:dev` — Inicia el servidor en modo de desarrollo. - `npm run lint` — Ejecuta la comprobación del código con eslint. Debe ejecutarse antes de cada PR y corregir todos los errores del linter. -- `npm lint:fix` — Lo mismo que la comprobación del linter, pero con correcciones automáticas de errores simples. \ No newline at end of file +- `npm lint:fix` — Lo mismo que la comprobación del linter, pero con correcciones automáticas de errores simples. diff --git a/readme.pl.md b/readme.pl.md index 817da777968..5cb9c5a39c4 100644 --- a/readme.pl.md +++ b/readme.pl.md @@ -23,7 +23,7 @@ Uważnie czytaj komentarze mentora. Popraw uwagi i zrób commit na gałęzi z za ### Komendy: -- `npm start` — uruchamia serwer w trybie produkcyjnym +- `npm start` — uruchamia serwer w trybie produkcyjnym - `npm run start:dev` — uruchamia serwer w trybie deweloperskim (development) - `npm run lint` — uruchamia sprawdzanie kodu z ESLint, należy wykonać przed każdym PR i poprawić wszystkie błędy lintera -- `npm lint:fix` — to samo co powyższe, ale również automatycznie poprawia proste błędy. \ No newline at end of file +- `npm lint:fix` — to samo co powyższe, ale również automatycznie poprawia proste błędy. diff --git a/routes/.DS_Store b/routes/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..941feefd24bf5da2c753d1819aa501371792b4ad GIT binary patch literal 6148 zcmeH~O=`nH427SXECStlndNMHfZkvT$q90S1_~h%(o$&GbM!v_Y~prZOnCz7jWiav zzlFyFV7t%PXJ7)bp}XSA!_18N3Mahd@^$>UUEgkJR=f&4M9hqp3A6p$mWY4|h=2%) zfCwyzK%U~*JTB;&^e7@A0?Q!a--kwb?WH3%J{=4(0#Mg1hjAUV1hsjA+Dk_&D>SR= z!K&3_4DoujQ(IlvOGj$9!)o}jy0iHdL$hp$H6}FcAqpZO0y6@u%qKtp5A@&W|5=Mt z5fFiYM!?ql<9^4Nsv{d9s=gj{YFy56_Y=UxkK!#ojQhk literal 0 HcmV?d00001 diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 447b16dd079..f89c368be09 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,81 +1,24 @@ -const express = require('express') -const { listContacts, getContactById, removeContact, addContact, updateContact } = require('../../models/contacts') +const express = require('express'); +const { getAllContacts, getContactById, createContact, updateExistingContact, deleteContact } = require('../../controllers/contactController'); +const { createContactSchema } = require('../../validation/contactValidation'); +const router = express.Router(); -const router = express.Router() +router.get('/', getAllContacts); -router.get('/', async (req, res, next) => { - try { - const contacts = await listContacts(); - res.status(200).json(contacts); - } catch (error) { - next(error); - } -}) - -router.get('/:contactId', async (req, res, next) => { - try { - const { contactId } = req.params; - const contact = await getContactById(contactId); - - if (contact) { - res.status(200).json(contact); - } else { - res.status(404).json({ message: 'Not found' }); - } - } catch (error) { - next(error); - } -}) +router.get('/:contactId', getContactById); router.post('/', async (req, res, next) => { - try { - const { name, email, phone } = req.body; - - if (!name || !email || !phone) { - return res.status(400).json({ message: 'Missing required value!' }); - } - - const newContact = await addContact({ name, email, phone }); - res.status(201).json(newContact); - } catch (error) { - next(error); - } -}); - -router.delete('/:contactId', async (req, res, next) => { - try { - const { contactId } = req.params; - const wasDeleted = await removeContact(contactId); - - if (wasDeleted) { - res.status(200).json({ message: 'Contact removed!' }); - } else { - res.status(404).json({ message: 'Not found' }); - } - } catch (error) { - next(error); - } -}); + const { error } = createContactSchema.validate(req.body); + if (error) return res.status(400).json({ message: error.details[0].message }); + next(); +}, createContact); router.put('/:contactId', async (req, res, next) => { - try { - const { contactId } = req.params; - const body = req.body; - - if (Object.keys(body).length === 0) { - return res.status(400).json({ message: "missing fields" }); - } - - const updatedContact = await updateContact(contactId, body); + const { error } = createContactSchema.validate(req.body); + if (error) return res.status(400).json({ message: error.details[0].message }); + next(); +}, updateExistingContact); - if (updatedContact) { - res.status(200).json(updatedContact); - } else { - res.status(404).json({ message: "Not found" }); - } - } catch (error) { - next(error); - } -}); +router.delete('/:contactId', deleteContact); -module.exports = router +module.exports = router; diff --git a/server.js b/server.js index db330824656..d3923aa3393 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,5 @@ -const app = require('./app') +const app = require("./app"); app.listen(3000, () => { - console.log("Server running. Use our API on port: 3000") -}) + console.log("Server running. Use our API on port: 3000"); +}); diff --git a/services/contactService.js b/services/contactService.js new file mode 100644 index 00000000000..1d5ea5c4b1e --- /dev/null +++ b/services/contactService.js @@ -0,0 +1,55 @@ +const fs = require("fs/promises"); +const path = require("path"); +const { nanoid } = require("nanoid"); + +const contactsPath = path.join(__dirname, "contacts.json"); + +const listContacts = async () => { + const data = await fs.readFile(contactsPath, "utf-8"); + return JSON.parse(data); +}; + +const getContactById = async (contactId) => { + const contacts = await listContacts(); + return contacts.find((contact) => contact.id === contactId) || null; +}; + +const removeContact = async (contactId) => { + const contacts = await listContacts(); + const index = contacts.findIndex((contact) => contact.id === contactId); + if (index === -1) return false; + contacts.splice(index, 1); + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + return true; +}; + +const addContact = async ({ name, email, phone }) => { + const contacts = await listContacts(); + const newContact = { + id: nanoid(21), + name, + email, + phone, + }; + contacts.push(newContact); + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + return newContact; +}; + +const updateContact = async (contactId, body) => { + const contacts = await listContacts(); + const index = contacts.findIndex((contact) => contact.id === contactId); + if (index === -1) throw new Error("Not found"); + const updatedContact = { ...contacts[index], ...body }; + contacts[index] = updatedContact; + await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); + return updatedContact; +}; + +module.exports = { + listContacts, + getContactById, + removeContact, + addContact, + updateContact, +}; diff --git a/models/contacts.json b/services/contacts.json similarity index 90% rename from models/contacts.json rename to services/contacts.json index e0309e18ecd..38e268e69e6 100644 --- a/models/contacts.json +++ b/services/contacts.json @@ -63,6 +63,12 @@ "id": "Vi8gav5WMhFpt-d-hSYbR", "name": "Mikolaj Zydorek", "email": "dfndnfj@wp.pl", - "phone": "23232" + "phone": "259483589" + }, + { + "id": "0MT494HUEYV365hXRwzq8", + "name": "Magdalena Zydorek", + "email": "sbkjsfbkjsf@gmail.com", + "phone": "335356456" } ] \ No newline at end of file diff --git a/validation/contactValidation.js b/validation/contactValidation.js new file mode 100644 index 00000000000..09fc7fdaab6 --- /dev/null +++ b/validation/contactValidation.js @@ -0,0 +1,16 @@ +const Joi = require("joi"); + +const createContactSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string() + .email() + .required(), + phone: Joi.string() + .min(7) + .max(15) + .required() +}); + +module.exports = { + createContactSchema +}; \ No newline at end of file From b11e704c4b072c24d995a4bb5b08f10a9dfa2fe4 Mon Sep 17 00:00:00 2001 From: zetdou Date: Mon, 26 Aug 2024 19:26:36 +0200 Subject: [PATCH 09/21] server.js Install mongoose, dotenv and connect to our database --- package-lock.json | 363 ++++++++++++++++++++++++++++++++++++++++++++-- package.json | 3 + server.js | 16 +- 3 files changed, 365 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 435b5f93cee..9bf3a298e44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,13 @@ "name": "template", "version": "0.0.0", "dependencies": { + "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.5", "express": "4.17.1", "joi": "^17.13.3", + "mongoose": "^8.5.4", "morgan": "1.10.0", "nanoid": "3.3.5" }, @@ -156,6 +159,14 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz", + "integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==", + "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", @@ -201,6 +212,19 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -485,6 +509,14 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -651,6 +683,14 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -761,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" }, @@ -856,6 +895,17 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -2260,6 +2310,14 @@ "json5": "lib/cli.js" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -2372,6 +2430,11 @@ "node": ">= 0.6" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -2442,6 +2505,86 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "node_modules/mongodb": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz", + "integrity": "sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.5.4.tgz", + "integrity": "sha512-nG3eehhWf9l1q80WuHvp5DV+4xDNFpDWLE5ZgcFD5tslUV2USJ56ogun8gaZ62MKAocJnoStjAdno08b8U57hg==", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -2478,11 +2621,29 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { "version": "3.3.5", @@ -2925,10 +3086,9 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -3247,6 +3407,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, "node_modules/signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", @@ -3270,6 +3435,14 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3454,6 +3627,17 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -3620,6 +3804,26 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3832,6 +4036,14 @@ "@hapi/hoek": "^9.0.0" } }, + "@mongodb-js/saslprep": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz", + "integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==", + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -3871,6 +4083,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", @@ -4090,6 +4315,11 @@ "fill-range": "^7.0.1" } }, + "bson": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==" + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -4211,6 +4441,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4291,7 +4526,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" } @@ -4360,6 +4594,11 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -5417,6 +5656,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", @@ -5504,6 +5748,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", @@ -5553,6 +5802,46 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mongodb": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz", + "integrity": "sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==", + "requires": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + } + }, + "mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "requires": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "mongoose": { + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.5.4.tgz", + "integrity": "sha512-nG3eehhWf9l1q80WuHvp5DV+4xDNFpDWLE5ZgcFD5tslUV2USJ56ogun8gaZ62MKAocJnoStjAdno08b8U57hg==", + "requires": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.7.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", @@ -5585,11 +5874,23 @@ } } }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "requires": { + "debug": "4.x" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { "version": "3.3.5", @@ -5905,10 +6206,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", @@ -6157,6 +6457,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", @@ -6174,6 +6479,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", @@ -6314,6 +6627,14 @@ "nopt": "~1.0.10" } }, + "tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "requires": { + "punycode": "^2.3.0" + } + }, "tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -6447,6 +6768,20 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "requires": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index cbd6f90f0ec..baa3601eb8b 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,13 @@ "lint:fix": "eslint --fix **/*.js" }, "dependencies": { + "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.5", "express": "4.17.1", "joi": "^17.13.3", + "mongoose": "^8.5.4", "morgan": "1.10.0", "nanoid": "3.3.5" }, diff --git a/server.js b/server.js index d3923aa3393..3f74f6ae32b 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,15 @@ +const colors = require("colors"); +const mongoose = require("mongoose"); + +require("dotenv").config(); + const app = require("./app"); -app.listen(3000, () => { - console.log("Server running. Use our API on port: 3000"); -}); +const port = process.env.PORT; + +mongoose.connect(process.env.DB_URL).then((db) => { + console.log("Database is connected.".cyan); + app.listen(port, () => { + console.info(`Server is running on port ${port}.`.green); + }); +}); \ No newline at end of file From 61bffd256db3b02f3c9176fad14fb35f6f65d177 Mon Sep 17 00:00:00 2001 From: zetdou Date: Mon, 26 Aug 2024 19:34:45 +0200 Subject: [PATCH 10/21] update server.js Add catch to promise on connection. --- server.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server.js b/server.js index 3f74f6ae32b..1b1663a89e4 100644 --- a/server.js +++ b/server.js @@ -11,5 +11,8 @@ mongoose.connect(process.env.DB_URL).then((db) => { console.log("Database is connected.".cyan); app.listen(port, () => { console.info(`Server is running on port ${port}.`.green); - }); -}); \ No newline at end of file + }) +}).catch((err) => { + console.log(err.red); + process.exit(1); +});; \ No newline at end of file From e2bf876bc98709bba9d9c338e9e25cd58e5d472e Mon Sep 17 00:00:00 2001 From: zetdou Date: Mon, 26 Aug 2024 21:15:26 +0200 Subject: [PATCH 11/21] contactSchema.js Create mongoose schema to contact model, test db with api get request and its work. Edit correct path to db and collection --- controllers/contactController.js | 118 +++++++++++++++--------------- models/contacts.js | 99 ------------------------- routes/api/contacts.js | 30 ++++---- server.js | 2 +- services/contactService.js | 96 ++++++++++++------------ services/contacts.json | 74 ------------------- services/schemas/contactSchema.js | 29 ++++++++ 7 files changed, 154 insertions(+), 294 deletions(-) delete mode 100644 models/contacts.js delete mode 100644 services/contacts.json create mode 100644 services/schemas/contactSchema.js diff --git a/controllers/contactController.js b/controllers/contactController.js index 7d3cd5655da..1b876345db8 100644 --- a/controllers/contactController.js +++ b/controllers/contactController.js @@ -1,65 +1,65 @@ -const contactService = require("../services/contactService"); +// const contactService = require("../services/contactService"); -async function getAllContacts(req, res, next) { - try { - const contacts = await contactService.listContacts(); - res.json(contacts); - } catch (error) { - next(error); - } -} +// async function getAllContacts(req, res, next) { +// try { +// const contacts = await contactService.listContacts(); +// res.json(contacts); +// } catch (error) { +// next(error); +// } +// } -async function getContactById(req, res, next) { - try { - const contact = await contactService.getContactById(req.params.contactId); - if (contact) { - res.json(contact); - } else { - res.status(404).json({ message: "Not found" }); - } - } catch (error) { - next(error); - } -} +// async function getContactById(req, res, next) { +// try { +// const contact = await contactService.getContactById(req.params.contactId); +// if (contact) { +// res.json(contact); +// } else { +// res.status(404).json({ message: "Not found" }); +// } +// } catch (error) { +// next(error); +// } +// } -async function createContact(req, res, next) { - try { - const newContact = await contactService.addContact(req.body); - res.status(201).json(newContact); - } catch (error) { - next(error); - } -} +// async function createContact(req, res, next) { +// try { +// const newContact = await contactService.addContact(req.body); +// res.status(201).json(newContact); +// } catch (error) { +// next(error); +// } +// } -async function updateExistingContact(req, res, next) { - try { - const updatedContact = await contactService.updateContact( - req.params.contactId, - req.body, - ); - res.json(updatedContact); - } catch (error) { - next(error); - } -} +// async function updateExistingContact(req, res, next) { +// try { +// const updatedContact = await contactService.updateContact( +// req.params.contactId, +// req.body, +// ); +// res.json(updatedContact); +// } catch (error) { +// next(error); +// } +// } -async function deleteContact(req, res, next) { - try { - const wasDeleted = await contactService.removeContact(req.params.contactId); - if (wasDeleted) { - res.status(200).json({ message: "Contact removed!" }); - } else { - res.status(404).json({ message: "Not found" }); - } - } catch (error) { - next(error); - } -} +// async function deleteContact(req, res, next) { +// try { +// const wasDeleted = await contactService.removeContact(req.params.contactId); +// if (wasDeleted) { +// res.status(200).json({ message: "Contact removed!" }); +// } else { +// res.status(404).json({ message: "Not found" }); +// } +// } catch (error) { +// next(error); +// } +// } -module.exports = { - getAllContacts, - getContactById, - createContact, - updateExistingContact, - deleteContact, -}; +// module.exports = { +// getAllContacts, +// getContactById, +// createContact, +// updateExistingContact, +// deleteContact, +// }; diff --git a/models/contacts.js b/models/contacts.js deleted file mode 100644 index 4bee1032f59..00000000000 --- a/models/contacts.js +++ /dev/null @@ -1,99 +0,0 @@ -// const fs = require('fs/promises'); -// const path = require('path'); -// const { nanoid } = require('nanoid'); - -// const contactsPath = path.join(__dirname, 'contacts.json'); - -// const listContacts = async () => { -// try { -// const data = await fs.readFile(contactsPath, 'utf-8'); -// const contacts = JSON.parse(data); - -// return contacts; -// } catch (error) { -// console.error("Error reading contacts file: ", error); -// throw error; -// } -// } - -// const getContactById = async (contactId) => { -// try { -// const contacts = await listContacts(); -// const contact = contacts.find(item => item.id === contactId); -// return contact || null; -// } catch (error) { -// console.error("Error getting contact by ID: ", error); -// throw error; -// } -// } - -// const removeContact = async (contactId) => { -// try { -// const contacts = await listContacts(); -// const index = contacts.findIndex(contact => contact.id === contactId); - -// if (index === -1) { -// return false; -// } - -// contacts.splice(index, 1); - -// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); -// return true; - -// } catch (error) { -// console.error("Error removing contact:", error); -// throw error; -// } -// }; - -// const addContact = async ({name, email, phone }) => { - -// const newContact = { -// id: nanoid(21), -// name, -// email, -// phone -// }; - -// try { -// const contacts = await listContacts(); - -// contacts.push(newContact); - -// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); -// return newContact; -// } catch (error) { -// console.error("Error adding contact: ", error); -// throw error; -// } -// }; - -// const updateContact = async (contactId, body) => { -// try { -// const contacts = await listContacts(); -// const index = contacts.findIndex(contact => contact.id === contactId); - -// if (index === -1) { -// return null; -// } - -// const updatedContact = { ...contacts[index], ...body }; -// contacts[index] = updatedContact; - -// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - -// return updatedContact; -// } catch (error) { -// console.error("Error updategin cotnact: ", error); -// throw error; -// } -// } - -// module.exports = { -// listContacts, -// getContactById, -// removeContact, -// addContact, -// updateContact, -// } diff --git a/routes/api/contacts.js b/routes/api/contacts.js index f89c368be09..006a4372bca 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -3,22 +3,26 @@ const { getAllContacts, getContactById, createContact, updateExistingContact, de const { createContactSchema } = require('../../validation/contactValidation'); const router = express.Router(); -router.get('/', getAllContacts); +router.get('/', (req, res) => { + res.json({ + message: "hello, db worked!" + }); +}); -router.get('/:contactId', getContactById); +// router.get('/:contactId', getContactById); -router.post('/', async (req, res, next) => { - const { error } = createContactSchema.validate(req.body); - if (error) return res.status(400).json({ message: error.details[0].message }); - next(); -}, createContact); +// router.post('/', async (req, res, next) => { +// const { error } = createContactSchema.validate(req.body); +// if (error) return res.status(400).json({ message: error.details[0].message }); +// next(); +// }, createContact); -router.put('/:contactId', async (req, res, next) => { - const { error } = createContactSchema.validate(req.body); - if (error) return res.status(400).json({ message: error.details[0].message }); - next(); -}, updateExistingContact); +// router.put('/:contactId', async (req, res, next) => { +// const { error } = createContactSchema.validate(req.body); +// if (error) return res.status(400).json({ message: error.details[0].message }); +// next(); +// }, updateExistingContact); -router.delete('/:contactId', deleteContact); +// router.delete('/:contactId', deleteContact); module.exports = router; diff --git a/server.js b/server.js index 1b1663a89e4..ef21e105b55 100644 --- a/server.js +++ b/server.js @@ -15,4 +15,4 @@ mongoose.connect(process.env.DB_URL).then((db) => { }).catch((err) => { console.log(err.red); process.exit(1); -});; \ No newline at end of file +}); \ No newline at end of file diff --git a/services/contactService.js b/services/contactService.js index 1d5ea5c4b1e..9bfcb87e3e4 100644 --- a/services/contactService.js +++ b/services/contactService.js @@ -1,55 +1,55 @@ -const fs = require("fs/promises"); -const path = require("path"); -const { nanoid } = require("nanoid"); +// const fs = require("fs/promises"); +// const path = require("path"); +// const { nanoid } = require("nanoid"); -const contactsPath = path.join(__dirname, "contacts.json"); +// const contactsPath = path.join(__dirname, "contacts.json"); -const listContacts = async () => { - const data = await fs.readFile(contactsPath, "utf-8"); - return JSON.parse(data); -}; +// const listContacts = async () => { +// const data = await fs.readFile(contactsPath, "utf-8"); +// return JSON.parse(data); +// }; -const getContactById = async (contactId) => { - const contacts = await listContacts(); - return contacts.find((contact) => contact.id === contactId) || null; -}; +// const getContactById = async (contactId) => { +// const contacts = await listContacts(); +// return contacts.find((contact) => contact.id === contactId) || null; +// }; -const removeContact = async (contactId) => { - const contacts = await listContacts(); - const index = contacts.findIndex((contact) => contact.id === contactId); - if (index === -1) return false; - contacts.splice(index, 1); - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - return true; -}; +// const removeContact = async (contactId) => { +// const contacts = await listContacts(); +// const index = contacts.findIndex((contact) => contact.id === contactId); +// if (index === -1) return false; +// contacts.splice(index, 1); +// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); +// return true; +// }; -const addContact = async ({ name, email, phone }) => { - const contacts = await listContacts(); - const newContact = { - id: nanoid(21), - name, - email, - phone, - }; - contacts.push(newContact); - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - return newContact; -}; +// const addContact = async ({ name, email, phone }) => { +// const contacts = await listContacts(); +// const newContact = { +// id: nanoid(21), +// name, +// email, +// phone, +// }; +// contacts.push(newContact); +// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); +// return newContact; +// }; -const updateContact = async (contactId, body) => { - const contacts = await listContacts(); - const index = contacts.findIndex((contact) => contact.id === contactId); - if (index === -1) throw new Error("Not found"); - const updatedContact = { ...contacts[index], ...body }; - contacts[index] = updatedContact; - await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); - return updatedContact; -}; +// const updateContact = async (contactId, body) => { +// const contacts = await listContacts(); +// const index = contacts.findIndex((contact) => contact.id === contactId); +// if (index === -1) throw new Error("Not found"); +// const updatedContact = { ...contacts[index], ...body }; +// contacts[index] = updatedContact; +// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); +// return updatedContact; +// }; -module.exports = { - listContacts, - getContactById, - removeContact, - addContact, - updateContact, -}; +// module.exports = { +// listContacts, +// getContactById, +// removeContact, +// addContact, +// updateContact, +// }; diff --git a/services/contacts.json b/services/contacts.json deleted file mode 100644 index 38e268e69e6..00000000000 --- a/services/contacts.json +++ /dev/null @@ -1,74 +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" - }, - { - "id": "Vi8gav5WMhFpt-d-hSYbR", - "name": "Mikolaj Zydorek", - "email": "dfndnfj@wp.pl", - "phone": "259483589" - }, - { - "id": "0MT494HUEYV365hXRwzq8", - "name": "Magdalena Zydorek", - "email": "sbkjsfbkjsf@gmail.com", - "phone": "335356456" - } -] \ No newline at end of file diff --git a/services/schemas/contactSchema.js b/services/schemas/contactSchema.js new file mode 100644 index 00000000000..94279ca5eab --- /dev/null +++ b/services/schemas/contactSchema.js @@ -0,0 +1,29 @@ +const moongose = require("mongoose"); +const Schema = mongoose.Schema; + +const ContactSchema = new Schema( +{ + name: { + type: String, + required: [true, "Name is required!"], + minLength: 3, + maxLength: 100, + }, + email: { + type: String, + required: [true, "Email is required!"], + }, + phone: { + type: String, + required: [true, "Phone number is required!"], + minLength: 7, + maxLength: 15, + }, + favourite: { + type: Boolean, + default: false, + }, +}); + +const Contact = mongoose.model("Contact", ContactSchema, "contacts"); +module.exports = Contact; \ No newline at end of file From fda5350f8120889045d8cd056e8cbc6dd145578c Mon Sep 17 00:00:00 2001 From: zetdou Date: Tue, 27 Aug 2024 21:20:36 +0200 Subject: [PATCH 12/21] contactController.js Add controller functions without removing and update favourite status plus making some changes in services --- app.js | 20 ++++++--- controllers/contactController.js | 53 ++++++++++++++++++++++ routes/api/contacts.js | 2 - services/contactService.js | 77 ++++++++++++-------------------- validation/contactValidation.js | 16 ------- 5 files changed, 97 insertions(+), 71 deletions(-) delete mode 100644 validation/contactValidation.js diff --git a/app.js b/app.js index 7d38bdaa23c..e531347e3aa 100644 --- a/app.js +++ b/app.js @@ -14,11 +14,21 @@ app.use(express.json()); app.use("/api/contacts", contactsRouter); -app.use((error, req, res, next) => { - console.error(error); - const status = error.status || 500; - const message = error.message || "Internal server error"; - res.status(status).json({ message }); +app.use((req, res) => { + res.status(404).json({ + message: `Not found - ${req.path}` + }); +}) + +app.use((err, req, res, next) => { + if(err.name === "ValidationError") { + return res.status(400).json({ + message: err.message, + }); + } + res.status(500).json({ + message: err.message + }); }); module.exports = app; diff --git a/controllers/contactController.js b/controllers/contactController.js index 1b876345db8..7eb9624cf76 100644 --- a/controllers/contactController.js +++ b/controllers/contactController.js @@ -1,3 +1,56 @@ +const fetchAll = async (req, res, next) => { + try { + const contacts = await getAllContacts() + res.json(contacts); + } catch (err) { + next(error) + } +} + +const fetchById = async (req, res, next) => { + try { + const contacts = await getAllContacts(req.params.id) + if(contacts) { + res.json(contacts); + } else { + next() + } + } catch (err) { + next(err) + } +} + +const insertContact = async (req, res, next) => { + const {name, email, phone} = req.body; + try { + const newContact = await createContact({ + name, + email, + phone + }) + res.status(201).json(newContact); + } catch (err) { + next(err); + } +} + +const updateContactDetails = async (req, res, next) => { + const {id} = req.params; + try { + const updatedContact = await updateExistingContact({ + id, + toUpdate: req.body, + }) + if(!updatedContact) { + next() + } else { + res.json(updateContact) + } catch (err) { + next(err) + } + } +} + // const contactService = require("../services/contactService"); // async function getAllContacts(req, res, next) { diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 006a4372bca..2e7dba7af6c 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,6 +1,4 @@ const express = require('express'); -const { getAllContacts, getContactById, createContact, updateExistingContact, deleteContact } = require('../../controllers/contactController'); -const { createContactSchema } = require('../../validation/contactValidation'); const router = express.Router(); router.get('/', (req, res) => { diff --git a/services/contactService.js b/services/contactService.js index 9bfcb87e3e4..15d3834282e 100644 --- a/services/contactService.js +++ b/services/contactService.js @@ -1,55 +1,36 @@ -// const fs = require("fs/promises"); -// const path = require("path"); -// const { nanoid } = require("nanoid"); +const Contact = require("./schemas/contactSchema"); -// const contactsPath = path.join(__dirname, "contacts.json"); +const getAllContacts = async () => { + return Contact.find() +}; -// const listContacts = async () => { -// const data = await fs.readFile(contactsPath, "utf-8"); -// return JSON.parse(data); -// }; +const getContactById = (id) => { + return Contact.findById({_id: id}) +}; -// const getContactById = async (contactId) => { -// const contacts = await listContacts(); -// return contacts.find((contact) => contact.id === contactId) || null; -// }; +const createContact = ({name, email, phone}) => { + return Contact.create({name, email, phone}) +} -// const removeContact = async (contactId) => { -// const contacts = await listContacts(); -// const index = contacts.findIndex((contact) => contact.id === contactId); -// if (index === -1) return false; -// contacts.splice(index, 1); -// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); -// return true; -// }; +const updateExistingContact = async ({id, toUpdate}) => { + const contact = await Contact.findById({_id: id}) + if(!contact) return null; -// const addContact = async ({ name, email, phone }) => { -// const contacts = await listContacts(); -// const newContact = { -// id: nanoid(21), -// name, -// email, -// phone, -// }; -// contacts.push(newContact); -// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); -// return newContact; -// }; + Object.keys(toUpdate).forEach((value) => { + contact[value] = toUpdate[value] + }) + await Contact.save() + return Contact; +} -// const updateContact = async (contactId, body) => { -// const contacts = await listContacts(); -// const index = contacts.findIndex((contact) => contact.id === contactId); -// if (index === -1) throw new Error("Not found"); -// const updatedContact = { ...contacts[index], ...body }; -// contacts[index] = updatedContact; -// await fs.writeFile(contactsPath, JSON.stringify(contacts, null, 2)); -// return updatedContact; -// }; +const deleteContact = (id) => { + return Contact.findByIdAndRemove({_id: id}); +} -// module.exports = { -// listContacts, -// getContactById, -// removeContact, -// addContact, -// updateContact, -// }; +module.exports = { + getAllContacts, + getContactById, + createContact, + updateExistingContact, + deleteContact, +}; \ No newline at end of file diff --git a/validation/contactValidation.js b/validation/contactValidation.js deleted file mode 100644 index 09fc7fdaab6..00000000000 --- a/validation/contactValidation.js +++ /dev/null @@ -1,16 +0,0 @@ -const Joi = require("joi"); - -const createContactSchema = Joi.object({ - name: Joi.string().required(), - email: Joi.string() - .email() - .required(), - phone: Joi.string() - .min(7) - .max(15) - .required() -}); - -module.exports = { - createContactSchema -}; \ No newline at end of file From 0ae5161189c7048d56942cd5586c4594832f750b Mon Sep 17 00:00:00 2001 From: zetdou Date: Thu, 29 Aug 2024 20:42:11 +0200 Subject: [PATCH 13/21] Update contactController.js Fix searching contacts by id and add delete function. Problem with adding contact to db --- controllers/contactController.js | 40 +++++++++++++++++++++---------- routes/api/contacts.js | 27 +++++---------------- services/contactService.js | 2 +- services/schemas/contactSchema.js | 4 ++-- 4 files changed, 37 insertions(+), 36 deletions(-) diff --git a/controllers/contactController.js b/controllers/contactController.js index 7eb9624cf76..5245d5ab11f 100644 --- a/controllers/contactController.js +++ b/controllers/contactController.js @@ -1,3 +1,5 @@ +const {getAllContacts, createContact, updateExistingContact, deleteContact, getContactById} = require("../services/contactService"); + const fetchAll = async (req, res, next) => { try { const contacts = await getAllContacts() @@ -9,7 +11,7 @@ const fetchAll = async (req, res, next) => { const fetchById = async (req, res, next) => { try { - const contacts = await getAllContacts(req.params.id) + const contacts = await getContactById(req.params.id); if(contacts) { res.json(contacts); } else { @@ -44,13 +46,33 @@ const updateContactDetails = async (req, res, next) => { if(!updatedContact) { next() } else { - res.json(updateContact) - } catch (err) { - next(err) - } + res.json(updatedContact) + } + } catch (err) { + next(err) } } +const removeContact = async (req, res, next) => { + const {id} = req.params; + try { + await deleteContact(id); + res.status(204).send({ + message: "Contact deleted!" + }); + } catch (err) { + next(err) + } +} + +module.exports = { + fetchAll, + fetchById, + insertContact, + updateContactDetails, + removeContact +}; + // const contactService = require("../services/contactService"); // async function getAllContacts(req, res, next) { @@ -109,10 +131,4 @@ const updateContactDetails = async (req, res, next) => { // } // } -// module.exports = { -// getAllContacts, -// getContactById, -// createContact, -// updateExistingContact, -// deleteContact, -// }; + diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 2e7dba7af6c..c16717a7fce 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,26 +1,11 @@ const express = require('express'); const router = express.Router(); +const { fetchAll, fetchById, insertContact, updateContactDetails, removeContact } = require("../../controllers/contactController"); -router.get('/', (req, res) => { - res.json({ - message: "hello, db worked!" - }); -}); - -// router.get('/:contactId', getContactById); - -// router.post('/', async (req, res, next) => { -// const { error } = createContactSchema.validate(req.body); -// if (error) return res.status(400).json({ message: error.details[0].message }); -// next(); -// }, createContact); - -// router.put('/:contactId', async (req, res, next) => { -// const { error } = createContactSchema.validate(req.body); -// if (error) return res.status(400).json({ message: error.details[0].message }); -// next(); -// }, updateExistingContact); - -// router.delete('/:contactId', deleteContact); +router.get('/', fetchAll); +router.get('/:id', fetchById); +router.post('/', insertContact); +router.put('/:id', updateContactDetails); +router.delete('/:id', removeContact); module.exports = router; diff --git a/services/contactService.js b/services/contactService.js index 15d3834282e..e3cc7207405 100644 --- a/services/contactService.js +++ b/services/contactService.js @@ -24,7 +24,7 @@ const updateExistingContact = async ({id, toUpdate}) => { } const deleteContact = (id) => { - return Contact.findByIdAndRemove({_id: id}); + return Contact.deleteOne({_id: id}); } module.exports = { diff --git a/services/schemas/contactSchema.js b/services/schemas/contactSchema.js index 94279ca5eab..b2697f79dbd 100644 --- a/services/schemas/contactSchema.js +++ b/services/schemas/contactSchema.js @@ -1,4 +1,4 @@ -const moongose = require("mongoose"); +const mongoose = require("mongoose"); const Schema = mongoose.Schema; const ContactSchema = new Schema( @@ -19,7 +19,7 @@ const ContactSchema = new Schema( minLength: 7, maxLength: 15, }, - favourite: { + favorite: { type: Boolean, default: false, }, From 06c5b973fe6544ead022b386cce731e6912c0ccd Mon Sep 17 00:00:00 2001 From: zetdou Date: Fri, 30 Aug 2024 18:48:26 +0200 Subject: [PATCH 14/21] contactController.js Make changes in updateContactDetails function and write updateContactStatus. Add run validators to services and change code in updateExistingContact function. Remove version key i schema --- controllers/contactController.js | 82 +++++++------------------------ routes/api/contacts.js | 3 +- services/contactService.js | 11 +---- services/schemas/contactSchema.js | 6 ++- 4 files changed, 27 insertions(+), 75 deletions(-) diff --git a/controllers/contactController.js b/controllers/contactController.js index 5245d5ab11f..1681e3df75b 100644 --- a/controllers/contactController.js +++ b/controllers/contactController.js @@ -38,11 +38,9 @@ const insertContact = async (req, res, next) => { const updateContactDetails = async (req, res, next) => { const {id} = req.params; + const {name, email, phone} = req.body; try { - const updatedContact = await updateExistingContact({ - id, - toUpdate: req.body, - }) + const updatedContact = await updateExistingContact(id, {name, email, phone}); if(!updatedContact) { next() } else { @@ -53,6 +51,21 @@ const updateContactDetails = async (req, res, next) => { } } +const updateContactStatus = async (req, res, next) => { + const {id} = req.params; + const {favorite = false} = req.body; + try { + const updatedStatus = await updateExistingContact(id, {favorite}); + if(!updatedStatus) { + next() + } else { + res.json(updatedStatus) + } + } catch (err) { + next(err) + } +} + const removeContact = async (req, res, next) => { const {id} = req.params; try { @@ -70,65 +83,8 @@ module.exports = { fetchById, insertContact, updateContactDetails, - removeContact + removeContact, + updateContactStatus }; -// const contactService = require("../services/contactService"); - -// async function getAllContacts(req, res, next) { -// try { -// const contacts = await contactService.listContacts(); -// res.json(contacts); -// } catch (error) { -// next(error); -// } -// } - -// async function getContactById(req, res, next) { -// try { -// const contact = await contactService.getContactById(req.params.contactId); -// if (contact) { -// res.json(contact); -// } else { -// res.status(404).json({ message: "Not found" }); -// } -// } catch (error) { -// next(error); -// } -// } - -// async function createContact(req, res, next) { -// try { -// const newContact = await contactService.addContact(req.body); -// res.status(201).json(newContact); -// } catch (error) { -// next(error); -// } -// } - -// async function updateExistingContact(req, res, next) { -// try { -// const updatedContact = await contactService.updateContact( -// req.params.contactId, -// req.body, -// ); -// res.json(updatedContact); -// } catch (error) { -// next(error); -// } -// } - -// async function deleteContact(req, res, next) { -// try { -// const wasDeleted = await contactService.removeContact(req.params.contactId); -// if (wasDeleted) { -// res.status(200).json({ message: "Contact removed!" }); -// } else { -// res.status(404).json({ message: "Not found" }); -// } -// } catch (error) { -// next(error); -// } -// } - diff --git a/routes/api/contacts.js b/routes/api/contacts.js index c16717a7fce..82ed131ac82 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,11 +1,12 @@ const express = require('express'); const router = express.Router(); -const { fetchAll, fetchById, insertContact, updateContactDetails, removeContact } = require("../../controllers/contactController"); +const { fetchAll, fetchById, insertContact, updateContactDetails, removeContact, updateContactStatus } = require("../../controllers/contactController"); router.get('/', fetchAll); router.get('/:id', fetchById); router.post('/', insertContact); router.put('/:id', updateContactDetails); router.delete('/:id', removeContact); +router.patch('/:id/favorite', updateContactStatus); module.exports = router; diff --git a/services/contactService.js b/services/contactService.js index e3cc7207405..247b71e6205 100644 --- a/services/contactService.js +++ b/services/contactService.js @@ -12,15 +12,8 @@ const createContact = ({name, email, phone}) => { return Contact.create({name, email, phone}) } -const updateExistingContact = async ({id, toUpdate}) => { - const contact = await Contact.findById({_id: id}) - if(!contact) return null; - - Object.keys(toUpdate).forEach((value) => { - contact[value] = toUpdate[value] - }) - await Contact.save() - return Contact; +const updateExistingContact = async (id, fields) => { + return Contact.findByIdAndUpdate({_id: id}, fields, {new: true, runValidators: true}); } const deleteContact = (id) => { diff --git a/services/schemas/contactSchema.js b/services/schemas/contactSchema.js index b2697f79dbd..72847d419cd 100644 --- a/services/schemas/contactSchema.js +++ b/services/schemas/contactSchema.js @@ -22,8 +22,10 @@ const ContactSchema = new Schema( favorite: { type: Boolean, default: false, - }, -}); + } +}, +{versionKey: false} +); const Contact = mongoose.model("Contact", ContactSchema, "contacts"); module.exports = Contact; \ No newline at end of file From d73573d414b6c454c43b2966faa07abfc9f87671 Mon Sep 17 00:00:00 2001 From: zetdou Date: Sat, 31 Aug 2024 12:57:49 +0200 Subject: [PATCH 15/21] userSchema.js Create the user schema without bcrypt --- app.js | 8 +- controllers/contactController.js | 152 ++++++++++++++++-------------- routes/api/contacts.js | 23 +++-- server.js | 19 ++-- services/contactService.js | 33 ++++--- services/schemas/contactSchema.js | 34 +++---- services/schemas/userSchema.js | 27 ++++++ 7 files changed, 172 insertions(+), 124 deletions(-) create mode 100644 services/schemas/userSchema.js diff --git a/app.js b/app.js index e531347e3aa..1f127c66f58 100644 --- a/app.js +++ b/app.js @@ -16,18 +16,18 @@ app.use("/api/contacts", contactsRouter); app.use((req, res) => { res.status(404).json({ - message: `Not found - ${req.path}` + message: `Not found - ${req.path}`, }); -}) +}); app.use((err, req, res, next) => { - if(err.name === "ValidationError") { + if (err.name === "ValidationError") { return res.status(400).json({ message: err.message, }); } res.status(500).json({ - message: err.message + message: err.message, }); }); diff --git a/controllers/contactController.js b/controllers/contactController.js index 1681e3df75b..57739c5f997 100644 --- a/controllers/contactController.js +++ b/controllers/contactController.js @@ -1,90 +1,98 @@ -const {getAllContacts, createContact, updateExistingContact, deleteContact, getContactById} = require("../services/contactService"); +const { + getAllContacts, + createContact, + updateExistingContact, + deleteContact, + getContactById, +} = require("../services/contactService"); const fetchAll = async (req, res, next) => { - try { - const contacts = await getAllContacts() - res.json(contacts); - } catch (err) { - next(error) - } -} + try { + const contacts = await getAllContacts(); + res.json(contacts); + } catch (err) { + next(error); + } +}; const fetchById = async (req, res, next) => { - try { - const contacts = await getContactById(req.params.id); - if(contacts) { - res.json(contacts); - } else { - next() - } - } catch (err) { - next(err) + try { + const contacts = await getContactById(req.params.id); + if (contacts) { + res.json(contacts); + } else { + next(); } -} + } catch (err) { + next(err); + } +}; const insertContact = async (req, res, next) => { - const {name, email, phone} = req.body; - try { - const newContact = await createContact({ - name, - email, - phone - }) - res.status(201).json(newContact); - } catch (err) { - next(err); - } -} + const { name, email, phone } = req.body; + try { + const newContact = await createContact({ + name, + email, + phone, + }); + res.status(201).json(newContact); + } catch (err) { + next(err); + } +}; const updateContactDetails = async (req, res, next) => { - const {id} = req.params; - const {name, email, phone} = req.body; - try { - const updatedContact = await updateExistingContact(id, {name, email, phone}); - if(!updatedContact) { - next() - } else { - res.json(updatedContact) - } - } catch (err) { - next(err) + const { id } = req.params; + const { name, email, phone } = req.body; + try { + const updatedContact = await updateExistingContact(id, { + name, + email, + phone, + }); + if (!updatedContact) { + next(); + } else { + res.json(updatedContact); } -} + } catch (err) { + next(err); + } +}; const updateContactStatus = async (req, res, next) => { - const {id} = req.params; - const {favorite = false} = req.body; - try { - const updatedStatus = await updateExistingContact(id, {favorite}); - if(!updatedStatus) { - next() - } else { - res.json(updatedStatus) - } - } catch (err) { - next(err) + const { id } = req.params; + const { favorite = false } = req.body; + try { + const updatedStatus = await updateExistingContact(id, { favorite }); + if (!updatedStatus) { + next(); + } else { + res.json(updatedStatus); } -} + } catch (err) { + next(err); + } +}; const removeContact = async (req, res, next) => { - const {id} = req.params; - try { - await deleteContact(id); - res.status(204).send({ - message: "Contact deleted!" - }); - } catch (err) { - next(err) - } -} + const { id } = req.params; + try { + await deleteContact(id); + res.status(204).send({ + message: "Contact deleted!", + }); + } catch (err) { + next(err); + } +}; module.exports = { - fetchAll, - fetchById, - insertContact, - updateContactDetails, - removeContact, - updateContactStatus + fetchAll, + fetchById, + insertContact, + updateContactDetails, + removeContact, + updateContactStatus, }; - - diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 82ed131ac82..6a0512773a9 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,12 +1,19 @@ -const express = require('express'); +const express = require("express"); const router = express.Router(); -const { fetchAll, fetchById, insertContact, updateContactDetails, removeContact, updateContactStatus } = require("../../controllers/contactController"); +const { + fetchAll, + fetchById, + insertContact, + updateContactDetails, + removeContact, + updateContactStatus, +} = require("../../controllers/contactController"); -router.get('/', fetchAll); -router.get('/:id', fetchById); -router.post('/', insertContact); -router.put('/:id', updateContactDetails); -router.delete('/:id', removeContact); -router.patch('/:id/favorite', updateContactStatus); +router.get("/", fetchAll); +router.get("/:id", fetchById); +router.post("/", insertContact); +router.put("/:id", updateContactDetails); +router.delete("/:id", removeContact); +router.patch("/:id/favorite", updateContactStatus); module.exports = router; diff --git a/server.js b/server.js index ef21e105b55..0842372652b 100644 --- a/server.js +++ b/server.js @@ -7,12 +7,15 @@ const app = require("./app"); const port = process.env.PORT; -mongoose.connect(process.env.DB_URL).then((db) => { - console.log("Database is connected.".cyan); - app.listen(port, () => { - console.info(`Server is running on port ${port}.`.green); +mongoose + .connect(process.env.DB_URL) + .then((db) => { + console.log("Database is connected.".cyan); + app.listen(port, () => { + console.info(`Server is running on port ${port}.`.green); + }); }) -}).catch((err) => { - console.log(err.red); - process.exit(1); -}); \ No newline at end of file + .catch((err) => { + console.log(err.red); + process.exit(1); + }); diff --git a/services/contactService.js b/services/contactService.js index 247b71e6205..8c471528371 100644 --- a/services/contactService.js +++ b/services/contactService.js @@ -1,29 +1,32 @@ const Contact = require("./schemas/contactSchema"); const getAllContacts = async () => { - return Contact.find() + return Contact.find(); }; const getContactById = (id) => { - return Contact.findById({_id: id}) + return Contact.findById({ _id: id }); }; -const createContact = ({name, email, phone}) => { - return Contact.create({name, email, phone}) -} +const createContact = ({ name, email, phone }) => { + return Contact.create({ name, email, phone }); +}; const updateExistingContact = async (id, fields) => { - return Contact.findByIdAndUpdate({_id: id}, fields, {new: true, runValidators: true}); -} + return Contact.findByIdAndUpdate({ _id: id }, fields, { + new: true, + runValidators: true, + }); +}; const deleteContact = (id) => { - return Contact.deleteOne({_id: id}); -} + return Contact.deleteOne({ _id: id }); +}; module.exports = { - getAllContacts, - getContactById, - createContact, - updateExistingContact, - deleteContact, -}; \ No newline at end of file + getAllContacts, + getContactById, + createContact, + updateExistingContact, + deleteContact, +}; diff --git a/services/schemas/contactSchema.js b/services/schemas/contactSchema.js index 72847d419cd..e3a4e5882c9 100644 --- a/services/schemas/contactSchema.js +++ b/services/schemas/contactSchema.js @@ -2,30 +2,30 @@ const mongoose = require("mongoose"); const Schema = mongoose.Schema; const ContactSchema = new Schema( -{ + { name: { - type: String, - required: [true, "Name is required!"], - minLength: 3, - maxLength: 100, + type: String, + required: [true, "Name is required!"], + minLength: 3, + maxLength: 100, }, email: { - type: String, - required: [true, "Email is required!"], + type: String, + required: [true, "Email is required!"], }, phone: { - type: String, - required: [true, "Phone number is required!"], - minLength: 7, - maxLength: 15, + type: String, + required: [true, "Phone number is required!"], + minLength: 7, + maxLength: 15, }, favorite: { - type: Boolean, - default: false, - } -}, -{versionKey: false} + type: Boolean, + default: false, + }, + }, + { versionKey: false }, ); const Contact = mongoose.model("Contact", ContactSchema, "contacts"); -module.exports = Contact; \ No newline at end of file +module.exports = Contact; diff --git a/services/schemas/userSchema.js b/services/schemas/userSchema.js new file mode 100644 index 00000000000..e88f5af154c --- /dev/null +++ b/services/schemas/userSchema.js @@ -0,0 +1,27 @@ +const mongoose = require("mongoose"); +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, + }, +}, {versionKey: false}, +); + +const User = mongoose.model("User", UserSchema, "users"); +module.exports = User; From 8b9097a4f58f632b2f595d660484bd634b0c20d5 Mon Sep 17 00:00:00 2001 From: zetdou Date: Mon, 2 Sep 2024 21:39:27 +0200 Subject: [PATCH 16/21] auth.js Add authRouter to app. Create signup and login method working good. Add function setPassword and validatePassword to userSchema --- app.js | 3 + package-lock.json | 968 +++++++++++++++++++++++++++++---- package.json | 6 +- routes/api/auth.js | 52 ++ routes/api/contacts.js | 1 + services/schemas/userSchema.js | 13 + 6 files changed, 944 insertions(+), 99 deletions(-) create mode 100644 routes/api/auth.js diff --git a/app.js b/app.js index 1f127c66f58..480aee2c98e 100644 --- a/app.js +++ b/app.js @@ -3,6 +3,7 @@ const logger = require("morgan"); const cors = require("cors"); const contactsRouter = require("./routes/api/contacts"); +const authRouter = require("./routes/api/auth"); const app = express(); @@ -13,6 +14,7 @@ app.use(cors()); app.use(express.json()); app.use("/api/contacts", contactsRouter); +app.use("/api/users", authRouter); app.use((req, res) => { res.status(404).json({ @@ -31,4 +33,5 @@ app.use((err, req, res, next) => { }); }); + module.exports = app; diff --git a/package-lock.json b/package-lock.json index 9bf3a298e44..479ca3ce1a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,15 +8,19 @@ "name": "template", "version": "0.0.0", "dependencies": { + "bcrypt": "^5.1.1", "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", "dotenv": "^16.4.5", "express": "4.17.1", "joi": "^17.13.3", + "jsonwebtoken": "^9.0.2", "mongoose": "^8.5.4", "morgan": "1.10.0", - "nanoid": "3.3.5" + "nanoid": "3.3.5", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1" }, "devDependencies": { "eslint": "7.19.0", @@ -159,6 +163,39 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz", @@ -228,8 +265,7 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/accepts": { "version": "1.3.7", @@ -264,6 +300,17 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -302,7 +349,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" } @@ -335,6 +381,24 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -397,8 +461,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/basic-auth": { "version": "2.0.1", @@ -411,6 +474,19 @@ "node": ">= 0.8" } }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -491,7 +567,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -517,6 +592,11 @@ "node": ">=16.20.1" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -638,6 +718,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -683,6 +771,14 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -694,8 +790,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/configstore": { "version": "5.0.1", @@ -714,6 +809,11 @@ "node": ">=8" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -858,6 +958,11 @@ "node": ">= 0.4" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -871,6 +976,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -912,6 +1025,14 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -920,8 +1041,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -1605,11 +1725,32 @@ "node": ">= 0.6" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", @@ -1637,6 +1778,26 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -1683,7 +1844,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1826,6 +1986,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -1856,6 +2021,18 @@ "node": ">= 0.6" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1920,7 +2097,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2066,7 +2242,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" } @@ -2310,6 +2485,46 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kareem": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", @@ -2371,6 +2586,41 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -2386,23 +2636,10 @@ "node": ">=0.10.0" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -2417,7 +2654,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -2491,7 +2727,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2505,6 +2740,48 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mongodb": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz", @@ -2676,6 +2953,49 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", @@ -2777,6 +3097,18 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2861,7 +3193,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -2969,6 +3300,40 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2982,7 +3347,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3006,6 +3370,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", @@ -3165,6 +3534,19 @@ "node": ">=0.10.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3257,7 +3639,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -3279,13 +3660,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -3369,6 +3746,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -3415,8 +3797,7 @@ "node_modules/signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, "node_modules/slice-ansi": { "version": "4.0.0", @@ -3457,11 +3838,37 @@ "node": ">= 0.6" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3501,7 +3908,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" }, @@ -3580,6 +3986,22 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3782,6 +4204,11 @@ "node": ">=4" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -3854,6 +4281,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -3895,8 +4330,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -3922,8 +4356,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } }, "dependencies": { @@ -4036,6 +4469,32 @@ "@hapi/hoek": "^9.0.0" } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + } + } + }, "@mongodb-js/saslprep": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz", @@ -4099,8 +4558,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { "version": "1.3.7", @@ -4124,6 +4582,14 @@ "dev": true, "requires": {} }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4154,8 +4620,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -4176,6 +4641,20 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -4223,8 +4702,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "basic-auth": { "version": "2.0.1", @@ -4234,6 +4712,15 @@ "safe-buffer": "5.1.2" } }, + "bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + } + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -4300,7 +4787,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4320,6 +4806,11 @@ "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==" }, + "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", @@ -4405,6 +4896,11 @@ "readdirp": "~3.6.0" } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -4441,6 +4937,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -4449,8 +4950,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "configstore": { "version": "5.0.1", @@ -4466,6 +4966,11 @@ "xdg-basedir": "^4.0.0" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -4566,6 +5071,11 @@ "object-keys": "^1.0.12" } }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -4576,6 +5086,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==" + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4605,6 +5120,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", @@ -4613,8 +5136,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -5150,11 +5672,28 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -5175,6 +5714,22 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -5209,7 +5764,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5307,6 +5861,11 @@ "has-symbols": "^1.0.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -5331,6 +5890,15 @@ "toidentifier": "1.0.0" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5377,7 +5945,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -5480,8 +6047,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", @@ -5656,6 +6222,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", @@ -5705,6 +6307,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", @@ -5717,20 +6354,10 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "requires": { "semver": "^6.0.0" }, @@ -5738,8 +6365,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -5791,7 +6417,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5802,6 +6427,35 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, "mongodb": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz", @@ -5908,6 +6562,40 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", @@ -5979,6 +6667,17 @@ "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6036,7 +6735,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -6119,6 +6817,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", @@ -6128,8 +6850,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", @@ -6147,6 +6868,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", @@ -6266,6 +6992,16 @@ } } }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6334,7 +7070,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -6350,13 +7085,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", @@ -6428,6 +7159,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", @@ -6465,8 +7201,7 @@ "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, "slice-ansi": { "version": "4.0.0", @@ -6498,11 +7233,25 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6533,7 +7282,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" } @@ -6592,6 +7340,19 @@ } } }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -6752,6 +7513,11 @@ "prepend-http": "^2.0.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -6803,6 +7569,14 @@ "is-symbol": "^1.0.3" } }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -6832,8 +7606,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "3.0.3", @@ -6856,8 +7629,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index baa3601eb8b..e563468b8a7 100644 --- a/package.json +++ b/package.json @@ -9,15 +9,19 @@ "lint:fix": "eslint --fix **/*.js" }, "dependencies": { + "bcrypt": "^5.1.1", "colors": "^1.4.0", "cors": "2.8.5", "cross-env": "7.0.3", "dotenv": "^16.4.5", "express": "4.17.1", "joi": "^17.13.3", + "jsonwebtoken": "^9.0.2", "mongoose": "^8.5.4", "morgan": "1.10.0", - "nanoid": "3.3.5" + "nanoid": "3.3.5", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1" }, "devDependencies": { "eslint": "7.19.0", diff --git a/routes/api/auth.js b/routes/api/auth.js new file mode 100644 index 00000000000..202845c74fa --- /dev/null +++ b/routes/api/auth.js @@ -0,0 +1,52 @@ +const express = require("express"); +const router = express.Router(); +const User = require("../../services/schemas/userSchema"); +const jwt = require("jsonwebtoken"); + +router.post("/signup", async (req, res, next) => { + const {username, email, password} = req.body; + const user = await User.findOne({email}); + if(user) { + return res.status(409).json({ + message: "This email is already taken!" + }) + } + try { + const newUser = new User({username, email}) + await newUser.setPassword(password); + await newUser.save(); + return res.status(201).json({message: "User created"}); + } catch (err) { + next(err) + } +}); + +router.post("/login", async (req, res) => { + const {email, password} = req.body; + const user = await User.findOne({email}) + + if(!user) { + return res.status(401).json({ + message: "User not exists!" + }); + } + const isPasswordCorrect = await user.validatePassword(password) + if(isPasswordCorrect) { + const payload = { + id: user._id, + username: user.username + } + const token = jwt.sign( + payload, + process.env.SECRET, + {expiresIn: "12h"} + ) + return res.json({token}) + } else { + return res.status(401).json({ + message: "Wrong password!" + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/api/contacts.js b/routes/api/contacts.js index 6a0512773a9..b990214bee5 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -16,4 +16,5 @@ router.put("/:id", updateContactDetails); router.delete("/:id", removeContact); router.patch("/:id/favorite", updateContactStatus); + module.exports = router; diff --git a/services/schemas/userSchema.js b/services/schemas/userSchema.js index e88f5af154c..0594615f4ee 100644 --- a/services/schemas/userSchema.js +++ b/services/schemas/userSchema.js @@ -1,7 +1,12 @@ +const bCrypt = require("bcrypt"); const mongoose = require("mongoose"); const Schema = mongoose.Schema; const UserSchema = new Schema({ + username: { + type: String, + required: [true, "Username is required"], + }, password: { type: String, required: [true, "Password is required"], @@ -23,5 +28,13 @@ const UserSchema = new Schema({ }, {versionKey: false}, ); +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, "users"); module.exports = User; From 4c5f5c56b8790a10fd1338d217e2935734c6de82 Mon Sep 17 00:00:00 2001 From: zetdou Date: Thu, 5 Sep 2024 19:31:50 +0200 Subject: [PATCH 17/21] authController, authService Split auth logic to service and controller, add authMiddleware --- app.js | 17 ++++------ config/jwt.js | 35 ++++++++++++++++++++ controllers/authController.js | 53 +++++++++++++++++++++++++++++++ controllers/contactController.js | 2 +- middleware/authMiddleware.js | 27 ++++++++++++++++ middleware/errorMiddleware.js | 18 +++++++++++ routes/api/auth.js | 53 ++++--------------------------- services/authService.js | 52 ++++++++++++++++++++++++++++++ services/schemas/contactSchema.js | 4 +++ 9 files changed, 203 insertions(+), 58 deletions(-) create mode 100644 config/jwt.js create mode 100644 controllers/authController.js create mode 100644 middleware/authMiddleware.js create mode 100644 middleware/errorMiddleware.js create mode 100644 services/authService.js diff --git a/app.js b/app.js index 480aee2c98e..42909e3a5af 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,9 @@ const express = require("express"); const logger = require("morgan"); const cors = require("cors"); +const {jwtStrategy} = require("./config/jwt"); +const {errorMiddleware} = require("./middleware/errorMiddleware"); + const contactsRouter = require("./routes/api/contacts"); const authRouter = require("./routes/api/auth"); @@ -13,6 +16,8 @@ app.use(logger(formatsLogger)); app.use(cors()); app.use(express.json()); +jwtStrategy(); + app.use("/api/contacts", contactsRouter); app.use("/api/users", authRouter); @@ -22,16 +27,8 @@ app.use((req, res) => { }); }); -app.use((err, req, res, next) => { - if (err.name === "ValidationError") { - return res.status(400).json({ - message: err.message, - }); - } - res.status(500).json({ - message: err.message, - }); -}); +app.use(errorMiddleware); + module.exports = app; diff --git a/config/jwt.js b/config/jwt.js new file mode 100644 index 00000000000..27de6734fc1 --- /dev/null +++ b/config/jwt.js @@ -0,0 +1,35 @@ +const passport = require("passport"); +const {ExtractJwt, Strategy} = require("passport-jwt"); +const User = require("../services/schemas/userSchema"); + +const jwtStrategy = () => { + const secret = process.env.SECRET; + + const params = { + secretOrKey: secret, + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken() + } + + passport.use( + new Strategy( + params, + async function(payload, done) { + try { + const user = await User.findOne({_id: payload.id}).lean(); + + if(!user) { + return done(new Error("User not found!")) + } + return done(null, user) + } catch(err) { + return done(err) + } + } + ) + ) +} + +module.exports = { + jwtStrategy, +} + diff --git a/controllers/authController.js b/controllers/authController.js new file mode 100644 index 00000000000..63d06a84db7 --- /dev/null +++ b/controllers/authController.js @@ -0,0 +1,53 @@ +const { registerUser, loginUser, logoutUser } = require("../services/authService"); + +const signup = async (req, res, next) => { + const { username, email, password } = req.body; + try { + const newUser = await registerUser({ username, email, password }); + return res.status(201).json({ + message: "User created", + user: { + email: newUser.email, + subscription: newUser.subscription, + }, + }); + } catch (err) { + next(err); + } +}; + +const login = async (req, res, next) => { + const { email, password } = req.body; + try { + const {token, user} = await loginUser({ email, password }); + return res.json({ token, user }); + } catch (err) { + next(err); + } +}; + +const logout = async (req, res, next) => { + try { + const userId = req.user._id; + await logoutUser(userId); + res.status(204).send(); + } catch (error) { + next(error); + } +}; + +const getCurrentUser = async (req, res, next) => { + try { + const { email, subscription } = req.user; + res.status(200).json({ email, subscription }); + } catch (error) { + next(error); + } +}; + +module.exports = { + signup, + login, + logout, + getCurrentUser, +}; \ No newline at end of file diff --git a/controllers/contactController.js b/controllers/contactController.js index 57739c5f997..f3afe202708 100644 --- a/controllers/contactController.js +++ b/controllers/contactController.js @@ -11,7 +11,7 @@ const fetchAll = async (req, res, next) => { const contacts = await getAllContacts(); res.json(contacts); } catch (err) { - next(error); + next(err); } }; diff --git a/middleware/authMiddleware.js b/middleware/authMiddleware.js new file mode 100644 index 00000000000..32c188dc316 --- /dev/null +++ b/middleware/authMiddleware.js @@ -0,0 +1,27 @@ +const passport = require("passport"); +const User = require("../services/schemas/userSchema"); + +const authMiddleware = (req, res, next) => { + passport.authenticate( + "jwt", + { + session: false, + }, + async (err, user) => { + if(!user || err) { + return res.status(401).json({message: "Unauthorized!"}); + } + + const foundUser = await User.findById(user._id); + if (!foundUser || foundUser.token !== req.headers.authorization.split(" ")[1]) { + return res.status(401).json({message: "Unauthorized!"}); + } + req.user = foundUser; + next(); + } + )(req, res, next) +}; + +module.exports = { + authMiddleware, +}; \ No newline at end of file diff --git a/middleware/errorMiddleware.js b/middleware/errorMiddleware.js new file mode 100644 index 00000000000..8fc595fb9f2 --- /dev/null +++ b/middleware/errorMiddleware.js @@ -0,0 +1,18 @@ +const errorMiddleware = (err, req, res, next) => { + if (err.message === "User not exists!" || err.message === "Wrong password!") { + return res.status(401).json({message: err.message}); + } + + if (err.name === "ValidationError") { + return res.status(400).json({ + message: err.message, + }); + } + res.status(500).json({ + message: err.message, + }); + }; + + module.exports = { + errorMiddleware, + } \ No newline at end of file diff --git a/routes/api/auth.js b/routes/api/auth.js index 202845c74fa..9458f60a373 100644 --- a/routes/api/auth.js +++ b/routes/api/auth.js @@ -1,52 +1,11 @@ const express = require("express"); const router = express.Router(); -const User = require("../../services/schemas/userSchema"); -const jwt = require("jsonwebtoken"); +const { signup, login, logout, getCurrentUser } = require("../../controllers/authController"); +const { authMiddleware } = require("../../middleware/authMiddleware"); -router.post("/signup", async (req, res, next) => { - const {username, email, password} = req.body; - const user = await User.findOne({email}); - if(user) { - return res.status(409).json({ - message: "This email is already taken!" - }) - } - try { - const newUser = new User({username, email}) - await newUser.setPassword(password); - await newUser.save(); - return res.status(201).json({message: "User created"}); - } catch (err) { - next(err) - } -}); - -router.post("/login", async (req, res) => { - const {email, password} = req.body; - const user = await User.findOne({email}) - - if(!user) { - return res.status(401).json({ - message: "User not exists!" - }); - } - const isPasswordCorrect = await user.validatePassword(password) - if(isPasswordCorrect) { - const payload = { - id: user._id, - username: user.username - } - const token = jwt.sign( - payload, - process.env.SECRET, - {expiresIn: "12h"} - ) - return res.json({token}) - } else { - return res.status(401).json({ - message: "Wrong password!" - }); - } -}); +router.post("/signup", signup); +router.post("/login", login); +router.get("/logout", authMiddleware, logout); +router.get("/current", authMiddleware, getCurrentUser); module.exports = router; \ No newline at end of file diff --git a/services/authService.js b/services/authService.js new file mode 100644 index 00000000000..d2a8b899bf5 --- /dev/null +++ b/services/authService.js @@ -0,0 +1,52 @@ +const User = require("./schemas/userSchema"); +const jwt = require("jsonwebtoken"); + +const registerUser = async ({ username, email, password }) => { + const userExists = await User.findOne({ email }); + if (userExists) { + throw new Error("This email is already taken!"); + } + + const newUser = new User({ username, email }); + await newUser.setPassword(password); + await newUser.save(); + return newUser; +}; + +const loginUser = async ({ email, password }) => { + const user = await User.findOne({ email }); + if (!user) { + throw new Error("User not exists!"); + } + + const isPasswordCorrect = await user.validatePassword(password); + if (!isPasswordCorrect) { + throw new Error("Wrong password!"); + } + + const payload = { + id: user._id, + username: user.username, + }; + + const token = jwt.sign(payload, process.env.SECRET, { expiresIn: "12h" }); + user.token = token; + await user.save(); + return {token, user: {email: user.email, subscriptin: user.subscription}}; +}; + +const logoutUser = async (userId) => { + const user = await User.findById(userId); + if (!user) { + throw new Error("Not authorized"); + } + + user.token = null; + await user.save(); +}; + +module.exports = { + registerUser, + loginUser, + logoutUser, +}; \ No newline at end of file diff --git a/services/schemas/contactSchema.js b/services/schemas/contactSchema.js index e3a4e5882c9..19a01b4d38a 100644 --- a/services/schemas/contactSchema.js +++ b/services/schemas/contactSchema.js @@ -23,6 +23,10 @@ const ContactSchema = new Schema( type: Boolean, default: false, }, + owner: { + type: Schema.Types.ObjectId, + ref: "user", + }, }, { versionKey: false }, ); From cc74fc259f227d7eebd803cc86b6044208eca2da Mon Sep 17 00:00:00 2001 From: zetdou Date: Fri, 13 Sep 2024 19:47:19 +0200 Subject: [PATCH 18/21] app.js Working version with error but avatar is updated --- .DS_Store | Bin 0 -> 6148 bytes app.js | 3 + controllers/authController.js | 5 +- controllers/uploadController.js | 58 + middleware/upload.js | 25 + package-lock.json | 2044 ++++++++++++++++- package.json | 6 +- public/.DS_Store | Bin 0 -> 6148 bytes .../2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg | Bin 0 -> 121840 bytes public/avatars/default-avatar-1.jpg | Bin 0 -> 8174 bytes routes/api/auth.js | 4 + routes/api/upload.js | 10 + services/authService.js | 4 +- services/schemas/userSchema.js | 4 + utils/folderUtils.js | 20 + 15 files changed, 2076 insertions(+), 107 deletions(-) create mode 100644 .DS_Store create mode 100644 controllers/uploadController.js create mode 100644 middleware/upload.js create mode 100644 public/.DS_Store create mode 100644 public/avatars/2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg create mode 100644 public/avatars/default-avatar-1.jpg create mode 100644 routes/api/upload.js create mode 100644 utils/folderUtils.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..87f68554d108fcb8261cb5d16516516882879fac GIT binary patch literal 6148 zcmeHK%}T>S5T0#on^1%t6a+5|UMu!T!Qv&v`T|Dupi&!KG?->fo0vl>C(?L0Q?b6@ux!ijJKOX5ZmZcn zZ17g6+gUXDyxVRz`2InAv9PVpoxP*e{zEj5#gpce;cus8-QW_QQ7NSL=uhKF#CK?y zF=a?#43iH(>mN_nB=jlGB^`vs05L!e6d5pwr&TYSX+;bW1H^#3C~@RLo)fOYT%$TV za8fM*qP#{bL0$F|GKL#;4dxng2ZiZSL>T literal 0 HcmV?d00001 diff --git a/app.js b/app.js index 42909e3a5af..f0cba8c6e01 100644 --- a/app.js +++ b/app.js @@ -3,6 +3,7 @@ const logger = require("morgan"); const cors = require("cors"); const {jwtStrategy} = require("./config/jwt"); const {errorMiddleware} = require("./middleware/errorMiddleware"); +const path = require("path"); const contactsRouter = require("./routes/api/contacts"); @@ -18,6 +19,8 @@ app.use(express.json()); jwtStrategy(); +app.use(express.static(path.join(__dirname, "public"))); + app.use("/api/contacts", contactsRouter); app.use("/api/users", authRouter); diff --git a/controllers/authController.js b/controllers/authController.js index 63d06a84db7..f9f11a8ed0a 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,14 +1,17 @@ +const gravatar = require("gravatar"); const { registerUser, loginUser, logoutUser } = require("../services/authService"); const signup = async (req, res, next) => { const { username, email, password } = req.body; try { - const newUser = await registerUser({ username, email, password }); + const avatarURL = gravatar.url(email, { s: "200", d: "retro" }, true); + const newUser = await registerUser({ username, email, password, avatarURL }); return res.status(201).json({ message: "User created", user: { email: newUser.email, subscription: newUser.subscription, + avatarURL: newUser.avatarURL, }, }); } catch (err) { diff --git a/controllers/uploadController.js b/controllers/uploadController.js new file mode 100644 index 00000000000..1fa50fdbd08 --- /dev/null +++ b/controllers/uploadController.js @@ -0,0 +1,58 @@ +const fs = require("fs/promises"); +const path = require("path"); +const Jimp = require("jimp"); +const { v4: uuidv4 } = require("uuid"); +const User = require("../services/schemas/userSchema"); +const { setupFolder } = require("../utils/folderUtils"); + +const avatarsDir = path.join(process.cwd(), "public/avatars"); +const MAX_AVATAR_WIDTH = 250; +const MAX_AVATAR_HEIGHT = 250; + +const updateAvatar = async (req, res, next) => { + try { + await setupFolder(avatarsDir); + + if (!req.file) { + return res.status(400).json({ message: "No file uploaded" }); + } + + const { path: tmpPath, originalname } = req.file; + const ext = path.extname(originalname).toLowerCase(); + const uniqueName = `${uuidv4()}${ext}`; + const avatarPath = path.join(avatarsDir, uniqueName); + + // Przeniesienie pliku z tmp do folderu avatars + await fs.rename(tmpPath, avatarPath); + console.log("File path:", avatarPath); // Sprawdź ścieżkę do pliku + // Przetwarzanie obrazu za pomocą Jimp (kadrowanie) + const image = await Jimp.read(avatarPath); + const w = image.bitmap.width; + const h = image.bitmap.height; + + // Przycięcie obrazu do maksymalnych wymiarów 250x250 + const cropWidth = w > MAX_AVATAR_WIDTH ? MAX_AVATAR_WIDTH : w; + const cropHeight = h > MAX_AVATAR_HEIGHT ? MAX_AVATAR_HEIGHT : h; + + const centerX = Math.round(w / 2 - cropWidth / 2); + const centerY = Math.round(h / 2 - cropHeight / 2); + + await image + .crop(centerX, centerY, cropWidth, cropHeight) + .resize(250, 250) // Zmiana rozmiaru na 250x250 + .writeAsync(avatarPath); // Zapis przetworzonego obrazu + + // Aktualizacja URL-a awatara w bazie danych użytkownika + const avatarURL = `/avatars/${uniqueName}`; + await User.findByIdAndUpdate(req.user._id, { avatarURL }); + + res.json({ avatarURL }); + } catch (err) { + console.error(err); + next(err); + } +}; + +module.exports = { + updateAvatar, +} \ No newline at end of file diff --git a/middleware/upload.js b/middleware/upload.js new file mode 100644 index 00000000000..41d51e3895e --- /dev/null +++ b/middleware/upload.js @@ -0,0 +1,25 @@ +const multer = require("multer"); +const path = require("path"); +const {v4: uuidv4} = require("uuid"); + +const tmpDir = path.join(__dirname, "../tmp"); + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, tmpDir); + }, + filename: (req, file, cb) => { + const ext = path.extname(file.originalname); + const uniqueName = `${uuidv4()}${ext}`; + cb(null, uniqueName); + } +}); + +const uploadAvatar = multer({ + storage, + limits: { + fileSize: 2 * 1024 * 1024, + }, +}).single("avatar"); + +module.exports = uploadAvatar; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 479ca3ce1a8..26ed65759a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,13 +14,17 @@ "cross-env": "7.0.3", "dotenv": "^16.4.5", "express": "4.17.1", + "gravatar": "^1.8.2", + "jimp": "^1.6.0", "joi": "^17.13.3", "jsonwebtoken": "^9.0.2", "mongoose": "^8.5.4", "morgan": "1.10.0", + "multer": "^1.4.5-lts.1", "nanoid": "3.3.5", "passport": "^0.7.0", - "passport-jwt": "^4.0.1" + "passport-jwt": "^4.0.1", + "uuid": "^10.0.0" }, "devDependencies": { "eslint": "7.19.0", @@ -163,6 +167,401 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@jimp/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", + "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", + "dependencies": { + "@jimp/file-ops": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "await-to-js": "^3.0.0", + "exif-parser": "^0.1.12", + "file-type": "^16.0.0", + "mime": "3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/core/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jimp/diff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", + "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", + "dependencies": { + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "pixelmatch": "^5.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/file-ops": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", + "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-bmp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", + "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "bmp-ts": "^1.0.9" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-gif": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", + "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "gifwrap": "^0.10.1", + "omggif": "^1.0.10" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-jpeg": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", + "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "jpeg-js": "^0.4.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-png": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", + "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "pngjs": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-tiff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", + "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "utif2": "^4.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", + "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", + "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/utils": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", + "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", + "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "tinycolor2": "^1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", + "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", + "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", + "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", + "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", + "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", + "dependencies": { + "@jimp/types": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", + "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", + "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-hash": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", + "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "any-base": "^1.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", + "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz", + "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/types": "1.6.0", + "parse-bmfont-ascii": "^1.0.6", + "parse-bmfont-binary": "^1.0.6", + "parse-bmfont-xml": "^1.1.6", + "simple-xml-to-json": "^1.2.2", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-quantize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", + "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", + "dependencies": { + "image-q": "^4.0.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", + "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", + "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-threshold": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", + "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/types": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", + "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", + "dependencies": { + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", + "dependencies": { + "@jimp/types": "1.6.0", + "tinycolor2": "^1.6.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", @@ -243,12 +642,22 @@ "node": ">=6" } }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -357,7 +766,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" }, @@ -368,6 +776,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -381,6 +794,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -458,6 +876,14 @@ "node": ">=8" } }, + "node_modules/await-to-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", + "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -496,6 +922,16 @@ "node": ">=8" } }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==" + }, + "node_modules/bmp-ts": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", + "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==" + }, "node_modules/body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -597,6 +1033,22 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -744,6 +1196,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -757,7 +1232,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" }, @@ -768,8 +1242,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/color-support": { "version": "1.1.3", @@ -792,6 +1265,42 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -846,6 +1355,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -913,6 +1427,14 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -1038,6 +1560,14 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "node_modules/email-validator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", + "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==", + "engines": { + "node": ">4.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1553,6 +2083,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", @@ -1636,6 +2171,22 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1798,6 +2349,14 @@ "node": ">=10" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -1840,6 +2399,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -1929,15 +2497,32 @@ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, + "node_modules/gravatar": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/gravatar/-/gravatar-1.8.2.tgz", + "integrity": "sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w==", "dependencies": { - "function-bind": "^1.1.1" + "blueimp-md5": "^2.16.0", + "email-validator": "^2.0.4", + "querystring": "0.2.0", + "yargs": "^15.4.1" }, - "engines": { + "bin": { + "gravatar": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { "node": ">= 0.4.0" } }, @@ -2044,6 +2629,25 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -2059,6 +2663,14 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "dependencies": { + "@types/node": "16.9.1" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2419,11 +3031,53 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "node_modules/jimp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz", + "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/diff": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-gif": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-blur": "1.6.0", + "@jimp/plugin-circle": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-contain": "1.6.0", + "@jimp/plugin-cover": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-displace": "1.6.0", + "@jimp/plugin-dither": "1.6.0", + "@jimp/plugin-fisheye": "1.6.0", + "@jimp/plugin-flip": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/plugin-mask": "1.6.0", + "@jimp/plugin-print": "1.6.0", + "@jimp/plugin-quantize": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/plugin-rotate": "1.6.0", + "@jimp/plugin-threshold": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/joi": { "version": "17.13.3", "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", @@ -2436,6 +3090,11 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2735,10 +3394,12 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minipass": { "version": "5.0.0", @@ -2922,6 +3583,34 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/nanoid": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.5.tgz", @@ -3170,6 +3859,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -3280,6 +3974,11 @@ "semver": "bin/semver.js" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3292,6 +3991,25 @@ "node": ">=6" } }, + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==" + }, + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==" + }, + "node_modules/parse-bmfont-xml": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", + "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", + "dependencies": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.5.0" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3375,6 +4093,18 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -3387,6 +4117,25 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pixelmatch": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", + "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==", + "dependencies": { + "pngjs": "^6.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pixelmatch/node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "engines": { + "node": ">=12.13.0" + } + }, "node_modules/pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -3399,6 +4148,14 @@ "node": ">=4" } }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "engines": { + "node": ">=14.19.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3417,6 +4174,11 @@ "node": ">=4" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -3482,6 +4244,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", @@ -3547,6 +4318,21 @@ "node": ">= 6" } }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3595,6 +4381,14 @@ "node": ">=8" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -3604,6 +4398,11 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -3659,6 +4458,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3799,6 +4603,14 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, + "node_modules/simple-xml-to-json": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.2.tgz", + "integrity": "sha512-bmJJf5YiYL60eOQk3gaVxbM6vgYuwrFydCEAA2x3jccHUTsAffiPyblS/yQGr8GDUQVxSDm3WwLNL5HmRqDUcg==", + "engines": { + "node": ">=14.20.0" + } + }, "node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -3838,6 +4650,14 @@ "node": ">= 0.6" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3936,6 +4756,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4008,6 +4844,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "node_modules/to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -4037,6 +4878,22 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -4105,6 +4962,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -4204,6 +5066,14 @@ "node": ">=4" } }, + "node_modules/utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "dependencies": { + "pako": "^1.0.11" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4217,6 +5087,18 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/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", @@ -4281,6 +5163,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -4353,10 +5240,161 @@ "node": ">=8" } }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } }, "dependencies": { @@ -4381,92 +5419,399 @@ "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.15.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/helper-validator-identifier": "^7.15.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@eslint/eslintrc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", + "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.20", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@jimp/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", + "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", + "requires": { + "@jimp/file-ops": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "await-to-js": "^3.0.0", + "exif-parser": "^0.1.12", + "file-type": "^16.0.0", + "mime": "3" + }, + "dependencies": { + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" + } + } + }, + "@jimp/diff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", + "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", + "requires": { + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "pixelmatch": "^5.3.0" + } + }, + "@jimp/file-ops": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", + "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==" + }, + "@jimp/js-bmp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", + "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "bmp-ts": "^1.0.9" + } + }, + "@jimp/js-gif": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", + "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "gifwrap": "^0.10.1", + "omggif": "^1.0.10" + } + }, + "@jimp/js-jpeg": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", + "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "jpeg-js": "^0.4.4" + } + }, + "@jimp/js-png": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", + "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "pngjs": "^7.0.0" + } + }, + "@jimp/js-tiff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", + "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "utif2": "^4.1.0" + } + }, + "@jimp/plugin-blit": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", + "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", + "requires": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-blur": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", + "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/utils": "1.6.0" + } + }, + "@jimp/plugin-circle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", + "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", + "requires": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-color": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", + "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "tinycolor2": "^1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-contain": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", + "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-cover": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", + "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-crop": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", + "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", + "requires": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@jimp/plugin-displace": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", + "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", + "requires": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + } + }, + "@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" } }, - "@eslint/eslintrc": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", - "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", - "dev": true, + "@jimp/plugin-threshold": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", + "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", "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-color": "1.6.0", + "@jimp/plugin-hash": "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/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" + } }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "@jimp/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", "requires": { - "@hapi/hoek": "^9.0.0" + "@jimp/types": "1.6.0", + "tinycolor2": "^1.6.0" } }, "@mapbox/node-pre-gyp": { @@ -4536,12 +5881,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", @@ -4626,11 +5981,15 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -4641,6 +6000,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -4699,6 +6063,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", @@ -4727,6 +6096,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", @@ -4811,6 +6190,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", @@ -4913,6 +6305,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", @@ -4926,7 +6340,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" } @@ -4934,8 +6347,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "color-support": { "version": "1.1.3", @@ -4952,6 +6364,41 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -4994,6 +6441,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", @@ -5035,6 +6487,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", @@ -5133,6 +6590,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "email-validator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", + "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -5520,6 +6982,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", @@ -5599,6 +7066,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", @@ -5730,6 +7207,11 @@ "wide-align": "^1.1.2" } }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -5760,6 +7242,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", @@ -5825,6 +7316,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", @@ -5907,6 +7409,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", @@ -5919,6 +7426,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", @@ -6162,11 +7677,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", @@ -6179,6 +7733,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", @@ -6422,10 +7981,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { "version": "5.0.0", @@ -6546,6 +8104,30 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + } + } + }, "nanoid": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.5.tgz", @@ -6718,6 +8300,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", @@ -6803,6 +8390,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", @@ -6812,6 +8404,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", @@ -6873,12 +8484,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", @@ -6888,6 +8519,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", @@ -6900,6 +8536,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", @@ -6950,6 +8591,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", @@ -7002,6 +8648,14 @@ "util-deprecate": "^1.0.1" } }, + "readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "requires": { + "readable-stream": "^3.6.0" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -7035,12 +8689,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", @@ -7084,6 +8748,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", @@ -7203,6 +8872,11 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" }, + "simple-xml-to-json": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.2.tgz", + "integrity": "sha512-bmJJf5YiYL60eOQk3gaVxbM6vgYuwrFydCEAA2x3jccHUTsAffiPyblS/yQGr8GDUQVxSDm3WwLNL5HmRqDUcg==" + }, "slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -7233,6 +8907,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -7298,6 +8977,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", @@ -7359,6 +9047,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", @@ -7379,6 +9072,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", @@ -7432,6 +9134,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", @@ -7513,6 +9220,14 @@ "prepend-http": "^2.0.0" } }, + "utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "requires": { + "pako": "^1.0.11" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7523,6 +9238,11 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -7569,6 +9289,11 @@ "is-symbol": "^1.0.3" } }, + "which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -7626,10 +9351,123 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" + }, + "xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + } + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + } + } + }, + "zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==" } } } diff --git a/package.json b/package.json index e563468b8a7..1399baf7c81 100644 --- a/package.json +++ b/package.json @@ -15,13 +15,17 @@ "cross-env": "7.0.3", "dotenv": "^16.4.5", "express": "4.17.1", + "gravatar": "^1.8.2", + "jimp": "^1.6.0", "joi": "^17.13.3", "jsonwebtoken": "^9.0.2", "mongoose": "^8.5.4", "morgan": "1.10.0", + "multer": "^1.4.5-lts.1", "nanoid": "3.3.5", "passport": "^0.7.0", - "passport-jwt": "^4.0.1" + "passport-jwt": "^4.0.1", + "uuid": "^10.0.0" }, "devDependencies": { "eslint": "7.19.0", diff --git a/public/.DS_Store b/public/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..64d97f0ac36abfe47ae4bd596f40ccf58271b914 GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8-BN@e6a+5|UMse>g2hXS^#zRRL8T_NXfS3=lQxG^$P4HT`5r!x zGrJq1+Jh$%I|H-d?9R+?=7a1HV~o4gVVkiAV@!Y|ax_*54zF~TY%n6%bNFn+k|0aQ zL9}9`zc_^7US&R;fu^9J->(AjyanSZOwv~CotMg$jm@g4in_S-9#!V0emYHDe{zGp zOQoWqu>IgF9A$&X_L+)PKa58coe&O35ORAR#zU34Y8np{o$DEgsEOL3u{WO|v|GKC zrfeVex{Icq_d2bn>>hU(i<;QkKRmq{JVnp3dNFKrAYRLs#R6Wz_)^%+o5YcdAHY*& z714ym05L!e5Cdz(fIS36eT{0SQi%a#;Aafr{vbgS9gDd^y>&o?*Jt!s5K+L!w*;cJ z=vd4Rf(L|~R6vu;?GuBWbQqU5&as#qH0g}%m0=#ca`AZKdUY6=I-GIGAhpB*F|f=) z*>oFt{-47yv+|L@oI*WffEf5^4Dd?d>$^~tJzKw(hi9z>y$40XxEu`-u$L|Y(7}CV fS38Ygq78A5#oQpyg5x?JkS+q65Ne2lUtr(^MKMiB literal 0 HcmV?d00001 diff --git a/public/avatars/2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg b/public/avatars/2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..4bb35027c9549f2cc31ec0a939ac69409f853378 GIT binary patch literal 121840 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 z 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

96m7e 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 Z2f@AEevAI|TN>B<2D>5Z;=v!o{|D?Wo@f97 diff --git a/routes/api/auth.js b/routes/api/auth.js index e9189d10ee4..a11b5ef9ed7 100644 --- a/routes/api/auth.js +++ b/routes/api/auth.js @@ -1,15 +1,19 @@ const express = require("express"); const router = express.Router(); -const { signup, login, logout, getCurrentUser } = require("../../controllers/authController"); +const { + signup, + login, + logout, + getCurrentUser, +} = require("../../controllers/authController"); const { authMiddleware } = require("../../middleware/authMiddleware"); const uploadAvatar = require("../../middleware/upload"); -const {updateAvatar} = require("../../controllers/uploadController"); - +const { updateAvatar } = require("../../controllers/uploadController"); router.post("/signup", signup); router.post("/login", login); -router.get("/logout", authMiddleware, logout); -router.get("/current", authMiddleware, getCurrentUser); +router.get("/logout", authMiddleware, logout); +router.get("/current", authMiddleware, getCurrentUser); router.patch("/avatars", authMiddleware, uploadAvatar, updateAvatar); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/routes/api/contacts.js b/routes/api/contacts.js index b990214bee5..6a0512773a9 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -16,5 +16,4 @@ router.put("/:id", updateContactDetails); router.delete("/:id", removeContact); router.patch("/:id/favorite", updateContactStatus); - module.exports = router; diff --git a/routes/api/upload.js b/routes/api/upload.js index 66e3f09eddd..5d7ccf8ccdf 100644 --- a/routes/api/upload.js +++ b/routes/api/upload.js @@ -7,4 +7,4 @@ // router.patch("/avatars", authMiddleware, uploadAvatar, updateAvatar); -// module.exports = router; \ No newline at end of file +// module.exports = router; diff --git a/services/authService.js b/services/authService.js index 54bc170e868..fc55b8e0c1b 100644 --- a/services/authService.js +++ b/services/authService.js @@ -32,7 +32,7 @@ const loginUser = async ({ email, password }) => { const token = jwt.sign(payload, process.env.SECRET, { expiresIn: "12h" }); user.token = token; await user.save(); - return {token, user: {email: user.email, subscriptin: user.subscription}}; + return { token, user: { email: user.email, subscriptin: user.subscription } }; }; const logoutUser = async (userId) => { @@ -40,7 +40,7 @@ const logoutUser = async (userId) => { if (!user) { throw new Error("Not authorized"); } - + user.token = null; await user.save(); }; @@ -49,4 +49,4 @@ module.exports = { registerUser, loginUser, logoutUser, -}; \ No newline at end of file +}; diff --git a/services/schemas/userSchema.js b/services/schemas/userSchema.js index b27ff2db38f..a696d32d4b3 100644 --- a/services/schemas/userSchema.js +++ b/services/schemas/userSchema.js @@ -2,43 +2,45 @@ const bCrypt = require("bcrypt"); const mongoose = require("mongoose"); const Schema = mongoose.Schema; -const UserSchema = new Schema({ - username: { - type: String, - required: [true, "Username is required"], +const UserSchema = new Schema( + { + username: { + type: String, + required: [true, "Username is required"], + }, + 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, + }, + avatarURL: { + type: String, + required: true, + }, }, - 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, - }, - avatarURL: { - type: String, - required: true, - }, -}, {versionKey: false}, + { versionKey: false }, ); -UserSchema.methods.setPassword = async function(password) { +UserSchema.methods.setPassword = async function (password) { this.password = await bCrypt.hash(password, 10); -} +}; -UserSchema.methods.validatePassword = async function(password) { +UserSchema.methods.validatePassword = async function (password) { return await bCrypt.compare(password, this.password); -} +}; const User = mongoose.model("User", UserSchema, "users"); module.exports = User; From 770e7f11553dc59b234873e76cb25d384fd8b566 Mon Sep 17 00:00:00 2001 From: zetdou Date: Sun, 15 Sep 2024 21:28:45 +0200 Subject: [PATCH 20/21] emailService.js Configure nodemailer, create endpoints, create mail verification and resend mail verification with brevo. --- controllers/authController.js | 41 ++++++++++++++++++++++++++++++++++ package-lock.json | 27 +++++++++++++++++++++- package.json | 4 +++- routes/api/auth.js | 4 ++++ services/authService.js | 38 ++++++++++++++++++++++++++++++- services/emailService.js | 33 +++++++++++++++++++++++++++ services/schemas/userSchema.js | 8 +++++++ 7 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 services/emailService.js diff --git a/controllers/authController.js b/controllers/authController.js index 35ebfb595a0..4c2f1609ac7 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -3,7 +3,10 @@ const { registerUser, loginUser, logoutUser, + verifyUser, + resendVerificationEmail, } = require("../services/authService"); +const User = require("../services/schemas/userSchema"); const signup = async (req, res, next) => { const { username, email, password } = req.body; @@ -57,9 +60,47 @@ const getCurrentUser = async (req, res, next) => { } }; +const verifyEmail = async (req, res, next) => { + const { verificationToken } = req.params; + + try { + const user = await verifyUser(verificationToken); + if (!user) { + const alreadyVerifiedUser = await User.findOne({ verificationToken: null, verify: true, email: req.body.email }); + + if (alreadyVerifiedUser) { + return res.status(400).json({ message: "Email has already been verified!" }); + } + return res.status(404).json({ message: "User not found!" }); + } + res.status(200).json({ message: "Verification succesful!" }); + } catch (err) { + next(err); + } +}; + +const resendVerificationEmailHandler = async (req, res, next) => { + const { email } = req.body; + + if(!email) { + return res.status(400).json({ message: "Missing required field email!" }); + } + try { + const result = await resendVerificationEmail(email); + if (result === "alreadyVerified") { + return res.status(400).json({ message: "Verification has already been passed!" }); + } + res.status(200).json({ message: "Verification email sent!" }); + } catch (err) { + next(err); + } +} + module.exports = { signup, login, logout, getCurrentUser, + verifyEmail, + resendVerificationEmailHandler, }; diff --git a/package-lock.json b/package-lock.json index 26ed65759a2..5a005ca67e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,9 +22,11 @@ "morgan": "1.10.0", "multer": "^1.4.5-lts.1", "nanoid": "3.3.5", + "nodemailer": "^6.9.15", "passport": "^0.7.0", "passport-jwt": "^4.0.1", - "uuid": "^10.0.0" + "uuid": "^10.0.0", + "xoauth2": "^1.2.0" }, "devDependencies": { "eslint": "7.19.0", @@ -3685,6 +3687,14 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/nodemailer": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", + "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", @@ -5265,6 +5275,11 @@ "node": ">=4.0" } }, + "node_modules/xoauth2": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/xoauth2/-/xoauth2-1.2.0.tgz", + "integrity": "sha512-hKuNbkj3q/ifCcfWnW6KURP+6ExSuLdLG007gasNhMEMKlLaejNkIA6eu5Ol1xPP0/kzTuA87XHDaAcUw5k73Q==" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -8178,6 +8193,11 @@ } } }, + "nodemailer": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", + "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==" + }, "nodemon": { "version": "2.0.15", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", @@ -9370,6 +9390,11 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, + "xoauth2": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/xoauth2/-/xoauth2-1.2.0.tgz", + "integrity": "sha512-hKuNbkj3q/ifCcfWnW6KURP+6ExSuLdLG007gasNhMEMKlLaejNkIA6eu5Ol1xPP0/kzTuA87XHDaAcUw5k73Q==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 1399baf7c81..3e5234117eb 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,11 @@ "morgan": "1.10.0", "multer": "^1.4.5-lts.1", "nanoid": "3.3.5", + "nodemailer": "^6.9.15", "passport": "^0.7.0", "passport-jwt": "^4.0.1", - "uuid": "^10.0.0" + "uuid": "^10.0.0", + "xoauth2": "^1.2.0" }, "devDependencies": { "eslint": "7.19.0", diff --git a/routes/api/auth.js b/routes/api/auth.js index a11b5ef9ed7..61fea3fe192 100644 --- a/routes/api/auth.js +++ b/routes/api/auth.js @@ -5,6 +5,8 @@ const { login, logout, getCurrentUser, + verifyEmail, + resendVerificationEmailHandler, } = require("../../controllers/authController"); const { authMiddleware } = require("../../middleware/authMiddleware"); const uploadAvatar = require("../../middleware/upload"); @@ -15,5 +17,7 @@ router.post("/login", login); router.get("/logout", authMiddleware, logout); router.get("/current", authMiddleware, getCurrentUser); router.patch("/avatars", authMiddleware, uploadAvatar, updateAvatar); +router.get("/verify/:verificationToken", verifyEmail); +router.post("/verify", resendVerificationEmailHandler); module.exports = router; diff --git a/services/authService.js b/services/authService.js index fc55b8e0c1b..8a11b0a92ab 100644 --- a/services/authService.js +++ b/services/authService.js @@ -1,3 +1,5 @@ +const { v4: uuid4 } = require("uuid"); +const { sendVerificationEmail } = require("./emailService"); const User = require("./schemas/userSchema"); const jwt = require("jsonwebtoken"); @@ -7,9 +9,12 @@ const registerUser = async ({ username, email, password, avatarURL }) => { throw new Error("This email is already taken!"); } - const newUser = new User({ username, email, avatarURL }); + const verificationToken = uuid4(); + const newUser = new User({ username, email, avatarURL, verificationToken }); await newUser.setPassword(password); await newUser.save(); + + await sendVerificationEmail(email, verificationToken); return newUser; }; @@ -45,8 +50,39 @@ const logoutUser = async (userId) => { await user.save(); }; +const verifyUser = async (verificationToken) => { + const user = await User.findOne({ verificationToken }); + if (!user) { + return null; + } + + user.verify = true; + user.verificationToken = null; + await user.save(); + + return user; +}; + +const resendVerificationEmail = async (email) => { + const user = await User.findOne({ email }); + + if (!user) { + throw new Error("User not found"); + } + + if (user.verify) { + return "alreadyVerified"; + } + + await sendVerificationEmail(user.email, user.verificationToken); + + return "resent"; +}; + module.exports = { registerUser, loginUser, logoutUser, + verifyUser, + resendVerificationEmail, }; diff --git a/services/emailService.js b/services/emailService.js new file mode 100644 index 00000000000..4429d1e7852 --- /dev/null +++ b/services/emailService.js @@ -0,0 +1,33 @@ +const nodemailer = require("nodemailer"); + +const transporter = nodemailer.createTransport({ + host: process.env.BREVO_SMTP_HOST, + port: process.env.BREVO_SMTP_PORT, + auth: { + user: process.env.BREVO_API_KEY, + pass: process.env.BREVO_API_PASS, + } +}); + +const sendVerificationEmail = async (email, verificationToken) => { + const verificationUrl = `http://localhost:3000/api/users/verify/${verificationToken}`; + + const mailOptions = { + from: process.env.BREVO_EMAIL, + to: email, + subject: "Verify your email adress", + html: `Click here to verify your email address.

`, + }; + + try { + await transporter.sendMail(mailOptions); + console.log("Verification email sent to", email); + } catch (err) { + console.error("Error sending email:", err); + throw err; + } +}; + +module.exports = { + sendVerificationEmail, +} \ No newline at end of file diff --git a/services/schemas/userSchema.js b/services/schemas/userSchema.js index a696d32d4b3..e3f67aa0bfe 100644 --- a/services/schemas/userSchema.js +++ b/services/schemas/userSchema.js @@ -30,6 +30,14 @@ const UserSchema = new Schema( type: String, required: true, }, + verify: { + type: Boolean, + default: false, + }, + verificationToken: { + type: String, + default: null, + }, }, { versionKey: false }, ); From dec5dc7ee54523d272470d74213610cf20a29a5f Mon Sep 17 00:00:00 2001 From: zetdou Date: Sun, 15 Sep 2024 21:36:38 +0200 Subject: [PATCH 21/21] authController and Service Modified code to user cannot login when verification mail is unclicked --- controllers/authController.js | 3 +++ services/authService.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/controllers/authController.js b/controllers/authController.js index 4c2f1609ac7..601b2d7f4ef 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -37,6 +37,9 @@ const login = async (req, res, next) => { const { token, user } = await loginUser({ email, password }); return res.json({ token, user }); } catch (err) { + if (err.message === "Email has not been verified! Please check your inbox.") { + return res.status(401).json({ message: err.message }); + } next(err); } }; diff --git a/services/authService.js b/services/authService.js index 8a11b0a92ab..ab677b1eecb 100644 --- a/services/authService.js +++ b/services/authService.js @@ -24,6 +24,10 @@ const loginUser = async ({ email, password }) => { throw new Error("User not exists!"); } + if (!user.verify) { + throw new Error("Email has not been verified! Please check your inbox."); + } + const isPasswordCorrect = await user.validatePassword(password); if (!isPasswordCorrect) { throw new Error("Wrong password!");

96m7e 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 Z2f@AEevAI|TN>B<2D>5Z;=v!o{|D?Wo@f97 literal 0 HcmV?d00001 diff --git a/public/avatars/default-avatar-1.jpg b/public/avatars/default-avatar-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8f553ceeccb811f37705e71d272e666ec459b321 GIT binary patch literal 8174 zcmdUUcT`ltlJ|un=PV*QGXw$23Je(r8DYptvcv&~B!VD0=cFWw1Iz%D84ysAoD|79 zgJeNORMPU^zJ1^RwP*kQw)&oPt8P`FuHWgZ(|xOMW^YyjDyX`aI)H-%064b;xLE)q zZl(V<;r>4Y{hR*VY+PI%T-<*v{{W}mjm6p z`CmjtOh|%D0K&t^xtRxu{(%Ajvj3$#*$UoT>+7KWd@Hjl_qaWE^ec)joO0}bXAJ-{ zCcP_Lop_2xzn1}k5*^$O1K8x^!QF2FoS)6gxgmf6^ld8ucz(Q)007r+%R+$m+)fk# zmG31c0l<$#*ZdFw-|#CVKs#es3jn`!;?5v|8@U4n0A@a5J3%uG=3)SVTjk^fD7@XU z=mc;`C5r*FSnTcE)UL*gV>pX`H@A-A^6V1;tnz)qvj8CY-BJ|TXjsGo0KTZcCm;g* z1_5v?H{k$*{Q~W+0riF<3<6xv;*LN7g7&k|0Ei1=x)K6V#hbl@0JO&T-+cfA=BX7H z0AL`j#m)c(4AZ$pApjm~*7zYnbO*vhbPKl9m0=<)M0L+Q)FK1`n78rzQ&>(X`jGD^ zSJ~JBfG~RaFCcULBLraPH7xjIB58mmeM4Dpo%Ln zgxq3}o*w|6T0gwCxkZyXc{k9l!2Xt}ZZllA-FCP5$LCsVnd3tTj$0NmK(ObPjomVY zD)HZMqk--}cl#fz|Du1!04~*kiT}sml>Y-L(EnvnkEsA05H2nr2|gha5#c{}1qb&w zWeKQh076<0B05ffF^H0$BZ^*BT-ky@*OuRo&j( z=U-Wlqlj}QG~ayWWQf7+Sexj?m_D=||8Bx3{9}=q>9mbLE1o{vyWZ~pg|z#4{dG&O8q6^IMYDgrd9)wa z&1@(ht?vM$7+*_l0G*7<&1b+F(i$%`M;?@)ryo*ukT4Hr^f^xsc!rnkS4@;6NPFK zd4$iX=RMeREou+iGD+0}W{M_HH?rp>X8Y8y)3UV?;<~{cD%!8ZdeikN&5K=W5qGy~_v^{^HK^1ZYwPqw-RPN6Ei74O3&bPF;Iz`XbR4eI zqWj#z&7n#rtH`0^%;zZQ#Zn=kB4>H_?<@{b;=381_pk-Aos_YBg?{;xh_30)ww{2d zakNzR`)v)g1asn+y@dSVSe8uzI{%~cqW-k<7@4SkSXO4Ni^*6^Vx4-t4m4zg2A+1P z>=MP;Dpz>oWr34-?O!y8R8ljvgyTCZ$JFi zS#xHTFByrcY%{9KG_vDGQ1^q7B4%F968+HY>g+)yk?}IY60Y`0>H)L&?TimF=|$ta zo|^_PzJw9}qMTgLy!!pYMiVV~MO@<3#Z(bt29OB@3$|T9&v?(J*hJH|5K7TLoISPo zP2>Y%kqHf8;qal1x>hR#8tKaE;aG;3j%%=_o&m2MeR10%XY9s+gB^b3sR&A^Wjs#LBip;J-*Gp65NeQFD!?rO zW<){OiR251o)v@C1G%qj3?GC zd@#y@(mw(^YFkLvVV~*ZBrf{RL{x|ROZ=jQ@;yu@o^>nVyt1dOAL;01(+z;}nWMMy z8RLpD^WAk2=WNVlDl}T*3B=>}GAlErkIQBqeqy`4TGkI=J+DLtEUC8{BsVr6-g%R@ z;m-9yQtqVd?@L_zLEji+T5_r-;z zGYSfZH?5KhqcD{htEMO94lhCnFjZkKK0db6&zuem*cdd7(E96!yAx>rc}iupN;-i# zU(xLNoH-@eT6R;u;G~w+s9%%&V;;DZp{!4D)eYblb7aG$F5mu)L#3d1|F?+wr|il< zk~8-N(tV~KhDa686y5~g!J}+wwAs1=VyAxVF08+^gJ80I~ht8XJtH@uNGltS-1Fo^5sId z7*2x=7llHgkR8As2PrL=FNAGT>q@-hLgSlK`y_ZLT9ExDiW==a}!?Nd8j| zCG9y`Kwn25`Ci;5-%2q$c|9F0;d3pUe>UW+cbrz>F8-B=(PulUu{}>grUdHNW8gdn zCSPkPAQ9@Z`I@Fr6eROf)XI2GQg_`9lh4R<7BEVY8>KMrzvtL`tpnjZKI_3HlEsfl`XIyFvaaei1|43>!uT@{2A@ptD;2p6h%Uvb} z-7JsFdMoAH#fOh!h|%bwO0jckRG)~Mt0S5CqpaOCgYsbRqV1BJOIXdji#L{LpIdpv zx5vqO`l?&-goNvtxa4?c=I+(E8Tg)_8vT0E&6Eu?v+Ec+^>gyGky9~kwM!(KcgaNB3Kp zE@PQZ!Fmq|WzK}PT^$b1rj04eu$B#ia4JlL0149IMJZ3?jIBhTmbz-hFoKJ|8MhOx zPLjy`Xy9Nt<`ix_czXzF+4MZ>iDHEy%d>s!OJycvbOm%}s3$$z)?+L80}Q*(eGcaT z^6Q!jY-E}qfqHk3bM>~`PwsuGpT{w))s(Zu8ruG9aa^35QT_(g)kZFG_m)AND&yd* z;a{1+h7;rak=jOQzB=0bA7C|kE{iQ0KZiNK!Fqcl#doV9tLCE`{`hJOaVTzF zPUsUm!Az#A_SSS7Jg?G2W`!R~fZcULKxLB`kg_{AtQsO z!aQ<|^p44|vO0lFzoiO7HV3Zcar;o#Y8}(=RB>uOGhMCCmb}sXOL}MT$7ZIQY>4SF zPlq@C&0W&IpA8d48hwJm#U>fX$9^cL6FPCtMAe><`mtPZUR?>GlPpQ&< zH|A6451+IlaQ@p>#*|Bp!^ZEF$kEzK_QID$o!?ezrx!UHejzOEy7#q%>m>JC#}iD5 z7&7YVpq!#QrvYKOH&<%%htNF_dEdQX0~8Mw8keA$(81!d9|n7}*aSB6`|(P5qkdc@ z?!NMj>hPfYNur!spzJM9*DI%F>0$?FbjUW=R7%L?&eLP$DqoNTXhcEeTN>*qW&;#$ z2UKraYx#*eLfd9jD`~$DB^l~s;AoM^Q%u2*<%pE}A$=~W9cUFWf%THgjg*|NP|USR z)z{MlQE0v$FP?;ScT72JuDShyXDl+PJ6wDj!wm9Y^g!du`CnDNV&U{GpQ_w_axd9O zKPv!!#;B!vEklD^CtNCd$t|h5+OtSAx3k%%QWfdJcu|`n?aUSN4*dqNxB;FSZSO*E zX@Au3=U=_6yJl%Cn!Yo{GhyIe3uXp;Yg}r1H;4a`s6MW1wg0Bp;R1Kof@?mGYoDVx zC6bS)UgreejYgV9ub_sjS!|Zp5Hs%Y)7E8MefC@;S@SgZF!B#=vFSHJle<#}2MCWx zfN>)X0-_y%?)SElArm3~k!3lttGp6NBiWEeoHG=RJZ6!RS`VJi4l&Cy;(u{3&!Gp6&6WQw zzN%ea5DJ={DEv|dea!TTcvERFVAR?jo zc##Ms-)*eo#f$o^rI74+p8+NP#+|J6euvAS8J6g0OK5?XLyWvhp2FM5Qoq+d8OhRf z$wxdW>+4V+VIAQQ<#w9xg)R9)xjE2@Qye7+W%4@ZZ;9CmqcTN^Uvoi?i@q}n_4U{1 zpu`dK6X)-^rtm1Y#*GQ`UHkROy0PV@fhYTI%qw0z-FD^cK30U)9wpb)3E!SfSg?UlAhP%g#7 z*bDlhR(P>4E0!O0R{{;pq_~sTIEw`QUzPe49Xn6?vZDqY|3>y5gXoQ2L^{|+&s!42 zNbWNJ5+E6WtzN3TLFD6NsgO=*^G9Be*&pGh4rFK`8qrp?AGberi)VX1$}&so9uRKt zJ}la{M3`qpGkFS-Do5KeI#-F1WnDQb>euDF&sJ7Gh{~$P3J+HD(WHFxme)WA{&{RW zEidfsx!}7Gt=MANLJgEo=HhEPU($_~DG6*y{6TE6`oJ}s=VSuA_?}n8(;_nYBTx?q zraY&2j!5D;s5+kpr zoS8xncgFM5)c`sYB$KO#LFSdoD0Gv43K5%pfPPJjuqQ_P-(Je1QU@Y+JH6=7;G&z> zRl4%F6-BeYZq8txZ3RMYqHOben&=s zH#122h08r!FdP z!N)ruQeQA1^fW434^m2ZMQGs5iNzmh@lv6X7|PaX$O$+`c1)BcXAYxrsG zePMB~-CoR@JGe_kW*#fAT`DIF`N5hd{++yv73;b1Gq)^Jx6qig7$H*5qPHbl-46;& z+1F++D-~T=UNG6>aK`gsawX_P@9phmBPI=6$+?m5B_Ee?x=cnhz1MWO2 zr)sZKHopFVgxRl;7?DMrDN_*Cd!enj+(ZLAo$;Nje0G-T)ZU}YZqaC24P8hnrcEde z?Gs44{nHtr%2pq>jP>Tc8kL2h1(oNKBt64Nt1FuKMGC*GRLi7gQhZW)u6|lh z5J+S`op!W)uvPUG2TkUvMA3sa1xpNEmPWFF1{ACYG|2+Ic3MsIg&Tsg$gF=h6tNc^YXRBF#>UqmR{&&m^f2~^?AEvQ@Ue@8UfGp zTpU5<%{Rm@#mo;PvrevJuR!lEj5m|&_fJe+9iCL7@9;dp!;`MZpu1(WLYA`R4YAQ( zU^cPdgR!Pnm};iA91O$^9P;THELd^-2D*$*C)8)79)ODm2T%qWnMuCPq_onZw9>2Y zpOmEc+!R%t-M4dL)2Vu1iL#v(-ng|PEq~g?CG}!L6htn&lI+(G9o1o1Wi}1nhmPHp zNqL)>Pfsmn2Y+{LzxPf*2^{tL#m^ajv;#n&L#AFO-wUG3Qdw%6~{Zs!zPmHp6r?FL}Gt<3UK-PW7`(d@v% z!v+1bvV7Z`;1E-S=!x2}>mox_sg8^4y8d0Cq`ER`6e89RLHoF^fx&AB*xEzUaLiw9 z?aF}l*EJW@c`*Nyi#fcv`5qN=Ve<7V#nr{B!( zBq=5<$bNRMv&S8H$KE?t#gb$>DLwj-%4P7YnNX4^BX^x;NRu+ZJD?a5t;?i(LXfNi z!~Ik;-OZ9Yp=nX7I5e+T04T&z5NX%{&z#02;u3@87jdIGwT1FDO@8FO=U%c&XPlVP1NGN4G-XrKM< zd0X^6d89*@r}ay2T~AO5$Hp|dsbdXF>Q5M4ri1XRyMW6}VoV5gasyCx6`m+vUz@@| zkvxXv2+Y;6%Tj&)`{bAY_idW_TGY;u@B;turDt&PA@j*1a338RGP9kMhM}~My-cF^ zrP6aSB%sttwuRrB##?-Mw)Us9uHuv9SO~tf?*{5~Ld3)l^dY6P%pP8s8x7I5?19>dnX8oA*5YnIPZ0*5_m;8Y`er zsPw)bn=HgQuRzul%KC`wRH?$aiVa9YKF~8l{Ys7>%cMqxtT>TFv9YFz<3t%CVs)~T znJ&!l4H3g2zZx3>Z^*&4p3%Ec++KTFPvRgGQ=N6Gk@y2-NIK5P_FrKA6pJkmbj8dP`Jf&P^GH2h{%bBs_Rx%9D~yUusq+sunD&CQ zlrI_YZl+m)c?Cb_gZX001<^DpK7l(*0E}16bM4v=KbLG%Ie;6i9_AE`u zN6sC_Al^U!EQHJRtuP>IPmK$;iFg=E z!_nW0tOBW)+xo`#C5ScO#z>@1Mo+r1aPwZZ8Iz1zbI<3o#l z{#xK2sv~;untAbaF8y@9h;shE2_ zx>(IbLL0_Whgb$@O3_|Z=_~u(~l*4^fw|06bkAO{gWBi z$V<#=Dg-_yipMbCwT<7u;xj^cC|`|uU|d7^ zgE?*h#;*j#0eJYafhz|AKjwDQ8r)7-7$7o5$t4eaJ9^BI1-iLsh*O+HdyGjF6Yy>E zRkX^A|73uu9LSsm+1WyR$fg&663DmsUuKX1B$a>^W(R~vcET@OjiX_%5Tv=nZ9+yc z=cCADgba#j$5tRj-|+UdLPVW_7vCXhPk8qEWNufWzc0x*x5PDykBliRec@9@8qR?Q zg-nngHvB5<6r284k|=2p5W=2fhBMsAkRG4?Ijs`q7=MgUaYd2p@rSePSLl%o>8BGD z3Ky^5HC+XVbEj$j`?+4zSG?3*`SXvyAoYK1djIqEDg4i7Ck~DxAW`r?Sb+XzG4~%h CYYzAT literal 0 HcmV?d00001 diff --git a/routes/api/auth.js b/routes/api/auth.js index 9458f60a373..e9189d10ee4 100644 --- a/routes/api/auth.js +++ b/routes/api/auth.js @@ -2,10 +2,14 @@ const express = require("express"); const router = express.Router(); const { signup, login, logout, getCurrentUser } = require("../../controllers/authController"); const { authMiddleware } = require("../../middleware/authMiddleware"); +const uploadAvatar = require("../../middleware/upload"); +const {updateAvatar} = require("../../controllers/uploadController"); + router.post("/signup", signup); router.post("/login", login); router.get("/logout", authMiddleware, logout); router.get("/current", authMiddleware, getCurrentUser); +router.patch("/avatars", authMiddleware, uploadAvatar, updateAvatar); module.exports = router; \ No newline at end of file diff --git a/routes/api/upload.js b/routes/api/upload.js new file mode 100644 index 00000000000..66e3f09eddd --- /dev/null +++ b/routes/api/upload.js @@ -0,0 +1,10 @@ +// const express = require("express"); +// const router = express.Router(); +// const {authMiddleware} = require("../../middleware/authMiddleware"); +// const uploadAvatar = require("../../middleware/upload"); + +// const {updateAvatar} = require("../../controllers/uploadController"); + +// router.patch("/avatars", authMiddleware, uploadAvatar, updateAvatar); + +// module.exports = router; \ No newline at end of file diff --git a/services/authService.js b/services/authService.js index d2a8b899bf5..54bc170e868 100644 --- a/services/authService.js +++ b/services/authService.js @@ -1,13 +1,13 @@ const User = require("./schemas/userSchema"); const jwt = require("jsonwebtoken"); -const registerUser = async ({ username, email, password }) => { +const registerUser = async ({ username, email, password, avatarURL }) => { const userExists = await User.findOne({ email }); if (userExists) { throw new Error("This email is already taken!"); } - const newUser = new User({ username, email }); + const newUser = new User({ username, email, avatarURL }); await newUser.setPassword(password); await newUser.save(); return newUser; diff --git a/services/schemas/userSchema.js b/services/schemas/userSchema.js index 0594615f4ee..b27ff2db38f 100644 --- a/services/schemas/userSchema.js +++ b/services/schemas/userSchema.js @@ -25,6 +25,10 @@ const UserSchema = new Schema({ type: String, default: null, }, + avatarURL: { + type: String, + required: true, + }, }, {versionKey: false}, ); diff --git a/utils/folderUtils.js b/utils/folderUtils.js new file mode 100644 index 00000000000..dd54a63786f --- /dev/null +++ b/utils/folderUtils.js @@ -0,0 +1,20 @@ +const fs = require("fs").promises; + +const isAccessible = (path) => + fs.access(path) + .then(() => true) + .catch(() => false); + +const setupFolder = async (path) => { + const folderExists = await isAccessible(path); + if (!folderExists) { + try { + await fs.mkdir(path); + } catch (e) { + console.error("No permissions to create folder!", e); + process.exit(1); + } + } +}; + +module.exports = { setupFolder }; \ No newline at end of file From e374004f6ecdab92a0fa4b7c45464e9476128e8d Mon Sep 17 00:00:00 2001 From: zetdou Date: Fri, 13 Sep 2024 20:22:34 +0200 Subject: [PATCH 19/21] formatting code prettier --- app.js | 7 +- config/jwt.js | 48 ++++++------- controllers/authController.js | 17 +++-- controllers/uploadController.js | 12 ++-- middleware/authMiddleware.js | 41 +++++------ middleware/errorMiddleware.js | 26 +++---- middleware/upload.js | 28 ++++---- .../2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg | Bin 121840 -> 0 bytes routes/api/auth.js | 16 +++-- routes/api/contacts.js | 1 - routes/api/upload.js | 2 +- services/authService.js | 6 +- services/schemas/userSchema.js | 64 +++++++++--------- 13 files changed, 140 insertions(+), 128 deletions(-) delete mode 100644 public/avatars/2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg diff --git a/app.js b/app.js index f0cba8c6e01..9913a61603e 100644 --- a/app.js +++ b/app.js @@ -1,11 +1,10 @@ const express = require("express"); const logger = require("morgan"); const cors = require("cors"); -const {jwtStrategy} = require("./config/jwt"); -const {errorMiddleware} = require("./middleware/errorMiddleware"); +const { jwtStrategy } = require("./config/jwt"); +const { errorMiddleware } = require("./middleware/errorMiddleware"); const path = require("path"); - const contactsRouter = require("./routes/api/contacts"); const authRouter = require("./routes/api/auth"); @@ -32,6 +31,4 @@ app.use((req, res) => { app.use(errorMiddleware); - - module.exports = app; diff --git a/config/jwt.js b/config/jwt.js index 27de6734fc1..89944d83370 100644 --- a/config/jwt.js +++ b/config/jwt.js @@ -1,35 +1,31 @@ const passport = require("passport"); -const {ExtractJwt, Strategy} = require("passport-jwt"); +const { ExtractJwt, Strategy } = require("passport-jwt"); const User = require("../services/schemas/userSchema"); const jwtStrategy = () => { - const secret = process.env.SECRET; + const secret = process.env.SECRET; - const params = { - secretOrKey: secret, - jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken() - } + const params = { + secretOrKey: secret, + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + }; - passport.use( - new Strategy( - params, - async function(payload, done) { - try { - const user = await User.findOne({_id: payload.id}).lean(); + passport.use( + new Strategy(params, async function (payload, done) { + try { + const user = await User.findOne({ _id: payload.id }).lean(); - if(!user) { - return done(new Error("User not found!")) - } - return done(null, user) - } catch(err) { - return done(err) - } - } - ) - ) -} + if (!user) { + return done(new Error("User not found!")); + } + return done(null, user); + } catch (err) { + return done(err); + } + }), + ); +}; module.exports = { - jwtStrategy, -} - + jwtStrategy, +}; diff --git a/controllers/authController.js b/controllers/authController.js index f9f11a8ed0a..35ebfb595a0 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,11 +1,20 @@ const gravatar = require("gravatar"); -const { registerUser, loginUser, logoutUser } = require("../services/authService"); +const { + registerUser, + loginUser, + logoutUser, +} = require("../services/authService"); const signup = async (req, res, next) => { const { username, email, password } = req.body; try { const avatarURL = gravatar.url(email, { s: "200", d: "retro" }, true); - const newUser = await registerUser({ username, email, password, avatarURL }); + const newUser = await registerUser({ + username, + email, + password, + avatarURL, + }); return res.status(201).json({ message: "User created", user: { @@ -22,7 +31,7 @@ const signup = async (req, res, next) => { const login = async (req, res, next) => { const { email, password } = req.body; try { - const {token, user} = await loginUser({ email, password }); + const { token, user } = await loginUser({ email, password }); return res.json({ token, user }); } catch (err) { next(err); @@ -53,4 +62,4 @@ module.exports = { login, logout, getCurrentUser, -}; \ No newline at end of file +}; diff --git a/controllers/uploadController.js b/controllers/uploadController.js index 1fa50fdbd08..3f16196ddcc 100644 --- a/controllers/uploadController.js +++ b/controllers/uploadController.js @@ -3,15 +3,17 @@ const path = require("path"); const Jimp = require("jimp"); const { v4: uuidv4 } = require("uuid"); const User = require("../services/schemas/userSchema"); -const { setupFolder } = require("../utils/folderUtils"); +const { setupFolder } = require("../utils/folderUtils"); // Import funkcji pomocniczej const avatarsDir = path.join(process.cwd(), "public/avatars"); const MAX_AVATAR_WIDTH = 250; const MAX_AVATAR_HEIGHT = 250; +// Funkcja aktualizacji awatara const updateAvatar = async (req, res, next) => { try { - await setupFolder(avatarsDir); + // Sprawdzenie, czy folder "avatars" istnieje + await setupFolder(avatarsDir); // Wywołanie funkcji, która sprawdza i tworzy folder if (!req.file) { return res.status(400).json({ message: "No file uploaded" }); @@ -24,7 +26,7 @@ const updateAvatar = async (req, res, next) => { // Przeniesienie pliku z tmp do folderu avatars await fs.rename(tmpPath, avatarPath); - console.log("File path:", avatarPath); // Sprawdź ścieżkę do pliku + // Przetwarzanie obrazu za pomocą Jimp (kadrowanie) const image = await Jimp.read(avatarPath); const w = image.bitmap.width; @@ -54,5 +56,5 @@ const updateAvatar = async (req, res, next) => { }; module.exports = { - updateAvatar, -} \ No newline at end of file + updateAvatar, +}; diff --git a/middleware/authMiddleware.js b/middleware/authMiddleware.js index 32c188dc316..bc7f96ca502 100644 --- a/middleware/authMiddleware.js +++ b/middleware/authMiddleware.js @@ -2,26 +2,29 @@ const passport = require("passport"); const User = require("../services/schemas/userSchema"); const authMiddleware = (req, res, next) => { - passport.authenticate( - "jwt", - { - session: false, - }, - async (err, user) => { - if(!user || err) { - return res.status(401).json({message: "Unauthorized!"}); - } + passport.authenticate( + "jwt", + { + session: false, + }, + async (err, user) => { + if (!user || err) { + return res.status(401).json({ message: "Unauthorized!" }); + } - const foundUser = await User.findById(user._id); - if (!foundUser || foundUser.token !== req.headers.authorization.split(" ")[1]) { - return res.status(401).json({message: "Unauthorized!"}); - } - req.user = foundUser; - next(); - } - )(req, res, next) + const foundUser = await User.findById(user._id); + if ( + !foundUser || + foundUser.token !== req.headers.authorization.split(" ")[1] + ) { + return res.status(401).json({ message: "Unauthorized!" }); + } + req.user = foundUser; + next(); + }, + )(req, res, next); }; module.exports = { - authMiddleware, -}; \ No newline at end of file + authMiddleware, +}; diff --git a/middleware/errorMiddleware.js b/middleware/errorMiddleware.js index 8fc595fb9f2..8f776855619 100644 --- a/middleware/errorMiddleware.js +++ b/middleware/errorMiddleware.js @@ -1,18 +1,18 @@ const errorMiddleware = (err, req, res, next) => { - if (err.message === "User not exists!" || err.message === "Wrong password!") { - return res.status(401).json({message: err.message}); - } + if (err.message === "User not exists!" || err.message === "Wrong password!") { + return res.status(401).json({ message: err.message }); + } - if (err.name === "ValidationError") { - return res.status(400).json({ - message: err.message, - }); - } - res.status(500).json({ + if (err.name === "ValidationError") { + return res.status(400).json({ message: err.message, }); - }; + } + res.status(500).json({ + message: err.message, + }); +}; - module.exports = { - errorMiddleware, - } \ No newline at end of file +module.exports = { + errorMiddleware, +}; diff --git a/middleware/upload.js b/middleware/upload.js index 41d51e3895e..eb7bd76e5eb 100644 --- a/middleware/upload.js +++ b/middleware/upload.js @@ -1,25 +1,25 @@ const multer = require("multer"); const path = require("path"); -const {v4: uuidv4} = require("uuid"); +const { v4: uuidv4 } = require("uuid"); const tmpDir = path.join(__dirname, "../tmp"); const storage = multer.diskStorage({ - destination: (req, file, cb) => { - cb(null, tmpDir); - }, - filename: (req, file, cb) => { - const ext = path.extname(file.originalname); - const uniqueName = `${uuidv4()}${ext}`; - cb(null, uniqueName); - } + destination: (req, file, cb) => { + cb(null, tmpDir); + }, + filename: (req, file, cb) => { + const ext = path.extname(file.originalname); + const uniqueName = `${uuidv4()}${ext}`; + cb(null, uniqueName); + }, }); const uploadAvatar = multer({ - storage, - limits: { - fileSize: 2 * 1024 * 1024, - }, + storage, + limits: { + fileSize: 2 * 1024 * 1024, + }, }).single("avatar"); -module.exports = uploadAvatar; \ No newline at end of file +module.exports = uploadAvatar; diff --git a/public/avatars/2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg b/public/avatars/2b2dbe31-d575-4bc1-bba9-4f3ec5d59077.jpeg deleted file mode 100644 index 4bb35027c9549f2cc31ec0a939ac69409f853378..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121840 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 z 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